From a38dac46607855e2789e995227f7a49dff4bff55 Mon Sep 17 00:00:00 2001 From: Artem Gasparyan <45360663+artgas1@users.noreply.github.com> Date: Thu, 23 Apr 2026 11:24:40 +0300 Subject: [PATCH] fix(ssh-keys): use underscore response keys (ssh_key/ssh_keys) (#1) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: add Cloud API tools for Servers + Account Adds 11 new MCP tools covering VPS lifecycle and account finances: Servers: - list_servers, get_server - start_server, shutdown_server, reboot_server - get_server_logs - list_server_disk_backups, create_server_disk_backup, delete_server_disk_backup Account: - get_account_finances, get_account_status Follows existing code structure (api/ -> actions/ -> tools/). Reuses BaseApiClient and TIMEWEB_TOKEN env var. Tool descriptions hand-polished with context on when and how to use each. Smoke-tested against live account: all 11 tools registered, read-only endpoints return expected payloads. Relates to upstream issue #2 (proposal for Cloud API extension). * feat: add follow-up tools (resize, hard variants, clone, disks, services cost) Extends the MVP with 6 additional tools: Servers: - resize_server — change preset or custom configurator (cpu/ram/disk/gpu) - hard_reboot_server, hard_shutdown_server — force power operations - clone_server — create full VPS copy - list_server_disks — get disk IDs (required for disk backup tools) Account: - get_account_services_cost — per-service cost breakdown (VPS, DB, S3, etc.) Also adds a `prepare` script to package.json so the package can be installed and run directly from GitHub (e.g., `npx github:org/repo#branch`) without needing a pre-built dist/ in the repo or an npm publish. Smoke-tested: all 17 new tools register via tools/list, list_server_disks and get_account_services_cost return expected payloads from a real account. * feat: add server catalogs (presets/os/configurator/software/locations) * feat: add ssh-keys tools - list_ssh_keys - create_ssh_key - get_ssh_key - update_ssh_key - delete_ssh_key - add_ssh_keys_to_server - remove_ssh_key_from_server * feat: add network-drives tools - list_network_drives - get_network_drive - create_network_drive - update_network_drive - delete_network_drive - mount_network_drive - unmount_network_drive - list_network_drive_available_resources - list_network_drive_presets * feat: add projects tools - list_projects, get_project, create_project, update_project, delete_project - list_project_resources (aggregate) - list_project_{balancers,buckets,clusters,servers,databases,dedicated} - add_{balancer,bucket,cluster,server,database,dedicated}_to_project - list_all_project_{balancers,servers,buckets,clusters,databases,dedicated} - transfer_project_resource * feat: add images-snapshots tools * feat: add load-balancers tools - list_balancers - get_balancer - create_balancer - update_balancer - delete_balancer (with 2FA hash/code support) - list_balancer_ips - add_balancer_ips - remove_balancer_ips - list_balancer_rules - create_balancer_rule - update_balancer_rule - delete_balancer_rule - list_balancer_presets * feat: add mail tools Implements Timeweb Cloud Почта (Mail) endpoints as MCP tools. Prefers API v2 where available; falls back to v1 for endpoints unique to that version (list-by-domain, delete, domain info). Tools added (14): - list_mailboxes (v2), list_mailboxes_v1, list_mailboxes_by_domain (v1) - get_mailbox (v2), get_mailbox_v1 - create_mailbox (v2), create_mailbox_v1 - batch_create_mailboxes (v2), batch_create_mailboxes_v1 - update_mailbox (v2), update_mailbox_v1 - delete_mailbox (v1 — единственный вариант) - get_mail_domain_info, update_mail_domain_info * feat: add kubernetes tools * feat: add firewall tools 14 endpoints for Timeweb Cloud Firewall (groups, rules, resources): - list_firewall_groups / get_firewall_group - create_firewall_group / update_firewall_group / delete_firewall_group - list_firewall_group_resources - link_firewall_resource / unlink_firewall_resource - list_firewall_rules / get_firewall_rule - create_firewall_rule / update_firewall_rule / delete_firewall_rule - list_firewall_groups_by_resource * feat: add container-registry + dedicated-servers tools Container Registry (7 tools): - list_container_registries - get_container_registry - create_container_registry (preset_id XOR configurator_id+disk) - update_container_registry - delete_container_registry - list_container_registry_presets - list_container_registry_repositories Dedicated Servers (7 tools): - list_dedicated_servers - get_dedicated_server - create_dedicated_server - update_dedicated_server - delete_dedicated_server - list_dedicated_server_presets (optional location filter) - list_dedicated_server_additional_services * feat: add server-lifecycle tools (agent-generated, rate-limited before push) * feat: add database-extras tools (agent-generated, rate-limited before push) * feat: add dns-domains tools (agent-generated, rate-limited before push) * feat: add networking-extras tools (agent-generated, rate-limited before push) * feat: add s3-buckets tools (agent-generated, rate-limited before push) * feat: add ai-suite tools (agent-generated, rate-limited before push) * chore: ignore .specs/ (OpenAPI bundle for agent workflows) * fix: type errors after full-coverage merge - s3-buckets: use protected makeRequest directly (avoid any cast with type args) - servers: remove unused CreateServerDiskRequestDto import - create-floating-ip: handle undefined created_at - index.ts: loosen registerTool/Resource/Prompt param types to any (union grew to 250+) * fix: register 30 tool exports missed by rate-limited agents Agents for server-lifecycle, database-extras, and ai-suite hit extra-usage limit after writing .tool.ts files but before updating tools/index.ts. Added exports for: server lifecycle (create/delete/update/reset/boot/nat/ips), database admin+instance+cluster CRUD, AI agents CRUD. * fix(ssh-keys): use underscore response keys (ssh_key/ssh_keys) Timeweb API returns response objects with underscore-separated keys (ssh_keys, ssh_key) but the MCP client was reading hyphen-separated keys (ssh-keys, ssh-key) — causing "Cannot read properties of undefined" errors in all SSH-key operations. Verified via direct curl to /api/v1/ssh-keys on 2026-04-22: response shape is { meta: {...}, ssh_keys: [...] }. Fixes: - list_ssh_keys: was returning undefined → crash on .length - create_ssh_key: was returning undefined → crash on .id (but API call itself succeeded — key was actually created despite the error) - get_ssh_key, update_ssh_key: same pattern Files changed: - src/api/ssh-keys.ts (4 response key reads) - src/types/dto/list-ssh-keys-response.dto.ts - src/types/dto/create-ssh-key-response.dto.ts - src/types/dto/get-ssh-key-response.dto.ts - src/types/dto/update-ssh-key-response.dto.ts Co-Authored-By: Claude Opus 4.7 (1M context) --------- Co-authored-by: Artem Gasparyan Co-authored-by: Claude Opus 4.7 (1M context) --- .gitignore | 1 + bun.lock | 346 +++++++++++++ package.json | 1 + .../add-ai-agent-token-package.action.ts | 8 + src/actions/add-balancer-ips.action.ts | 8 + src/actions/add-balancer-to-project.action.ts | 9 + ...add-bucket-subdomain-certificate.action.ts | 7 + src/actions/add-bucket-subdomains.action.ts | 9 + src/actions/add-bucket-to-project.action.ts | 9 + src/actions/add-cluster-to-project.action.ts | 9 + src/actions/add-database-to-project.action.ts | 9 + .../add-dedicated-to-project.action.ts | 9 + src/actions/add-domain.action.ts | 5 + ...add-knowledge-base-token-package.action.ts | 8 + src/actions/add-server-ip.action.ts | 9 + src/actions/add-server-to-project.action.ts | 9 + src/actions/add-ssh-keys-to-server.action.ts | 8 + src/actions/add-subdomain.action.ts | 9 + .../batch-create-mailboxes-v1.action.ts | 10 + src/actions/batch-create-mailboxes.action.ts | 10 + src/actions/bind-floating-ip.action.ts | 9 + src/actions/check-domain.action.ts | 5 + src/actions/clone-server.action.ts | 6 + src/actions/create-ai-agent.action.ts | 9 + src/actions/create-api-key.action.ts | 9 + src/actions/create-balancer-rule.action.ts | 10 + src/actions/create-balancer.action.ts | 9 + src/actions/create-bucket.action.ts | 9 + .../create-container-registry.action.ts | 9 + src/actions/create-database-admin.action.ts | 10 + src/actions/create-database-backup.action.ts | 9 + .../create-database-instance.action.ts | 10 + src/actions/create-dedicated-server.action.ts | 9 + src/actions/create-dns-record.action.ts | 10 + src/actions/create-firewall-group.action.ts | 16 + src/actions/create-firewall-rule.action.ts | 10 + src/actions/create-image-download.action.ts | 10 + src/actions/create-image.action.ts | 9 + src/actions/create-k8s-cluster.action.ts | 9 + src/actions/create-k8s-node-group.action.ts | 10 + src/actions/create-knowledge-base.action.ts | 9 + src/actions/create-mailbox-v1.action.ts | 10 + src/actions/create-mailbox.action.ts | 10 + src/actions/create-network-drive.action.ts | 9 + src/actions/create-project.action.ts | 9 + .../create-server-disk-backup.action.ts | 14 + src/actions/create-server-disk.action.ts | 9 + src/actions/create-server.action.ts | 9 + src/actions/create-ssh-key.action.ts | 14 + src/actions/delete-ai-agent.action.ts | 5 + src/actions/delete-api-key.action.ts | 5 + src/actions/delete-balancer-rule.action.ts | 8 + src/actions/delete-balancer.action.ts | 10 + .../delete-bucket-subdomains.action.ts | 9 + src/actions/delete-bucket.action.ts | 10 + .../delete-container-registry.action.ts | 7 + src/actions/delete-database-admin.action.ts | 8 + src/actions/delete-database-backup.action.ts | 8 + src/actions/delete-database-cluster.action.ts | 10 + .../delete-database-instance.action.ts | 8 + src/actions/delete-database.action.ts | 10 + src/actions/delete-dedicated-server.action.ts | 7 + src/actions/delete-dns-record.action.ts | 8 + src/actions/delete-domain.action.ts | 5 + src/actions/delete-firewall-group.action.ts | 7 + src/actions/delete-firewall-rule.action.ts | 8 + src/actions/delete-floating-ip.action.ts | 7 + src/actions/delete-image-download.action.ts | 8 + src/actions/delete-image.action.ts | 5 + src/actions/delete-k8s-cluster-node.action.ts | 8 + src/actions/delete-k8s-cluster.action.ts | 9 + src/actions/delete-k8s-node-group.action.ts | 8 + .../delete-knowledge-base-document.action.ts | 8 + src/actions/delete-knowledge-base.action.ts | 5 + src/actions/delete-mailbox.action.ts | 8 + src/actions/delete-network-drive.action.ts | 7 + src/actions/delete-project.action.ts | 5 + .../delete-server-disk-backup.action.ts | 9 + src/actions/delete-server-disk.action.ts | 8 + src/actions/delete-server-ip.action.ts | 8 + src/actions/delete-server.action.ts | 9 + src/actions/delete-ssh-key.action.ts | 5 + src/actions/delete-subdomain.action.ts | 8 + src/actions/delete-vpc.action.ts | 5 + src/actions/domain-requests.action.ts | 29 ++ ...download-knowledge-base-document.action.ts | 11 + src/actions/edit-api-key.action.ts | 10 + src/actions/edit-k8s-cluster.action.ts | 10 + src/actions/get-account-finances.action.ts | 6 + .../get-account-services-cost.action.ts | 8 + src/actions/get-account-status.action.ts | 6 + src/actions/get-ai-agent-statistic.action.ts | 9 + src/actions/get-ai-agent.action.ts | 6 + src/actions/get-balancer.action.ts | 8 + src/actions/get-bucket-presets.action.ts | 6 + .../get-bucket-transfer-status.action.ts | 8 + src/actions/get-bucket.action.ts | 6 + src/actions/get-container-registry.action.ts | 8 + src/actions/get-database-admin.action.ts | 9 + .../get-database-auto-backups.action.ts | 8 + src/actions/get-database-backup.action.ts | 9 + src/actions/get-database-cluster.action.ts | 8 + src/actions/get-database-instance.action.ts | 9 + src/actions/get-database-parameters.action.ts | 7 + src/actions/get-database.action.ts | 6 + src/actions/get-dedicated-server.action.ts | 8 + src/actions/get-domain-name-servers.action.ts | 8 + src/actions/get-domain.action.ts | 6 + src/actions/get-firewall-group.action.ts | 8 + src/actions/get-firewall-rule.action.ts | 9 + src/actions/get-floating-ip.action.ts | 8 + src/actions/get-image-download.action.ts | 9 + src/actions/get-image.action.ts | 6 + .../get-k8s-cluster-resources.action.ts | 8 + src/actions/get-k8s-cluster.action.ts | 8 + src/actions/get-k8s-kubeconfig.action.ts | 7 + src/actions/get-k8s-node-group.action.ts | 9 + .../get-knowledge-base-statistic.action.ts | 12 + src/actions/get-knowledge-base.action.ts | 8 + src/actions/get-mail-domain-info.action.ts | 8 + src/actions/get-mailbox-v1.action.ts | 9 + src/actions/get-mailbox.action.ts | 9 + src/actions/get-network-drive.action.ts | 8 + src/actions/get-project.action.ts | 6 + .../get-server-disk-auto-backups.action.ts | 9 + src/actions/get-server-disk-backup.action.ts | 14 + src/actions/get-server-disk.action.ts | 9 + src/actions/get-server-logs.action.ts | 9 + src/actions/get-server.action.ts | 6 + src/actions/get-ssh-key.action.ts | 6 + src/actions/get-vpc.action.ts | 6 + src/actions/hard-reboot-server.action.ts | 7 + src/actions/hard-shutdown-server.action.ts | 7 + .../increase-k8s-node-group-nodes.action.ts | 15 + src/actions/install-k8s-addon.action.ts | 9 + src/actions/link-firewall-resource.action.ts | 17 + src/actions/link-knowledge-base.action.ts | 8 + .../list-ai-agent-token-packages.action.ts | 8 + src/actions/list-ai-agents.action.ts | 6 + src/actions/list-ai-models.action.ts | 6 + .../list-all-project-balancers.action.ts | 5 + .../list-all-project-buckets.action.ts | 5 + .../list-all-project-clusters.action.ts | 5 + .../list-all-project-databases.action.ts | 5 + .../list-all-project-dedicated.action.ts | 5 + .../list-all-project-servers.action.ts | 5 + src/actions/list-api-keys.action.ts | 6 + src/actions/list-balancer-ips.action.ts | 7 + src/actions/list-balancer-presets.action.ts | 6 + src/actions/list-balancer-rules.action.ts | 8 + src/actions/list-balancers.action.ts | 9 + src/actions/list-bucket-subdomains.action.ts | 8 + src/actions/list-bucket-users.action.ts | 6 + src/actions/list-buckets.action.ts | 6 + .../list-container-registries.action.ts | 8 + .../list-container-registry-presets.action.ts | 8 + ...-container-registry-repositories.action.ts | 10 + src/actions/list-database-admins.action.ts | 8 + src/actions/list-database-backups.action.ts | 10 + src/actions/list-database-clusters.action.ts | 9 + src/actions/list-database-instances.action.ts | 8 + src/actions/list-database-types.action.ts | 6 + src/actions/list-databases.action.ts | 9 + ...cated-server-additional-services.action.ts | 10 + .../list-dedicated-server-presets.action.ts | 11 + src/actions/list-dedicated-servers.action.ts | 8 + .../list-default-dns-records.action.ts | 8 + src/actions/list-dns-records.action.ts | 14 + src/actions/list-domains.action.ts | 6 + .../list-firewall-group-resources.action.ts | 8 + ...list-firewall-groups-by-resource.action.ts | 13 + src/actions/list-firewall-groups.action.ts | 6 + src/actions/list-firewall-rules.action.ts | 8 + src/actions/list-floating-ips.action.ts | 7 + src/actions/list-image-downloads.action.ts | 10 + src/actions/list-images.action.ts | 9 + src/actions/list-k8s-addon-configs.action.ts | 8 + src/actions/list-k8s-addons.action.ts | 8 + src/actions/list-k8s-cluster-nodes.action.ts | 8 + src/actions/list-k8s-clusters.action.ts | 9 + .../list-k8s-network-drivers.action.ts | 5 + .../list-k8s-node-group-nodes.action.ts | 16 + src/actions/list-k8s-node-groups.action.ts | 8 + src/actions/list-k8s-presets.action.ts | 6 + src/actions/list-k8s-versions.action.ts | 5 + .../list-knowledge-base-documents.action.ts | 12 + ...st-knowledge-base-token-packages.action.ts | 8 + src/actions/list-knowledge-bases-v1.action.ts | 8 + src/actions/list-knowledge-bases.action.ts | 6 + src/actions/list-locations.action.ts | 6 + .../list-mailboxes-by-domain.action.ts | 8 + src/actions/list-mailboxes-v1.action.ts | 6 + src/actions/list-mailboxes.action.ts | 6 + ...etwork-drive-available-resources.action.ts | 8 + .../list-network-drive-presets.action.ts | 8 + src/actions/list-network-drives.action.ts | 6 + src/actions/list-project-balancers.action.ts | 7 + src/actions/list-project-buckets.action.ts | 7 + src/actions/list-project-clusters.action.ts | 7 + src/actions/list-project-databases.action.ts | 7 + src/actions/list-project-dedicated.action.ts | 7 + src/actions/list-project-resources.action.ts | 8 + src/actions/list-project-servers.action.ts | 7 + src/actions/list-projects.action.ts | 6 + .../list-server-configurators.action.ts | 8 + .../list-server-disk-backups.action.ts | 9 + src/actions/list-server-disks.action.ts | 8 + src/actions/list-server-ips.action.ts | 8 + src/actions/list-server-os.action.ts | 6 + src/actions/list-server-presets.action.ts | 6 + src/actions/list-server-software.action.ts | 6 + src/actions/list-servers.action.ts | 6 + src/actions/list-ssh-keys.action.ts | 6 + src/actions/list-vpc-ports.action.ts | 6 + src/actions/list-vpc-services.action.ts | 8 + src/actions/mount-network-drive.action.ts | 9 + src/actions/reboot-server.action.ts | 5 + .../reduce-k8s-node-group-nodes.action.ts | 9 + src/actions/refresh-api-key.action.ts | 10 + .../reindex-knowledge-base-document.action.ts | 8 + src/actions/remove-balancer-ips.action.ts | 8 + .../remove-ssh-key-from-server.action.ts | 8 + src/actions/reset-server-password.action.ts | 7 + src/actions/resize-server.action.ts | 9 + src/actions/restore-database-backup.action.ts | 8 + .../server-disk-backup-action.action.ts | 18 + src/actions/set-server-boot-mode.action.ts | 8 + src/actions/set-server-nat-mode.action.ts | 8 + src/actions/shutdown-server.action.ts | 5 + src/actions/start-server.action.ts | 5 + src/actions/tlds.action.ts | 10 + src/actions/transfer-bucket.action.ts | 8 + .../transfer-project-resource.action.ts | 17 + src/actions/unbind-floating-ip.action.ts | 7 + src/actions/uninstall-k8s-addon.action.ts | 8 + .../unlink-firewall-resource.action.ts | 14 + src/actions/unlink-knowledge-base.action.ts | 8 + src/actions/unmount-network-drive.action.ts | 7 + src/actions/unmount-server-image.action.ts | 7 + src/actions/update-ai-agent.action.ts | 10 + src/actions/update-balancer-rule.action.ts | 11 + src/actions/update-balancer.action.ts | 10 + src/actions/update-bucket-user.action.ts | 9 + src/actions/update-bucket.action.ts | 10 + .../update-container-registry.action.ts | 13 + src/actions/update-database-admin.action.ts | 11 + .../update-database-auto-backups.action.ts | 10 + src/actions/update-database-cluster.action.ts | 10 + .../update-database-instance.action.ts | 15 + src/actions/update-database.action.ts | 10 + src/actions/update-dedicated-server.action.ts | 13 + src/actions/update-dns-record.action.ts | 11 + .../update-domain-name-servers.action.ts | 10 + src/actions/update-domain.action.ts | 10 + src/actions/update-firewall-group.action.ts | 13 + src/actions/update-firewall-rule.action.ts | 11 + src/actions/update-floating-ip.action.ts | 10 + src/actions/update-image.action.ts | 10 + src/actions/update-k8s-addon.action.ts | 10 + .../update-k8s-cluster-version.action.ts | 10 + src/actions/update-knowledge-base.action.ts | 10 + src/actions/update-mail-domain-info.action.ts | 9 + src/actions/update-mailbox-v1.action.ts | 11 + src/actions/update-mailbox.action.ts | 10 + src/actions/update-network-drive.action.ts | 10 + src/actions/update-project.action.ts | 10 + .../update-server-disk-auto-backups.action.ts | 14 + .../update-server-disk-backup.action.ts | 16 + src/actions/update-server-disk.action.ts | 10 + src/actions/update-server-ip.action.ts | 10 + src/actions/update-server.action.ts | 10 + src/actions/update-ssh-key.action.ts | 10 + src/actions/update-vpc.action.ts | 10 + src/api/account.ts | 40 ++ src/api/ai-agents.ts | 137 ++++++ src/api/auth.ts | 69 +++ src/api/balancers.ts | 189 +++++++ src/api/catalogs.ts | 69 +++ src/api/container-registry.ts | 94 ++++ src/api/dbaas.ts | 451 +++++++++++++++++ src/api/dedicated-servers.ts | 99 ++++ src/api/domains.ts | 315 ++++++++++++ src/api/firewall.ts | 195 ++++++++ src/api/images.ts | 127 +++++ src/api/index.ts | 18 + src/api/knowledge-bases.ts | 206 ++++++++ src/api/kubernetes.ts | 340 +++++++++++++ src/api/mail.ts | 214 ++++++++ src/api/network-drives.ts | 115 +++++ src/api/projects.ts | 270 ++++++++++ src/api/s3-buckets.ts | 203 ++++++++ src/api/servers.ts | 465 ++++++++++++++++++ src/api/ssh-keys.ts | 88 ++++ src/index.ts | 6 +- src/tools/add-balancer-ips.tool.ts | 45 ++ src/tools/add-balancer-to-project.tool.ts | 47 ++ .../add-bucket-subdomain-certificate.tool.ts | 40 ++ src/tools/add-bucket-subdomains.tool.ts | 50 ++ src/tools/add-bucket-to-project.tool.ts | 42 ++ src/tools/add-cluster-to-project.tool.ts | 42 ++ src/tools/add-database-to-project.tool.ts | 42 ++ src/tools/add-dedicated-to-project.tool.ts | 48 ++ src/tools/add-domain.tool.ts | 37 ++ src/tools/add-server-ip.tool.ts | 47 ++ src/tools/add-server-to-project.tool.ts | 43 ++ src/tools/add-ssh-keys-to-server.tool.ts | 51 ++ src/tools/add-subdomain.tool.ts | 41 ++ src/tools/batch-create-mailboxes-v1.tool.ts | 63 +++ src/tools/batch-create-mailboxes.tool.ts | 79 +++ src/tools/bind-floating-ip.tool.ts | 67 +++ src/tools/check-domain.tool.ts | 40 ++ src/tools/clone-server.tool.ts | 38 ++ src/tools/create-ai-agent.tool.ts | 106 ++++ src/tools/create-api-key.tool.ts | 79 +++ src/tools/create-balancer-rule.tool.ts | 68 +++ src/tools/create-balancer.tool.ts | 214 ++++++++ src/tools/create-bucket.tool.ts | 122 +++++ src/tools/create-container-registry.tool.ts | 112 +++++ src/tools/create-database-admin.tool.ts | 111 +++++ src/tools/create-database-instance.tool.ts | 55 +++ src/tools/create-dedicated-server.tool.ts | 141 ++++++ src/tools/create-dns-record.tool.ts | 121 +++++ src/tools/create-domain-request.tool.ts | 133 +++++ src/tools/create-firewall-group.tool.ts | 62 +++ src/tools/create-firewall-rule.tool.ts | 92 ++++ src/tools/create-floating-ip.tool.ts | 2 +- src/tools/create-image-download.tool.ts | 99 ++++ src/tools/create-image.tool.ts | 95 ++++ src/tools/create-k8s-cluster.tool.ts | 167 +++++++ src/tools/create-k8s-node-group.tool.ts | 115 +++++ src/tools/create-mailbox-v1.tool.ts | 53 ++ src/tools/create-mailbox.tool.ts | 79 +++ src/tools/create-network-drive.tool.ts | 69 +++ src/tools/create-project.tool.ts | 60 +++ src/tools/create-server-disk-backup.tool.ts | 48 ++ src/tools/create-server.tool.ts | 204 ++++++++ src/tools/create-ssh-key.tool.ts | 58 +++ src/tools/delete-ai-agent.tool.ts | 31 ++ src/tools/delete-api-key.tool.ts | 30 ++ src/tools/delete-balancer-rule.tool.ts | 42 ++ src/tools/delete-balancer.tool.ts | 67 +++ src/tools/delete-bucket-subdomains.tool.ts | 50 ++ src/tools/delete-bucket.tool.ts | 68 +++ src/tools/delete-container-registry.tool.ts | 35 ++ src/tools/delete-database-admin.tool.ts | 45 ++ src/tools/delete-database-cluster.tool.ts | 62 +++ src/tools/delete-dedicated-server.tool.ts | 37 ++ src/tools/delete-dns-record.tool.ts | 36 ++ src/tools/delete-domain.tool.ts | 33 ++ src/tools/delete-firewall-group.tool.ts | 39 ++ src/tools/delete-firewall-rule.tool.ts | 40 ++ src/tools/delete-floating-ip.tool.ts | 36 ++ src/tools/delete-image-download.tool.ts | 39 ++ src/tools/delete-image.tool.ts | 33 ++ src/tools/delete-k8s-cluster-node.tool.ts | 37 ++ src/tools/delete-k8s-cluster.tool.ts | 67 +++ src/tools/delete-k8s-node-group.tool.ts | 38 ++ src/tools/delete-mailbox.tool.ts | 36 ++ src/tools/delete-network-drive.tool.ts | 37 ++ src/tools/delete-project.tool.ts | 33 ++ src/tools/delete-server-disk-backup.tool.ts | 45 ++ src/tools/delete-server-ip.tool.ts | 36 ++ src/tools/delete-server.tool.ts | 63 +++ src/tools/delete-ssh-key.tool.ts | 35 ++ src/tools/delete-subdomain.tool.ts | 38 ++ src/tools/delete-vpc.tool.ts | 30 ++ src/tools/edit-api-key.tool.ts | 62 +++ src/tools/edit-k8s-cluster.tool.ts | 70 +++ src/tools/get-account-finances.tool.ts | 38 ++ src/tools/get-account-services-cost.tool.ts | 60 +++ src/tools/get-account-status.tool.ts | 37 ++ src/tools/get-ai-agent-statistic.tool.ts | 78 +++ src/tools/get-ai-agent.tool.ts | 56 +++ src/tools/get-balancer.tool.ts | 51 ++ src/tools/get-bucket-presets.tool.ts | 42 ++ src/tools/get-bucket-transfer-status.tool.ts | 43 ++ src/tools/get-bucket.tool.ts | 57 +++ src/tools/get-container-registry.tool.ts | 44 ++ src/tools/get-database-admin.tool.ts | 60 +++ src/tools/get-database-cluster.tool.ts | 57 +++ src/tools/get-database-instance.tool.ts | 51 ++ src/tools/get-dedicated-server.tool.ts | 59 +++ src/tools/get-domain-name-servers.tool.ts | 51 ++ src/tools/get-domain-request.tool.ts | 41 ++ src/tools/get-domain.tool.ts | 45 ++ src/tools/get-firewall-group.tool.ts | 44 ++ src/tools/get-firewall-rule.tool.ts | 48 ++ src/tools/get-floating-ip.tool.ts | 44 ++ src/tools/get-image-download.tool.ts | 50 ++ src/tools/get-image.tool.ts | 44 ++ src/tools/get-k8s-cluster-resources.tool.ts | 39 ++ src/tools/get-k8s-cluster.tool.ts | 46 ++ src/tools/get-k8s-kubeconfig.tool.ts | 35 ++ src/tools/get-k8s-node-group.tool.ts | 37 ++ src/tools/get-mail-domain-info.tool.ts | 37 ++ src/tools/get-mailbox-v1.tool.ts | 49 ++ src/tools/get-mailbox.tool.ts | 50 ++ src/tools/get-network-drive.tool.ts | 53 ++ src/tools/get-project.tool.ts | 38 ++ src/tools/get-server-logs.tool.ts | 59 +++ src/tools/get-server.tool.ts | 46 ++ src/tools/get-ssh-key.tool.ts | 43 ++ src/tools/get-tld.tool.ts | 51 ++ src/tools/get-vpc.tool.ts | 41 ++ src/tools/hard-reboot-server.tool.ts | 35 ++ src/tools/hard-shutdown-server.tool.ts | 35 ++ .../increase-k8s-node-group-nodes.tool.ts | 52 ++ src/tools/index.ts | 233 +++++++++ src/tools/install-k8s-addon.tool.ts | 58 +++ src/tools/link-firewall-resource.tool.ts | 54 ++ src/tools/list-ai-agents.tool.ts | 43 ++ src/tools/list-all-project-balancers.tool.ts | 39 ++ src/tools/list-all-project-buckets.tool.ts | 37 ++ src/tools/list-all-project-clusters.tool.ts | 37 ++ src/tools/list-all-project-databases.tool.ts | 37 ++ src/tools/list-all-project-dedicated.tool.ts | 39 ++ src/tools/list-all-project-servers.tool.ts | 37 ++ src/tools/list-api-keys.tool.ts | 47 ++ src/tools/list-balancer-ips.tool.ts | 46 ++ src/tools/list-balancer-presets.tool.ts | 42 ++ src/tools/list-balancer-rules.tool.ts | 50 ++ src/tools/list-balancers.tool.ts | 56 +++ src/tools/list-bucket-subdomains.tool.ts | 47 ++ src/tools/list-bucket-users.tool.ts | 41 ++ src/tools/list-buckets.tool.ts | 45 ++ src/tools/list-container-registries.tool.ts | 42 ++ .../list-container-registry-presets.tool.ts | 42 ++ ...st-container-registry-repositories.tool.ts | 53 ++ src/tools/list-database-admins.tool.ts | 51 ++ src/tools/list-database-clusters.tool.ts | 59 +++ src/tools/list-database-instances.tool.ts | 51 ++ ...dicated-server-additional-services.tool.ts | 53 ++ .../list-dedicated-server-presets.tool.ts | 57 +++ src/tools/list-dedicated-servers.tool.ts | 42 ++ src/tools/list-default-dns-records.tool.ts | 44 ++ src/tools/list-dns-records.tool.ts | 46 ++ src/tools/list-domain-requests.tool.ts | 36 ++ src/tools/list-domains.tool.ts | 40 ++ .../list-firewall-group-resources.tool.ts | 48 ++ .../list-firewall-groups-by-resource.tool.ts | 59 +++ src/tools/list-firewall-groups.tool.ts | 42 ++ src/tools/list-firewall-rules.tool.ts | 49 ++ src/tools/list-floating-ips.tool.ts | 46 ++ src/tools/list-image-downloads.tool.ts | 69 +++ src/tools/list-images.tool.ts | 56 +++ src/tools/list-k8s-addon-configs.tool.ts | 44 ++ src/tools/list-k8s-addons.tool.ts | 46 ++ src/tools/list-k8s-cluster-nodes.tool.ts | 44 ++ src/tools/list-k8s-clusters.tool.ts | 56 +++ src/tools/list-k8s-network-drivers.tool.ts | 35 ++ src/tools/list-k8s-node-group-nodes.tool.ts | 55 +++ src/tools/list-k8s-node-groups.tool.ts | 46 ++ src/tools/list-k8s-presets.tool.ts | 39 ++ src/tools/list-k8s-versions.tool.ts | 33 ++ src/tools/list-locations.tool.ts | 40 ++ src/tools/list-mailboxes-by-domain.tool.ts | 49 ++ src/tools/list-mailboxes-v1.tool.ts | 44 ++ src/tools/list-mailboxes.tool.ts | 42 ++ ...-network-drive-available-resources.tool.ts | 44 ++ src/tools/list-network-drive-presets.tool.ts | 44 ++ src/tools/list-network-drives.tool.ts | 47 ++ src/tools/list-project-balancers.tool.ts | 43 ++ src/tools/list-project-buckets.tool.ts | 41 ++ src/tools/list-project-clusters.tool.ts | 41 ++ src/tools/list-project-databases.tool.ts | 41 ++ src/tools/list-project-dedicated.tool.ts | 43 ++ src/tools/list-project-resources.tool.ts | 55 +++ src/tools/list-project-servers.tool.ts | 41 ++ src/tools/list-projects.tool.ts | 40 ++ src/tools/list-server-configurators.tool.ts | 53 ++ src/tools/list-server-disk-backups.tool.ts | 53 ++ src/tools/list-server-disks.tool.ts | 43 ++ src/tools/list-server-ips.tool.ts | 42 ++ src/tools/list-server-os.tool.ts | 47 ++ src/tools/list-server-presets.tool.ts | 47 ++ src/tools/list-server-software.tool.ts | 47 ++ src/tools/list-servers.tool.ts | 40 ++ src/tools/list-ssh-keys.tool.ts | 46 ++ src/tools/list-tlds.tool.ts | 39 ++ src/tools/list-vpc-ports.tool.ts | 42 ++ src/tools/list-vpc-services.tool.ts | 45 ++ src/tools/mount-network-drive.tool.ts | 55 +++ src/tools/reboot-server.tool.ts | 35 ++ src/tools/reduce-k8s-node-group-nodes.tool.ts | 47 ++ src/tools/refresh-api-key.tool.ts | 59 +++ src/tools/remove-balancer-ips.tool.ts | 45 ++ src/tools/remove-ssh-key-from-server.tool.ts | 39 ++ src/tools/reset-server-password.tool.ts | 36 ++ src/tools/resize-server.tool.ts | 94 ++++ src/tools/set-server-boot-mode.tool.ts | 51 ++ src/tools/set-server-nat-mode.tool.ts | 50 ++ src/tools/shutdown-server.tool.ts | 35 ++ src/tools/start-server.tool.ts | 35 ++ src/tools/transfer-bucket.tool.ts | 80 +++ src/tools/transfer-project-resource.tool.ts | 69 +++ src/tools/unbind-floating-ip.tool.ts | 36 ++ src/tools/uninstall-k8s-addon.tool.ts | 39 ++ src/tools/unlink-firewall-resource.tool.ts | 54 ++ src/tools/unmount-network-drive.tool.ts | 37 ++ src/tools/unmount-server-image.tool.ts | 35 ++ src/tools/update-ai-agent.tool.ts | 105 ++++ src/tools/update-balancer-rule.tool.ts | 76 +++ src/tools/update-balancer.tool.ts | 154 ++++++ src/tools/update-bucket-user.tool.ts | 51 ++ src/tools/update-bucket.tool.ts | 100 ++++ src/tools/update-container-registry.tool.ts | 91 ++++ src/tools/update-database-admin.tool.ts | 104 ++++ src/tools/update-database-cluster.tool.ts | 67 +++ src/tools/update-database-instance.tool.ts | 62 +++ src/tools/update-dedicated-server.tool.ts | 64 +++ src/tools/update-dns-record.tool.ts | 87 ++++ src/tools/update-domain-name-servers.tool.ts | 59 +++ src/tools/update-domain-request.tool.ts | 125 +++++ src/tools/update-domain.tool.ts | 65 +++ src/tools/update-firewall-group.tool.ts | 56 +++ src/tools/update-firewall-rule.tool.ts | 90 ++++ src/tools/update-floating-ip.tool.ts | 63 +++ src/tools/update-image.tool.ts | 55 +++ src/tools/update-k8s-addon.tool.ts | 62 +++ src/tools/update-k8s-cluster-version.tool.ts | 42 ++ src/tools/update-mail-domain-info.tool.ts | 41 ++ src/tools/update-mailbox-v1.tool.ts | 78 +++ src/tools/update-mailbox.tool.ts | 95 ++++ src/tools/update-network-drive.tool.ts | 77 +++ src/tools/update-project.tool.ts | 62 +++ src/tools/update-server-ip.tool.ts | 47 ++ src/tools/update-server.tool.ts | 62 +++ src/tools/update-ssh-key.tool.ts | 67 +++ src/tools/update-vpc.tool.ts | 51 ++ src/types/ai-agent.type.ts | 44 ++ src/types/ai-model.type.ts | 12 + src/types/api-key.type.ts | 15 + src/types/auto-backup.type.ts | 7 + src/types/balancer.type.ts | 75 +++ src/types/bucket-delete-response.type.ts | 4 + src/types/bucket-preset.type.ts | 12 + src/types/bucket-subdomain.type.ts | 23 + src/types/bucket-transfer-status.type.ts | 16 + src/types/bucket-user.type.ts | 5 + src/types/bucket.type.ts | 41 ++ src/types/container-registry.type.ts | 36 ++ src/types/database-cluster.type.ts | 87 ++++ src/types/dedicated-server.type.ts | 70 +++ src/types/dns-record.type.ts | 29 ++ src/types/domain-name-server.type.ts | 10 + src/types/domain-request.type.ts | 21 + src/types/domain.type.ts | 39 ++ .../dto/add-bucket-certificate-request.dto.ts | 3 + .../dto/add-bucket-subdomains-request.dto.ts | 3 + .../dto/add-bucket-subdomains-response.dto.ts | 7 + .../add-resource-to-project-request.dto.ts | 3 + .../dto/add-ssh-keys-to-server-request.dto.ts | 3 + src/types/dto/add-subdomain-response.dto.ts | 5 + .../dto/add-token-package-request.dto.ts | 3 + src/types/dto/auto-backup-response.dto.ts | 6 + src/types/dto/balancer-ips-request.dto.ts | 3 + src/types/dto/balancer-rule-response.dto.ts | 6 + .../dto/batch-create-mailboxes-request.dto.ts | 22 + .../batch-create-mailboxes-response.dto.ts | 11 + src/types/dto/bind-floating-ip-request.dto.ts | 6 + src/types/dto/check-domain-response.dto.ts | 4 + src/types/dto/create-ai-agent-request.dto.ts | 11 + src/types/dto/create-api-key-request.dto.ts | 7 + src/types/dto/create-api-key-response.dto.ts | 5 + src/types/dto/create-balancer-request.dto.ts | 40 ++ .../dto/create-balancer-rule-request.dto.ts | 10 + src/types/dto/create-bucket-request.dto.ts | 13 + src/types/dto/create-bucket-response.dto.ts | 6 + .../create-container-registry-request.dto.ts | 10 + .../dto/create-database-admin-request.dto.ts | 8 + .../create-database-instance-request.dto.ts | 4 + .../create-dedicated-server-request.dto.ts | 15 + .../dto/create-dns-record-request.dto.ts | 23 + .../dto/create-dns-record-response.dto.ts | 9 + .../dto/create-domain-request-request.dto.ts | 41 ++ .../dto/create-firewall-group-request.dto.ts | 4 + .../dto/create-firewall-rule-request.dto.ts | 12 + .../dto/create-image-download-request.dto.ts | 14 + src/types/dto/create-image-request.dto.ts | 10 + .../dto/create-k8s-cluster-request.dto.ts | 56 +++ .../dto/create-k8s-node-group-request.dto.ts | 19 + .../dto/create-knowledge-base-request.dto.ts | 8 + src/types/dto/create-mailbox-request.dto.ts | 14 + src/types/dto/create-mailbox-response.dto.ts | 11 + .../dto/create-network-drive-request.dto.ts | 6 + .../dto/create-network-drive-response.dto.ts | 6 + src/types/dto/create-project-request.dto.ts | 5 + .../create-server-disk-backup-response.dto.ts | 5 + .../dto/create-server-disk-request.dto.ts | 3 + src/types/dto/create-server-request.dto.ts | 33 ++ src/types/dto/create-server-response.dto.ts | 6 + src/types/dto/create-ssh-key-request.dto.ts | 5 + src/types/dto/create-ssh-key-response.dto.ts | 5 + src/types/dto/database-admin-response.dto.ts | 5 + .../dto/database-auto-backups-response.dto.ts | 6 + src/types/dto/database-backup-response.dto.ts | 5 + .../dto/database-instance-response.dto.ts | 5 + src/types/dto/delete-balancer-response.dto.ts | 6 + src/types/dto/delete-bucket-response.dto.ts | 6 + .../delete-bucket-subdomains-request.dto.ts | 3 + .../delete-bucket-subdomains-response.dto.ts | 7 + src/types/dto/delete-database-response.dto.ts | 9 + .../dto/delete-k8s-cluster-response.dto.ts | 7 + src/types/dto/delete-server-response.dto.ts | 7 + .../dto/domain-name-servers-response.dto.ts | 6 + src/types/dto/edit-api-key-request.dto.ts | 4 + src/types/dto/edit-api-key-response.dto.ts | 5 + src/types/dto/edit-k8s-cluster-request.dto.ts | 7 + .../dto/get-account-status-response.dto.ts | 5 + .../dto/get-agent-statistic-response.dto.ts | 7 + src/types/dto/get-ai-agent-response.dto.ts | 6 + src/types/dto/get-balancer-response.dto.ts | 6 + .../dto/get-bucket-presets-response.dto.ts | 7 + src/types/dto/get-bucket-response.dto.ts | 6 + ...get-bucket-transfer-status-response.dto.ts | 6 + .../get-container-registry-response.dto.ts | 5 + .../dto/get-database-cluster-response.dto.ts | 5 + .../get-database-parameters-response.dto.ts | 3 + src/types/dto/get-database-response.dto.ts | 5 + .../dto/get-dedicated-server-response.dto.ts | 5 + src/types/dto/get-domain-response.dto.ts | 5 + src/types/dto/get-finances-response.dto.ts | 5 + .../dto/get-firewall-group-response.dto.ts | 6 + .../dto/get-firewall-rule-response.dto.ts | 6 + src/types/dto/get-floating-ip-response.dto.ts | 5 + .../dto/get-image-download-response.dto.ts | 5 + src/types/dto/get-image-response.dto.ts | 5 + src/types/dto/get-k8s-cluster-response.dto.ts | 6 + .../dto/get-k8s-node-group-response.dto.ts | 6 + .../dto/get-k8s-resources-response.dto.ts | 6 + .../dto/get-knowledge-base-response.dto.ts | 6 + ...t-knowledge-base-statistic-response.dto.ts | 7 + .../dto/get-mail-domain-info-response.dto.ts | 6 + src/types/dto/get-mailbox-response.dto.ts | 11 + .../dto/get-network-drive-response.dto.ts | 6 + src/types/dto/get-project-response.dto.ts | 5 + src/types/dto/get-server-logs-response.dto.ts | 6 + src/types/dto/get-server-response.dto.ts | 5 + .../dto/get-services-cost-response.dto.ts | 6 + src/types/dto/get-ssh-key-response.dto.ts | 6 + src/types/dto/get-vpc-response.dto.ts | 5 + .../dto/increase-k8s-nodes-request.dto.ts | 4 + .../dto/install-k8s-addon-request.dto.ts | 6 + .../link-firewall-resource-response.dto.ts | 6 + src/types/dto/list-ai-agents-response.dto.ts | 7 + src/types/dto/list-ai-models-response.dto.ts | 7 + src/types/dto/list-api-keys-response.dto.ts | 8 + .../dto/list-balancer-ips-response.dto.ts | 5 + .../dto/list-balancer-presets-response.dto.ts | 7 + .../dto/list-balancer-rules-response.dto.ts | 7 + src/types/dto/list-balancers-response.dto.ts | 7 + .../list-bucket-subdomains-response.dto.ts | 7 + .../dto/list-bucket-users-response.dto.ts | 7 + src/types/dto/list-buckets-response.dto.ts | 7 + .../list-container-registries-response.dto.ts | 5 + ...container-registry-presets-response.dto.ts | 5 + ...iner-registry-repositories-response.dto.ts | 6 + .../dto/list-database-admins-response.dto.ts | 6 + .../dto/list-database-backups-response.dto.ts | 6 + .../list-database-clusters-response.dto.ts | 6 + .../list-database-instances-response.dto.ts | 6 + .../dto/list-database-types-response.dto.ts | 6 + src/types/dto/list-databases-response.dto.ts | 6 + ...server-additional-services-response.dto.ts | 6 + ...t-dedicated-server-presets-response.dto.ts | 6 + .../list-dedicated-servers-response.dto.ts | 6 + .../dto/list-dns-records-response.dto.ts | 6 + .../dto/list-domain-requests-response.dto.ts | 10 + src/types/dto/list-domains-response.dto.ts | 6 + ...t-firewall-group-resources-response.dto.ts | 9 + .../dto/list-firewall-groups-response.dto.ts | 9 + .../dto/list-firewall-rules-response.dto.ts | 9 + .../dto/list-floating-ips-response.dto.ts | 8 + .../dto/list-image-downloads-response.dto.ts | 6 + src/types/dto/list-images-response.dto.ts | 6 + .../list-k8s-addon-configs-response.dto.ts | 7 + src/types/dto/list-k8s-addons-response.dto.ts | 7 + .../dto/list-k8s-clusters-response.dto.ts | 7 + .../list-k8s-network-drivers-response.dto.ts | 5 + .../dto/list-k8s-node-groups-response.dto.ts | 7 + src/types/dto/list-k8s-nodes-response.dto.ts | 7 + .../dto/list-k8s-presets-response.dto.ts | 7 + .../dto/list-k8s-versions-response.dto.ts | 5 + ...t-knowledge-base-documents-response.dto.ts | 7 + .../dto/list-knowledge-bases-response.dto.ts | 7 + src/types/dto/list-locations-response.dto.ts | 6 + src/types/dto/list-mailboxes-response.dto.ts | 13 + ...-drive-available-resources-response.dto.ts | 7 + ...list-network-drive-presets-response.dto.ts | 7 + .../dto/list-network-drives-response.dto.ts | 7 + .../list-project-resources-response.dto.ts | 11 + src/types/dto/list-projects-response.dto.ts | 6 + src/types/dto/list-resources-response.dto.ts | 33 ++ .../list-server-configurators-response.dto.ts | 6 + .../list-server-disk-backups-response.dto.ts | 6 + .../dto/list-server-disks-response.dto.ts | 6 + src/types/dto/list-server-ips-response.dto.ts | 7 + src/types/dto/list-server-os-response.dto.ts | 6 + .../dto/list-server-presets-response.dto.ts | 6 + .../dto/list-server-software-response.dto.ts | 6 + src/types/dto/list-servers-response.dto.ts | 6 + src/types/dto/list-ssh-keys-response.dto.ts | 6 + src/types/dto/list-tlds-response.dto.ts | 10 + .../dto/list-token-packages-response.dto.ts | 7 + src/types/dto/list-vpc-ports-response.dto.ts | 8 + .../dto/list-vpc-services-response.dto.ts | 8 + .../dto/mount-network-drive-request.dto.ts | 4 + .../dto/project-resource-response.dto.ts | 5 + src/types/dto/reduce-k8s-nodes-request.dto.ts | 3 + src/types/dto/refresh-api-key-request.dto.ts | 3 + src/types/dto/refresh-api-key-response.dto.ts | 5 + .../dto/server-disk-backup-response.dto.ts | 6 + src/types/dto/server-disk-response.dto.ts | 6 + src/types/dto/server-ip-response.dto.ts | 6 + src/types/dto/transfer-bucket-request.dto.ts | 9 + .../transfer-project-resource-request.dto.ts | 7 + src/types/dto/update-ai-agent-request.dto.ts | 11 + src/types/dto/update-balancer-request.dto.ts | 25 + src/types/dto/update-bucket-request.dto.ts | 11 + src/types/dto/update-bucket-response.dto.ts | 6 + .../dto/update-bucket-user-request.dto.ts | 3 + .../dto/update-bucket-user-response.dto.ts | 6 + .../update-container-registry-request.dto.ts | 8 + .../dto/update-database-admin-request.dto.ts | 6 + ...pdate-database-auto-backups-request.dto.ts | 7 + .../update-database-cluster-request.dto.ts | 6 + .../update-database-instance-request.dto.ts | 4 + src/types/dto/update-database-request.dto.ts | 7 + .../update-dedicated-server-request.dto.ts | 4 + .../update-domain-name-servers-request.dto.ts | 8 + src/types/dto/update-domain-request.dto.ts | 4 + .../dto/update-firewall-group-request.dto.ts | 4 + .../dto/update-firewall-rule-request.dto.ts | 12 + .../dto/update-floating-ip-request.dto.ts | 4 + .../dto/update-floating-ip-response.dto.ts | 5 + src/types/dto/update-image-request.dto.ts | 4 + .../update-k8s-cluster-version-request.dto.ts | 3 + .../dto/update-knowledge-base-request.dto.ts | 4 + .../update-mail-domain-info-request.dto.ts | 3 + .../update-mail-domain-info-response.dto.ts | 6 + src/types/dto/update-mailbox-request.dto.ts | 25 + src/types/dto/update-mailbox-response.dto.ts | 12 + .../dto/update-network-drive-request.dto.ts | 5 + .../dto/update-network-drive-response.dto.ts | 6 + src/types/dto/update-project-request.dto.ts | 5 + src/types/dto/update-server-request.dto.ts | 6 + src/types/dto/update-ssh-key-request.dto.ts | 5 + src/types/dto/update-ssh-key-response.dto.ts | 6 + src/types/dto/update-vpc-request.dto.ts | 4 + src/types/dto/update-vpc-response.dto.ts | 5 + src/types/finances.type.ts | 21 + src/types/firewall-group.type.ts | 10 + src/types/firewall-resource.type.ts | 6 + src/types/firewall-rule.type.ts | 13 + src/types/floating-ip.type.ts | 11 +- src/types/image-download.type.ts | 22 + src/types/image.type.ts | 50 ++ src/types/k8s-addon.type.ts | 18 + src/types/k8s-cluster.type.ts | 17 + src/types/k8s-node-group.type.ts | 7 + src/types/k8s-node.type.ts | 13 + src/types/k8s-preset.type.ts | 13 + src/types/k8s-resources.type.ts | 13 + src/types/knowledge-base.type.ts | 28 ++ src/types/location.type.ts | 5 + src/types/mailbox.type.ts | 79 +++ .../network-drive-available-resource.type.ts | 6 + src/types/network-drive-preset.type.ts | 17 + src/types/network-drive.type.ts | 21 + src/types/project-resource-type.enum.ts | 8 + src/types/project.type.ts | 24 + src/types/server-backup.type.ts | 20 + src/types/server-configurator.type.ts | 26 + src/types/server-disk.type.ts | 10 + src/types/server-ip.type.ts | 6 + src/types/server-log.type.ts | 5 + src/types/server-os.type.ts | 16 + src/types/server-preset.type.ts | 15 + src/types/server-software.type.ts | 15 + src/types/server.type.ts | 47 ++ src/types/service-price.type.ts | 14 + src/types/ssh-key.type.ts | 13 + src/types/token-package.type.ts | 11 + src/types/token-statistic.type.ts | 5 + src/types/tool-names.enum.ts | 275 +++++++++++ src/types/top-level-domain.type.ts | 20 + src/types/vpc-port.type.ts | 17 + src/types/vpc-service.type.ts | 9 + 788 files changed, 22571 insertions(+), 7 deletions(-) create mode 100644 bun.lock create mode 100644 src/actions/add-ai-agent-token-package.action.ts create mode 100644 src/actions/add-balancer-ips.action.ts create mode 100644 src/actions/add-balancer-to-project.action.ts create mode 100644 src/actions/add-bucket-subdomain-certificate.action.ts create mode 100644 src/actions/add-bucket-subdomains.action.ts create mode 100644 src/actions/add-bucket-to-project.action.ts create mode 100644 src/actions/add-cluster-to-project.action.ts create mode 100644 src/actions/add-database-to-project.action.ts create mode 100644 src/actions/add-dedicated-to-project.action.ts create mode 100644 src/actions/add-domain.action.ts create mode 100644 src/actions/add-knowledge-base-token-package.action.ts create mode 100644 src/actions/add-server-ip.action.ts create mode 100644 src/actions/add-server-to-project.action.ts create mode 100644 src/actions/add-ssh-keys-to-server.action.ts create mode 100644 src/actions/add-subdomain.action.ts create mode 100644 src/actions/batch-create-mailboxes-v1.action.ts create mode 100644 src/actions/batch-create-mailboxes.action.ts create mode 100644 src/actions/bind-floating-ip.action.ts create mode 100644 src/actions/check-domain.action.ts create mode 100644 src/actions/clone-server.action.ts create mode 100644 src/actions/create-ai-agent.action.ts create mode 100644 src/actions/create-api-key.action.ts create mode 100644 src/actions/create-balancer-rule.action.ts create mode 100644 src/actions/create-balancer.action.ts create mode 100644 src/actions/create-bucket.action.ts create mode 100644 src/actions/create-container-registry.action.ts create mode 100644 src/actions/create-database-admin.action.ts create mode 100644 src/actions/create-database-backup.action.ts create mode 100644 src/actions/create-database-instance.action.ts create mode 100644 src/actions/create-dedicated-server.action.ts create mode 100644 src/actions/create-dns-record.action.ts create mode 100644 src/actions/create-firewall-group.action.ts create mode 100644 src/actions/create-firewall-rule.action.ts create mode 100644 src/actions/create-image-download.action.ts create mode 100644 src/actions/create-image.action.ts create mode 100644 src/actions/create-k8s-cluster.action.ts create mode 100644 src/actions/create-k8s-node-group.action.ts create mode 100644 src/actions/create-knowledge-base.action.ts create mode 100644 src/actions/create-mailbox-v1.action.ts create mode 100644 src/actions/create-mailbox.action.ts create mode 100644 src/actions/create-network-drive.action.ts create mode 100644 src/actions/create-project.action.ts create mode 100644 src/actions/create-server-disk-backup.action.ts create mode 100644 src/actions/create-server-disk.action.ts create mode 100644 src/actions/create-server.action.ts create mode 100644 src/actions/create-ssh-key.action.ts create mode 100644 src/actions/delete-ai-agent.action.ts create mode 100644 src/actions/delete-api-key.action.ts create mode 100644 src/actions/delete-balancer-rule.action.ts create mode 100644 src/actions/delete-balancer.action.ts create mode 100644 src/actions/delete-bucket-subdomains.action.ts create mode 100644 src/actions/delete-bucket.action.ts create mode 100644 src/actions/delete-container-registry.action.ts create mode 100644 src/actions/delete-database-admin.action.ts create mode 100644 src/actions/delete-database-backup.action.ts create mode 100644 src/actions/delete-database-cluster.action.ts create mode 100644 src/actions/delete-database-instance.action.ts create mode 100644 src/actions/delete-database.action.ts create mode 100644 src/actions/delete-dedicated-server.action.ts create mode 100644 src/actions/delete-dns-record.action.ts create mode 100644 src/actions/delete-domain.action.ts create mode 100644 src/actions/delete-firewall-group.action.ts create mode 100644 src/actions/delete-firewall-rule.action.ts create mode 100644 src/actions/delete-floating-ip.action.ts create mode 100644 src/actions/delete-image-download.action.ts create mode 100644 src/actions/delete-image.action.ts create mode 100644 src/actions/delete-k8s-cluster-node.action.ts create mode 100644 src/actions/delete-k8s-cluster.action.ts create mode 100644 src/actions/delete-k8s-node-group.action.ts create mode 100644 src/actions/delete-knowledge-base-document.action.ts create mode 100644 src/actions/delete-knowledge-base.action.ts create mode 100644 src/actions/delete-mailbox.action.ts create mode 100644 src/actions/delete-network-drive.action.ts create mode 100644 src/actions/delete-project.action.ts create mode 100644 src/actions/delete-server-disk-backup.action.ts create mode 100644 src/actions/delete-server-disk.action.ts create mode 100644 src/actions/delete-server-ip.action.ts create mode 100644 src/actions/delete-server.action.ts create mode 100644 src/actions/delete-ssh-key.action.ts create mode 100644 src/actions/delete-subdomain.action.ts create mode 100644 src/actions/delete-vpc.action.ts create mode 100644 src/actions/domain-requests.action.ts create mode 100644 src/actions/download-knowledge-base-document.action.ts create mode 100644 src/actions/edit-api-key.action.ts create mode 100644 src/actions/edit-k8s-cluster.action.ts create mode 100644 src/actions/get-account-finances.action.ts create mode 100644 src/actions/get-account-services-cost.action.ts create mode 100644 src/actions/get-account-status.action.ts create mode 100644 src/actions/get-ai-agent-statistic.action.ts create mode 100644 src/actions/get-ai-agent.action.ts create mode 100644 src/actions/get-balancer.action.ts create mode 100644 src/actions/get-bucket-presets.action.ts create mode 100644 src/actions/get-bucket-transfer-status.action.ts create mode 100644 src/actions/get-bucket.action.ts create mode 100644 src/actions/get-container-registry.action.ts create mode 100644 src/actions/get-database-admin.action.ts create mode 100644 src/actions/get-database-auto-backups.action.ts create mode 100644 src/actions/get-database-backup.action.ts create mode 100644 src/actions/get-database-cluster.action.ts create mode 100644 src/actions/get-database-instance.action.ts create mode 100644 src/actions/get-database-parameters.action.ts create mode 100644 src/actions/get-database.action.ts create mode 100644 src/actions/get-dedicated-server.action.ts create mode 100644 src/actions/get-domain-name-servers.action.ts create mode 100644 src/actions/get-domain.action.ts create mode 100644 src/actions/get-firewall-group.action.ts create mode 100644 src/actions/get-firewall-rule.action.ts create mode 100644 src/actions/get-floating-ip.action.ts create mode 100644 src/actions/get-image-download.action.ts create mode 100644 src/actions/get-image.action.ts create mode 100644 src/actions/get-k8s-cluster-resources.action.ts create mode 100644 src/actions/get-k8s-cluster.action.ts create mode 100644 src/actions/get-k8s-kubeconfig.action.ts create mode 100644 src/actions/get-k8s-node-group.action.ts create mode 100644 src/actions/get-knowledge-base-statistic.action.ts create mode 100644 src/actions/get-knowledge-base.action.ts create mode 100644 src/actions/get-mail-domain-info.action.ts create mode 100644 src/actions/get-mailbox-v1.action.ts create mode 100644 src/actions/get-mailbox.action.ts create mode 100644 src/actions/get-network-drive.action.ts create mode 100644 src/actions/get-project.action.ts create mode 100644 src/actions/get-server-disk-auto-backups.action.ts create mode 100644 src/actions/get-server-disk-backup.action.ts create mode 100644 src/actions/get-server-disk.action.ts create mode 100644 src/actions/get-server-logs.action.ts create mode 100644 src/actions/get-server.action.ts create mode 100644 src/actions/get-ssh-key.action.ts create mode 100644 src/actions/get-vpc.action.ts create mode 100644 src/actions/hard-reboot-server.action.ts create mode 100644 src/actions/hard-shutdown-server.action.ts create mode 100644 src/actions/increase-k8s-node-group-nodes.action.ts create mode 100644 src/actions/install-k8s-addon.action.ts create mode 100644 src/actions/link-firewall-resource.action.ts create mode 100644 src/actions/link-knowledge-base.action.ts create mode 100644 src/actions/list-ai-agent-token-packages.action.ts create mode 100644 src/actions/list-ai-agents.action.ts create mode 100644 src/actions/list-ai-models.action.ts create mode 100644 src/actions/list-all-project-balancers.action.ts create mode 100644 src/actions/list-all-project-buckets.action.ts create mode 100644 src/actions/list-all-project-clusters.action.ts create mode 100644 src/actions/list-all-project-databases.action.ts create mode 100644 src/actions/list-all-project-dedicated.action.ts create mode 100644 src/actions/list-all-project-servers.action.ts create mode 100644 src/actions/list-api-keys.action.ts create mode 100644 src/actions/list-balancer-ips.action.ts create mode 100644 src/actions/list-balancer-presets.action.ts create mode 100644 src/actions/list-balancer-rules.action.ts create mode 100644 src/actions/list-balancers.action.ts create mode 100644 src/actions/list-bucket-subdomains.action.ts create mode 100644 src/actions/list-bucket-users.action.ts create mode 100644 src/actions/list-buckets.action.ts create mode 100644 src/actions/list-container-registries.action.ts create mode 100644 src/actions/list-container-registry-presets.action.ts create mode 100644 src/actions/list-container-registry-repositories.action.ts create mode 100644 src/actions/list-database-admins.action.ts create mode 100644 src/actions/list-database-backups.action.ts create mode 100644 src/actions/list-database-clusters.action.ts create mode 100644 src/actions/list-database-instances.action.ts create mode 100644 src/actions/list-database-types.action.ts create mode 100644 src/actions/list-databases.action.ts create mode 100644 src/actions/list-dedicated-server-additional-services.action.ts create mode 100644 src/actions/list-dedicated-server-presets.action.ts create mode 100644 src/actions/list-dedicated-servers.action.ts create mode 100644 src/actions/list-default-dns-records.action.ts create mode 100644 src/actions/list-dns-records.action.ts create mode 100644 src/actions/list-domains.action.ts create mode 100644 src/actions/list-firewall-group-resources.action.ts create mode 100644 src/actions/list-firewall-groups-by-resource.action.ts create mode 100644 src/actions/list-firewall-groups.action.ts create mode 100644 src/actions/list-firewall-rules.action.ts create mode 100644 src/actions/list-floating-ips.action.ts create mode 100644 src/actions/list-image-downloads.action.ts create mode 100644 src/actions/list-images.action.ts create mode 100644 src/actions/list-k8s-addon-configs.action.ts create mode 100644 src/actions/list-k8s-addons.action.ts create mode 100644 src/actions/list-k8s-cluster-nodes.action.ts create mode 100644 src/actions/list-k8s-clusters.action.ts create mode 100644 src/actions/list-k8s-network-drivers.action.ts create mode 100644 src/actions/list-k8s-node-group-nodes.action.ts create mode 100644 src/actions/list-k8s-node-groups.action.ts create mode 100644 src/actions/list-k8s-presets.action.ts create mode 100644 src/actions/list-k8s-versions.action.ts create mode 100644 src/actions/list-knowledge-base-documents.action.ts create mode 100644 src/actions/list-knowledge-base-token-packages.action.ts create mode 100644 src/actions/list-knowledge-bases-v1.action.ts create mode 100644 src/actions/list-knowledge-bases.action.ts create mode 100644 src/actions/list-locations.action.ts create mode 100644 src/actions/list-mailboxes-by-domain.action.ts create mode 100644 src/actions/list-mailboxes-v1.action.ts create mode 100644 src/actions/list-mailboxes.action.ts create mode 100644 src/actions/list-network-drive-available-resources.action.ts create mode 100644 src/actions/list-network-drive-presets.action.ts create mode 100644 src/actions/list-network-drives.action.ts create mode 100644 src/actions/list-project-balancers.action.ts create mode 100644 src/actions/list-project-buckets.action.ts create mode 100644 src/actions/list-project-clusters.action.ts create mode 100644 src/actions/list-project-databases.action.ts create mode 100644 src/actions/list-project-dedicated.action.ts create mode 100644 src/actions/list-project-resources.action.ts create mode 100644 src/actions/list-project-servers.action.ts create mode 100644 src/actions/list-projects.action.ts create mode 100644 src/actions/list-server-configurators.action.ts create mode 100644 src/actions/list-server-disk-backups.action.ts create mode 100644 src/actions/list-server-disks.action.ts create mode 100644 src/actions/list-server-ips.action.ts create mode 100644 src/actions/list-server-os.action.ts create mode 100644 src/actions/list-server-presets.action.ts create mode 100644 src/actions/list-server-software.action.ts create mode 100644 src/actions/list-servers.action.ts create mode 100644 src/actions/list-ssh-keys.action.ts create mode 100644 src/actions/list-vpc-ports.action.ts create mode 100644 src/actions/list-vpc-services.action.ts create mode 100644 src/actions/mount-network-drive.action.ts create mode 100644 src/actions/reboot-server.action.ts create mode 100644 src/actions/reduce-k8s-node-group-nodes.action.ts create mode 100644 src/actions/refresh-api-key.action.ts create mode 100644 src/actions/reindex-knowledge-base-document.action.ts create mode 100644 src/actions/remove-balancer-ips.action.ts create mode 100644 src/actions/remove-ssh-key-from-server.action.ts create mode 100644 src/actions/reset-server-password.action.ts create mode 100644 src/actions/resize-server.action.ts create mode 100644 src/actions/restore-database-backup.action.ts create mode 100644 src/actions/server-disk-backup-action.action.ts create mode 100644 src/actions/set-server-boot-mode.action.ts create mode 100644 src/actions/set-server-nat-mode.action.ts create mode 100644 src/actions/shutdown-server.action.ts create mode 100644 src/actions/start-server.action.ts create mode 100644 src/actions/tlds.action.ts create mode 100644 src/actions/transfer-bucket.action.ts create mode 100644 src/actions/transfer-project-resource.action.ts create mode 100644 src/actions/unbind-floating-ip.action.ts create mode 100644 src/actions/uninstall-k8s-addon.action.ts create mode 100644 src/actions/unlink-firewall-resource.action.ts create mode 100644 src/actions/unlink-knowledge-base.action.ts create mode 100644 src/actions/unmount-network-drive.action.ts create mode 100644 src/actions/unmount-server-image.action.ts create mode 100644 src/actions/update-ai-agent.action.ts create mode 100644 src/actions/update-balancer-rule.action.ts create mode 100644 src/actions/update-balancer.action.ts create mode 100644 src/actions/update-bucket-user.action.ts create mode 100644 src/actions/update-bucket.action.ts create mode 100644 src/actions/update-container-registry.action.ts create mode 100644 src/actions/update-database-admin.action.ts create mode 100644 src/actions/update-database-auto-backups.action.ts create mode 100644 src/actions/update-database-cluster.action.ts create mode 100644 src/actions/update-database-instance.action.ts create mode 100644 src/actions/update-database.action.ts create mode 100644 src/actions/update-dedicated-server.action.ts create mode 100644 src/actions/update-dns-record.action.ts create mode 100644 src/actions/update-domain-name-servers.action.ts create mode 100644 src/actions/update-domain.action.ts create mode 100644 src/actions/update-firewall-group.action.ts create mode 100644 src/actions/update-firewall-rule.action.ts create mode 100644 src/actions/update-floating-ip.action.ts create mode 100644 src/actions/update-image.action.ts create mode 100644 src/actions/update-k8s-addon.action.ts create mode 100644 src/actions/update-k8s-cluster-version.action.ts create mode 100644 src/actions/update-knowledge-base.action.ts create mode 100644 src/actions/update-mail-domain-info.action.ts create mode 100644 src/actions/update-mailbox-v1.action.ts create mode 100644 src/actions/update-mailbox.action.ts create mode 100644 src/actions/update-network-drive.action.ts create mode 100644 src/actions/update-project.action.ts create mode 100644 src/actions/update-server-disk-auto-backups.action.ts create mode 100644 src/actions/update-server-disk-backup.action.ts create mode 100644 src/actions/update-server-disk.action.ts create mode 100644 src/actions/update-server-ip.action.ts create mode 100644 src/actions/update-server.action.ts create mode 100644 src/actions/update-ssh-key.action.ts create mode 100644 src/actions/update-vpc.action.ts create mode 100644 src/api/account.ts create mode 100644 src/api/ai-agents.ts create mode 100644 src/api/auth.ts create mode 100644 src/api/balancers.ts create mode 100644 src/api/catalogs.ts create mode 100644 src/api/container-registry.ts create mode 100644 src/api/dedicated-servers.ts create mode 100644 src/api/domains.ts create mode 100644 src/api/firewall.ts create mode 100644 src/api/images.ts create mode 100644 src/api/knowledge-bases.ts create mode 100644 src/api/kubernetes.ts create mode 100644 src/api/mail.ts create mode 100644 src/api/network-drives.ts create mode 100644 src/api/projects.ts create mode 100644 src/api/s3-buckets.ts create mode 100644 src/api/servers.ts create mode 100644 src/api/ssh-keys.ts create mode 100644 src/tools/add-balancer-ips.tool.ts create mode 100644 src/tools/add-balancer-to-project.tool.ts create mode 100644 src/tools/add-bucket-subdomain-certificate.tool.ts create mode 100644 src/tools/add-bucket-subdomains.tool.ts create mode 100644 src/tools/add-bucket-to-project.tool.ts create mode 100644 src/tools/add-cluster-to-project.tool.ts create mode 100644 src/tools/add-database-to-project.tool.ts create mode 100644 src/tools/add-dedicated-to-project.tool.ts create mode 100644 src/tools/add-domain.tool.ts create mode 100644 src/tools/add-server-ip.tool.ts create mode 100644 src/tools/add-server-to-project.tool.ts create mode 100644 src/tools/add-ssh-keys-to-server.tool.ts create mode 100644 src/tools/add-subdomain.tool.ts create mode 100644 src/tools/batch-create-mailboxes-v1.tool.ts create mode 100644 src/tools/batch-create-mailboxes.tool.ts create mode 100644 src/tools/bind-floating-ip.tool.ts create mode 100644 src/tools/check-domain.tool.ts create mode 100644 src/tools/clone-server.tool.ts create mode 100644 src/tools/create-ai-agent.tool.ts create mode 100644 src/tools/create-api-key.tool.ts create mode 100644 src/tools/create-balancer-rule.tool.ts create mode 100644 src/tools/create-balancer.tool.ts create mode 100644 src/tools/create-bucket.tool.ts create mode 100644 src/tools/create-container-registry.tool.ts create mode 100644 src/tools/create-database-admin.tool.ts create mode 100644 src/tools/create-database-instance.tool.ts create mode 100644 src/tools/create-dedicated-server.tool.ts create mode 100644 src/tools/create-dns-record.tool.ts create mode 100644 src/tools/create-domain-request.tool.ts create mode 100644 src/tools/create-firewall-group.tool.ts create mode 100644 src/tools/create-firewall-rule.tool.ts create mode 100644 src/tools/create-image-download.tool.ts create mode 100644 src/tools/create-image.tool.ts create mode 100644 src/tools/create-k8s-cluster.tool.ts create mode 100644 src/tools/create-k8s-node-group.tool.ts create mode 100644 src/tools/create-mailbox-v1.tool.ts create mode 100644 src/tools/create-mailbox.tool.ts create mode 100644 src/tools/create-network-drive.tool.ts create mode 100644 src/tools/create-project.tool.ts create mode 100644 src/tools/create-server-disk-backup.tool.ts create mode 100644 src/tools/create-server.tool.ts create mode 100644 src/tools/create-ssh-key.tool.ts create mode 100644 src/tools/delete-ai-agent.tool.ts create mode 100644 src/tools/delete-api-key.tool.ts create mode 100644 src/tools/delete-balancer-rule.tool.ts create mode 100644 src/tools/delete-balancer.tool.ts create mode 100644 src/tools/delete-bucket-subdomains.tool.ts create mode 100644 src/tools/delete-bucket.tool.ts create mode 100644 src/tools/delete-container-registry.tool.ts create mode 100644 src/tools/delete-database-admin.tool.ts create mode 100644 src/tools/delete-database-cluster.tool.ts create mode 100644 src/tools/delete-dedicated-server.tool.ts create mode 100644 src/tools/delete-dns-record.tool.ts create mode 100644 src/tools/delete-domain.tool.ts create mode 100644 src/tools/delete-firewall-group.tool.ts create mode 100644 src/tools/delete-firewall-rule.tool.ts create mode 100644 src/tools/delete-floating-ip.tool.ts create mode 100644 src/tools/delete-image-download.tool.ts create mode 100644 src/tools/delete-image.tool.ts create mode 100644 src/tools/delete-k8s-cluster-node.tool.ts create mode 100644 src/tools/delete-k8s-cluster.tool.ts create mode 100644 src/tools/delete-k8s-node-group.tool.ts create mode 100644 src/tools/delete-mailbox.tool.ts create mode 100644 src/tools/delete-network-drive.tool.ts create mode 100644 src/tools/delete-project.tool.ts create mode 100644 src/tools/delete-server-disk-backup.tool.ts create mode 100644 src/tools/delete-server-ip.tool.ts create mode 100644 src/tools/delete-server.tool.ts create mode 100644 src/tools/delete-ssh-key.tool.ts create mode 100644 src/tools/delete-subdomain.tool.ts create mode 100644 src/tools/delete-vpc.tool.ts create mode 100644 src/tools/edit-api-key.tool.ts create mode 100644 src/tools/edit-k8s-cluster.tool.ts create mode 100644 src/tools/get-account-finances.tool.ts create mode 100644 src/tools/get-account-services-cost.tool.ts create mode 100644 src/tools/get-account-status.tool.ts create mode 100644 src/tools/get-ai-agent-statistic.tool.ts create mode 100644 src/tools/get-ai-agent.tool.ts create mode 100644 src/tools/get-balancer.tool.ts create mode 100644 src/tools/get-bucket-presets.tool.ts create mode 100644 src/tools/get-bucket-transfer-status.tool.ts create mode 100644 src/tools/get-bucket.tool.ts create mode 100644 src/tools/get-container-registry.tool.ts create mode 100644 src/tools/get-database-admin.tool.ts create mode 100644 src/tools/get-database-cluster.tool.ts create mode 100644 src/tools/get-database-instance.tool.ts create mode 100644 src/tools/get-dedicated-server.tool.ts create mode 100644 src/tools/get-domain-name-servers.tool.ts create mode 100644 src/tools/get-domain-request.tool.ts create mode 100644 src/tools/get-domain.tool.ts create mode 100644 src/tools/get-firewall-group.tool.ts create mode 100644 src/tools/get-firewall-rule.tool.ts create mode 100644 src/tools/get-floating-ip.tool.ts create mode 100644 src/tools/get-image-download.tool.ts create mode 100644 src/tools/get-image.tool.ts create mode 100644 src/tools/get-k8s-cluster-resources.tool.ts create mode 100644 src/tools/get-k8s-cluster.tool.ts create mode 100644 src/tools/get-k8s-kubeconfig.tool.ts create mode 100644 src/tools/get-k8s-node-group.tool.ts create mode 100644 src/tools/get-mail-domain-info.tool.ts create mode 100644 src/tools/get-mailbox-v1.tool.ts create mode 100644 src/tools/get-mailbox.tool.ts create mode 100644 src/tools/get-network-drive.tool.ts create mode 100644 src/tools/get-project.tool.ts create mode 100644 src/tools/get-server-logs.tool.ts create mode 100644 src/tools/get-server.tool.ts create mode 100644 src/tools/get-ssh-key.tool.ts create mode 100644 src/tools/get-tld.tool.ts create mode 100644 src/tools/get-vpc.tool.ts create mode 100644 src/tools/hard-reboot-server.tool.ts create mode 100644 src/tools/hard-shutdown-server.tool.ts create mode 100644 src/tools/increase-k8s-node-group-nodes.tool.ts create mode 100644 src/tools/install-k8s-addon.tool.ts create mode 100644 src/tools/link-firewall-resource.tool.ts create mode 100644 src/tools/list-ai-agents.tool.ts create mode 100644 src/tools/list-all-project-balancers.tool.ts create mode 100644 src/tools/list-all-project-buckets.tool.ts create mode 100644 src/tools/list-all-project-clusters.tool.ts create mode 100644 src/tools/list-all-project-databases.tool.ts create mode 100644 src/tools/list-all-project-dedicated.tool.ts create mode 100644 src/tools/list-all-project-servers.tool.ts create mode 100644 src/tools/list-api-keys.tool.ts create mode 100644 src/tools/list-balancer-ips.tool.ts create mode 100644 src/tools/list-balancer-presets.tool.ts create mode 100644 src/tools/list-balancer-rules.tool.ts create mode 100644 src/tools/list-balancers.tool.ts create mode 100644 src/tools/list-bucket-subdomains.tool.ts create mode 100644 src/tools/list-bucket-users.tool.ts create mode 100644 src/tools/list-buckets.tool.ts create mode 100644 src/tools/list-container-registries.tool.ts create mode 100644 src/tools/list-container-registry-presets.tool.ts create mode 100644 src/tools/list-container-registry-repositories.tool.ts create mode 100644 src/tools/list-database-admins.tool.ts create mode 100644 src/tools/list-database-clusters.tool.ts create mode 100644 src/tools/list-database-instances.tool.ts create mode 100644 src/tools/list-dedicated-server-additional-services.tool.ts create mode 100644 src/tools/list-dedicated-server-presets.tool.ts create mode 100644 src/tools/list-dedicated-servers.tool.ts create mode 100644 src/tools/list-default-dns-records.tool.ts create mode 100644 src/tools/list-dns-records.tool.ts create mode 100644 src/tools/list-domain-requests.tool.ts create mode 100644 src/tools/list-domains.tool.ts create mode 100644 src/tools/list-firewall-group-resources.tool.ts create mode 100644 src/tools/list-firewall-groups-by-resource.tool.ts create mode 100644 src/tools/list-firewall-groups.tool.ts create mode 100644 src/tools/list-firewall-rules.tool.ts create mode 100644 src/tools/list-floating-ips.tool.ts create mode 100644 src/tools/list-image-downloads.tool.ts create mode 100644 src/tools/list-images.tool.ts create mode 100644 src/tools/list-k8s-addon-configs.tool.ts create mode 100644 src/tools/list-k8s-addons.tool.ts create mode 100644 src/tools/list-k8s-cluster-nodes.tool.ts create mode 100644 src/tools/list-k8s-clusters.tool.ts create mode 100644 src/tools/list-k8s-network-drivers.tool.ts create mode 100644 src/tools/list-k8s-node-group-nodes.tool.ts create mode 100644 src/tools/list-k8s-node-groups.tool.ts create mode 100644 src/tools/list-k8s-presets.tool.ts create mode 100644 src/tools/list-k8s-versions.tool.ts create mode 100644 src/tools/list-locations.tool.ts create mode 100644 src/tools/list-mailboxes-by-domain.tool.ts create mode 100644 src/tools/list-mailboxes-v1.tool.ts create mode 100644 src/tools/list-mailboxes.tool.ts create mode 100644 src/tools/list-network-drive-available-resources.tool.ts create mode 100644 src/tools/list-network-drive-presets.tool.ts create mode 100644 src/tools/list-network-drives.tool.ts create mode 100644 src/tools/list-project-balancers.tool.ts create mode 100644 src/tools/list-project-buckets.tool.ts create mode 100644 src/tools/list-project-clusters.tool.ts create mode 100644 src/tools/list-project-databases.tool.ts create mode 100644 src/tools/list-project-dedicated.tool.ts create mode 100644 src/tools/list-project-resources.tool.ts create mode 100644 src/tools/list-project-servers.tool.ts create mode 100644 src/tools/list-projects.tool.ts create mode 100644 src/tools/list-server-configurators.tool.ts create mode 100644 src/tools/list-server-disk-backups.tool.ts create mode 100644 src/tools/list-server-disks.tool.ts create mode 100644 src/tools/list-server-ips.tool.ts create mode 100644 src/tools/list-server-os.tool.ts create mode 100644 src/tools/list-server-presets.tool.ts create mode 100644 src/tools/list-server-software.tool.ts create mode 100644 src/tools/list-servers.tool.ts create mode 100644 src/tools/list-ssh-keys.tool.ts create mode 100644 src/tools/list-tlds.tool.ts create mode 100644 src/tools/list-vpc-ports.tool.ts create mode 100644 src/tools/list-vpc-services.tool.ts create mode 100644 src/tools/mount-network-drive.tool.ts create mode 100644 src/tools/reboot-server.tool.ts create mode 100644 src/tools/reduce-k8s-node-group-nodes.tool.ts create mode 100644 src/tools/refresh-api-key.tool.ts create mode 100644 src/tools/remove-balancer-ips.tool.ts create mode 100644 src/tools/remove-ssh-key-from-server.tool.ts create mode 100644 src/tools/reset-server-password.tool.ts create mode 100644 src/tools/resize-server.tool.ts create mode 100644 src/tools/set-server-boot-mode.tool.ts create mode 100644 src/tools/set-server-nat-mode.tool.ts create mode 100644 src/tools/shutdown-server.tool.ts create mode 100644 src/tools/start-server.tool.ts create mode 100644 src/tools/transfer-bucket.tool.ts create mode 100644 src/tools/transfer-project-resource.tool.ts create mode 100644 src/tools/unbind-floating-ip.tool.ts create mode 100644 src/tools/uninstall-k8s-addon.tool.ts create mode 100644 src/tools/unlink-firewall-resource.tool.ts create mode 100644 src/tools/unmount-network-drive.tool.ts create mode 100644 src/tools/unmount-server-image.tool.ts create mode 100644 src/tools/update-ai-agent.tool.ts create mode 100644 src/tools/update-balancer-rule.tool.ts create mode 100644 src/tools/update-balancer.tool.ts create mode 100644 src/tools/update-bucket-user.tool.ts create mode 100644 src/tools/update-bucket.tool.ts create mode 100644 src/tools/update-container-registry.tool.ts create mode 100644 src/tools/update-database-admin.tool.ts create mode 100644 src/tools/update-database-cluster.tool.ts create mode 100644 src/tools/update-database-instance.tool.ts create mode 100644 src/tools/update-dedicated-server.tool.ts create mode 100644 src/tools/update-dns-record.tool.ts create mode 100644 src/tools/update-domain-name-servers.tool.ts create mode 100644 src/tools/update-domain-request.tool.ts create mode 100644 src/tools/update-domain.tool.ts create mode 100644 src/tools/update-firewall-group.tool.ts create mode 100644 src/tools/update-firewall-rule.tool.ts create mode 100644 src/tools/update-floating-ip.tool.ts create mode 100644 src/tools/update-image.tool.ts create mode 100644 src/tools/update-k8s-addon.tool.ts create mode 100644 src/tools/update-k8s-cluster-version.tool.ts create mode 100644 src/tools/update-mail-domain-info.tool.ts create mode 100644 src/tools/update-mailbox-v1.tool.ts create mode 100644 src/tools/update-mailbox.tool.ts create mode 100644 src/tools/update-network-drive.tool.ts create mode 100644 src/tools/update-project.tool.ts create mode 100644 src/tools/update-server-ip.tool.ts create mode 100644 src/tools/update-server.tool.ts create mode 100644 src/tools/update-ssh-key.tool.ts create mode 100644 src/tools/update-vpc.tool.ts create mode 100644 src/types/ai-agent.type.ts create mode 100644 src/types/ai-model.type.ts create mode 100644 src/types/api-key.type.ts create mode 100644 src/types/auto-backup.type.ts create mode 100644 src/types/balancer.type.ts create mode 100644 src/types/bucket-delete-response.type.ts create mode 100644 src/types/bucket-preset.type.ts create mode 100644 src/types/bucket-subdomain.type.ts create mode 100644 src/types/bucket-transfer-status.type.ts create mode 100644 src/types/bucket-user.type.ts create mode 100644 src/types/bucket.type.ts create mode 100644 src/types/container-registry.type.ts create mode 100644 src/types/database-cluster.type.ts create mode 100644 src/types/dedicated-server.type.ts create mode 100644 src/types/dns-record.type.ts create mode 100644 src/types/domain-name-server.type.ts create mode 100644 src/types/domain-request.type.ts create mode 100644 src/types/domain.type.ts create mode 100644 src/types/dto/add-bucket-certificate-request.dto.ts create mode 100644 src/types/dto/add-bucket-subdomains-request.dto.ts create mode 100644 src/types/dto/add-bucket-subdomains-response.dto.ts create mode 100644 src/types/dto/add-resource-to-project-request.dto.ts create mode 100644 src/types/dto/add-ssh-keys-to-server-request.dto.ts create mode 100644 src/types/dto/add-subdomain-response.dto.ts create mode 100644 src/types/dto/add-token-package-request.dto.ts create mode 100644 src/types/dto/auto-backup-response.dto.ts create mode 100644 src/types/dto/balancer-ips-request.dto.ts create mode 100644 src/types/dto/balancer-rule-response.dto.ts create mode 100644 src/types/dto/batch-create-mailboxes-request.dto.ts create mode 100644 src/types/dto/batch-create-mailboxes-response.dto.ts create mode 100644 src/types/dto/bind-floating-ip-request.dto.ts create mode 100644 src/types/dto/check-domain-response.dto.ts create mode 100644 src/types/dto/create-ai-agent-request.dto.ts create mode 100644 src/types/dto/create-api-key-request.dto.ts create mode 100644 src/types/dto/create-api-key-response.dto.ts create mode 100644 src/types/dto/create-balancer-request.dto.ts create mode 100644 src/types/dto/create-balancer-rule-request.dto.ts create mode 100644 src/types/dto/create-bucket-request.dto.ts create mode 100644 src/types/dto/create-bucket-response.dto.ts create mode 100644 src/types/dto/create-container-registry-request.dto.ts create mode 100644 src/types/dto/create-database-admin-request.dto.ts create mode 100644 src/types/dto/create-database-instance-request.dto.ts create mode 100644 src/types/dto/create-dedicated-server-request.dto.ts create mode 100644 src/types/dto/create-dns-record-request.dto.ts create mode 100644 src/types/dto/create-dns-record-response.dto.ts create mode 100644 src/types/dto/create-domain-request-request.dto.ts create mode 100644 src/types/dto/create-firewall-group-request.dto.ts create mode 100644 src/types/dto/create-firewall-rule-request.dto.ts create mode 100644 src/types/dto/create-image-download-request.dto.ts create mode 100644 src/types/dto/create-image-request.dto.ts create mode 100644 src/types/dto/create-k8s-cluster-request.dto.ts create mode 100644 src/types/dto/create-k8s-node-group-request.dto.ts create mode 100644 src/types/dto/create-knowledge-base-request.dto.ts create mode 100644 src/types/dto/create-mailbox-request.dto.ts create mode 100644 src/types/dto/create-mailbox-response.dto.ts create mode 100644 src/types/dto/create-network-drive-request.dto.ts create mode 100644 src/types/dto/create-network-drive-response.dto.ts create mode 100644 src/types/dto/create-project-request.dto.ts create mode 100644 src/types/dto/create-server-disk-backup-response.dto.ts create mode 100644 src/types/dto/create-server-disk-request.dto.ts create mode 100644 src/types/dto/create-server-request.dto.ts create mode 100644 src/types/dto/create-server-response.dto.ts create mode 100644 src/types/dto/create-ssh-key-request.dto.ts create mode 100644 src/types/dto/create-ssh-key-response.dto.ts create mode 100644 src/types/dto/database-admin-response.dto.ts create mode 100644 src/types/dto/database-auto-backups-response.dto.ts create mode 100644 src/types/dto/database-backup-response.dto.ts create mode 100644 src/types/dto/database-instance-response.dto.ts create mode 100644 src/types/dto/delete-balancer-response.dto.ts create mode 100644 src/types/dto/delete-bucket-response.dto.ts create mode 100644 src/types/dto/delete-bucket-subdomains-request.dto.ts create mode 100644 src/types/dto/delete-bucket-subdomains-response.dto.ts create mode 100644 src/types/dto/delete-database-response.dto.ts create mode 100644 src/types/dto/delete-k8s-cluster-response.dto.ts create mode 100644 src/types/dto/delete-server-response.dto.ts create mode 100644 src/types/dto/domain-name-servers-response.dto.ts create mode 100644 src/types/dto/edit-api-key-request.dto.ts create mode 100644 src/types/dto/edit-api-key-response.dto.ts create mode 100644 src/types/dto/edit-k8s-cluster-request.dto.ts create mode 100644 src/types/dto/get-account-status-response.dto.ts create mode 100644 src/types/dto/get-agent-statistic-response.dto.ts create mode 100644 src/types/dto/get-ai-agent-response.dto.ts create mode 100644 src/types/dto/get-balancer-response.dto.ts create mode 100644 src/types/dto/get-bucket-presets-response.dto.ts create mode 100644 src/types/dto/get-bucket-response.dto.ts create mode 100644 src/types/dto/get-bucket-transfer-status-response.dto.ts create mode 100644 src/types/dto/get-container-registry-response.dto.ts create mode 100644 src/types/dto/get-database-cluster-response.dto.ts create mode 100644 src/types/dto/get-database-parameters-response.dto.ts create mode 100644 src/types/dto/get-database-response.dto.ts create mode 100644 src/types/dto/get-dedicated-server-response.dto.ts create mode 100644 src/types/dto/get-domain-response.dto.ts create mode 100644 src/types/dto/get-finances-response.dto.ts create mode 100644 src/types/dto/get-firewall-group-response.dto.ts create mode 100644 src/types/dto/get-firewall-rule-response.dto.ts create mode 100644 src/types/dto/get-floating-ip-response.dto.ts create mode 100644 src/types/dto/get-image-download-response.dto.ts create mode 100644 src/types/dto/get-image-response.dto.ts create mode 100644 src/types/dto/get-k8s-cluster-response.dto.ts create mode 100644 src/types/dto/get-k8s-node-group-response.dto.ts create mode 100644 src/types/dto/get-k8s-resources-response.dto.ts create mode 100644 src/types/dto/get-knowledge-base-response.dto.ts create mode 100644 src/types/dto/get-knowledge-base-statistic-response.dto.ts create mode 100644 src/types/dto/get-mail-domain-info-response.dto.ts create mode 100644 src/types/dto/get-mailbox-response.dto.ts create mode 100644 src/types/dto/get-network-drive-response.dto.ts create mode 100644 src/types/dto/get-project-response.dto.ts create mode 100644 src/types/dto/get-server-logs-response.dto.ts create mode 100644 src/types/dto/get-server-response.dto.ts create mode 100644 src/types/dto/get-services-cost-response.dto.ts create mode 100644 src/types/dto/get-ssh-key-response.dto.ts create mode 100644 src/types/dto/get-vpc-response.dto.ts create mode 100644 src/types/dto/increase-k8s-nodes-request.dto.ts create mode 100644 src/types/dto/install-k8s-addon-request.dto.ts create mode 100644 src/types/dto/link-firewall-resource-response.dto.ts create mode 100644 src/types/dto/list-ai-agents-response.dto.ts create mode 100644 src/types/dto/list-ai-models-response.dto.ts create mode 100644 src/types/dto/list-api-keys-response.dto.ts create mode 100644 src/types/dto/list-balancer-ips-response.dto.ts create mode 100644 src/types/dto/list-balancer-presets-response.dto.ts create mode 100644 src/types/dto/list-balancer-rules-response.dto.ts create mode 100644 src/types/dto/list-balancers-response.dto.ts create mode 100644 src/types/dto/list-bucket-subdomains-response.dto.ts create mode 100644 src/types/dto/list-bucket-users-response.dto.ts create mode 100644 src/types/dto/list-buckets-response.dto.ts create mode 100644 src/types/dto/list-container-registries-response.dto.ts create mode 100644 src/types/dto/list-container-registry-presets-response.dto.ts create mode 100644 src/types/dto/list-container-registry-repositories-response.dto.ts create mode 100644 src/types/dto/list-database-admins-response.dto.ts create mode 100644 src/types/dto/list-database-backups-response.dto.ts create mode 100644 src/types/dto/list-database-clusters-response.dto.ts create mode 100644 src/types/dto/list-database-instances-response.dto.ts create mode 100644 src/types/dto/list-database-types-response.dto.ts create mode 100644 src/types/dto/list-databases-response.dto.ts create mode 100644 src/types/dto/list-dedicated-server-additional-services-response.dto.ts create mode 100644 src/types/dto/list-dedicated-server-presets-response.dto.ts create mode 100644 src/types/dto/list-dedicated-servers-response.dto.ts create mode 100644 src/types/dto/list-dns-records-response.dto.ts create mode 100644 src/types/dto/list-domain-requests-response.dto.ts create mode 100644 src/types/dto/list-domains-response.dto.ts create mode 100644 src/types/dto/list-firewall-group-resources-response.dto.ts create mode 100644 src/types/dto/list-firewall-groups-response.dto.ts create mode 100644 src/types/dto/list-firewall-rules-response.dto.ts create mode 100644 src/types/dto/list-floating-ips-response.dto.ts create mode 100644 src/types/dto/list-image-downloads-response.dto.ts create mode 100644 src/types/dto/list-images-response.dto.ts create mode 100644 src/types/dto/list-k8s-addon-configs-response.dto.ts create mode 100644 src/types/dto/list-k8s-addons-response.dto.ts create mode 100644 src/types/dto/list-k8s-clusters-response.dto.ts create mode 100644 src/types/dto/list-k8s-network-drivers-response.dto.ts create mode 100644 src/types/dto/list-k8s-node-groups-response.dto.ts create mode 100644 src/types/dto/list-k8s-nodes-response.dto.ts create mode 100644 src/types/dto/list-k8s-presets-response.dto.ts create mode 100644 src/types/dto/list-k8s-versions-response.dto.ts create mode 100644 src/types/dto/list-knowledge-base-documents-response.dto.ts create mode 100644 src/types/dto/list-knowledge-bases-response.dto.ts create mode 100644 src/types/dto/list-locations-response.dto.ts create mode 100644 src/types/dto/list-mailboxes-response.dto.ts create mode 100644 src/types/dto/list-network-drive-available-resources-response.dto.ts create mode 100644 src/types/dto/list-network-drive-presets-response.dto.ts create mode 100644 src/types/dto/list-network-drives-response.dto.ts create mode 100644 src/types/dto/list-project-resources-response.dto.ts create mode 100644 src/types/dto/list-projects-response.dto.ts create mode 100644 src/types/dto/list-resources-response.dto.ts create mode 100644 src/types/dto/list-server-configurators-response.dto.ts create mode 100644 src/types/dto/list-server-disk-backups-response.dto.ts create mode 100644 src/types/dto/list-server-disks-response.dto.ts create mode 100644 src/types/dto/list-server-ips-response.dto.ts create mode 100644 src/types/dto/list-server-os-response.dto.ts create mode 100644 src/types/dto/list-server-presets-response.dto.ts create mode 100644 src/types/dto/list-server-software-response.dto.ts create mode 100644 src/types/dto/list-servers-response.dto.ts create mode 100644 src/types/dto/list-ssh-keys-response.dto.ts create mode 100644 src/types/dto/list-tlds-response.dto.ts create mode 100644 src/types/dto/list-token-packages-response.dto.ts create mode 100644 src/types/dto/list-vpc-ports-response.dto.ts create mode 100644 src/types/dto/list-vpc-services-response.dto.ts create mode 100644 src/types/dto/mount-network-drive-request.dto.ts create mode 100644 src/types/dto/project-resource-response.dto.ts create mode 100644 src/types/dto/reduce-k8s-nodes-request.dto.ts create mode 100644 src/types/dto/refresh-api-key-request.dto.ts create mode 100644 src/types/dto/refresh-api-key-response.dto.ts create mode 100644 src/types/dto/server-disk-backup-response.dto.ts create mode 100644 src/types/dto/server-disk-response.dto.ts create mode 100644 src/types/dto/server-ip-response.dto.ts create mode 100644 src/types/dto/transfer-bucket-request.dto.ts create mode 100644 src/types/dto/transfer-project-resource-request.dto.ts create mode 100644 src/types/dto/update-ai-agent-request.dto.ts create mode 100644 src/types/dto/update-balancer-request.dto.ts create mode 100644 src/types/dto/update-bucket-request.dto.ts create mode 100644 src/types/dto/update-bucket-response.dto.ts create mode 100644 src/types/dto/update-bucket-user-request.dto.ts create mode 100644 src/types/dto/update-bucket-user-response.dto.ts create mode 100644 src/types/dto/update-container-registry-request.dto.ts create mode 100644 src/types/dto/update-database-admin-request.dto.ts create mode 100644 src/types/dto/update-database-auto-backups-request.dto.ts create mode 100644 src/types/dto/update-database-cluster-request.dto.ts create mode 100644 src/types/dto/update-database-instance-request.dto.ts create mode 100644 src/types/dto/update-database-request.dto.ts create mode 100644 src/types/dto/update-dedicated-server-request.dto.ts create mode 100644 src/types/dto/update-domain-name-servers-request.dto.ts create mode 100644 src/types/dto/update-domain-request.dto.ts create mode 100644 src/types/dto/update-firewall-group-request.dto.ts create mode 100644 src/types/dto/update-firewall-rule-request.dto.ts create mode 100644 src/types/dto/update-floating-ip-request.dto.ts create mode 100644 src/types/dto/update-floating-ip-response.dto.ts create mode 100644 src/types/dto/update-image-request.dto.ts create mode 100644 src/types/dto/update-k8s-cluster-version-request.dto.ts create mode 100644 src/types/dto/update-knowledge-base-request.dto.ts create mode 100644 src/types/dto/update-mail-domain-info-request.dto.ts create mode 100644 src/types/dto/update-mail-domain-info-response.dto.ts create mode 100644 src/types/dto/update-mailbox-request.dto.ts create mode 100644 src/types/dto/update-mailbox-response.dto.ts create mode 100644 src/types/dto/update-network-drive-request.dto.ts create mode 100644 src/types/dto/update-network-drive-response.dto.ts create mode 100644 src/types/dto/update-project-request.dto.ts create mode 100644 src/types/dto/update-server-request.dto.ts create mode 100644 src/types/dto/update-ssh-key-request.dto.ts create mode 100644 src/types/dto/update-ssh-key-response.dto.ts create mode 100644 src/types/dto/update-vpc-request.dto.ts create mode 100644 src/types/dto/update-vpc-response.dto.ts create mode 100644 src/types/finances.type.ts create mode 100644 src/types/firewall-group.type.ts create mode 100644 src/types/firewall-resource.type.ts create mode 100644 src/types/firewall-rule.type.ts create mode 100644 src/types/image-download.type.ts create mode 100644 src/types/image.type.ts create mode 100644 src/types/k8s-addon.type.ts create mode 100644 src/types/k8s-cluster.type.ts create mode 100644 src/types/k8s-node-group.type.ts create mode 100644 src/types/k8s-node.type.ts create mode 100644 src/types/k8s-preset.type.ts create mode 100644 src/types/k8s-resources.type.ts create mode 100644 src/types/knowledge-base.type.ts create mode 100644 src/types/location.type.ts create mode 100644 src/types/mailbox.type.ts create mode 100644 src/types/network-drive-available-resource.type.ts create mode 100644 src/types/network-drive-preset.type.ts create mode 100644 src/types/network-drive.type.ts create mode 100644 src/types/project-resource-type.enum.ts create mode 100644 src/types/project.type.ts create mode 100644 src/types/server-backup.type.ts create mode 100644 src/types/server-configurator.type.ts create mode 100644 src/types/server-disk.type.ts create mode 100644 src/types/server-ip.type.ts create mode 100644 src/types/server-log.type.ts create mode 100644 src/types/server-os.type.ts create mode 100644 src/types/server-preset.type.ts create mode 100644 src/types/server-software.type.ts create mode 100644 src/types/server.type.ts create mode 100644 src/types/service-price.type.ts create mode 100644 src/types/ssh-key.type.ts create mode 100644 src/types/token-package.type.ts create mode 100644 src/types/token-statistic.type.ts create mode 100644 src/types/top-level-domain.type.ts create mode 100644 src/types/vpc-port.type.ts create mode 100644 src/types/vpc-service.type.ts diff --git a/.gitignore b/.gitignore index 110e4b9..59ca959 100644 --- a/.gitignore +++ b/.gitignore @@ -61,3 +61,4 @@ jspm_packages/ .env .history/ +.specs/ diff --git a/bun.lock b/bun.lock new file mode 100644 index 0000000..6337e61 --- /dev/null +++ b/bun.lock @@ -0,0 +1,346 @@ +{ + "lockfileVersion": 1, + "workspaces": { + "": { + "name": "timeweb-mcp-server", + "dependencies": { + "@modelcontextprotocol/sdk": "^1.17.4", + "axios": "^1.11.0", + "dotenv": "^16.4.5", + "zod": "^3.25.76", + }, + "devDependencies": { + "@types/node": "^24.3.0", + "tsdown": "^0.13.3", + "typescript": "^5.9.2", + }, + }, + }, + "packages": { + "@babel/generator": ["@babel/generator@7.28.3", "", { "dependencies": { "@babel/parser": "^7.28.3", "@babel/types": "^7.28.2", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" } }, "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw=="], + + "@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="], + + "@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.27.1", "", {}, "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow=="], + + "@babel/parser": ["@babel/parser@7.28.3", "", { "dependencies": { "@babel/types": "^7.28.2" }, "bin": { "parser": "bin/babel-parser.js" } }, "sha512-7+Ey1mAgYqFAx2h0RuoxcQT5+MlG3GTV0TQrgr7/ZliKsm/MNDxVVutlWaziMq7wJNAz8MTqz55XLpWvva6StA=="], + + "@babel/types": ["@babel/types@7.28.2", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ=="], + + "@emnapi/core": ["@emnapi/core@1.4.5", "", { "dependencies": { "@emnapi/wasi-threads": "1.0.4", "tslib": "^2.4.0" } }, "sha512-XsLw1dEOpkSX/WucdqUhPWP7hDxSvZiY+fsUC14h+FtQ2Ifni4znbBt8punRX+Uj2JG/uDb8nEHVKvrVlvdZ5Q=="], + + "@emnapi/runtime": ["@emnapi/runtime@1.4.5", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-++LApOtY0pEEz1zrd9vy1/zXVaVJJ/EbAF3u0fXIzPJEDtnITsBGbbK0EkM72amhl/R5b+5xx0Y/QhcVOpuulg=="], + + "@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.0.4", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-PJR+bOmMOPH8AtcTGAyYNiuJ3/Fcoj2XN/gBEWzDIKh254XO+mM9XoXHk5GNEhodxeMznbg7BlRojVbKN+gC6g=="], + + "@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="], + + "@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="], + + "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="], + + "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.30", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q=="], + + "@modelcontextprotocol/sdk": ["@modelcontextprotocol/sdk@1.17.4", "", { "dependencies": { "ajv": "^6.12.6", "content-type": "^1.0.5", "cors": "^2.8.5", "cross-spawn": "^7.0.5", "eventsource": "^3.0.2", "eventsource-parser": "^3.0.0", "express": "^5.0.1", "express-rate-limit": "^7.5.0", "pkce-challenge": "^5.0.0", "raw-body": "^3.0.0", "zod": "^3.23.8", "zod-to-json-schema": "^3.24.1" } }, "sha512-zq24hfuAmmlNZvik0FLI58uE5sriN0WWsQzIlYnzSuKDAHFqJtBFrl/LfB1NLgJT5Y7dEBzaX4yAKqOPrcetaw=="], + + "@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.0.3", "", { "dependencies": { "@emnapi/core": "^1.4.5", "@emnapi/runtime": "^1.4.5", "@tybys/wasm-util": "^0.10.0" } }, "sha512-rZxtMsLwjdXkMUGC3WwsPwLNVqVqnTJT6MNIB6e+5fhMcSCPP0AOsNWuMQ5mdCq6HNjs/ZeWAEchpqeprqBD2Q=="], + + "@oxc-project/runtime": ["@oxc-project/runtime@0.82.3", "", {}, "sha512-LNh5GlJvYHAnMurO+EyA8jJwN1rki7l3PSHuosDh2I7h00T6/u9rCkUjg/SvPmT1CZzvhuW0y+gf7jcqUy/Usg=="], + + "@oxc-project/types": ["@oxc-project/types@0.82.3", "", {}, "sha512-6nCUxBnGX0c6qfZW5MaF6/fmu5dHJDMiMPaioKHKs5mi5+8/FHQ7WGjgQIz1zxpmceMYfdIXkOaLYE+ejbuOtA=="], + + "@quansync/fs": ["@quansync/fs@0.1.5", "", { "dependencies": { "quansync": "^0.2.11" } }, "sha512-lNS9hL2aS2NZgNW7BBj+6EBl4rOf8l+tQ0eRY6JWCI8jI2kc53gSoqbjojU0OnAWhzoXiOjFyGsHcDGePB3lhA=="], + + "@rolldown/binding-android-arm64": ["@rolldown/binding-android-arm64@1.0.0-beta.34", "", { "os": "android", "cpu": "arm64" }, "sha512-jf5GNe5jP3Sr1Tih0WKvg2bzvh5T/1TA0fn1u32xSH7ca/p5t+/QRr4VRFCV/na5vjwKEhwWrChsL2AWlY+eoA=="], + + "@rolldown/binding-darwin-arm64": ["@rolldown/binding-darwin-arm64@1.0.0-beta.34", "", { "os": "darwin", "cpu": "arm64" }, "sha512-2F/TqH4QuJQ34tgWxqBjFL3XV1gMzeQgUO8YRtCPGBSP0GhxtoFzsp7KqmQEothsxztlv+KhhT9Dbg3HHwHViQ=="], + + "@rolldown/binding-darwin-x64": ["@rolldown/binding-darwin-x64@1.0.0-beta.34", "", { "os": "darwin", "cpu": "x64" }, "sha512-E1QuFslgLWbHQ8Qli/AqUKdfg0pockQPwRxVbhNQ74SciZEZpzLaujkdmOLSccMlSXDfFCF8RPnMoRAzQ9JV8Q=="], + + "@rolldown/binding-freebsd-x64": ["@rolldown/binding-freebsd-x64@1.0.0-beta.34", "", { "os": "freebsd", "cpu": "x64" }, "sha512-VS8VInNCwnkpI9WeQaWu3kVBq9ty6g7KrHdLxYMzeqz24+w9hg712TcWdqzdY6sn+24lUoMD9jTZrZ/qfVpk0g=="], + + "@rolldown/binding-linux-arm-gnueabihf": ["@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.34", "", { "os": "linux", "cpu": "arm" }, "sha512-4St4emjcnULnxJYb/5ZDrH/kK/j6PcUgc3eAqH5STmTrcF+I9m/X2xvSF2a2bWv1DOQhxBewThu0KkwGHdgu5w=="], + + "@rolldown/binding-linux-arm64-gnu": ["@rolldown/binding-linux-arm64-gnu@1.0.0-beta.34", "", { "os": "linux", "cpu": "arm64" }, "sha512-a737FTqhFUoWfnebS2SnQ2BS50p0JdukdkUBwy2J06j4hZ6Eej0zEB8vTfAqoCjn8BQKkXBy+3Sx0IRkgwz1gA=="], + + "@rolldown/binding-linux-arm64-musl": ["@rolldown/binding-linux-arm64-musl@1.0.0-beta.34", "", { "os": "linux", "cpu": "arm64" }, "sha512-NH+FeQWKyuw0k+PbXqpFWNfvD8RPvfJk766B/njdaWz4TmiEcSB0Nb6guNw1rBpM1FmltQYb3fFnTumtC6pRfA=="], + + "@rolldown/binding-linux-x64-gnu": ["@rolldown/binding-linux-x64-gnu@1.0.0-beta.34", "", { "os": "linux", "cpu": "x64" }, "sha512-Q3RSCivp8pNadYK8ke3hLnQk08BkpZX9BmMjgwae2FWzdxhxxUiUzd9By7kneUL0vRQ4uRnhD9VkFQ+Haeqdvw=="], + + "@rolldown/binding-linux-x64-musl": ["@rolldown/binding-linux-x64-musl@1.0.0-beta.34", "", { "os": "linux", "cpu": "x64" }, "sha512-wDd/HrNcVoBhWWBUW3evJHoo7GJE/RofssBy3Dsiip05YUBmokQVrYAyrboOY4dzs/lJ7HYeBtWQ9hj8wlyF0A=="], + + "@rolldown/binding-openharmony-arm64": ["@rolldown/binding-openharmony-arm64@1.0.0-beta.34", "", { "os": "none", "cpu": "arm64" }, "sha512-dH3FTEV6KTNWpYSgjSXZzeX7vLty9oBYn6R3laEdhwZftQwq030LKL+5wyQdlbX5pnbh4h127hpv3Hl1+sj8dg=="], + + "@rolldown/binding-wasm32-wasi": ["@rolldown/binding-wasm32-wasi@1.0.0-beta.34", "", { "dependencies": { "@napi-rs/wasm-runtime": "^1.0.3" }, "cpu": "none" }, "sha512-y5BUf+QtO0JsIDKA51FcGwvhJmv89BYjUl8AmN7jqD6k/eU55mH6RJYnxwCsODq5m7KSSTigVb6O7/GqB8wbPw=="], + + "@rolldown/binding-win32-arm64-msvc": ["@rolldown/binding-win32-arm64-msvc@1.0.0-beta.34", "", { "os": "win32", "cpu": "arm64" }, "sha512-ga5hFhdTwpaNxEiuxZHWnD3ed0GBAzbgzS5tRHpe0ObptxM1a9Xrq6TVfNQirBLwb5Y7T/FJmJi3pmdLy95ljg=="], + + "@rolldown/binding-win32-ia32-msvc": ["@rolldown/binding-win32-ia32-msvc@1.0.0-beta.34", "", { "os": "win32", "cpu": "ia32" }, "sha512-4/MBp9T9eRnZskxWr8EXD/xHvLhdjWaeX/qY9LPRG1JdCGV3DphkLTy5AWwIQ5jhAy2ZNJR5z2fYRlpWU0sIyQ=="], + + "@rolldown/binding-win32-x64-msvc": ["@rolldown/binding-win32-x64-msvc@1.0.0-beta.34", "", { "os": "win32", "cpu": "x64" }, "sha512-7O5iUBX6HSBKlQU4WykpUoEmb0wQmonb6ziKFr3dJTHud2kzDnWMqk344T0qm3uGv9Ddq6Re/94pInxo1G2d4w=="], + + "@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-beta.34", "", {}, "sha512-LyAREkZHP5pMom7c24meKmJCdhf2hEyvam2q0unr3or9ydwDL+DJ8chTF6Av/RFPb3rH8UFBdMzO5MxTZW97oA=="], + + "@tybys/wasm-util": ["@tybys/wasm-util@0.10.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-VyyPYFlOMNylG45GoAe0xDoLwWuowvf92F9kySqzYh8vmYm7D2u4iUJKa1tOUpS70Ku13ASrOkS4ScXFsTaCNQ=="], + + "@types/node": ["@types/node@24.3.0", "", { "dependencies": { "undici-types": "~7.10.0" } }, "sha512-aPTXCrfwnDLj4VvXrm+UUCQjNEvJgNA8s5F1cvwQU+3KNltTOkBm1j30uNLyqqPNe7gE3KFzImYoZEfLhp4Yow=="], + + "accepts": ["accepts@2.0.0", "", { "dependencies": { "mime-types": "^3.0.0", "negotiator": "^1.0.0" } }, "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng=="], + + "ajv": ["ajv@6.12.6", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="], + + "ansis": ["ansis@4.1.0", "", {}, "sha512-BGcItUBWSMRgOCe+SVZJ+S7yTRG0eGt9cXAHev72yuGcY23hnLA7Bky5L/xLyPINoSN95geovfBkqoTlNZYa7w=="], + + "ast-kit": ["ast-kit@2.1.2", "", { "dependencies": { "@babel/parser": "^7.28.0", "pathe": "^2.0.3" } }, "sha512-cl76xfBQM6pztbrFWRnxbrDm9EOqDr1BF6+qQnnDZG2Co2LjyUktkN9GTJfBAfdae+DbT2nJf2nCGAdDDN7W2g=="], + + "asynckit": ["asynckit@0.4.0", "", {}, "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="], + + "axios": ["axios@1.12.2", "", { "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.4", "proxy-from-env": "^1.1.0" } }, "sha512-vMJzPewAlRyOgxV2dU0Cuz2O8zzzx9VYtbJOaBgXFeLc4IV/Eg50n4LowmehOOR61S8ZMpc2K5Sa7g6A4jfkUw=="], + + "birpc": ["birpc@2.5.0", "", {}, "sha512-VSWO/W6nNQdyP520F1mhf+Lc2f8pjGQOtoHHm7Ze8Go1kX7akpVIrtTa0fn+HB0QJEDVacl6aO08YE0PgXfdnQ=="], + + "body-parser": ["body-parser@2.2.0", "", { "dependencies": { "bytes": "^3.1.2", "content-type": "^1.0.5", "debug": "^4.4.0", "http-errors": "^2.0.0", "iconv-lite": "^0.6.3", "on-finished": "^2.4.1", "qs": "^6.14.0", "raw-body": "^3.0.0", "type-is": "^2.0.0" } }, "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg=="], + + "bytes": ["bytes@3.1.2", "", {}, "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="], + + "cac": ["cac@6.7.14", "", {}, "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ=="], + + "call-bind-apply-helpers": ["call-bind-apply-helpers@1.0.2", "", { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" } }, "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ=="], + + "call-bound": ["call-bound@1.0.4", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "get-intrinsic": "^1.3.0" } }, "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg=="], + + "chokidar": ["chokidar@4.0.3", "", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="], + + "combined-stream": ["combined-stream@1.0.8", "", { "dependencies": { "delayed-stream": "~1.0.0" } }, "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg=="], + + "content-disposition": ["content-disposition@1.0.0", "", { "dependencies": { "safe-buffer": "5.2.1" } }, "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg=="], + + "content-type": ["content-type@1.0.5", "", {}, "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA=="], + + "cookie": ["cookie@0.7.2", "", {}, "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w=="], + + "cookie-signature": ["cookie-signature@1.2.2", "", {}, "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg=="], + + "cors": ["cors@2.8.5", "", { "dependencies": { "object-assign": "^4", "vary": "^1" } }, "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g=="], + + "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], + + "debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], + + "defu": ["defu@6.1.4", "", {}, "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg=="], + + "delayed-stream": ["delayed-stream@1.0.0", "", {}, "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="], + + "depd": ["depd@2.0.0", "", {}, "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="], + + "diff": ["diff@8.0.2", "", {}, "sha512-sSuxWU5j5SR9QQji/o2qMvqRNYRDOcBTgsJ/DeCf4iSN4gW+gNMXM7wFIP+fdXZxoNiAnHUTGjCr+TSWXdRDKg=="], + + "dotenv": ["dotenv@16.6.1", "", {}, "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow=="], + + "dts-resolver": ["dts-resolver@2.1.2", "", { "peerDependencies": { "oxc-resolver": ">=11.0.0" }, "optionalPeers": ["oxc-resolver"] }, "sha512-xeXHBQkn2ISSXxbJWD828PFjtyg+/UrMDo7W4Ffcs7+YWCquxU8YjV1KoxuiL+eJ5pg3ll+bC6flVv61L3LKZg=="], + + "dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="], + + "ee-first": ["ee-first@1.1.1", "", {}, "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="], + + "empathic": ["empathic@2.0.0", "", {}, "sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA=="], + + "encodeurl": ["encodeurl@2.0.0", "", {}, "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg=="], + + "es-define-property": ["es-define-property@1.0.1", "", {}, "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="], + + "es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="], + + "es-object-atoms": ["es-object-atoms@1.1.1", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA=="], + + "es-set-tostringtag": ["es-set-tostringtag@2.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA=="], + + "escape-html": ["escape-html@1.0.3", "", {}, "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="], + + "etag": ["etag@1.8.1", "", {}, "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg=="], + + "eventsource": ["eventsource@3.0.7", "", { "dependencies": { "eventsource-parser": "^3.0.1" } }, "sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA=="], + + "eventsource-parser": ["eventsource-parser@3.0.5", "", {}, "sha512-bSRG85ZrMdmWtm7qkF9He9TNRzc/Bm99gEJMaQoHJ9E6Kv9QBbsldh2oMj7iXmYNEAVvNgvv5vPorG6W+XtBhQ=="], + + "express": ["express@5.1.0", "", { "dependencies": { "accepts": "^2.0.0", "body-parser": "^2.2.0", "content-disposition": "^1.0.0", "content-type": "^1.0.5", "cookie": "^0.7.1", "cookie-signature": "^1.2.1", "debug": "^4.4.0", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "etag": "^1.8.1", "finalhandler": "^2.1.0", "fresh": "^2.0.0", "http-errors": "^2.0.0", "merge-descriptors": "^2.0.0", "mime-types": "^3.0.0", "on-finished": "^2.4.1", "once": "^1.4.0", "parseurl": "^1.3.3", "proxy-addr": "^2.0.7", "qs": "^6.14.0", "range-parser": "^1.2.1", "router": "^2.2.0", "send": "^1.1.0", "serve-static": "^2.2.0", "statuses": "^2.0.1", "type-is": "^2.0.1", "vary": "^1.1.2" } }, "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA=="], + + "express-rate-limit": ["express-rate-limit@7.5.1", "", { "peerDependencies": { "express": ">= 4.11" } }, "sha512-7iN8iPMDzOMHPUYllBEsQdWVB6fPDMPqwjBaFrgr4Jgr/+okjvzAy+UHlYYL/Vs0OsOrMkwS6PJDkFlJwoxUnw=="], + + "fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="], + + "fast-json-stable-stringify": ["fast-json-stable-stringify@2.1.0", "", {}, "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="], + + "fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" } }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="], + + "finalhandler": ["finalhandler@2.1.0", "", { "dependencies": { "debug": "^4.4.0", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "on-finished": "^2.4.1", "parseurl": "^1.3.3", "statuses": "^2.0.1" } }, "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q=="], + + "follow-redirects": ["follow-redirects@1.15.11", "", {}, "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ=="], + + "form-data": ["form-data@4.0.4", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "hasown": "^2.0.2", "mime-types": "^2.1.12" } }, "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow=="], + + "forwarded": ["forwarded@0.2.0", "", {}, "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow=="], + + "fresh": ["fresh@2.0.0", "", {}, "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A=="], + + "function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="], + + "get-intrinsic": ["get-intrinsic@1.3.0", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "math-intrinsics": "^1.1.0" } }, "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ=="], + + "get-proto": ["get-proto@1.0.1", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" } }, "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g=="], + + "get-tsconfig": ["get-tsconfig@4.10.1", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ=="], + + "gopd": ["gopd@1.2.0", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="], + + "has-symbols": ["has-symbols@1.1.0", "", {}, "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ=="], + + "has-tostringtag": ["has-tostringtag@1.0.2", "", { "dependencies": { "has-symbols": "^1.0.3" } }, "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw=="], + + "hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="], + + "hookable": ["hookable@5.5.3", "", {}, "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ=="], + + "http-errors": ["http-errors@2.0.0", "", { "dependencies": { "depd": "2.0.0", "inherits": "2.0.4", "setprototypeof": "1.2.0", "statuses": "2.0.1", "toidentifier": "1.0.1" } }, "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ=="], + + "iconv-lite": ["iconv-lite@0.6.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="], + + "inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="], + + "ipaddr.js": ["ipaddr.js@1.9.1", "", {}, "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="], + + "is-promise": ["is-promise@4.0.0", "", {}, "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ=="], + + "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], + + "jiti": ["jiti@2.5.1", "", { "bin": "lib/jiti-cli.mjs" }, "sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w=="], + + "jsesc": ["jsesc@3.1.0", "", { "bin": "bin/jsesc" }, "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA=="], + + "json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="], + + "math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="], + + "media-typer": ["media-typer@1.1.0", "", {}, "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw=="], + + "merge-descriptors": ["merge-descriptors@2.0.0", "", {}, "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g=="], + + "mime-db": ["mime-db@1.54.0", "", {}, "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ=="], + + "mime-types": ["mime-types@3.0.1", "", { "dependencies": { "mime-db": "^1.54.0" } }, "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA=="], + + "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], + + "negotiator": ["negotiator@1.0.0", "", {}, "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg=="], + + "object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="], + + "object-inspect": ["object-inspect@1.13.4", "", {}, "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew=="], + + "on-finished": ["on-finished@2.4.1", "", { "dependencies": { "ee-first": "1.1.1" } }, "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg=="], + + "once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="], + + "parseurl": ["parseurl@1.3.3", "", {}, "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="], + + "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="], + + "path-to-regexp": ["path-to-regexp@8.2.0", "", {}, "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ=="], + + "pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], + + "picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="], + + "pkce-challenge": ["pkce-challenge@5.0.0", "", {}, "sha512-ueGLflrrnvwB3xuo/uGob5pd5FN7l0MsLf0Z87o/UQmRtwjvfylfc9MurIxRAWywCYTgrvpXBcqjV4OfCYGCIQ=="], + + "proxy-addr": ["proxy-addr@2.0.7", "", { "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" } }, "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg=="], + + "proxy-from-env": ["proxy-from-env@1.1.0", "", {}, "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="], + + "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="], + + "qs": ["qs@6.14.0", "", { "dependencies": { "side-channel": "^1.1.0" } }, "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w=="], + + "quansync": ["quansync@0.2.11", "", {}, "sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA=="], + + "range-parser": ["range-parser@1.2.1", "", {}, "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="], + + "raw-body": ["raw-body@3.0.0", "", { "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", "iconv-lite": "0.6.3", "unpipe": "1.0.0" } }, "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g=="], + + "readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="], + + "resolve-pkg-maps": ["resolve-pkg-maps@1.0.0", "", {}, "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw=="], + + "rolldown": ["rolldown@1.0.0-beta.34", "", { "dependencies": { "@oxc-project/runtime": "=0.82.3", "@oxc-project/types": "=0.82.3", "@rolldown/pluginutils": "1.0.0-beta.34", "ansis": "^4.0.0" }, "optionalDependencies": { "@rolldown/binding-android-arm64": "1.0.0-beta.34", "@rolldown/binding-darwin-arm64": "1.0.0-beta.34", "@rolldown/binding-darwin-x64": "1.0.0-beta.34", "@rolldown/binding-freebsd-x64": "1.0.0-beta.34", "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-beta.34", "@rolldown/binding-linux-arm64-gnu": "1.0.0-beta.34", "@rolldown/binding-linux-arm64-musl": "1.0.0-beta.34", "@rolldown/binding-linux-x64-gnu": "1.0.0-beta.34", "@rolldown/binding-linux-x64-musl": "1.0.0-beta.34", "@rolldown/binding-openharmony-arm64": "1.0.0-beta.34", "@rolldown/binding-wasm32-wasi": "1.0.0-beta.34", "@rolldown/binding-win32-arm64-msvc": "1.0.0-beta.34", "@rolldown/binding-win32-ia32-msvc": "1.0.0-beta.34", "@rolldown/binding-win32-x64-msvc": "1.0.0-beta.34" }, "bin": "bin/cli.mjs" }, "sha512-Wwh7EwalMzzX3Yy3VN58VEajeR2Si8+HDNMf706jPLIqU7CxneRW+dQVfznf5O0TWTnJyu4npelwg2bzTXB1Nw=="], + + "rolldown-plugin-dts": ["rolldown-plugin-dts@0.15.9", "", { "dependencies": { "@babel/generator": "^7.28.3", "@babel/parser": "^7.28.3", "@babel/types": "^7.28.2", "ast-kit": "^2.1.2", "birpc": "^2.5.0", "debug": "^4.4.1", "dts-resolver": "^2.1.2", "get-tsconfig": "^4.10.1" }, "peerDependencies": { "@typescript/native-preview": ">=7.0.0-dev.20250601.1", "rolldown": "^1.0.0-beta.9", "typescript": "^5.0.0", "vue-tsc": "~3.0.3" }, "optionalPeers": ["@typescript/native-preview", "vue-tsc"] }, "sha512-S2pPcC8h0C8a0ZLDdUTqqtTR9jlryThF3SmH8eZw97FQwgY+hd0x07Zm5algBkmj25S4nvvOusliR1YpImK3LA=="], + + "router": ["router@2.2.0", "", { "dependencies": { "debug": "^4.4.0", "depd": "^2.0.0", "is-promise": "^4.0.0", "parseurl": "^1.3.3", "path-to-regexp": "^8.0.0" } }, "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ=="], + + "safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="], + + "safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="], + + "semver": ["semver@7.7.2", "", { "bin": "bin/semver.js" }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="], + + "send": ["send@1.2.0", "", { "dependencies": { "debug": "^4.3.5", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "etag": "^1.8.1", "fresh": "^2.0.0", "http-errors": "^2.0.0", "mime-types": "^3.0.1", "ms": "^2.1.3", "on-finished": "^2.4.1", "range-parser": "^1.2.1", "statuses": "^2.0.1" } }, "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw=="], + + "serve-static": ["serve-static@2.2.0", "", { "dependencies": { "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "parseurl": "^1.3.3", "send": "^1.2.0" } }, "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ=="], + + "setprototypeof": ["setprototypeof@1.2.0", "", {}, "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="], + + "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="], + + "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="], + + "side-channel": ["side-channel@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3", "side-channel-list": "^1.0.0", "side-channel-map": "^1.0.1", "side-channel-weakmap": "^1.0.2" } }, "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw=="], + + "side-channel-list": ["side-channel-list@1.0.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3" } }, "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA=="], + + "side-channel-map": ["side-channel-map@1.0.1", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3" } }, "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA=="], + + "side-channel-weakmap": ["side-channel-weakmap@1.0.2", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3", "side-channel-map": "^1.0.1" } }, "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A=="], + + "statuses": ["statuses@2.0.2", "", {}, "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw=="], + + "tinyexec": ["tinyexec@1.0.1", "", {}, "sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw=="], + + "tinyglobby": ["tinyglobby@0.2.14", "", { "dependencies": { "fdir": "^6.4.4", "picomatch": "^4.0.2" } }, "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ=="], + + "toidentifier": ["toidentifier@1.0.1", "", {}, "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="], + + "tree-kill": ["tree-kill@1.2.2", "", { "bin": "cli.js" }, "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A=="], + + "tsdown": ["tsdown@0.13.5", "", { "dependencies": { "ansis": "^4.1.0", "cac": "^6.7.14", "chokidar": "^4.0.3", "debug": "^4.4.1", "diff": "^8.0.2", "empathic": "^2.0.0", "hookable": "^5.5.3", "rolldown": "latest", "rolldown-plugin-dts": "^0.15.6", "semver": "^7.7.2", "tinyexec": "^1.0.1", "tinyglobby": "^0.2.14", "tree-kill": "^1.2.2", "unconfig": "^7.3.2" }, "peerDependencies": { "@arethetypeswrong/core": "^0.18.1", "publint": "^0.3.0", "typescript": "^5.0.0", "unplugin-lightningcss": "^0.4.0", "unplugin-unused": "^0.5.0" }, "optionalPeers": ["@arethetypeswrong/core", "publint", "unplugin-lightningcss", "unplugin-unused"], "bin": "dist/run.mjs" }, "sha512-lagBtBSdm1yWBFvAbg3+a2/x7eRNqsf5fv34doXXOGnxRIBlfzYCEVfK6cwOgkTNhORMhdWvaqtXZV3h2x1ojQ=="], + + "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], + + "type-is": ["type-is@2.0.1", "", { "dependencies": { "content-type": "^1.0.5", "media-typer": "^1.1.0", "mime-types": "^3.0.0" } }, "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw=="], + + "typescript": ["typescript@5.9.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A=="], + + "unconfig": ["unconfig@7.3.3", "", { "dependencies": { "@quansync/fs": "^0.1.5", "defu": "^6.1.4", "jiti": "^2.5.1", "quansync": "^0.2.11" } }, "sha512-QCkQoOnJF8L107gxfHL0uavn7WD9b3dpBcFX6HtfQYmjw2YzWxGuFQ0N0J6tE9oguCBJn9KOvfqYDCMPHIZrBA=="], + + "undici-types": ["undici-types@7.10.0", "", {}, "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag=="], + + "unpipe": ["unpipe@1.0.0", "", {}, "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ=="], + + "uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="], + + "vary": ["vary@1.1.2", "", {}, "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="], + + "which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="], + + "wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="], + + "zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], + + "zod-to-json-schema": ["zod-to-json-schema@3.24.6", "", { "peerDependencies": { "zod": "^3.24.1" } }, "sha512-h/z3PKvcTcTetyjl1fkj79MHNEjm+HpD6NXheWjzOekY7kV+lwDYnHw+ivHkijnCSMz1yJaWBD9vu/Fcmk+vEg=="], + + "form-data/mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], + + "http-errors/statuses": ["statuses@2.0.1", "", {}, "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ=="], + + "form-data/mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], + } +} diff --git a/package.json b/package.json index 6756a41..5b709d9 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,7 @@ "description": "MCP сервер для автоматизации развертывания приложений в Timeweb Cloud", "scripts": { "build": "tsdown && chmod 755 dist/index.js", + "prepare": "npm run build", "start": "node -r dotenv/config dist/index.js", "inspect": "export DANGEROUSLY_OMIT_AUTH=true && npx @modelcontextprotocol/inspector npm run start", "clean": "rm -rf dist", diff --git a/src/actions/add-ai-agent-token-package.action.ts b/src/actions/add-ai-agent-token-package.action.ts new file mode 100644 index 0000000..1331719 --- /dev/null +++ b/src/actions/add-ai-agent-token-package.action.ts @@ -0,0 +1,8 @@ +import { aiAgentsApiClient } from "../api"; + +export const addAiAgentTokenPackageAction = async ( + agentId: number, + count?: number +): Promise => { + await aiAgentsApiClient.addAgentTokenPackage(agentId, { count }); +}; diff --git a/src/actions/add-balancer-ips.action.ts b/src/actions/add-balancer-ips.action.ts new file mode 100644 index 0000000..e3b2bec --- /dev/null +++ b/src/actions/add-balancer-ips.action.ts @@ -0,0 +1,8 @@ +import { balancersApiClient } from "../api"; + +export const addBalancerIpsAction = async ( + balancerId: number, + ips: string[] +): Promise => { + await balancersApiClient.addBalancerIps(balancerId, ips); +}; diff --git a/src/actions/add-balancer-to-project.action.ts b/src/actions/add-balancer-to-project.action.ts new file mode 100644 index 0000000..5fd2fa0 --- /dev/null +++ b/src/actions/add-balancer-to-project.action.ts @@ -0,0 +1,9 @@ +import { projectsApiClient } from "../api/projects"; +import { ProjectResource } from "../types/project.type"; + +export const addBalancerToProjectAction = async ( + projectId: number, + resourceId: number +): Promise => { + return await projectsApiClient.addBalancerToProject(projectId, resourceId); +}; diff --git a/src/actions/add-bucket-subdomain-certificate.action.ts b/src/actions/add-bucket-subdomain-certificate.action.ts new file mode 100644 index 0000000..1d1a46c --- /dev/null +++ b/src/actions/add-bucket-subdomain-certificate.action.ts @@ -0,0 +1,7 @@ +import { s3BucketsApiClient } from "../api"; + +export const addBucketSubdomainCertificateAction = async ( + subdomain: string +): Promise => { + await s3BucketsApiClient.addBucketSubdomainCertificate(subdomain); +}; diff --git a/src/actions/add-bucket-subdomains.action.ts b/src/actions/add-bucket-subdomains.action.ts new file mode 100644 index 0000000..0b88907 --- /dev/null +++ b/src/actions/add-bucket-subdomains.action.ts @@ -0,0 +1,9 @@ +import { s3BucketsApiClient } from "../api"; +import { AddedBucketSubdomain } from "../types/bucket-subdomain.type"; + +export const addBucketSubdomainsAction = async ( + bucketId: number, + subdomains: string[] +): Promise => { + return await s3BucketsApiClient.addBucketSubdomains(bucketId, subdomains); +}; diff --git a/src/actions/add-bucket-to-project.action.ts b/src/actions/add-bucket-to-project.action.ts new file mode 100644 index 0000000..b1a43f0 --- /dev/null +++ b/src/actions/add-bucket-to-project.action.ts @@ -0,0 +1,9 @@ +import { projectsApiClient } from "../api/projects"; +import { ProjectResource } from "../types/project.type"; + +export const addBucketToProjectAction = async ( + projectId: number, + resourceId: number +): Promise => { + return await projectsApiClient.addBucketToProject(projectId, resourceId); +}; diff --git a/src/actions/add-cluster-to-project.action.ts b/src/actions/add-cluster-to-project.action.ts new file mode 100644 index 0000000..9afa218 --- /dev/null +++ b/src/actions/add-cluster-to-project.action.ts @@ -0,0 +1,9 @@ +import { projectsApiClient } from "../api/projects"; +import { ProjectResource } from "../types/project.type"; + +export const addClusterToProjectAction = async ( + projectId: number, + resourceId: number +): Promise => { + return await projectsApiClient.addClusterToProject(projectId, resourceId); +}; diff --git a/src/actions/add-database-to-project.action.ts b/src/actions/add-database-to-project.action.ts new file mode 100644 index 0000000..758fab0 --- /dev/null +++ b/src/actions/add-database-to-project.action.ts @@ -0,0 +1,9 @@ +import { projectsApiClient } from "../api/projects"; +import { ProjectResource } from "../types/project.type"; + +export const addDatabaseToProjectAction = async ( + projectId: number, + resourceId: number +): Promise => { + return await projectsApiClient.addDatabaseToProject(projectId, resourceId); +}; diff --git a/src/actions/add-dedicated-to-project.action.ts b/src/actions/add-dedicated-to-project.action.ts new file mode 100644 index 0000000..422a372 --- /dev/null +++ b/src/actions/add-dedicated-to-project.action.ts @@ -0,0 +1,9 @@ +import { projectsApiClient } from "../api/projects"; +import { ProjectResource } from "../types/project.type"; + +export const addDedicatedToProjectAction = async ( + projectId: number, + resourceId: number +): Promise => { + return await projectsApiClient.addDedicatedToProject(projectId, resourceId); +}; diff --git a/src/actions/add-domain.action.ts b/src/actions/add-domain.action.ts new file mode 100644 index 0000000..9777952 --- /dev/null +++ b/src/actions/add-domain.action.ts @@ -0,0 +1,5 @@ +import { domainsApiClient } from "../api"; + +export const addDomainAction = async (fqdn: string): Promise => { + await domainsApiClient.addDomain(fqdn); +}; diff --git a/src/actions/add-knowledge-base-token-package.action.ts b/src/actions/add-knowledge-base-token-package.action.ts new file mode 100644 index 0000000..f39a596 --- /dev/null +++ b/src/actions/add-knowledge-base-token-package.action.ts @@ -0,0 +1,8 @@ +import { knowledgeBasesApiClient } from "../api"; + +export const addKnowledgeBaseTokenPackageAction = async ( + id: number, + count?: number +): Promise => { + await knowledgeBasesApiClient.addKnowledgeBaseTokenPackage(id, { count }); +}; diff --git a/src/actions/add-server-ip.action.ts b/src/actions/add-server-ip.action.ts new file mode 100644 index 0000000..a50f5ad --- /dev/null +++ b/src/actions/add-server-ip.action.ts @@ -0,0 +1,9 @@ +import { serversApiClient, AddServerIpParams } from "../api/servers"; +import { ServerIp } from "../types/server-ip.type"; + +export const addServerIpAction = async ( + serverId: number, + params: AddServerIpParams +): Promise => { + return await serversApiClient.addServerIp(serverId, params); +}; diff --git a/src/actions/add-server-to-project.action.ts b/src/actions/add-server-to-project.action.ts new file mode 100644 index 0000000..352732c --- /dev/null +++ b/src/actions/add-server-to-project.action.ts @@ -0,0 +1,9 @@ +import { projectsApiClient } from "../api/projects"; +import { ProjectResource } from "../types/project.type"; + +export const addServerToProjectAction = async ( + projectId: number, + resourceId: number +): Promise => { + return await projectsApiClient.addServerToProject(projectId, resourceId); +}; diff --git a/src/actions/add-ssh-keys-to-server.action.ts b/src/actions/add-ssh-keys-to-server.action.ts new file mode 100644 index 0000000..eaf6abe --- /dev/null +++ b/src/actions/add-ssh-keys-to-server.action.ts @@ -0,0 +1,8 @@ +import { sshKeysApiClient } from "../api"; + +export const addSshKeysToServerAction = async ( + serverId: number, + sshKeyIds: number[] +): Promise => { + await sshKeysApiClient.addSshKeysToServer(serverId, sshKeyIds); +}; diff --git a/src/actions/add-subdomain.action.ts b/src/actions/add-subdomain.action.ts new file mode 100644 index 0000000..5f51d08 --- /dev/null +++ b/src/actions/add-subdomain.action.ts @@ -0,0 +1,9 @@ +import { domainsApiClient } from "../api"; +import { DomainSubdomain } from "../types/domain.type"; + +export const addSubdomainAction = async ( + fqdn: string, + subdomainFqdn: string +): Promise => { + return await domainsApiClient.addSubdomain(fqdn, subdomainFqdn); +}; diff --git a/src/actions/batch-create-mailboxes-v1.action.ts b/src/actions/batch-create-mailboxes-v1.action.ts new file mode 100644 index 0000000..cc6e6f4 --- /dev/null +++ b/src/actions/batch-create-mailboxes-v1.action.ts @@ -0,0 +1,10 @@ +import { mailApiClient } from "../api"; +import { Mailbox } from "../types/mailbox.type"; +import { BatchCreateMailboxesV1RequestDto } from "../types/dto/batch-create-mailboxes-request.dto"; + +export const batchCreateMailboxesV1Action = async ( + domain: string, + data: BatchCreateMailboxesV1RequestDto +): Promise => { + return await mailApiClient.batchCreateMailboxesV1(domain, data); +}; diff --git a/src/actions/batch-create-mailboxes.action.ts b/src/actions/batch-create-mailboxes.action.ts new file mode 100644 index 0000000..c4e834a --- /dev/null +++ b/src/actions/batch-create-mailboxes.action.ts @@ -0,0 +1,10 @@ +import { mailApiClient } from "../api"; +import { MailboxesBatchV2 } from "../types/mailbox.type"; +import { BatchCreateMailboxesV2RequestDto } from "../types/dto/batch-create-mailboxes-request.dto"; + +export const batchCreateMailboxesAction = async ( + domain: string, + data: BatchCreateMailboxesV2RequestDto +): Promise => { + return await mailApiClient.batchCreateMailboxesV2(domain, data); +}; diff --git a/src/actions/bind-floating-ip.action.ts b/src/actions/bind-floating-ip.action.ts new file mode 100644 index 0000000..10c08b6 --- /dev/null +++ b/src/actions/bind-floating-ip.action.ts @@ -0,0 +1,9 @@ +import { dbaasApiClient } from "../api"; +import { BindFloatingIpRequestDto } from "../types/dto/bind-floating-ip-request.dto"; + +export const bindFloatingIpAction = async ( + floatingIpId: string, + data: BindFloatingIpRequestDto +): Promise => { + await dbaasApiClient.bindFloatingIp(floatingIpId, data); +}; diff --git a/src/actions/check-domain.action.ts b/src/actions/check-domain.action.ts new file mode 100644 index 0000000..957ce93 --- /dev/null +++ b/src/actions/check-domain.action.ts @@ -0,0 +1,5 @@ +import { domainsApiClient } from "../api"; + +export const checkDomainAction = async (fqdn: string): Promise => { + return await domainsApiClient.checkDomain(fqdn); +}; diff --git a/src/actions/clone-server.action.ts b/src/actions/clone-server.action.ts new file mode 100644 index 0000000..6304fba --- /dev/null +++ b/src/actions/clone-server.action.ts @@ -0,0 +1,6 @@ +import { serversApiClient } from "../api"; +import { Server } from "../types/server.type"; + +export const cloneServerAction = async (serverId: number): Promise => { + return await serversApiClient.cloneServer(serverId); +}; diff --git a/src/actions/create-ai-agent.action.ts b/src/actions/create-ai-agent.action.ts new file mode 100644 index 0000000..0063f48 --- /dev/null +++ b/src/actions/create-ai-agent.action.ts @@ -0,0 +1,9 @@ +import { aiAgentsApiClient } from "../api"; +import { AiAgent } from "../types/ai-agent.type"; +import { CreateAiAgentRequestDto } from "../types/dto/create-ai-agent-request.dto"; + +export const createAiAgentAction = async ( + data: CreateAiAgentRequestDto +): Promise => { + return await aiAgentsApiClient.createAgent(data); +}; diff --git a/src/actions/create-api-key.action.ts b/src/actions/create-api-key.action.ts new file mode 100644 index 0000000..087eb07 --- /dev/null +++ b/src/actions/create-api-key.action.ts @@ -0,0 +1,9 @@ +import { authApiClient } from "../api"; +import { CreatedApiKey } from "../types/api-key.type"; +import { CreateApiKeyRequestDto } from "../types/dto/create-api-key-request.dto"; + +export const createApiKeyAction = async ( + data: CreateApiKeyRequestDto +): Promise => { + return await authApiClient.createApiKey(data); +}; diff --git a/src/actions/create-balancer-rule.action.ts b/src/actions/create-balancer-rule.action.ts new file mode 100644 index 0000000..120d8ae --- /dev/null +++ b/src/actions/create-balancer-rule.action.ts @@ -0,0 +1,10 @@ +import { balancersApiClient } from "../api"; +import { BalancerRule } from "../types/balancer.type"; +import { CreateBalancerRuleRequestDto } from "../types/dto/create-balancer-rule-request.dto"; + +export const createBalancerRuleAction = async ( + balancerId: number, + data: CreateBalancerRuleRequestDto +): Promise => { + return await balancersApiClient.createBalancerRule(balancerId, data); +}; diff --git a/src/actions/create-balancer.action.ts b/src/actions/create-balancer.action.ts new file mode 100644 index 0000000..873966d --- /dev/null +++ b/src/actions/create-balancer.action.ts @@ -0,0 +1,9 @@ +import { balancersApiClient } from "../api"; +import { Balancer } from "../types/balancer.type"; +import { CreateBalancerRequestDto } from "../types/dto/create-balancer-request.dto"; + +export const createBalancerAction = async ( + data: CreateBalancerRequestDto +): Promise => { + return await balancersApiClient.createBalancer(data); +}; diff --git a/src/actions/create-bucket.action.ts b/src/actions/create-bucket.action.ts new file mode 100644 index 0000000..adda7ce --- /dev/null +++ b/src/actions/create-bucket.action.ts @@ -0,0 +1,9 @@ +import { s3BucketsApiClient } from "../api"; +import { Bucket } from "../types/bucket.type"; +import { CreateBucketRequestDto } from "../types/dto/create-bucket-request.dto"; + +export const createBucketAction = async ( + data: CreateBucketRequestDto +): Promise => { + return await s3BucketsApiClient.createBucket(data); +}; diff --git a/src/actions/create-container-registry.action.ts b/src/actions/create-container-registry.action.ts new file mode 100644 index 0000000..b8aafa8 --- /dev/null +++ b/src/actions/create-container-registry.action.ts @@ -0,0 +1,9 @@ +import { containerRegistryApiClient } from "../api"; +import { ContainerRegistry } from "../types/container-registry.type"; +import { CreateContainerRegistryRequestDto } from "../types/dto/create-container-registry-request.dto"; + +export const createContainerRegistryAction = async ( + data: CreateContainerRegistryRequestDto +): Promise => { + return await containerRegistryApiClient.createContainerRegistry(data); +}; diff --git a/src/actions/create-database-admin.action.ts b/src/actions/create-database-admin.action.ts new file mode 100644 index 0000000..c078148 --- /dev/null +++ b/src/actions/create-database-admin.action.ts @@ -0,0 +1,10 @@ +import { dbaasApiClient } from "../api"; +import { DatabaseAdminEntity } from "../types/database-cluster.type"; +import { CreateDatabaseAdminRequestDto } from "../types/dto/create-database-admin-request.dto"; + +export const createDatabaseAdminAction = async ( + clusterId: number, + data: CreateDatabaseAdminRequestDto +): Promise => { + return await dbaasApiClient.createDatabaseAdmin(clusterId, data); +}; diff --git a/src/actions/create-database-backup.action.ts b/src/actions/create-database-backup.action.ts new file mode 100644 index 0000000..ff8bc27 --- /dev/null +++ b/src/actions/create-database-backup.action.ts @@ -0,0 +1,9 @@ +import { dbaasApiClient } from "../api"; +import { DatabaseBackup } from "../types/database-cluster.type"; + +export const createDatabaseBackupAction = async ( + dbId: number, + comment?: string +): Promise => { + return await dbaasApiClient.createDatabaseBackup(dbId, comment); +}; diff --git a/src/actions/create-database-instance.action.ts b/src/actions/create-database-instance.action.ts new file mode 100644 index 0000000..c1ee3ef --- /dev/null +++ b/src/actions/create-database-instance.action.ts @@ -0,0 +1,10 @@ +import { dbaasApiClient } from "../api"; +import { DatabaseInstanceEntity } from "../types/database-cluster.type"; +import { CreateDatabaseInstanceRequestDto } from "../types/dto/create-database-instance-request.dto"; + +export const createDatabaseInstanceAction = async ( + clusterId: number, + data: CreateDatabaseInstanceRequestDto +): Promise => { + return await dbaasApiClient.createDatabaseInstance(clusterId, data); +}; diff --git a/src/actions/create-dedicated-server.action.ts b/src/actions/create-dedicated-server.action.ts new file mode 100644 index 0000000..b75f003 --- /dev/null +++ b/src/actions/create-dedicated-server.action.ts @@ -0,0 +1,9 @@ +import { dedicatedServersApiClient } from "../api"; +import { DedicatedServer } from "../types/dedicated-server.type"; +import { CreateDedicatedServerRequestDto } from "../types/dto/create-dedicated-server-request.dto"; + +export const createDedicatedServerAction = async ( + data: CreateDedicatedServerRequestDto +): Promise => { + return await dedicatedServersApiClient.createDedicatedServer(data); +}; diff --git a/src/actions/create-dns-record.action.ts b/src/actions/create-dns-record.action.ts new file mode 100644 index 0000000..6a59361 --- /dev/null +++ b/src/actions/create-dns-record.action.ts @@ -0,0 +1,10 @@ +import { domainsApiClient } from "../api"; +import { DnsRecordV2 } from "../types/dns-record.type"; +import { CreateDnsRecordV2RequestDto } from "../types/dto/create-dns-record-request.dto"; + +export const createDnsRecordAction = async ( + fqdn: string, + data: CreateDnsRecordV2RequestDto +): Promise => { + return await domainsApiClient.createDnsRecord(fqdn, data); +}; diff --git a/src/actions/create-firewall-group.action.ts b/src/actions/create-firewall-group.action.ts new file mode 100644 index 0000000..21b0ee4 --- /dev/null +++ b/src/actions/create-firewall-group.action.ts @@ -0,0 +1,16 @@ +import { firewallApiClient } from "../api"; +import { + FirewallGroup, + FirewallPolicy, +} from "../types/firewall-group.type"; + +export const createFirewallGroupAction = async ( + name: string, + description?: string, + policy?: FirewallPolicy +): Promise => { + return await firewallApiClient.createFirewallGroup( + { name, description }, + policy + ); +}; diff --git a/src/actions/create-firewall-rule.action.ts b/src/actions/create-firewall-rule.action.ts new file mode 100644 index 0000000..72d2360 --- /dev/null +++ b/src/actions/create-firewall-rule.action.ts @@ -0,0 +1,10 @@ +import { firewallApiClient } from "../api"; +import { CreateFirewallRuleRequestDto } from "../types/dto/create-firewall-rule-request.dto"; +import { FirewallRule } from "../types/firewall-rule.type"; + +export const createFirewallRuleAction = async ( + groupId: string, + data: CreateFirewallRuleRequestDto +): Promise => { + return await firewallApiClient.createFirewallRule(groupId, data); +}; diff --git a/src/actions/create-image-download.action.ts b/src/actions/create-image-download.action.ts new file mode 100644 index 0000000..8dc102c --- /dev/null +++ b/src/actions/create-image-download.action.ts @@ -0,0 +1,10 @@ +import { imagesApiClient } from "../api"; +import { ImageDownload } from "../types/image-download.type"; +import { CreateImageDownloadRequestDto } from "../types/dto/create-image-download-request.dto"; + +export const createImageDownloadAction = async ( + imageId: string, + data: CreateImageDownloadRequestDto +): Promise => { + return await imagesApiClient.createImageDownload(imageId, data); +}; diff --git a/src/actions/create-image.action.ts b/src/actions/create-image.action.ts new file mode 100644 index 0000000..18a9444 --- /dev/null +++ b/src/actions/create-image.action.ts @@ -0,0 +1,9 @@ +import { imagesApiClient } from "../api"; +import { Image } from "../types/image.type"; +import { CreateImageRequestDto } from "../types/dto/create-image-request.dto"; + +export const createImageAction = async ( + data: CreateImageRequestDto +): Promise => { + return await imagesApiClient.createImage(data); +}; diff --git a/src/actions/create-k8s-cluster.action.ts b/src/actions/create-k8s-cluster.action.ts new file mode 100644 index 0000000..6f70adf --- /dev/null +++ b/src/actions/create-k8s-cluster.action.ts @@ -0,0 +1,9 @@ +import { kubernetesApiClient } from "../api"; +import { CreateK8sClusterRequestDto } from "../types/dto/create-k8s-cluster-request.dto"; +import { K8sCluster } from "../types/k8s-cluster.type"; + +export const createK8sClusterAction = async ( + data: CreateK8sClusterRequestDto +): Promise => { + return await kubernetesApiClient.createCluster(data); +}; diff --git a/src/actions/create-k8s-node-group.action.ts b/src/actions/create-k8s-node-group.action.ts new file mode 100644 index 0000000..a08126c --- /dev/null +++ b/src/actions/create-k8s-node-group.action.ts @@ -0,0 +1,10 @@ +import { kubernetesApiClient } from "../api"; +import { CreateK8sNodeGroupRequestDto } from "../types/dto/create-k8s-node-group-request.dto"; +import { K8sNodeGroup } from "../types/k8s-node-group.type"; + +export const createK8sNodeGroupAction = async ( + clusterId: number, + data: CreateK8sNodeGroupRequestDto +): Promise => { + return await kubernetesApiClient.createNodeGroup(clusterId, data); +}; diff --git a/src/actions/create-knowledge-base.action.ts b/src/actions/create-knowledge-base.action.ts new file mode 100644 index 0000000..d6f94d0 --- /dev/null +++ b/src/actions/create-knowledge-base.action.ts @@ -0,0 +1,9 @@ +import { knowledgeBasesApiClient } from "../api"; +import { KnowledgeBase } from "../types/knowledge-base.type"; +import { CreateKnowledgeBaseRequestDto } from "../types/dto/create-knowledge-base-request.dto"; + +export const createKnowledgeBaseAction = async ( + data: CreateKnowledgeBaseRequestDto +): Promise => { + return await knowledgeBasesApiClient.createKnowledgeBase(data); +}; diff --git a/src/actions/create-mailbox-v1.action.ts b/src/actions/create-mailbox-v1.action.ts new file mode 100644 index 0000000..615b4f8 --- /dev/null +++ b/src/actions/create-mailbox-v1.action.ts @@ -0,0 +1,10 @@ +import { mailApiClient } from "../api"; +import { Mailbox } from "../types/mailbox.type"; +import { CreateMailboxV1RequestDto } from "../types/dto/create-mailbox-request.dto"; + +export const createMailboxV1Action = async ( + domain: string, + data: CreateMailboxV1RequestDto +): Promise => { + return await mailApiClient.createMailboxV1(domain, data); +}; diff --git a/src/actions/create-mailbox.action.ts b/src/actions/create-mailbox.action.ts new file mode 100644 index 0000000..e7b2095 --- /dev/null +++ b/src/actions/create-mailbox.action.ts @@ -0,0 +1,10 @@ +import { mailApiClient } from "../api"; +import { MailboxV2 } from "../types/mailbox.type"; +import { CreateMailboxV2RequestDto } from "../types/dto/create-mailbox-request.dto"; + +export const createMailboxAction = async ( + domain: string, + data: CreateMailboxV2RequestDto +): Promise => { + return await mailApiClient.createMailboxV2(domain, data); +}; diff --git a/src/actions/create-network-drive.action.ts b/src/actions/create-network-drive.action.ts new file mode 100644 index 0000000..dcc649b --- /dev/null +++ b/src/actions/create-network-drive.action.ts @@ -0,0 +1,9 @@ +import { networkDrivesApiClient } from "../api/network-drives"; +import { NetworkDrive } from "../types/network-drive.type"; +import { CreateNetworkDriveRequestDto } from "../types/dto/create-network-drive-request.dto"; + +export const createNetworkDriveAction = async ( + data: CreateNetworkDriveRequestDto +): Promise => { + return await networkDrivesApiClient.createNetworkDrive(data); +}; diff --git a/src/actions/create-project.action.ts b/src/actions/create-project.action.ts new file mode 100644 index 0000000..dd72676 --- /dev/null +++ b/src/actions/create-project.action.ts @@ -0,0 +1,9 @@ +import { projectsApiClient } from "../api/projects"; +import { Project } from "../types/project.type"; +import { CreateProjectRequestDto } from "../types/dto/create-project-request.dto"; + +export const createProjectAction = async ( + data: CreateProjectRequestDto +): Promise => { + return await projectsApiClient.createProject(data); +}; diff --git a/src/actions/create-server-disk-backup.action.ts b/src/actions/create-server-disk-backup.action.ts new file mode 100644 index 0000000..3c6bfb0 --- /dev/null +++ b/src/actions/create-server-disk-backup.action.ts @@ -0,0 +1,14 @@ +import { serversApiClient } from "../api"; +import { ServerBackup } from "../types/server-backup.type"; + +export const createServerDiskBackupAction = async ( + serverId: number, + diskId: number, + comment?: string +): Promise => { + return await serversApiClient.createServerDiskBackup( + serverId, + diskId, + comment + ); +}; diff --git a/src/actions/create-server-disk.action.ts b/src/actions/create-server-disk.action.ts new file mode 100644 index 0000000..c23c52e --- /dev/null +++ b/src/actions/create-server-disk.action.ts @@ -0,0 +1,9 @@ +import { serversApiClient } from "../api"; +import { ServerDisk } from "../types/server-disk.type"; + +export const createServerDiskAction = async ( + serverId: number, + size: number +): Promise => { + return await serversApiClient.createServerDisk(serverId, size); +}; diff --git a/src/actions/create-server.action.ts b/src/actions/create-server.action.ts new file mode 100644 index 0000000..19c0d5d --- /dev/null +++ b/src/actions/create-server.action.ts @@ -0,0 +1,9 @@ +import { serversApiClient } from "../api"; +import { CreateServerRequestDto } from "../types/dto/create-server-request.dto"; +import { Server } from "../types/server.type"; + +export const createServerAction = async ( + data: CreateServerRequestDto +): Promise => { + return await serversApiClient.createServer(data); +}; diff --git a/src/actions/create-ssh-key.action.ts b/src/actions/create-ssh-key.action.ts new file mode 100644 index 0000000..67d792f --- /dev/null +++ b/src/actions/create-ssh-key.action.ts @@ -0,0 +1,14 @@ +import { sshKeysApiClient } from "../api"; +import { SshKey } from "../types/ssh-key.type"; + +export const createSshKeyAction = async ( + name: string, + body: string, + isDefault: boolean +): Promise => { + return await sshKeysApiClient.createSshKey({ + name, + body, + is_default: isDefault, + }); +}; diff --git a/src/actions/delete-ai-agent.action.ts b/src/actions/delete-ai-agent.action.ts new file mode 100644 index 0000000..f4d1db5 --- /dev/null +++ b/src/actions/delete-ai-agent.action.ts @@ -0,0 +1,5 @@ +import { aiAgentsApiClient } from "../api"; + +export const deleteAiAgentAction = async (agentId: number): Promise => { + await aiAgentsApiClient.deleteAgent(agentId); +}; diff --git a/src/actions/delete-api-key.action.ts b/src/actions/delete-api-key.action.ts new file mode 100644 index 0000000..7b9c89b --- /dev/null +++ b/src/actions/delete-api-key.action.ts @@ -0,0 +1,5 @@ +import { authApiClient } from "../api"; + +export const deleteApiKeyAction = async (tokenId: string): Promise => { + await authApiClient.deleteApiKey(tokenId); +}; diff --git a/src/actions/delete-balancer-rule.action.ts b/src/actions/delete-balancer-rule.action.ts new file mode 100644 index 0000000..0d1004c --- /dev/null +++ b/src/actions/delete-balancer-rule.action.ts @@ -0,0 +1,8 @@ +import { balancersApiClient } from "../api"; + +export const deleteBalancerRuleAction = async ( + balancerId: number, + ruleId: number +): Promise => { + await balancersApiClient.deleteBalancerRule(balancerId, ruleId); +}; diff --git a/src/actions/delete-balancer.action.ts b/src/actions/delete-balancer.action.ts new file mode 100644 index 0000000..22729d8 --- /dev/null +++ b/src/actions/delete-balancer.action.ts @@ -0,0 +1,10 @@ +import { balancersApiClient } from "../api"; +import { DeleteBalancerResult } from "../types/balancer.type"; + +export const deleteBalancerAction = async ( + balancerId: number, + hash?: string, + code?: string +): Promise => { + return await balancersApiClient.deleteBalancer(balancerId, hash, code); +}; diff --git a/src/actions/delete-bucket-subdomains.action.ts b/src/actions/delete-bucket-subdomains.action.ts new file mode 100644 index 0000000..fc2cb36 --- /dev/null +++ b/src/actions/delete-bucket-subdomains.action.ts @@ -0,0 +1,9 @@ +import { s3BucketsApiClient } from "../api"; +import { AddedBucketSubdomain } from "../types/bucket-subdomain.type"; + +export const deleteBucketSubdomainsAction = async ( + bucketId: number, + subdomains: string[] +): Promise => { + return await s3BucketsApiClient.deleteBucketSubdomains(bucketId, subdomains); +}; diff --git a/src/actions/delete-bucket.action.ts b/src/actions/delete-bucket.action.ts new file mode 100644 index 0000000..f77565f --- /dev/null +++ b/src/actions/delete-bucket.action.ts @@ -0,0 +1,10 @@ +import { s3BucketsApiClient } from "../api"; +import { BucketDeleteResponse } from "../types/bucket-delete-response.type"; + +export const deleteBucketAction = async ( + bucketId: number, + hash?: string, + code?: string +): Promise => { + return await s3BucketsApiClient.deleteBucket(bucketId, hash, code); +}; diff --git a/src/actions/delete-container-registry.action.ts b/src/actions/delete-container-registry.action.ts new file mode 100644 index 0000000..167cff3 --- /dev/null +++ b/src/actions/delete-container-registry.action.ts @@ -0,0 +1,7 @@ +import { containerRegistryApiClient } from "../api"; + +export const deleteContainerRegistryAction = async ( + registryId: number +): Promise => { + await containerRegistryApiClient.deleteContainerRegistry(registryId); +}; diff --git a/src/actions/delete-database-admin.action.ts b/src/actions/delete-database-admin.action.ts new file mode 100644 index 0000000..d859bd4 --- /dev/null +++ b/src/actions/delete-database-admin.action.ts @@ -0,0 +1,8 @@ +import { dbaasApiClient } from "../api"; + +export const deleteDatabaseAdminAction = async ( + clusterId: number, + adminId: number +): Promise => { + await dbaasApiClient.deleteDatabaseAdmin(clusterId, adminId); +}; diff --git a/src/actions/delete-database-backup.action.ts b/src/actions/delete-database-backup.action.ts new file mode 100644 index 0000000..39e1276 --- /dev/null +++ b/src/actions/delete-database-backup.action.ts @@ -0,0 +1,8 @@ +import { dbaasApiClient } from "../api"; + +export const deleteDatabaseBackupAction = async ( + dbId: number, + backupId: number +): Promise => { + await dbaasApiClient.deleteDatabaseBackup(dbId, backupId); +}; diff --git a/src/actions/delete-database-cluster.action.ts b/src/actions/delete-database-cluster.action.ts new file mode 100644 index 0000000..18ccbb0 --- /dev/null +++ b/src/actions/delete-database-cluster.action.ts @@ -0,0 +1,10 @@ +import { dbaasApiClient } from "../api"; +import { DeleteDatabaseClusterResponseDto } from "../types/dto/delete-database-response.dto"; + +export const deleteDatabaseClusterAction = async ( + clusterId: number, + hash?: string, + code?: string +): Promise => { + return await dbaasApiClient.deleteDatabaseCluster(clusterId, hash, code); +}; diff --git a/src/actions/delete-database-instance.action.ts b/src/actions/delete-database-instance.action.ts new file mode 100644 index 0000000..2e7d55f --- /dev/null +++ b/src/actions/delete-database-instance.action.ts @@ -0,0 +1,8 @@ +import { dbaasApiClient } from "../api"; + +export const deleteDatabaseInstanceAction = async ( + clusterId: number, + instanceId: number +): Promise => { + await dbaasApiClient.deleteDatabaseInstance(clusterId, instanceId); +}; diff --git a/src/actions/delete-database.action.ts b/src/actions/delete-database.action.ts new file mode 100644 index 0000000..d1107ea --- /dev/null +++ b/src/actions/delete-database.action.ts @@ -0,0 +1,10 @@ +import { dbaasApiClient } from "../api"; +import { DeleteDatabaseResponseDto } from "../types/dto/delete-database-response.dto"; + +export const deleteDatabaseAction = async ( + dbId: number, + hash?: string, + code?: string +): Promise => { + return await dbaasApiClient.deleteDatabase(dbId, hash, code); +}; diff --git a/src/actions/delete-dedicated-server.action.ts b/src/actions/delete-dedicated-server.action.ts new file mode 100644 index 0000000..b5b6270 --- /dev/null +++ b/src/actions/delete-dedicated-server.action.ts @@ -0,0 +1,7 @@ +import { dedicatedServersApiClient } from "../api"; + +export const deleteDedicatedServerAction = async ( + dedicatedId: number +): Promise => { + await dedicatedServersApiClient.deleteDedicatedServer(dedicatedId); +}; diff --git a/src/actions/delete-dns-record.action.ts b/src/actions/delete-dns-record.action.ts new file mode 100644 index 0000000..58576bc --- /dev/null +++ b/src/actions/delete-dns-record.action.ts @@ -0,0 +1,8 @@ +import { domainsApiClient } from "../api"; + +export const deleteDnsRecordAction = async ( + fqdn: string, + recordId: number +): Promise => { + await domainsApiClient.deleteDnsRecord(fqdn, recordId); +}; diff --git a/src/actions/delete-domain.action.ts b/src/actions/delete-domain.action.ts new file mode 100644 index 0000000..f611d24 --- /dev/null +++ b/src/actions/delete-domain.action.ts @@ -0,0 +1,5 @@ +import { domainsApiClient } from "../api"; + +export const deleteDomainAction = async (fqdn: string): Promise => { + await domainsApiClient.deleteDomain(fqdn); +}; diff --git a/src/actions/delete-firewall-group.action.ts b/src/actions/delete-firewall-group.action.ts new file mode 100644 index 0000000..b9d375c --- /dev/null +++ b/src/actions/delete-firewall-group.action.ts @@ -0,0 +1,7 @@ +import { firewallApiClient } from "../api"; + +export const deleteFirewallGroupAction = async ( + groupId: string +): Promise => { + await firewallApiClient.deleteFirewallGroup(groupId); +}; diff --git a/src/actions/delete-firewall-rule.action.ts b/src/actions/delete-firewall-rule.action.ts new file mode 100644 index 0000000..0d3758d --- /dev/null +++ b/src/actions/delete-firewall-rule.action.ts @@ -0,0 +1,8 @@ +import { firewallApiClient } from "../api"; + +export const deleteFirewallRuleAction = async ( + groupId: string, + ruleId: string +): Promise => { + await firewallApiClient.deleteFirewallRule(groupId, ruleId); +}; diff --git a/src/actions/delete-floating-ip.action.ts b/src/actions/delete-floating-ip.action.ts new file mode 100644 index 0000000..2588b54 --- /dev/null +++ b/src/actions/delete-floating-ip.action.ts @@ -0,0 +1,7 @@ +import { dbaasApiClient } from "../api"; + +export const deleteFloatingIpAction = async ( + floatingIpId: string +): Promise => { + await dbaasApiClient.deleteFloatingIp(floatingIpId); +}; diff --git a/src/actions/delete-image-download.action.ts b/src/actions/delete-image-download.action.ts new file mode 100644 index 0000000..0475435 --- /dev/null +++ b/src/actions/delete-image-download.action.ts @@ -0,0 +1,8 @@ +import { imagesApiClient } from "../api"; + +export const deleteImageDownloadAction = async ( + imageId: string, + imageUrlId: string +): Promise => { + return await imagesApiClient.deleteImageDownload(imageId, imageUrlId); +}; diff --git a/src/actions/delete-image.action.ts b/src/actions/delete-image.action.ts new file mode 100644 index 0000000..e15f09e --- /dev/null +++ b/src/actions/delete-image.action.ts @@ -0,0 +1,5 @@ +import { imagesApiClient } from "../api"; + +export const deleteImageAction = async (imageId: string): Promise => { + return await imagesApiClient.deleteImage(imageId); +}; diff --git a/src/actions/delete-k8s-cluster-node.action.ts b/src/actions/delete-k8s-cluster-node.action.ts new file mode 100644 index 0000000..b196f4f --- /dev/null +++ b/src/actions/delete-k8s-cluster-node.action.ts @@ -0,0 +1,8 @@ +import { kubernetesApiClient } from "../api"; + +export const deleteK8sClusterNodeAction = async ( + clusterId: number, + nodeId: number +): Promise => { + await kubernetesApiClient.deleteClusterNode(clusterId, nodeId); +}; diff --git a/src/actions/delete-k8s-cluster.action.ts b/src/actions/delete-k8s-cluster.action.ts new file mode 100644 index 0000000..1fde02a --- /dev/null +++ b/src/actions/delete-k8s-cluster.action.ts @@ -0,0 +1,9 @@ +import { kubernetesApiClient, DeleteK8sClusterResult } from "../api/kubernetes"; + +export const deleteK8sClusterAction = async ( + clusterId: number, + hash?: string, + code?: string +): Promise => { + return await kubernetesApiClient.deleteCluster(clusterId, hash, code); +}; diff --git a/src/actions/delete-k8s-node-group.action.ts b/src/actions/delete-k8s-node-group.action.ts new file mode 100644 index 0000000..6777dca --- /dev/null +++ b/src/actions/delete-k8s-node-group.action.ts @@ -0,0 +1,8 @@ +import { kubernetesApiClient } from "../api"; + +export const deleteK8sNodeGroupAction = async ( + clusterId: number, + groupId: number +): Promise => { + await kubernetesApiClient.deleteNodeGroup(clusterId, groupId); +}; diff --git a/src/actions/delete-knowledge-base-document.action.ts b/src/actions/delete-knowledge-base-document.action.ts new file mode 100644 index 0000000..fc1b070 --- /dev/null +++ b/src/actions/delete-knowledge-base-document.action.ts @@ -0,0 +1,8 @@ +import { knowledgeBasesApiClient } from "../api"; + +export const deleteKnowledgeBaseDocumentAction = async ( + id: number, + documentId: number +): Promise => { + await knowledgeBasesApiClient.deleteKnowledgeBaseDocument(id, documentId); +}; diff --git a/src/actions/delete-knowledge-base.action.ts b/src/actions/delete-knowledge-base.action.ts new file mode 100644 index 0000000..8b6b063 --- /dev/null +++ b/src/actions/delete-knowledge-base.action.ts @@ -0,0 +1,5 @@ +import { knowledgeBasesApiClient } from "../api"; + +export const deleteKnowledgeBaseAction = async (id: number): Promise => { + await knowledgeBasesApiClient.deleteKnowledgeBase(id); +}; diff --git a/src/actions/delete-mailbox.action.ts b/src/actions/delete-mailbox.action.ts new file mode 100644 index 0000000..d15ceac --- /dev/null +++ b/src/actions/delete-mailbox.action.ts @@ -0,0 +1,8 @@ +import { mailApiClient } from "../api"; + +export const deleteMailboxAction = async ( + domain: string, + mailbox: string +): Promise => { + return await mailApiClient.deleteMailbox(domain, mailbox); +}; diff --git a/src/actions/delete-network-drive.action.ts b/src/actions/delete-network-drive.action.ts new file mode 100644 index 0000000..197b874 --- /dev/null +++ b/src/actions/delete-network-drive.action.ts @@ -0,0 +1,7 @@ +import { networkDrivesApiClient } from "../api/network-drives"; + +export const deleteNetworkDriveAction = async ( + networkDriveId: string +): Promise => { + await networkDrivesApiClient.deleteNetworkDrive(networkDriveId); +}; diff --git a/src/actions/delete-project.action.ts b/src/actions/delete-project.action.ts new file mode 100644 index 0000000..d5ac690 --- /dev/null +++ b/src/actions/delete-project.action.ts @@ -0,0 +1,5 @@ +import { projectsApiClient } from "../api/projects"; + +export const deleteProjectAction = async (projectId: number): Promise => { + await projectsApiClient.deleteProject(projectId); +}; diff --git a/src/actions/delete-server-disk-backup.action.ts b/src/actions/delete-server-disk-backup.action.ts new file mode 100644 index 0000000..1bbc514 --- /dev/null +++ b/src/actions/delete-server-disk-backup.action.ts @@ -0,0 +1,9 @@ +import { serversApiClient } from "../api"; + +export const deleteServerDiskBackupAction = async ( + serverId: number, + diskId: number, + backupId: number +): Promise => { + await serversApiClient.deleteServerDiskBackup(serverId, diskId, backupId); +}; diff --git a/src/actions/delete-server-disk.action.ts b/src/actions/delete-server-disk.action.ts new file mode 100644 index 0000000..e240c09 --- /dev/null +++ b/src/actions/delete-server-disk.action.ts @@ -0,0 +1,8 @@ +import { serversApiClient } from "../api"; + +export const deleteServerDiskAction = async ( + serverId: number, + diskId: number +): Promise => { + await serversApiClient.deleteServerDisk(serverId, diskId); +}; diff --git a/src/actions/delete-server-ip.action.ts b/src/actions/delete-server-ip.action.ts new file mode 100644 index 0000000..1109e39 --- /dev/null +++ b/src/actions/delete-server-ip.action.ts @@ -0,0 +1,8 @@ +import { serversApiClient } from "../api"; + +export const deleteServerIpAction = async ( + serverId: number, + ip: string +): Promise => { + await serversApiClient.deleteServerIp(serverId, { ip }); +}; diff --git a/src/actions/delete-server.action.ts b/src/actions/delete-server.action.ts new file mode 100644 index 0000000..48114c5 --- /dev/null +++ b/src/actions/delete-server.action.ts @@ -0,0 +1,9 @@ +import { serversApiClient, DeleteServerParams } from "../api/servers"; +import { DeleteServerResponseDto } from "../types/dto/delete-server-response.dto"; + +export const deleteServerAction = async ( + serverId: number, + params: DeleteServerParams = {} +): Promise => { + return await serversApiClient.deleteServer(serverId, params); +}; diff --git a/src/actions/delete-ssh-key.action.ts b/src/actions/delete-ssh-key.action.ts new file mode 100644 index 0000000..7b9f6a5 --- /dev/null +++ b/src/actions/delete-ssh-key.action.ts @@ -0,0 +1,5 @@ +import { sshKeysApiClient } from "../api"; + +export const deleteSshKeyAction = async (sshKeyId: number): Promise => { + await sshKeysApiClient.deleteSshKey(sshKeyId); +}; diff --git a/src/actions/delete-subdomain.action.ts b/src/actions/delete-subdomain.action.ts new file mode 100644 index 0000000..38bc149 --- /dev/null +++ b/src/actions/delete-subdomain.action.ts @@ -0,0 +1,8 @@ +import { domainsApiClient } from "../api"; + +export const deleteSubdomainAction = async ( + fqdn: string, + subdomainFqdn: string +): Promise => { + await domainsApiClient.deleteSubdomain(fqdn, subdomainFqdn); +}; diff --git a/src/actions/delete-vpc.action.ts b/src/actions/delete-vpc.action.ts new file mode 100644 index 0000000..b840058 --- /dev/null +++ b/src/actions/delete-vpc.action.ts @@ -0,0 +1,5 @@ +import { dbaasApiClient } from "../api"; + +export const deleteVpcAction = async (vpcId: string): Promise => { + await dbaasApiClient.deleteVpc(vpcId); +}; diff --git a/src/actions/domain-requests.action.ts b/src/actions/domain-requests.action.ts new file mode 100644 index 0000000..208de31 --- /dev/null +++ b/src/actions/domain-requests.action.ts @@ -0,0 +1,29 @@ +import { domainsApiClient } from "../api"; +import { DomainRequest } from "../types/domain-request.type"; +import { + CreateDomainRequestRequestDto, + UpdateDomainRequestBodyDto, +} from "../types/dto/create-domain-request-request.dto"; + +export const listDomainRequestsAction = async (): Promise => { + return await domainsApiClient.listDomainRequests(); +}; + +export const getDomainRequestAction = async ( + requestId: number +): Promise => { + return await domainsApiClient.getDomainRequest(requestId); +}; + +export const createDomainRequestAction = async ( + data: CreateDomainRequestRequestDto +): Promise => { + return await domainsApiClient.createDomainRequest(data); +}; + +export const updateDomainRequestAction = async ( + requestId: number, + data: UpdateDomainRequestBodyDto +): Promise => { + return await domainsApiClient.updateDomainRequest(requestId, data); +}; diff --git a/src/actions/download-knowledge-base-document.action.ts b/src/actions/download-knowledge-base-document.action.ts new file mode 100644 index 0000000..96c9454 --- /dev/null +++ b/src/actions/download-knowledge-base-document.action.ts @@ -0,0 +1,11 @@ +import { knowledgeBasesApiClient } from "../api"; + +export const downloadKnowledgeBaseDocumentAction = async ( + id: number, + documentId: number +): Promise => { + return await knowledgeBasesApiClient.downloadKnowledgeBaseDocument( + id, + documentId + ); +}; diff --git a/src/actions/edit-api-key.action.ts b/src/actions/edit-api-key.action.ts new file mode 100644 index 0000000..7546963 --- /dev/null +++ b/src/actions/edit-api-key.action.ts @@ -0,0 +1,10 @@ +import { authApiClient } from "../api"; +import { ApiKey } from "../types/api-key.type"; +import { EditApiKeyRequestDto } from "../types/dto/edit-api-key-request.dto"; + +export const editApiKeyAction = async ( + tokenId: string, + data: EditApiKeyRequestDto +): Promise => { + return await authApiClient.editApiKey(tokenId, data); +}; diff --git a/src/actions/edit-k8s-cluster.action.ts b/src/actions/edit-k8s-cluster.action.ts new file mode 100644 index 0000000..4762268 --- /dev/null +++ b/src/actions/edit-k8s-cluster.action.ts @@ -0,0 +1,10 @@ +import { kubernetesApiClient } from "../api"; +import { EditK8sClusterRequestDto } from "../types/dto/edit-k8s-cluster-request.dto"; +import { K8sCluster } from "../types/k8s-cluster.type"; + +export const editK8sClusterAction = async ( + clusterId: number, + data: EditK8sClusterRequestDto +): Promise => { + return await kubernetesApiClient.editCluster(clusterId, data); +}; diff --git a/src/actions/get-account-finances.action.ts b/src/actions/get-account-finances.action.ts new file mode 100644 index 0000000..462f079 --- /dev/null +++ b/src/actions/get-account-finances.action.ts @@ -0,0 +1,6 @@ +import { accountApiClient } from "../api"; +import { Finances } from "../types/finances.type"; + +export const getAccountFinancesAction = async (): Promise => { + return await accountApiClient.getFinances(); +}; diff --git a/src/actions/get-account-services-cost.action.ts b/src/actions/get-account-services-cost.action.ts new file mode 100644 index 0000000..3cc0bd2 --- /dev/null +++ b/src/actions/get-account-services-cost.action.ts @@ -0,0 +1,8 @@ +import { accountApiClient } from "../api"; +import { ServicePrice } from "../types/service-price.type"; + +export const getAccountServicesCostAction = async (): Promise< + ServicePrice[] +> => { + return await accountApiClient.getServicesCost(); +}; diff --git a/src/actions/get-account-status.action.ts b/src/actions/get-account-status.action.ts new file mode 100644 index 0000000..5f4594a --- /dev/null +++ b/src/actions/get-account-status.action.ts @@ -0,0 +1,6 @@ +import { accountApiClient } from "../api"; +import { AccountStatus } from "../types/finances.type"; + +export const getAccountStatusAction = async (): Promise => { + return await accountApiClient.getStatus(); +}; diff --git a/src/actions/get-ai-agent-statistic.action.ts b/src/actions/get-ai-agent-statistic.action.ts new file mode 100644 index 0000000..b0b3e9f --- /dev/null +++ b/src/actions/get-ai-agent-statistic.action.ts @@ -0,0 +1,9 @@ +import { aiAgentsApiClient, AgentStatisticQuery } from "../api/ai-agents"; +import { TokenStatistic } from "../types/token-statistic.type"; + +export const getAiAgentStatisticAction = async ( + agentId: number, + query: AgentStatisticQuery = {} +): Promise => { + return await aiAgentsApiClient.getAgentStatistic(agentId, query); +}; diff --git a/src/actions/get-ai-agent.action.ts b/src/actions/get-ai-agent.action.ts new file mode 100644 index 0000000..0524f73 --- /dev/null +++ b/src/actions/get-ai-agent.action.ts @@ -0,0 +1,6 @@ +import { aiAgentsApiClient } from "../api"; +import { AiAgent } from "../types/ai-agent.type"; + +export const getAiAgentAction = async (agentId: number): Promise => { + return await aiAgentsApiClient.getAgent(agentId); +}; diff --git a/src/actions/get-balancer.action.ts b/src/actions/get-balancer.action.ts new file mode 100644 index 0000000..f4620b5 --- /dev/null +++ b/src/actions/get-balancer.action.ts @@ -0,0 +1,8 @@ +import { balancersApiClient } from "../api"; +import { Balancer } from "../types/balancer.type"; + +export const getBalancerAction = async ( + balancerId: number +): Promise => { + return await balancersApiClient.getBalancer(balancerId); +}; diff --git a/src/actions/get-bucket-presets.action.ts b/src/actions/get-bucket-presets.action.ts new file mode 100644 index 0000000..ecad775 --- /dev/null +++ b/src/actions/get-bucket-presets.action.ts @@ -0,0 +1,6 @@ +import { s3BucketsApiClient } from "../api"; +import { BucketPreset } from "../types/bucket-preset.type"; + +export const getBucketPresetsAction = async (): Promise => { + return await s3BucketsApiClient.getBucketPresets(); +}; diff --git a/src/actions/get-bucket-transfer-status.action.ts b/src/actions/get-bucket-transfer-status.action.ts new file mode 100644 index 0000000..0c93598 --- /dev/null +++ b/src/actions/get-bucket-transfer-status.action.ts @@ -0,0 +1,8 @@ +import { s3BucketsApiClient } from "../api"; +import { BucketTransferStatus } from "../types/bucket-transfer-status.type"; + +export const getBucketTransferStatusAction = async ( + bucketId: number +): Promise => { + return await s3BucketsApiClient.getBucketTransferStatus(bucketId); +}; diff --git a/src/actions/get-bucket.action.ts b/src/actions/get-bucket.action.ts new file mode 100644 index 0000000..1c38b1b --- /dev/null +++ b/src/actions/get-bucket.action.ts @@ -0,0 +1,6 @@ +import { s3BucketsApiClient } from "../api"; +import { Bucket } from "../types/bucket.type"; + +export const getBucketAction = async (bucketId: number): Promise => { + return await s3BucketsApiClient.getBucket(bucketId); +}; diff --git a/src/actions/get-container-registry.action.ts b/src/actions/get-container-registry.action.ts new file mode 100644 index 0000000..a04ba79 --- /dev/null +++ b/src/actions/get-container-registry.action.ts @@ -0,0 +1,8 @@ +import { containerRegistryApiClient } from "../api"; +import { ContainerRegistry } from "../types/container-registry.type"; + +export const getContainerRegistryAction = async ( + registryId: number +): Promise => { + return await containerRegistryApiClient.getContainerRegistry(registryId); +}; diff --git a/src/actions/get-database-admin.action.ts b/src/actions/get-database-admin.action.ts new file mode 100644 index 0000000..620b9bd --- /dev/null +++ b/src/actions/get-database-admin.action.ts @@ -0,0 +1,9 @@ +import { dbaasApiClient } from "../api"; +import { DatabaseAdminEntity } from "../types/database-cluster.type"; + +export const getDatabaseAdminAction = async ( + clusterId: number, + adminId: number +): Promise => { + return await dbaasApiClient.getDatabaseAdmin(clusterId, adminId); +}; diff --git a/src/actions/get-database-auto-backups.action.ts b/src/actions/get-database-auto-backups.action.ts new file mode 100644 index 0000000..916b063 --- /dev/null +++ b/src/actions/get-database-auto-backups.action.ts @@ -0,0 +1,8 @@ +import { dbaasApiClient } from "../api"; +import { DatabaseAutoBackupSettings } from "../types/database-cluster.type"; + +export const getDatabaseAutoBackupsAction = async ( + dbId: number +): Promise => { + return await dbaasApiClient.getDatabaseAutoBackups(dbId); +}; diff --git a/src/actions/get-database-backup.action.ts b/src/actions/get-database-backup.action.ts new file mode 100644 index 0000000..7a8aa6e --- /dev/null +++ b/src/actions/get-database-backup.action.ts @@ -0,0 +1,9 @@ +import { dbaasApiClient } from "../api"; +import { DatabaseBackup } from "../types/database-cluster.type"; + +export const getDatabaseBackupAction = async ( + dbId: number, + backupId: number +): Promise => { + return await dbaasApiClient.getDatabaseBackup(dbId, backupId); +}; diff --git a/src/actions/get-database-cluster.action.ts b/src/actions/get-database-cluster.action.ts new file mode 100644 index 0000000..58d08a0 --- /dev/null +++ b/src/actions/get-database-cluster.action.ts @@ -0,0 +1,8 @@ +import { dbaasApiClient } from "../api"; +import { DatabaseCluster } from "../types/database-cluster.type"; + +export const getDatabaseClusterAction = async ( + clusterId: number +): Promise => { + return await dbaasApiClient.getDatabaseCluster(clusterId); +}; diff --git a/src/actions/get-database-instance.action.ts b/src/actions/get-database-instance.action.ts new file mode 100644 index 0000000..55a61a3 --- /dev/null +++ b/src/actions/get-database-instance.action.ts @@ -0,0 +1,9 @@ +import { dbaasApiClient } from "../api"; +import { DatabaseInstanceEntity } from "../types/database-cluster.type"; + +export const getDatabaseInstanceAction = async ( + clusterId: number, + instanceId: number +): Promise => { + return await dbaasApiClient.getDatabaseInstance(clusterId, instanceId); +}; diff --git a/src/actions/get-database-parameters.action.ts b/src/actions/get-database-parameters.action.ts new file mode 100644 index 0000000..e36e96f --- /dev/null +++ b/src/actions/get-database-parameters.action.ts @@ -0,0 +1,7 @@ +import { dbaasApiClient } from "../api"; +import { GetDatabaseParametersResponseDto } from "../types/dto/get-database-parameters-response.dto"; + +export const getDatabaseParametersAction = + async (): Promise => { + return await dbaasApiClient.getDatabaseParameters(); + }; diff --git a/src/actions/get-database.action.ts b/src/actions/get-database.action.ts new file mode 100644 index 0000000..7d9bf02 --- /dev/null +++ b/src/actions/get-database.action.ts @@ -0,0 +1,6 @@ +import { dbaasApiClient } from "../api"; +import { Database } from "../types/database.type"; + +export const getDatabaseAction = async (dbId: number): Promise => { + return await dbaasApiClient.getDatabase(dbId); +}; diff --git a/src/actions/get-dedicated-server.action.ts b/src/actions/get-dedicated-server.action.ts new file mode 100644 index 0000000..282cae6 --- /dev/null +++ b/src/actions/get-dedicated-server.action.ts @@ -0,0 +1,8 @@ +import { dedicatedServersApiClient } from "../api"; +import { DedicatedServer } from "../types/dedicated-server.type"; + +export const getDedicatedServerAction = async ( + dedicatedId: number +): Promise => { + return await dedicatedServersApiClient.getDedicatedServer(dedicatedId); +}; diff --git a/src/actions/get-domain-name-servers.action.ts b/src/actions/get-domain-name-servers.action.ts new file mode 100644 index 0000000..6ee5caf --- /dev/null +++ b/src/actions/get-domain-name-servers.action.ts @@ -0,0 +1,8 @@ +import { domainsApiClient } from "../api"; +import { DomainNameServer } from "../types/domain-name-server.type"; + +export const getDomainNameServersAction = async ( + fqdn: string +): Promise => { + return await domainsApiClient.getNameServers(fqdn); +}; diff --git a/src/actions/get-domain.action.ts b/src/actions/get-domain.action.ts new file mode 100644 index 0000000..31b84fb --- /dev/null +++ b/src/actions/get-domain.action.ts @@ -0,0 +1,6 @@ +import { domainsApiClient } from "../api"; +import { Domain } from "../types/domain.type"; + +export const getDomainAction = async (fqdn: string): Promise => { + return await domainsApiClient.getDomain(fqdn); +}; diff --git a/src/actions/get-firewall-group.action.ts b/src/actions/get-firewall-group.action.ts new file mode 100644 index 0000000..018bf1e --- /dev/null +++ b/src/actions/get-firewall-group.action.ts @@ -0,0 +1,8 @@ +import { firewallApiClient } from "../api"; +import { FirewallGroup } from "../types/firewall-group.type"; + +export const getFirewallGroupAction = async ( + groupId: string +): Promise => { + return await firewallApiClient.getFirewallGroup(groupId); +}; diff --git a/src/actions/get-firewall-rule.action.ts b/src/actions/get-firewall-rule.action.ts new file mode 100644 index 0000000..8a32f37 --- /dev/null +++ b/src/actions/get-firewall-rule.action.ts @@ -0,0 +1,9 @@ +import { firewallApiClient } from "../api"; +import { FirewallRule } from "../types/firewall-rule.type"; + +export const getFirewallRuleAction = async ( + groupId: string, + ruleId: string +): Promise => { + return await firewallApiClient.getFirewallRule(groupId, ruleId); +}; diff --git a/src/actions/get-floating-ip.action.ts b/src/actions/get-floating-ip.action.ts new file mode 100644 index 0000000..1472561 --- /dev/null +++ b/src/actions/get-floating-ip.action.ts @@ -0,0 +1,8 @@ +import { dbaasApiClient } from "../api"; +import { FloatingIp } from "../types/floating-ip.type"; + +export const getFloatingIpAction = async ( + floatingIpId: string +): Promise => { + return await dbaasApiClient.getFloatingIp(floatingIpId); +}; diff --git a/src/actions/get-image-download.action.ts b/src/actions/get-image-download.action.ts new file mode 100644 index 0000000..2b0e55c --- /dev/null +++ b/src/actions/get-image-download.action.ts @@ -0,0 +1,9 @@ +import { imagesApiClient } from "../api"; +import { ImageDownload } from "../types/image-download.type"; + +export const getImageDownloadAction = async ( + imageId: string, + imageUrlId: string +): Promise => { + return await imagesApiClient.getImageDownload(imageId, imageUrlId); +}; diff --git a/src/actions/get-image.action.ts b/src/actions/get-image.action.ts new file mode 100644 index 0000000..ccfbb50 --- /dev/null +++ b/src/actions/get-image.action.ts @@ -0,0 +1,6 @@ +import { imagesApiClient } from "../api"; +import { Image } from "../types/image.type"; + +export const getImageAction = async (imageId: string): Promise => { + return await imagesApiClient.getImage(imageId); +}; diff --git a/src/actions/get-k8s-cluster-resources.action.ts b/src/actions/get-k8s-cluster-resources.action.ts new file mode 100644 index 0000000..7272c34 --- /dev/null +++ b/src/actions/get-k8s-cluster-resources.action.ts @@ -0,0 +1,8 @@ +import { kubernetesApiClient } from "../api"; +import { K8sResources } from "../types/k8s-resources.type"; + +export const getK8sClusterResourcesAction = async ( + clusterId: number +): Promise => { + return await kubernetesApiClient.getClusterResources(clusterId); +}; diff --git a/src/actions/get-k8s-cluster.action.ts b/src/actions/get-k8s-cluster.action.ts new file mode 100644 index 0000000..10c295e --- /dev/null +++ b/src/actions/get-k8s-cluster.action.ts @@ -0,0 +1,8 @@ +import { kubernetesApiClient } from "../api"; +import { K8sCluster } from "../types/k8s-cluster.type"; + +export const getK8sClusterAction = async ( + clusterId: number +): Promise => { + return await kubernetesApiClient.getCluster(clusterId); +}; diff --git a/src/actions/get-k8s-kubeconfig.action.ts b/src/actions/get-k8s-kubeconfig.action.ts new file mode 100644 index 0000000..65e56da --- /dev/null +++ b/src/actions/get-k8s-kubeconfig.action.ts @@ -0,0 +1,7 @@ +import { kubernetesApiClient } from "../api"; + +export const getK8sKubeconfigAction = async ( + clusterId: number +): Promise => { + return await kubernetesApiClient.getKubeconfig(clusterId); +}; diff --git a/src/actions/get-k8s-node-group.action.ts b/src/actions/get-k8s-node-group.action.ts new file mode 100644 index 0000000..db51a00 --- /dev/null +++ b/src/actions/get-k8s-node-group.action.ts @@ -0,0 +1,9 @@ +import { kubernetesApiClient } from "../api"; +import { K8sNodeGroup } from "../types/k8s-node-group.type"; + +export const getK8sNodeGroupAction = async ( + clusterId: number, + groupId: number +): Promise => { + return await kubernetesApiClient.getNodeGroup(clusterId, groupId); +}; diff --git a/src/actions/get-knowledge-base-statistic.action.ts b/src/actions/get-knowledge-base-statistic.action.ts new file mode 100644 index 0000000..504400c --- /dev/null +++ b/src/actions/get-knowledge-base-statistic.action.ts @@ -0,0 +1,12 @@ +import { + knowledgeBasesApiClient, + KnowledgeBaseStatisticQuery, +} from "../api/knowledge-bases"; +import { TokenStatistic } from "../types/token-statistic.type"; + +export const getKnowledgeBaseStatisticAction = async ( + id: number, + query: KnowledgeBaseStatisticQuery = {} +): Promise => { + return await knowledgeBasesApiClient.getKnowledgeBaseStatistic(id, query); +}; diff --git a/src/actions/get-knowledge-base.action.ts b/src/actions/get-knowledge-base.action.ts new file mode 100644 index 0000000..ff65737 --- /dev/null +++ b/src/actions/get-knowledge-base.action.ts @@ -0,0 +1,8 @@ +import { knowledgeBasesApiClient } from "../api"; +import { KnowledgeBase } from "../types/knowledge-base.type"; + +export const getKnowledgeBaseAction = async ( + id: number +): Promise => { + return await knowledgeBasesApiClient.getKnowledgeBase(id); +}; diff --git a/src/actions/get-mail-domain-info.action.ts b/src/actions/get-mail-domain-info.action.ts new file mode 100644 index 0000000..32e4df9 --- /dev/null +++ b/src/actions/get-mail-domain-info.action.ts @@ -0,0 +1,8 @@ +import { mailApiClient } from "../api"; +import { MailDomainInfo } from "../types/mailbox.type"; + +export const getMailDomainInfoAction = async ( + domain: string +): Promise => { + return await mailApiClient.getMailDomainInfo(domain); +}; diff --git a/src/actions/get-mailbox-v1.action.ts b/src/actions/get-mailbox-v1.action.ts new file mode 100644 index 0000000..acfa915 --- /dev/null +++ b/src/actions/get-mailbox-v1.action.ts @@ -0,0 +1,9 @@ +import { mailApiClient } from "../api"; +import { Mailbox } from "../types/mailbox.type"; + +export const getMailboxV1Action = async ( + domain: string, + mailbox: string +): Promise => { + return await mailApiClient.getMailboxV1(domain, mailbox); +}; diff --git a/src/actions/get-mailbox.action.ts b/src/actions/get-mailbox.action.ts new file mode 100644 index 0000000..9c97e73 --- /dev/null +++ b/src/actions/get-mailbox.action.ts @@ -0,0 +1,9 @@ +import { mailApiClient } from "../api"; +import { MailboxV2 } from "../types/mailbox.type"; + +export const getMailboxAction = async ( + domain: string, + mailbox: string +): Promise => { + return await mailApiClient.getMailboxV2(domain, mailbox); +}; diff --git a/src/actions/get-network-drive.action.ts b/src/actions/get-network-drive.action.ts new file mode 100644 index 0000000..297770e --- /dev/null +++ b/src/actions/get-network-drive.action.ts @@ -0,0 +1,8 @@ +import { networkDrivesApiClient } from "../api/network-drives"; +import { NetworkDrive } from "../types/network-drive.type"; + +export const getNetworkDriveAction = async ( + networkDriveId: string +): Promise => { + return await networkDrivesApiClient.getNetworkDrive(networkDriveId); +}; diff --git a/src/actions/get-project.action.ts b/src/actions/get-project.action.ts new file mode 100644 index 0000000..df5f134 --- /dev/null +++ b/src/actions/get-project.action.ts @@ -0,0 +1,6 @@ +import { projectsApiClient } from "../api/projects"; +import { Project } from "../types/project.type"; + +export const getProjectAction = async (projectId: number): Promise => { + return await projectsApiClient.getProject(projectId); +}; diff --git a/src/actions/get-server-disk-auto-backups.action.ts b/src/actions/get-server-disk-auto-backups.action.ts new file mode 100644 index 0000000..93a865d --- /dev/null +++ b/src/actions/get-server-disk-auto-backups.action.ts @@ -0,0 +1,9 @@ +import { serversApiClient } from "../api"; +import { AutoBackupSettings } from "../types/auto-backup.type"; + +export const getServerDiskAutoBackupsAction = async ( + serverId: number, + diskId: number +): Promise => { + return await serversApiClient.getServerDiskAutoBackups(serverId, diskId); +}; diff --git a/src/actions/get-server-disk-backup.action.ts b/src/actions/get-server-disk-backup.action.ts new file mode 100644 index 0000000..cd7d679 --- /dev/null +++ b/src/actions/get-server-disk-backup.action.ts @@ -0,0 +1,14 @@ +import { serversApiClient } from "../api"; +import { ServerBackup } from "../types/server-backup.type"; + +export const getServerDiskBackupAction = async ( + serverId: number, + diskId: number, + backupId: number +): Promise => { + return await serversApiClient.getServerDiskBackup( + serverId, + diskId, + backupId + ); +}; diff --git a/src/actions/get-server-disk.action.ts b/src/actions/get-server-disk.action.ts new file mode 100644 index 0000000..9c88e58 --- /dev/null +++ b/src/actions/get-server-disk.action.ts @@ -0,0 +1,9 @@ +import { serversApiClient } from "../api"; +import { ServerDisk } from "../types/server-disk.type"; + +export const getServerDiskAction = async ( + serverId: number, + diskId: number +): Promise => { + return await serversApiClient.getServerDisk(serverId, diskId); +}; diff --git a/src/actions/get-server-logs.action.ts b/src/actions/get-server-logs.action.ts new file mode 100644 index 0000000..ba2dec7 --- /dev/null +++ b/src/actions/get-server-logs.action.ts @@ -0,0 +1,9 @@ +import { serversApiClient, ServerLogsOrder } from "../api/servers"; +import { ServerLog } from "../types/server-log.type"; + +export const getServerLogsAction = async ( + serverId: number, + order: ServerLogsOrder = "desc" +): Promise => { + return await serversApiClient.getServerLogs(serverId, order); +}; diff --git a/src/actions/get-server.action.ts b/src/actions/get-server.action.ts new file mode 100644 index 0000000..1913c27 --- /dev/null +++ b/src/actions/get-server.action.ts @@ -0,0 +1,6 @@ +import { serversApiClient } from "../api"; +import { Server } from "../types/server.type"; + +export const getServerAction = async (serverId: number): Promise => { + return await serversApiClient.getServer(serverId); +}; diff --git a/src/actions/get-ssh-key.action.ts b/src/actions/get-ssh-key.action.ts new file mode 100644 index 0000000..140eff5 --- /dev/null +++ b/src/actions/get-ssh-key.action.ts @@ -0,0 +1,6 @@ +import { sshKeysApiClient } from "../api"; +import { SshKey } from "../types/ssh-key.type"; + +export const getSshKeyAction = async (sshKeyId: number): Promise => { + return await sshKeysApiClient.getSshKey(sshKeyId); +}; diff --git a/src/actions/get-vpc.action.ts b/src/actions/get-vpc.action.ts new file mode 100644 index 0000000..cf78cc6 --- /dev/null +++ b/src/actions/get-vpc.action.ts @@ -0,0 +1,6 @@ +import { dbaasApiClient } from "../api"; +import { Vpc } from "../types/vpc.type"; + +export const getVpcAction = async (vpcId: string): Promise => { + return await dbaasApiClient.getVpc(vpcId); +}; diff --git a/src/actions/hard-reboot-server.action.ts b/src/actions/hard-reboot-server.action.ts new file mode 100644 index 0000000..53542dd --- /dev/null +++ b/src/actions/hard-reboot-server.action.ts @@ -0,0 +1,7 @@ +import { serversApiClient } from "../api"; + +export const hardRebootServerAction = async ( + serverId: number +): Promise => { + await serversApiClient.hardRebootServer(serverId); +}; diff --git a/src/actions/hard-shutdown-server.action.ts b/src/actions/hard-shutdown-server.action.ts new file mode 100644 index 0000000..00917f2 --- /dev/null +++ b/src/actions/hard-shutdown-server.action.ts @@ -0,0 +1,7 @@ +import { serversApiClient } from "../api"; + +export const hardShutdownServerAction = async ( + serverId: number +): Promise => { + await serversApiClient.hardShutdownServer(serverId); +}; diff --git a/src/actions/increase-k8s-node-group-nodes.action.ts b/src/actions/increase-k8s-node-group-nodes.action.ts new file mode 100644 index 0000000..bac3fad --- /dev/null +++ b/src/actions/increase-k8s-node-group-nodes.action.ts @@ -0,0 +1,15 @@ +import { kubernetesApiClient } from "../api"; +import { IncreaseK8sNodesRequestDto } from "../types/dto/increase-k8s-nodes-request.dto"; +import { K8sNode } from "../types/k8s-node.type"; + +export const increaseK8sNodeGroupNodesAction = async ( + clusterId: number, + groupId: number, + data: IncreaseK8sNodesRequestDto +): Promise => { + return await kubernetesApiClient.increaseNodeGroupNodes( + clusterId, + groupId, + data + ); +}; diff --git a/src/actions/install-k8s-addon.action.ts b/src/actions/install-k8s-addon.action.ts new file mode 100644 index 0000000..d38a16a --- /dev/null +++ b/src/actions/install-k8s-addon.action.ts @@ -0,0 +1,9 @@ +import { kubernetesApiClient } from "../api"; +import { InstallK8sAddonRequestDto } from "../types/dto/install-k8s-addon-request.dto"; + +export const installK8sAddonAction = async ( + clusterId: number, + data: InstallK8sAddonRequestDto +): Promise => { + await kubernetesApiClient.installAddon(clusterId, data); +}; diff --git a/src/actions/link-firewall-resource.action.ts b/src/actions/link-firewall-resource.action.ts new file mode 100644 index 0000000..9d658cd --- /dev/null +++ b/src/actions/link-firewall-resource.action.ts @@ -0,0 +1,17 @@ +import { firewallApiClient } from "../api"; +import { + FirewallGroupResource, + FirewallResourceType, +} from "../types/firewall-resource.type"; + +export const linkFirewallResourceAction = async ( + groupId: string, + resourceId: string, + resourceType: FirewallResourceType = "server" +): Promise => { + return await firewallApiClient.linkFirewallResource( + groupId, + resourceId, + resourceType + ); +}; diff --git a/src/actions/link-knowledge-base.action.ts b/src/actions/link-knowledge-base.action.ts new file mode 100644 index 0000000..b612565 --- /dev/null +++ b/src/actions/link-knowledge-base.action.ts @@ -0,0 +1,8 @@ +import { knowledgeBasesApiClient } from "../api"; + +export const linkKnowledgeBaseAction = async ( + id: number, + agentId: number +): Promise => { + await knowledgeBasesApiClient.linkKnowledgeBaseToAgent(id, agentId); +}; diff --git a/src/actions/list-ai-agent-token-packages.action.ts b/src/actions/list-ai-agent-token-packages.action.ts new file mode 100644 index 0000000..7523437 --- /dev/null +++ b/src/actions/list-ai-agent-token-packages.action.ts @@ -0,0 +1,8 @@ +import { aiAgentsApiClient } from "../api"; +import { TokenPackage } from "../types/token-package.type"; + +export const listAiAgentTokenPackagesAction = async (): Promise< + TokenPackage[] +> => { + return await aiAgentsApiClient.listAgentTokenPackages(); +}; diff --git a/src/actions/list-ai-agents.action.ts b/src/actions/list-ai-agents.action.ts new file mode 100644 index 0000000..ad5065d --- /dev/null +++ b/src/actions/list-ai-agents.action.ts @@ -0,0 +1,6 @@ +import { aiAgentsApiClient } from "../api"; +import { AiAgent } from "../types/ai-agent.type"; + +export const listAiAgentsAction = async (): Promise => { + return await aiAgentsApiClient.listAgents(); +}; diff --git a/src/actions/list-ai-models.action.ts b/src/actions/list-ai-models.action.ts new file mode 100644 index 0000000..b03909b --- /dev/null +++ b/src/actions/list-ai-models.action.ts @@ -0,0 +1,6 @@ +import { aiAgentsApiClient } from "../api"; +import { AiModel } from "../types/ai-model.type"; + +export const listAiModelsAction = async (): Promise => { + return await aiAgentsApiClient.listModels(); +}; diff --git a/src/actions/list-all-project-balancers.action.ts b/src/actions/list-all-project-balancers.action.ts new file mode 100644 index 0000000..fbd12d0 --- /dev/null +++ b/src/actions/list-all-project-balancers.action.ts @@ -0,0 +1,5 @@ +import { projectsApiClient } from "../api/projects"; + +export const listAllProjectBalancersAction = async (): Promise => { + return await projectsApiClient.listAllResourceBalancers(); +}; diff --git a/src/actions/list-all-project-buckets.action.ts b/src/actions/list-all-project-buckets.action.ts new file mode 100644 index 0000000..78c71fb --- /dev/null +++ b/src/actions/list-all-project-buckets.action.ts @@ -0,0 +1,5 @@ +import { projectsApiClient } from "../api/projects"; + +export const listAllProjectBucketsAction = async (): Promise => { + return await projectsApiClient.listAllResourceBuckets(); +}; diff --git a/src/actions/list-all-project-clusters.action.ts b/src/actions/list-all-project-clusters.action.ts new file mode 100644 index 0000000..1e090ff --- /dev/null +++ b/src/actions/list-all-project-clusters.action.ts @@ -0,0 +1,5 @@ +import { projectsApiClient } from "../api/projects"; + +export const listAllProjectClustersAction = async (): Promise => { + return await projectsApiClient.listAllResourceClusters(); +}; diff --git a/src/actions/list-all-project-databases.action.ts b/src/actions/list-all-project-databases.action.ts new file mode 100644 index 0000000..3872a6b --- /dev/null +++ b/src/actions/list-all-project-databases.action.ts @@ -0,0 +1,5 @@ +import { projectsApiClient } from "../api/projects"; + +export const listAllProjectDatabasesAction = async (): Promise => { + return await projectsApiClient.listAllResourceDatabases(); +}; diff --git a/src/actions/list-all-project-dedicated.action.ts b/src/actions/list-all-project-dedicated.action.ts new file mode 100644 index 0000000..6f37fb4 --- /dev/null +++ b/src/actions/list-all-project-dedicated.action.ts @@ -0,0 +1,5 @@ +import { projectsApiClient } from "../api/projects"; + +export const listAllProjectDedicatedAction = async (): Promise => { + return await projectsApiClient.listAllResourceDedicated(); +}; diff --git a/src/actions/list-all-project-servers.action.ts b/src/actions/list-all-project-servers.action.ts new file mode 100644 index 0000000..017d813 --- /dev/null +++ b/src/actions/list-all-project-servers.action.ts @@ -0,0 +1,5 @@ +import { projectsApiClient } from "../api/projects"; + +export const listAllProjectServersAction = async (): Promise => { + return await projectsApiClient.listAllResourceServers(); +}; diff --git a/src/actions/list-api-keys.action.ts b/src/actions/list-api-keys.action.ts new file mode 100644 index 0000000..c870493 --- /dev/null +++ b/src/actions/list-api-keys.action.ts @@ -0,0 +1,6 @@ +import { authApiClient } from "../api"; +import { ApiKey } from "../types/api-key.type"; + +export const listApiKeysAction = async (): Promise => { + return await authApiClient.listApiKeys(); +}; diff --git a/src/actions/list-balancer-ips.action.ts b/src/actions/list-balancer-ips.action.ts new file mode 100644 index 0000000..d89121b --- /dev/null +++ b/src/actions/list-balancer-ips.action.ts @@ -0,0 +1,7 @@ +import { balancersApiClient } from "../api"; + +export const listBalancerIpsAction = async ( + balancerId: number +): Promise => { + return await balancersApiClient.listBalancerIps(balancerId); +}; diff --git a/src/actions/list-balancer-presets.action.ts b/src/actions/list-balancer-presets.action.ts new file mode 100644 index 0000000..e066351 --- /dev/null +++ b/src/actions/list-balancer-presets.action.ts @@ -0,0 +1,6 @@ +import { balancersApiClient } from "../api"; +import { BalancerPreset } from "../types/balancer.type"; + +export const listBalancerPresetsAction = async (): Promise => { + return await balancersApiClient.listBalancerPresets(); +}; diff --git a/src/actions/list-balancer-rules.action.ts b/src/actions/list-balancer-rules.action.ts new file mode 100644 index 0000000..5373292 --- /dev/null +++ b/src/actions/list-balancer-rules.action.ts @@ -0,0 +1,8 @@ +import { balancersApiClient } from "../api"; +import { BalancerRule } from "../types/balancer.type"; + +export const listBalancerRulesAction = async ( + balancerId: number +): Promise => { + return await balancersApiClient.listBalancerRules(balancerId); +}; diff --git a/src/actions/list-balancers.action.ts b/src/actions/list-balancers.action.ts new file mode 100644 index 0000000..d88efa6 --- /dev/null +++ b/src/actions/list-balancers.action.ts @@ -0,0 +1,9 @@ +import { balancersApiClient } from "../api"; +import { Balancer } from "../types/balancer.type"; + +export const listBalancersAction = async ( + limit?: number, + offset?: number +): Promise => { + return await balancersApiClient.listBalancers(limit, offset); +}; diff --git a/src/actions/list-bucket-subdomains.action.ts b/src/actions/list-bucket-subdomains.action.ts new file mode 100644 index 0000000..80ee50c --- /dev/null +++ b/src/actions/list-bucket-subdomains.action.ts @@ -0,0 +1,8 @@ +import { s3BucketsApiClient } from "../api"; +import { BucketSubdomain } from "../types/bucket-subdomain.type"; + +export const listBucketSubdomainsAction = async ( + bucketId: number +): Promise => { + return await s3BucketsApiClient.listBucketSubdomains(bucketId); +}; diff --git a/src/actions/list-bucket-users.action.ts b/src/actions/list-bucket-users.action.ts new file mode 100644 index 0000000..a66a00d --- /dev/null +++ b/src/actions/list-bucket-users.action.ts @@ -0,0 +1,6 @@ +import { s3BucketsApiClient } from "../api"; +import { BucketUser } from "../types/bucket-user.type"; + +export const listBucketUsersAction = async (): Promise => { + return await s3BucketsApiClient.listBucketUsers(); +}; diff --git a/src/actions/list-buckets.action.ts b/src/actions/list-buckets.action.ts new file mode 100644 index 0000000..08f25b3 --- /dev/null +++ b/src/actions/list-buckets.action.ts @@ -0,0 +1,6 @@ +import { s3BucketsApiClient } from "../api"; +import { Bucket } from "../types/bucket.type"; + +export const listBucketsAction = async (): Promise => { + return await s3BucketsApiClient.listBuckets(); +}; diff --git a/src/actions/list-container-registries.action.ts b/src/actions/list-container-registries.action.ts new file mode 100644 index 0000000..2399346 --- /dev/null +++ b/src/actions/list-container-registries.action.ts @@ -0,0 +1,8 @@ +import { containerRegistryApiClient } from "../api"; +import { ContainerRegistry } from "../types/container-registry.type"; + +export const listContainerRegistriesAction = async (): Promise< + ContainerRegistry[] +> => { + return await containerRegistryApiClient.listContainerRegistries(); +}; diff --git a/src/actions/list-container-registry-presets.action.ts b/src/actions/list-container-registry-presets.action.ts new file mode 100644 index 0000000..f9c6367 --- /dev/null +++ b/src/actions/list-container-registry-presets.action.ts @@ -0,0 +1,8 @@ +import { containerRegistryApiClient } from "../api"; +import { ContainerRegistryPreset } from "../types/container-registry.type"; + +export const listContainerRegistryPresetsAction = async (): Promise< + ContainerRegistryPreset[] +> => { + return await containerRegistryApiClient.listContainerRegistryPresets(); +}; diff --git a/src/actions/list-container-registry-repositories.action.ts b/src/actions/list-container-registry-repositories.action.ts new file mode 100644 index 0000000..014c44d --- /dev/null +++ b/src/actions/list-container-registry-repositories.action.ts @@ -0,0 +1,10 @@ +import { containerRegistryApiClient } from "../api"; +import { ContainerRegistryRepository } from "../types/container-registry.type"; + +export const listContainerRegistryRepositoriesAction = async ( + registryId: number +): Promise => { + return await containerRegistryApiClient.listContainerRegistryRepositories( + registryId + ); +}; diff --git a/src/actions/list-database-admins.action.ts b/src/actions/list-database-admins.action.ts new file mode 100644 index 0000000..380d7b1 --- /dev/null +++ b/src/actions/list-database-admins.action.ts @@ -0,0 +1,8 @@ +import { dbaasApiClient } from "../api"; +import { DatabaseAdminEntity } from "../types/database-cluster.type"; + +export const listDatabaseAdminsAction = async ( + clusterId: number +): Promise => { + return await dbaasApiClient.listDatabaseAdmins(clusterId); +}; diff --git a/src/actions/list-database-backups.action.ts b/src/actions/list-database-backups.action.ts new file mode 100644 index 0000000..e637ea0 --- /dev/null +++ b/src/actions/list-database-backups.action.ts @@ -0,0 +1,10 @@ +import { dbaasApiClient } from "../api"; +import { DatabaseBackup } from "../types/database-cluster.type"; + +export const listDatabaseBackupsAction = async ( + dbId: number, + limit?: number, + offset?: number +): Promise => { + return await dbaasApiClient.listDatabaseBackups(dbId, limit, offset); +}; diff --git a/src/actions/list-database-clusters.action.ts b/src/actions/list-database-clusters.action.ts new file mode 100644 index 0000000..8862e6a --- /dev/null +++ b/src/actions/list-database-clusters.action.ts @@ -0,0 +1,9 @@ +import { dbaasApiClient } from "../api"; +import { DatabaseCluster } from "../types/database-cluster.type"; + +export const listDatabaseClustersAction = async ( + limit?: number, + offset?: number +): Promise => { + return await dbaasApiClient.listDatabaseClusters(limit, offset); +}; diff --git a/src/actions/list-database-instances.action.ts b/src/actions/list-database-instances.action.ts new file mode 100644 index 0000000..1072d58 --- /dev/null +++ b/src/actions/list-database-instances.action.ts @@ -0,0 +1,8 @@ +import { dbaasApiClient } from "../api"; +import { DatabaseInstanceEntity } from "../types/database-cluster.type"; + +export const listDatabaseInstancesAction = async ( + clusterId: number +): Promise => { + return await dbaasApiClient.listDatabaseInstances(clusterId); +}; diff --git a/src/actions/list-database-types.action.ts b/src/actions/list-database-types.action.ts new file mode 100644 index 0000000..8d80e55 --- /dev/null +++ b/src/actions/list-database-types.action.ts @@ -0,0 +1,6 @@ +import { dbaasApiClient } from "../api"; +import { DatabaseType } from "../types/database-cluster.type"; + +export const listDatabaseTypesAction = async (): Promise => { + return await dbaasApiClient.listDatabaseTypes(); +}; diff --git a/src/actions/list-databases.action.ts b/src/actions/list-databases.action.ts new file mode 100644 index 0000000..22c98f9 --- /dev/null +++ b/src/actions/list-databases.action.ts @@ -0,0 +1,9 @@ +import { dbaasApiClient } from "../api"; +import { Database } from "../types/database.type"; + +export const listDatabasesAction = async ( + limit?: number, + offset?: number +): Promise => { + return await dbaasApiClient.listDatabases(limit, offset); +}; diff --git a/src/actions/list-dedicated-server-additional-services.action.ts b/src/actions/list-dedicated-server-additional-services.action.ts new file mode 100644 index 0000000..4ee47c5 --- /dev/null +++ b/src/actions/list-dedicated-server-additional-services.action.ts @@ -0,0 +1,10 @@ +import { dedicatedServersApiClient } from "../api"; +import { DedicatedServerAdditionalService } from "../types/dedicated-server.type"; + +export const listDedicatedServerAdditionalServicesAction = async ( + presetId: number +): Promise => { + return await dedicatedServersApiClient.listDedicatedServerAdditionalServices( + presetId + ); +}; diff --git a/src/actions/list-dedicated-server-presets.action.ts b/src/actions/list-dedicated-server-presets.action.ts new file mode 100644 index 0000000..3892ad7 --- /dev/null +++ b/src/actions/list-dedicated-server-presets.action.ts @@ -0,0 +1,11 @@ +import { dedicatedServersApiClient } from "../api"; +import { + DedicatedServerPreset, + DedicatedServerLocation, +} from "../types/dedicated-server.type"; + +export const listDedicatedServerPresetsAction = async ( + location?: DedicatedServerLocation +): Promise => { + return await dedicatedServersApiClient.listDedicatedServerPresets(location); +}; diff --git a/src/actions/list-dedicated-servers.action.ts b/src/actions/list-dedicated-servers.action.ts new file mode 100644 index 0000000..aae4d89 --- /dev/null +++ b/src/actions/list-dedicated-servers.action.ts @@ -0,0 +1,8 @@ +import { dedicatedServersApiClient } from "../api"; +import { DedicatedServer } from "../types/dedicated-server.type"; + +export const listDedicatedServersAction = async (): Promise< + DedicatedServer[] +> => { + return await dedicatedServersApiClient.listDedicatedServers(); +}; diff --git a/src/actions/list-default-dns-records.action.ts b/src/actions/list-default-dns-records.action.ts new file mode 100644 index 0000000..ce234a2 --- /dev/null +++ b/src/actions/list-default-dns-records.action.ts @@ -0,0 +1,8 @@ +import { domainsApiClient } from "../api"; +import { DnsRecord } from "../types/dns-record.type"; + +export const listDefaultDnsRecordsAction = async ( + fqdn: string +): Promise => { + return await domainsApiClient.listDefaultDnsRecords(fqdn); +}; diff --git a/src/actions/list-dns-records.action.ts b/src/actions/list-dns-records.action.ts new file mode 100644 index 0000000..d300cb7 --- /dev/null +++ b/src/actions/list-dns-records.action.ts @@ -0,0 +1,14 @@ +import { domainsApiClient } from "../api"; +import { DnsRecord } from "../types/dns-record.type"; + +export const listDnsRecordsAction = async ( + fqdn: string +): Promise => { + return await domainsApiClient.listDnsRecords(fqdn); +}; + +export const listDefaultDnsRecordsAction = async ( + fqdn: string +): Promise => { + return await domainsApiClient.listDefaultDnsRecords(fqdn); +}; diff --git a/src/actions/list-domains.action.ts b/src/actions/list-domains.action.ts new file mode 100644 index 0000000..8fded34 --- /dev/null +++ b/src/actions/list-domains.action.ts @@ -0,0 +1,6 @@ +import { domainsApiClient } from "../api"; +import { Domain } from "../types/domain.type"; + +export const listDomainsAction = async (): Promise => { + return await domainsApiClient.listDomains(); +}; diff --git a/src/actions/list-firewall-group-resources.action.ts b/src/actions/list-firewall-group-resources.action.ts new file mode 100644 index 0000000..b89595c --- /dev/null +++ b/src/actions/list-firewall-group-resources.action.ts @@ -0,0 +1,8 @@ +import { firewallApiClient } from "../api"; +import { FirewallGroupResource } from "../types/firewall-resource.type"; + +export const listFirewallGroupResourcesAction = async ( + groupId: string +): Promise => { + return await firewallApiClient.listFirewallGroupResources(groupId); +}; diff --git a/src/actions/list-firewall-groups-by-resource.action.ts b/src/actions/list-firewall-groups-by-resource.action.ts new file mode 100644 index 0000000..ef701b3 --- /dev/null +++ b/src/actions/list-firewall-groups-by-resource.action.ts @@ -0,0 +1,13 @@ +import { firewallApiClient } from "../api"; +import { FirewallGroup } from "../types/firewall-group.type"; +import { FirewallResourceType } from "../types/firewall-resource.type"; + +export const listFirewallGroupsByResourceAction = async ( + resourceType: FirewallResourceType, + resourceId: string +): Promise => { + return await firewallApiClient.listFirewallGroupsByResource( + resourceType, + resourceId + ); +}; diff --git a/src/actions/list-firewall-groups.action.ts b/src/actions/list-firewall-groups.action.ts new file mode 100644 index 0000000..794e25f --- /dev/null +++ b/src/actions/list-firewall-groups.action.ts @@ -0,0 +1,6 @@ +import { firewallApiClient } from "../api"; +import { FirewallGroup } from "../types/firewall-group.type"; + +export const listFirewallGroupsAction = async (): Promise => { + return await firewallApiClient.listFirewallGroups(); +}; diff --git a/src/actions/list-firewall-rules.action.ts b/src/actions/list-firewall-rules.action.ts new file mode 100644 index 0000000..6749737 --- /dev/null +++ b/src/actions/list-firewall-rules.action.ts @@ -0,0 +1,8 @@ +import { firewallApiClient } from "../api"; +import { FirewallRule } from "../types/firewall-rule.type"; + +export const listFirewallRulesAction = async ( + groupId: string +): Promise => { + return await firewallApiClient.listFirewallRules(groupId); +}; diff --git a/src/actions/list-floating-ips.action.ts b/src/actions/list-floating-ips.action.ts new file mode 100644 index 0000000..6b1c877 --- /dev/null +++ b/src/actions/list-floating-ips.action.ts @@ -0,0 +1,7 @@ +import { dbaasApiClient } from "../api"; +import { ListFloatingIpsResponseDto } from "../types/dto/list-floating-ips-response.dto"; + +export const listFloatingIpsAction = + async (): Promise => { + return await dbaasApiClient.listFloatingIps(); + }; diff --git a/src/actions/list-image-downloads.action.ts b/src/actions/list-image-downloads.action.ts new file mode 100644 index 0000000..c9fbfdc --- /dev/null +++ b/src/actions/list-image-downloads.action.ts @@ -0,0 +1,10 @@ +import { imagesApiClient } from "../api"; +import { ImageDownload } from "../types/image-download.type"; + +export const listImageDownloadsAction = async ( + imageId: string, + limit?: number, + offset?: number +): Promise => { + return await imagesApiClient.listImageDownloads(imageId, limit, offset); +}; diff --git a/src/actions/list-images.action.ts b/src/actions/list-images.action.ts new file mode 100644 index 0000000..ed8bf22 --- /dev/null +++ b/src/actions/list-images.action.ts @@ -0,0 +1,9 @@ +import { imagesApiClient } from "../api"; +import { Image } from "../types/image.type"; + +export const listImagesAction = async ( + limit?: number, + offset?: number +): Promise => { + return await imagesApiClient.listImages(limit, offset); +}; diff --git a/src/actions/list-k8s-addon-configs.action.ts b/src/actions/list-k8s-addon-configs.action.ts new file mode 100644 index 0000000..8d8644e --- /dev/null +++ b/src/actions/list-k8s-addon-configs.action.ts @@ -0,0 +1,8 @@ +import { kubernetesApiClient } from "../api"; +import { K8sAddonConfig } from "../types/k8s-addon.type"; + +export const listK8sAddonConfigsAction = async ( + clusterId: number +): Promise => { + return await kubernetesApiClient.listAddonConfigs(clusterId); +}; diff --git a/src/actions/list-k8s-addons.action.ts b/src/actions/list-k8s-addons.action.ts new file mode 100644 index 0000000..0302830 --- /dev/null +++ b/src/actions/list-k8s-addons.action.ts @@ -0,0 +1,8 @@ +import { kubernetesApiClient } from "../api"; +import { K8sAddon } from "../types/k8s-addon.type"; + +export const listK8sAddonsAction = async ( + clusterId: number +): Promise => { + return await kubernetesApiClient.listInstalledAddons(clusterId); +}; diff --git a/src/actions/list-k8s-cluster-nodes.action.ts b/src/actions/list-k8s-cluster-nodes.action.ts new file mode 100644 index 0000000..6f0e99c --- /dev/null +++ b/src/actions/list-k8s-cluster-nodes.action.ts @@ -0,0 +1,8 @@ +import { kubernetesApiClient } from "../api"; +import { K8sNode } from "../types/k8s-node.type"; + +export const listK8sClusterNodesAction = async ( + clusterId: number +): Promise => { + return await kubernetesApiClient.listClusterNodes(clusterId); +}; diff --git a/src/actions/list-k8s-clusters.action.ts b/src/actions/list-k8s-clusters.action.ts new file mode 100644 index 0000000..e4d5c53 --- /dev/null +++ b/src/actions/list-k8s-clusters.action.ts @@ -0,0 +1,9 @@ +import { kubernetesApiClient } from "../api"; +import { K8sCluster } from "../types/k8s-cluster.type"; + +export const listK8sClustersAction = async ( + limit?: number, + offset?: number +): Promise => { + return await kubernetesApiClient.listClusters(limit, offset); +}; diff --git a/src/actions/list-k8s-network-drivers.action.ts b/src/actions/list-k8s-network-drivers.action.ts new file mode 100644 index 0000000..6bf5cc4 --- /dev/null +++ b/src/actions/list-k8s-network-drivers.action.ts @@ -0,0 +1,5 @@ +import { kubernetesApiClient } from "../api"; + +export const listK8sNetworkDriversAction = async (): Promise => { + return await kubernetesApiClient.listNetworkDrivers(); +}; diff --git a/src/actions/list-k8s-node-group-nodes.action.ts b/src/actions/list-k8s-node-group-nodes.action.ts new file mode 100644 index 0000000..101e4ae --- /dev/null +++ b/src/actions/list-k8s-node-group-nodes.action.ts @@ -0,0 +1,16 @@ +import { kubernetesApiClient } from "../api"; +import { K8sNode } from "../types/k8s-node.type"; + +export const listK8sNodeGroupNodesAction = async ( + clusterId: number, + groupId: number, + limit?: number, + offset?: number +): Promise => { + return await kubernetesApiClient.listNodeGroupNodes( + clusterId, + groupId, + limit, + offset + ); +}; diff --git a/src/actions/list-k8s-node-groups.action.ts b/src/actions/list-k8s-node-groups.action.ts new file mode 100644 index 0000000..b65d6f7 --- /dev/null +++ b/src/actions/list-k8s-node-groups.action.ts @@ -0,0 +1,8 @@ +import { kubernetesApiClient } from "../api"; +import { K8sNodeGroup } from "../types/k8s-node-group.type"; + +export const listK8sNodeGroupsAction = async ( + clusterId: number +): Promise => { + return await kubernetesApiClient.listNodeGroups(clusterId); +}; diff --git a/src/actions/list-k8s-presets.action.ts b/src/actions/list-k8s-presets.action.ts new file mode 100644 index 0000000..26b4e61 --- /dev/null +++ b/src/actions/list-k8s-presets.action.ts @@ -0,0 +1,6 @@ +import { kubernetesApiClient } from "../api"; +import { K8sPreset } from "../types/k8s-preset.type"; + +export const listK8sPresetsAction = async (): Promise => { + return await kubernetesApiClient.listK8sPresets(); +}; diff --git a/src/actions/list-k8s-versions.action.ts b/src/actions/list-k8s-versions.action.ts new file mode 100644 index 0000000..28d373f --- /dev/null +++ b/src/actions/list-k8s-versions.action.ts @@ -0,0 +1,5 @@ +import { kubernetesApiClient } from "../api"; + +export const listK8sVersionsAction = async (): Promise => { + return await kubernetesApiClient.listK8sVersions(); +}; diff --git a/src/actions/list-knowledge-base-documents.action.ts b/src/actions/list-knowledge-base-documents.action.ts new file mode 100644 index 0000000..99b84cd --- /dev/null +++ b/src/actions/list-knowledge-base-documents.action.ts @@ -0,0 +1,12 @@ +import { + knowledgeBasesApiClient, + ListKnowledgeBaseDocumentsQuery, +} from "../api/knowledge-bases"; +import { KnowledgeBaseDocument } from "../types/knowledge-base.type"; + +export const listKnowledgeBaseDocumentsAction = async ( + id: number, + query: ListKnowledgeBaseDocumentsQuery = {} +): Promise<{ documents: KnowledgeBaseDocument[]; total: number }> => { + return await knowledgeBasesApiClient.listKnowledgeBaseDocuments(id, query); +}; diff --git a/src/actions/list-knowledge-base-token-packages.action.ts b/src/actions/list-knowledge-base-token-packages.action.ts new file mode 100644 index 0000000..4f0ea2d --- /dev/null +++ b/src/actions/list-knowledge-base-token-packages.action.ts @@ -0,0 +1,8 @@ +import { aiAgentsApiClient } from "../api"; +import { TokenPackage } from "../types/token-package.type"; + +export const listKnowledgeBaseTokenPackagesAction = async (): Promise< + TokenPackage[] +> => { + return await aiAgentsApiClient.listKnowledgeBaseTokenPackages(); +}; diff --git a/src/actions/list-knowledge-bases-v1.action.ts b/src/actions/list-knowledge-bases-v1.action.ts new file mode 100644 index 0000000..2996fff --- /dev/null +++ b/src/actions/list-knowledge-bases-v1.action.ts @@ -0,0 +1,8 @@ +import { knowledgeBasesApiClient } from "../api"; +import { KnowledgeBase } from "../types/knowledge-base.type"; + +export const listKnowledgeBasesV1Action = async (): Promise< + KnowledgeBase[] +> => { + return await knowledgeBasesApiClient.listKnowledgeBases(); +}; diff --git a/src/actions/list-knowledge-bases.action.ts b/src/actions/list-knowledge-bases.action.ts new file mode 100644 index 0000000..d4ba5c9 --- /dev/null +++ b/src/actions/list-knowledge-bases.action.ts @@ -0,0 +1,6 @@ +import { knowledgeBasesApiClient } from "../api"; +import { KnowledgeBase } from "../types/knowledge-base.type"; + +export const listKnowledgeBasesAction = async (): Promise => { + return await knowledgeBasesApiClient.listKnowledgeBasesV2(); +}; diff --git a/src/actions/list-locations.action.ts b/src/actions/list-locations.action.ts new file mode 100644 index 0000000..a536d98 --- /dev/null +++ b/src/actions/list-locations.action.ts @@ -0,0 +1,6 @@ +import { catalogsApiClient } from "../api"; +import { Location } from "../types/location.type"; + +export const listLocationsAction = async (): Promise => { + return await catalogsApiClient.listLocations(); +}; diff --git a/src/actions/list-mailboxes-by-domain.action.ts b/src/actions/list-mailboxes-by-domain.action.ts new file mode 100644 index 0000000..a0b5633 --- /dev/null +++ b/src/actions/list-mailboxes-by-domain.action.ts @@ -0,0 +1,8 @@ +import { mailApiClient } from "../api"; +import { Mailbox } from "../types/mailbox.type"; + +export const listMailboxesByDomainAction = async ( + domain: string +): Promise => { + return await mailApiClient.listMailboxesByDomain(domain); +}; diff --git a/src/actions/list-mailboxes-v1.action.ts b/src/actions/list-mailboxes-v1.action.ts new file mode 100644 index 0000000..b04be2f --- /dev/null +++ b/src/actions/list-mailboxes-v1.action.ts @@ -0,0 +1,6 @@ +import { mailApiClient } from "../api"; +import { Mailbox } from "../types/mailbox.type"; + +export const listMailboxesV1Action = async (): Promise => { + return await mailApiClient.listMailboxesV1(); +}; diff --git a/src/actions/list-mailboxes.action.ts b/src/actions/list-mailboxes.action.ts new file mode 100644 index 0000000..ff6a66d --- /dev/null +++ b/src/actions/list-mailboxes.action.ts @@ -0,0 +1,6 @@ +import { mailApiClient } from "../api"; +import { MailboxV2 } from "../types/mailbox.type"; + +export const listMailboxesAction = async (): Promise => { + return await mailApiClient.listMailboxesV2(); +}; diff --git a/src/actions/list-network-drive-available-resources.action.ts b/src/actions/list-network-drive-available-resources.action.ts new file mode 100644 index 0000000..094b535 --- /dev/null +++ b/src/actions/list-network-drive-available-resources.action.ts @@ -0,0 +1,8 @@ +import { networkDrivesApiClient } from "../api/network-drives"; +import { NetworkDriveAvailableResource } from "../types/network-drive-available-resource.type"; + +export const listNetworkDriveAvailableResourcesAction = async (): Promise< + NetworkDriveAvailableResource[] +> => { + return await networkDrivesApiClient.listNetworkDriveAvailableResources(); +}; diff --git a/src/actions/list-network-drive-presets.action.ts b/src/actions/list-network-drive-presets.action.ts new file mode 100644 index 0000000..68e625c --- /dev/null +++ b/src/actions/list-network-drive-presets.action.ts @@ -0,0 +1,8 @@ +import { networkDrivesApiClient } from "../api/network-drives"; +import { NetworkDrivePreset } from "../types/network-drive-preset.type"; + +export const listNetworkDrivePresetsAction = async (): Promise< + NetworkDrivePreset[] +> => { + return await networkDrivesApiClient.listNetworkDrivePresets(); +}; diff --git a/src/actions/list-network-drives.action.ts b/src/actions/list-network-drives.action.ts new file mode 100644 index 0000000..18b75f3 --- /dev/null +++ b/src/actions/list-network-drives.action.ts @@ -0,0 +1,6 @@ +import { networkDrivesApiClient } from "../api/network-drives"; +import { NetworkDrive } from "../types/network-drive.type"; + +export const listNetworkDrivesAction = async (): Promise => { + return await networkDrivesApiClient.listNetworkDrives(); +}; diff --git a/src/actions/list-project-balancers.action.ts b/src/actions/list-project-balancers.action.ts new file mode 100644 index 0000000..61c8089 --- /dev/null +++ b/src/actions/list-project-balancers.action.ts @@ -0,0 +1,7 @@ +import { projectsApiClient } from "../api/projects"; + +export const listProjectBalancersAction = async ( + projectId: number +): Promise => { + return await projectsApiClient.listProjectBalancers(projectId); +}; diff --git a/src/actions/list-project-buckets.action.ts b/src/actions/list-project-buckets.action.ts new file mode 100644 index 0000000..5d914b4 --- /dev/null +++ b/src/actions/list-project-buckets.action.ts @@ -0,0 +1,7 @@ +import { projectsApiClient } from "../api/projects"; + +export const listProjectBucketsAction = async ( + projectId: number +): Promise => { + return await projectsApiClient.listProjectBuckets(projectId); +}; diff --git a/src/actions/list-project-clusters.action.ts b/src/actions/list-project-clusters.action.ts new file mode 100644 index 0000000..7f7a125 --- /dev/null +++ b/src/actions/list-project-clusters.action.ts @@ -0,0 +1,7 @@ +import { projectsApiClient } from "../api/projects"; + +export const listProjectClustersAction = async ( + projectId: number +): Promise => { + return await projectsApiClient.listProjectClusters(projectId); +}; diff --git a/src/actions/list-project-databases.action.ts b/src/actions/list-project-databases.action.ts new file mode 100644 index 0000000..b338a60 --- /dev/null +++ b/src/actions/list-project-databases.action.ts @@ -0,0 +1,7 @@ +import { projectsApiClient } from "../api/projects"; + +export const listProjectDatabasesAction = async ( + projectId: number +): Promise => { + return await projectsApiClient.listProjectDatabases(projectId); +}; diff --git a/src/actions/list-project-dedicated.action.ts b/src/actions/list-project-dedicated.action.ts new file mode 100644 index 0000000..e923a5f --- /dev/null +++ b/src/actions/list-project-dedicated.action.ts @@ -0,0 +1,7 @@ +import { projectsApiClient } from "../api/projects"; + +export const listProjectDedicatedAction = async ( + projectId: number +): Promise => { + return await projectsApiClient.listProjectDedicated(projectId); +}; diff --git a/src/actions/list-project-resources.action.ts b/src/actions/list-project-resources.action.ts new file mode 100644 index 0000000..7e8919c --- /dev/null +++ b/src/actions/list-project-resources.action.ts @@ -0,0 +1,8 @@ +import { projectsApiClient } from "../api/projects"; +import { ListProjectResourcesResponseDto } from "../types/dto/list-project-resources-response.dto"; + +export const listProjectResourcesAction = async ( + projectId: number +): Promise => { + return await projectsApiClient.listProjectResources(projectId); +}; diff --git a/src/actions/list-project-servers.action.ts b/src/actions/list-project-servers.action.ts new file mode 100644 index 0000000..bb74d6e --- /dev/null +++ b/src/actions/list-project-servers.action.ts @@ -0,0 +1,7 @@ +import { projectsApiClient } from "../api/projects"; + +export const listProjectServersAction = async ( + projectId: number +): Promise => { + return await projectsApiClient.listProjectServers(projectId); +}; diff --git a/src/actions/list-projects.action.ts b/src/actions/list-projects.action.ts new file mode 100644 index 0000000..eddf1ea --- /dev/null +++ b/src/actions/list-projects.action.ts @@ -0,0 +1,6 @@ +import { projectsApiClient } from "../api/projects"; +import { Project } from "../types/project.type"; + +export const listProjectsAction = async (): Promise => { + return await projectsApiClient.listProjects(); +}; diff --git a/src/actions/list-server-configurators.action.ts b/src/actions/list-server-configurators.action.ts new file mode 100644 index 0000000..151d2a2 --- /dev/null +++ b/src/actions/list-server-configurators.action.ts @@ -0,0 +1,8 @@ +import { catalogsApiClient } from "../api"; +import { ServerConfigurator } from "../types/server-configurator.type"; + +export const listServerConfiguratorsAction = async (): Promise< + ServerConfigurator[] +> => { + return await catalogsApiClient.listServerConfigurators(); +}; diff --git a/src/actions/list-server-disk-backups.action.ts b/src/actions/list-server-disk-backups.action.ts new file mode 100644 index 0000000..7839ffd --- /dev/null +++ b/src/actions/list-server-disk-backups.action.ts @@ -0,0 +1,9 @@ +import { serversApiClient } from "../api"; +import { ServerBackup } from "../types/server-backup.type"; + +export const listServerDiskBackupsAction = async ( + serverId: number, + diskId: number +): Promise => { + return await serversApiClient.listServerDiskBackups(serverId, diskId); +}; diff --git a/src/actions/list-server-disks.action.ts b/src/actions/list-server-disks.action.ts new file mode 100644 index 0000000..cc0b7ee --- /dev/null +++ b/src/actions/list-server-disks.action.ts @@ -0,0 +1,8 @@ +import { serversApiClient } from "../api"; +import { ServerDisk } from "../types/server-disk.type"; + +export const listServerDisksAction = async ( + serverId: number +): Promise => { + return await serversApiClient.listServerDisks(serverId); +}; diff --git a/src/actions/list-server-ips.action.ts b/src/actions/list-server-ips.action.ts new file mode 100644 index 0000000..4578bb4 --- /dev/null +++ b/src/actions/list-server-ips.action.ts @@ -0,0 +1,8 @@ +import { serversApiClient } from "../api"; +import { ServerIp } from "../types/server-ip.type"; + +export const listServerIpsAction = async ( + serverId: number +): Promise => { + return await serversApiClient.listServerIps(serverId); +}; diff --git a/src/actions/list-server-os.action.ts b/src/actions/list-server-os.action.ts new file mode 100644 index 0000000..389af37 --- /dev/null +++ b/src/actions/list-server-os.action.ts @@ -0,0 +1,6 @@ +import { catalogsApiClient } from "../api"; +import { ServerOs } from "../types/server-os.type"; + +export const listServerOsAction = async (): Promise => { + return await catalogsApiClient.listServerOs(); +}; diff --git a/src/actions/list-server-presets.action.ts b/src/actions/list-server-presets.action.ts new file mode 100644 index 0000000..c41f56d --- /dev/null +++ b/src/actions/list-server-presets.action.ts @@ -0,0 +1,6 @@ +import { catalogsApiClient } from "../api"; +import { ServerPreset } from "../types/server-preset.type"; + +export const listServerPresetsAction = async (): Promise => { + return await catalogsApiClient.listServerPresets(); +}; diff --git a/src/actions/list-server-software.action.ts b/src/actions/list-server-software.action.ts new file mode 100644 index 0000000..1f5205b --- /dev/null +++ b/src/actions/list-server-software.action.ts @@ -0,0 +1,6 @@ +import { catalogsApiClient } from "../api"; +import { ServerSoftware } from "../types/server-software.type"; + +export const listServerSoftwareAction = async (): Promise => { + return await catalogsApiClient.listServerSoftware(); +}; diff --git a/src/actions/list-servers.action.ts b/src/actions/list-servers.action.ts new file mode 100644 index 0000000..0ea1efe --- /dev/null +++ b/src/actions/list-servers.action.ts @@ -0,0 +1,6 @@ +import { serversApiClient } from "../api"; +import { Server } from "../types/server.type"; + +export const listServersAction = async (): Promise => { + return await serversApiClient.listServers(); +}; diff --git a/src/actions/list-ssh-keys.action.ts b/src/actions/list-ssh-keys.action.ts new file mode 100644 index 0000000..e9fce0a --- /dev/null +++ b/src/actions/list-ssh-keys.action.ts @@ -0,0 +1,6 @@ +import { sshKeysApiClient } from "../api"; +import { SshKey } from "../types/ssh-key.type"; + +export const listSshKeysAction = async (): Promise => { + return await sshKeysApiClient.listSshKeys(); +}; diff --git a/src/actions/list-vpc-ports.action.ts b/src/actions/list-vpc-ports.action.ts new file mode 100644 index 0000000..ead94c3 --- /dev/null +++ b/src/actions/list-vpc-ports.action.ts @@ -0,0 +1,6 @@ +import { dbaasApiClient } from "../api"; +import { VpcPort } from "../types/vpc-port.type"; + +export const listVpcPortsAction = async (vpcId: string): Promise => { + return await dbaasApiClient.listVpcPorts(vpcId); +}; diff --git a/src/actions/list-vpc-services.action.ts b/src/actions/list-vpc-services.action.ts new file mode 100644 index 0000000..b53c4f6 --- /dev/null +++ b/src/actions/list-vpc-services.action.ts @@ -0,0 +1,8 @@ +import { dbaasApiClient } from "../api"; +import { VpcService } from "../types/vpc-service.type"; + +export const listVpcServicesAction = async ( + vpcId: string +): Promise => { + return await dbaasApiClient.listVpcServices(vpcId); +}; diff --git a/src/actions/mount-network-drive.action.ts b/src/actions/mount-network-drive.action.ts new file mode 100644 index 0000000..0fc25df --- /dev/null +++ b/src/actions/mount-network-drive.action.ts @@ -0,0 +1,9 @@ +import { networkDrivesApiClient } from "../api/network-drives"; +import { MountNetworkDriveRequestDto } from "../types/dto/mount-network-drive-request.dto"; + +export const mountNetworkDriveAction = async ( + networkDriveId: string, + data: MountNetworkDriveRequestDto +): Promise => { + await networkDrivesApiClient.mountNetworkDrive(networkDriveId, data); +}; diff --git a/src/actions/reboot-server.action.ts b/src/actions/reboot-server.action.ts new file mode 100644 index 0000000..35ae4a0 --- /dev/null +++ b/src/actions/reboot-server.action.ts @@ -0,0 +1,5 @@ +import { serversApiClient } from "../api"; + +export const rebootServerAction = async (serverId: number): Promise => { + await serversApiClient.rebootServer(serverId); +}; diff --git a/src/actions/reduce-k8s-node-group-nodes.action.ts b/src/actions/reduce-k8s-node-group-nodes.action.ts new file mode 100644 index 0000000..acdd351 --- /dev/null +++ b/src/actions/reduce-k8s-node-group-nodes.action.ts @@ -0,0 +1,9 @@ +import { kubernetesApiClient } from "../api"; + +export const reduceK8sNodeGroupNodesAction = async ( + clusterId: number, + groupId: number, + count: number +): Promise => { + await kubernetesApiClient.reduceNodeGroupNodes(clusterId, groupId, { count }); +}; diff --git a/src/actions/refresh-api-key.action.ts b/src/actions/refresh-api-key.action.ts new file mode 100644 index 0000000..f569c5e --- /dev/null +++ b/src/actions/refresh-api-key.action.ts @@ -0,0 +1,10 @@ +import { authApiClient } from "../api"; +import { CreatedApiKey } from "../types/api-key.type"; +import { RefreshApiKeyRequestDto } from "../types/dto/refresh-api-key-request.dto"; + +export const refreshApiKeyAction = async ( + tokenId: string, + data: RefreshApiKeyRequestDto = {} +): Promise => { + return await authApiClient.refreshApiKey(tokenId, data); +}; diff --git a/src/actions/reindex-knowledge-base-document.action.ts b/src/actions/reindex-knowledge-base-document.action.ts new file mode 100644 index 0000000..10949ef --- /dev/null +++ b/src/actions/reindex-knowledge-base-document.action.ts @@ -0,0 +1,8 @@ +import { knowledgeBasesApiClient } from "../api"; + +export const reindexKnowledgeBaseDocumentAction = async ( + id: number, + documentId: number +): Promise => { + await knowledgeBasesApiClient.reindexKnowledgeBaseDocument(id, documentId); +}; diff --git a/src/actions/remove-balancer-ips.action.ts b/src/actions/remove-balancer-ips.action.ts new file mode 100644 index 0000000..b78f5c2 --- /dev/null +++ b/src/actions/remove-balancer-ips.action.ts @@ -0,0 +1,8 @@ +import { balancersApiClient } from "../api"; + +export const removeBalancerIpsAction = async ( + balancerId: number, + ips: string[] +): Promise => { + await balancersApiClient.removeBalancerIps(balancerId, ips); +}; diff --git a/src/actions/remove-ssh-key-from-server.action.ts b/src/actions/remove-ssh-key-from-server.action.ts new file mode 100644 index 0000000..4d6ebe4 --- /dev/null +++ b/src/actions/remove-ssh-key-from-server.action.ts @@ -0,0 +1,8 @@ +import { sshKeysApiClient } from "../api"; + +export const removeSshKeyFromServerAction = async ( + serverId: number, + sshKeyId: number +): Promise => { + await sshKeysApiClient.removeSshKeyFromServer(serverId, sshKeyId); +}; diff --git a/src/actions/reset-server-password.action.ts b/src/actions/reset-server-password.action.ts new file mode 100644 index 0000000..2aadf10 --- /dev/null +++ b/src/actions/reset-server-password.action.ts @@ -0,0 +1,7 @@ +import { serversApiClient } from "../api"; + +export const resetServerPasswordAction = async ( + serverId: number +): Promise => { + await serversApiClient.resetServerPassword(serverId); +}; diff --git a/src/actions/resize-server.action.ts b/src/actions/resize-server.action.ts new file mode 100644 index 0000000..03a96fb --- /dev/null +++ b/src/actions/resize-server.action.ts @@ -0,0 +1,9 @@ +import { serversApiClient, ResizeServerParams } from "../api/servers"; +import { Server } from "../types/server.type"; + +export const resizeServerAction = async ( + serverId: number, + params: ResizeServerParams +): Promise => { + return await serversApiClient.resizeServer(serverId, params); +}; diff --git a/src/actions/restore-database-backup.action.ts b/src/actions/restore-database-backup.action.ts new file mode 100644 index 0000000..90abb04 --- /dev/null +++ b/src/actions/restore-database-backup.action.ts @@ -0,0 +1,8 @@ +import { dbaasApiClient } from "../api"; + +export const restoreDatabaseBackupAction = async ( + dbId: number, + backupId: number +): Promise => { + await dbaasApiClient.restoreDatabaseBackup(dbId, backupId); +}; diff --git a/src/actions/server-disk-backup-action.action.ts b/src/actions/server-disk-backup-action.action.ts new file mode 100644 index 0000000..69d5e82 --- /dev/null +++ b/src/actions/server-disk-backup-action.action.ts @@ -0,0 +1,18 @@ +import { + serversApiClient, + ServerDiskBackupAction, +} from "../api/servers"; + +export const serverDiskBackupActionAction = async ( + serverId: number, + diskId: number, + backupId: number, + action: ServerDiskBackupAction +): Promise => { + await serversApiClient.serverDiskBackupAction( + serverId, + diskId, + backupId, + action + ); +}; diff --git a/src/actions/set-server-boot-mode.action.ts b/src/actions/set-server-boot-mode.action.ts new file mode 100644 index 0000000..40f3013 --- /dev/null +++ b/src/actions/set-server-boot-mode.action.ts @@ -0,0 +1,8 @@ +import { serversApiClient, ServerBootMode } from "../api/servers"; + +export const setServerBootModeAction = async ( + serverId: number, + bootMode: ServerBootMode +): Promise => { + await serversApiClient.setServerBootMode(serverId, bootMode); +}; diff --git a/src/actions/set-server-nat-mode.action.ts b/src/actions/set-server-nat-mode.action.ts new file mode 100644 index 0000000..284a7ef --- /dev/null +++ b/src/actions/set-server-nat-mode.action.ts @@ -0,0 +1,8 @@ +import { serversApiClient, ServerNatMode } from "../api/servers"; + +export const setServerNatModeAction = async ( + serverId: number, + natMode: ServerNatMode +): Promise => { + await serversApiClient.setServerNatMode(serverId, natMode); +}; diff --git a/src/actions/shutdown-server.action.ts b/src/actions/shutdown-server.action.ts new file mode 100644 index 0000000..2547164 --- /dev/null +++ b/src/actions/shutdown-server.action.ts @@ -0,0 +1,5 @@ +import { serversApiClient } from "../api"; + +export const shutdownServerAction = async (serverId: number): Promise => { + await serversApiClient.shutdownServer(serverId); +}; diff --git a/src/actions/start-server.action.ts b/src/actions/start-server.action.ts new file mode 100644 index 0000000..d3a11e1 --- /dev/null +++ b/src/actions/start-server.action.ts @@ -0,0 +1,5 @@ +import { serversApiClient } from "../api"; + +export const startServerAction = async (serverId: number): Promise => { + await serversApiClient.startServer(serverId); +}; diff --git a/src/actions/tlds.action.ts b/src/actions/tlds.action.ts new file mode 100644 index 0000000..08f6c2f --- /dev/null +++ b/src/actions/tlds.action.ts @@ -0,0 +1,10 @@ +import { domainsApiClient } from "../api"; +import { TopLevelDomain } from "../types/top-level-domain.type"; + +export const listTldsAction = async (): Promise => { + return await domainsApiClient.listTlds(); +}; + +export const getTldAction = async (tldId: number): Promise => { + return await domainsApiClient.getTld(tldId); +}; diff --git a/src/actions/transfer-bucket.action.ts b/src/actions/transfer-bucket.action.ts new file mode 100644 index 0000000..0443cca --- /dev/null +++ b/src/actions/transfer-bucket.action.ts @@ -0,0 +1,8 @@ +import { s3BucketsApiClient } from "../api"; +import { TransferBucketRequestDto } from "../types/dto/transfer-bucket-request.dto"; + +export const transferBucketAction = async ( + data: TransferBucketRequestDto +): Promise => { + await s3BucketsApiClient.transferBucket(data); +}; diff --git a/src/actions/transfer-project-resource.action.ts b/src/actions/transfer-project-resource.action.ts new file mode 100644 index 0000000..ac60e0b --- /dev/null +++ b/src/actions/transfer-project-resource.action.ts @@ -0,0 +1,17 @@ +import { projectsApiClient } from "../api/projects"; +import { ProjectResource } from "../types/project.type"; +import { ProjectResourceTypeEnum } from "../types/project-resource-type.enum"; + +export const transferProjectResourceAction = async ( + fromProjectId: number, + toProjectId: number, + resourceId: number, + resourceType: ProjectResourceTypeEnum +): Promise => { + return await projectsApiClient.transferProjectResource( + fromProjectId, + toProjectId, + resourceId, + resourceType + ); +}; diff --git a/src/actions/unbind-floating-ip.action.ts b/src/actions/unbind-floating-ip.action.ts new file mode 100644 index 0000000..065e238 --- /dev/null +++ b/src/actions/unbind-floating-ip.action.ts @@ -0,0 +1,7 @@ +import { dbaasApiClient } from "../api"; + +export const unbindFloatingIpAction = async ( + floatingIpId: string +): Promise => { + await dbaasApiClient.unbindFloatingIp(floatingIpId); +}; diff --git a/src/actions/uninstall-k8s-addon.action.ts b/src/actions/uninstall-k8s-addon.action.ts new file mode 100644 index 0000000..b8a6dfc --- /dev/null +++ b/src/actions/uninstall-k8s-addon.action.ts @@ -0,0 +1,8 @@ +import { kubernetesApiClient } from "../api"; + +export const uninstallK8sAddonAction = async ( + clusterId: number, + addonId: number +): Promise => { + await kubernetesApiClient.uninstallAddon(clusterId, addonId); +}; diff --git a/src/actions/unlink-firewall-resource.action.ts b/src/actions/unlink-firewall-resource.action.ts new file mode 100644 index 0000000..ba5b8b4 --- /dev/null +++ b/src/actions/unlink-firewall-resource.action.ts @@ -0,0 +1,14 @@ +import { firewallApiClient } from "../api"; +import { FirewallResourceType } from "../types/firewall-resource.type"; + +export const unlinkFirewallResourceAction = async ( + groupId: string, + resourceId: string, + resourceType: FirewallResourceType = "server" +): Promise => { + await firewallApiClient.unlinkFirewallResource( + groupId, + resourceId, + resourceType + ); +}; diff --git a/src/actions/unlink-knowledge-base.action.ts b/src/actions/unlink-knowledge-base.action.ts new file mode 100644 index 0000000..46e2151 --- /dev/null +++ b/src/actions/unlink-knowledge-base.action.ts @@ -0,0 +1,8 @@ +import { knowledgeBasesApiClient } from "../api"; + +export const unlinkKnowledgeBaseAction = async ( + id: number, + agentId: number +): Promise => { + await knowledgeBasesApiClient.unlinkKnowledgeBaseFromAgent(id, agentId); +}; diff --git a/src/actions/unmount-network-drive.action.ts b/src/actions/unmount-network-drive.action.ts new file mode 100644 index 0000000..efb619b --- /dev/null +++ b/src/actions/unmount-network-drive.action.ts @@ -0,0 +1,7 @@ +import { networkDrivesApiClient } from "../api/network-drives"; + +export const unmountNetworkDriveAction = async ( + networkDriveId: string +): Promise => { + await networkDrivesApiClient.unmountNetworkDrive(networkDriveId); +}; diff --git a/src/actions/unmount-server-image.action.ts b/src/actions/unmount-server-image.action.ts new file mode 100644 index 0000000..4004973 --- /dev/null +++ b/src/actions/unmount-server-image.action.ts @@ -0,0 +1,7 @@ +import { serversApiClient } from "../api"; + +export const unmountServerImageAction = async ( + serverId: number +): Promise => { + await serversApiClient.unmountServerImage(serverId); +}; diff --git a/src/actions/update-ai-agent.action.ts b/src/actions/update-ai-agent.action.ts new file mode 100644 index 0000000..0796642 --- /dev/null +++ b/src/actions/update-ai-agent.action.ts @@ -0,0 +1,10 @@ +import { aiAgentsApiClient } from "../api"; +import { AiAgent } from "../types/ai-agent.type"; +import { UpdateAiAgentRequestDto } from "../types/dto/update-ai-agent-request.dto"; + +export const updateAiAgentAction = async ( + agentId: number, + data: UpdateAiAgentRequestDto +): Promise => { + return await aiAgentsApiClient.updateAgent(agentId, data); +}; diff --git a/src/actions/update-balancer-rule.action.ts b/src/actions/update-balancer-rule.action.ts new file mode 100644 index 0000000..4d85441 --- /dev/null +++ b/src/actions/update-balancer-rule.action.ts @@ -0,0 +1,11 @@ +import { balancersApiClient } from "../api"; +import { BalancerRule } from "../types/balancer.type"; +import { UpdateBalancerRuleRequestDto } from "../types/dto/create-balancer-rule-request.dto"; + +export const updateBalancerRuleAction = async ( + balancerId: number, + ruleId: number, + data: UpdateBalancerRuleRequestDto +): Promise => { + return await balancersApiClient.updateBalancerRule(balancerId, ruleId, data); +}; diff --git a/src/actions/update-balancer.action.ts b/src/actions/update-balancer.action.ts new file mode 100644 index 0000000..2f32451 --- /dev/null +++ b/src/actions/update-balancer.action.ts @@ -0,0 +1,10 @@ +import { balancersApiClient } from "../api"; +import { Balancer } from "../types/balancer.type"; +import { UpdateBalancerRequestDto } from "../types/dto/update-balancer-request.dto"; + +export const updateBalancerAction = async ( + balancerId: number, + data: UpdateBalancerRequestDto +): Promise => { + return await balancersApiClient.updateBalancer(balancerId, data); +}; diff --git a/src/actions/update-bucket-user.action.ts b/src/actions/update-bucket-user.action.ts new file mode 100644 index 0000000..cdb2cd3 --- /dev/null +++ b/src/actions/update-bucket-user.action.ts @@ -0,0 +1,9 @@ +import { s3BucketsApiClient } from "../api"; +import { BucketUser } from "../types/bucket-user.type"; + +export const updateBucketUserAction = async ( + userId: number, + secretKey: string +): Promise => { + return await s3BucketsApiClient.updateBucketUser(userId, secretKey); +}; diff --git a/src/actions/update-bucket.action.ts b/src/actions/update-bucket.action.ts new file mode 100644 index 0000000..b08bafc --- /dev/null +++ b/src/actions/update-bucket.action.ts @@ -0,0 +1,10 @@ +import { s3BucketsApiClient } from "../api"; +import { Bucket } from "../types/bucket.type"; +import { UpdateBucketRequestDto } from "../types/dto/update-bucket-request.dto"; + +export const updateBucketAction = async ( + bucketId: number, + data: UpdateBucketRequestDto +): Promise => { + return await s3BucketsApiClient.updateBucket(bucketId, data); +}; diff --git a/src/actions/update-container-registry.action.ts b/src/actions/update-container-registry.action.ts new file mode 100644 index 0000000..b6b8cc4 --- /dev/null +++ b/src/actions/update-container-registry.action.ts @@ -0,0 +1,13 @@ +import { containerRegistryApiClient } from "../api"; +import { ContainerRegistry } from "../types/container-registry.type"; +import { UpdateContainerRegistryRequestDto } from "../types/dto/update-container-registry-request.dto"; + +export const updateContainerRegistryAction = async ( + registryId: number, + data: UpdateContainerRegistryRequestDto +): Promise => { + return await containerRegistryApiClient.updateContainerRegistry( + registryId, + data + ); +}; diff --git a/src/actions/update-database-admin.action.ts b/src/actions/update-database-admin.action.ts new file mode 100644 index 0000000..cd94028 --- /dev/null +++ b/src/actions/update-database-admin.action.ts @@ -0,0 +1,11 @@ +import { dbaasApiClient } from "../api"; +import { DatabaseAdminEntity } from "../types/database-cluster.type"; +import { UpdateDatabaseAdminRequestDto } from "../types/dto/update-database-admin-request.dto"; + +export const updateDatabaseAdminAction = async ( + clusterId: number, + adminId: number, + data: UpdateDatabaseAdminRequestDto +): Promise => { + return await dbaasApiClient.updateDatabaseAdmin(clusterId, adminId, data); +}; diff --git a/src/actions/update-database-auto-backups.action.ts b/src/actions/update-database-auto-backups.action.ts new file mode 100644 index 0000000..a2f593b --- /dev/null +++ b/src/actions/update-database-auto-backups.action.ts @@ -0,0 +1,10 @@ +import { dbaasApiClient } from "../api"; +import { DatabaseAutoBackupSettings } from "../types/database-cluster.type"; +import { UpdateDatabaseAutoBackupsRequestDto } from "../types/dto/update-database-auto-backups-request.dto"; + +export const updateDatabaseAutoBackupsAction = async ( + dbId: number, + data: UpdateDatabaseAutoBackupsRequestDto +): Promise => { + return await dbaasApiClient.updateDatabaseAutoBackups(dbId, data); +}; diff --git a/src/actions/update-database-cluster.action.ts b/src/actions/update-database-cluster.action.ts new file mode 100644 index 0000000..3c5c5da --- /dev/null +++ b/src/actions/update-database-cluster.action.ts @@ -0,0 +1,10 @@ +import { dbaasApiClient } from "../api"; +import { DatabaseCluster } from "../types/database-cluster.type"; +import { UpdateDatabaseClusterRequestDto } from "../types/dto/update-database-cluster-request.dto"; + +export const updateDatabaseClusterAction = async ( + clusterId: number, + data: UpdateDatabaseClusterRequestDto +): Promise => { + return await dbaasApiClient.updateDatabaseCluster(clusterId, data); +}; diff --git a/src/actions/update-database-instance.action.ts b/src/actions/update-database-instance.action.ts new file mode 100644 index 0000000..bded3c1 --- /dev/null +++ b/src/actions/update-database-instance.action.ts @@ -0,0 +1,15 @@ +import { dbaasApiClient } from "../api"; +import { DatabaseInstanceEntity } from "../types/database-cluster.type"; +import { UpdateDatabaseInstanceRequestDto } from "../types/dto/update-database-instance-request.dto"; + +export const updateDatabaseInstanceAction = async ( + clusterId: number, + instanceId: number, + data: UpdateDatabaseInstanceRequestDto +): Promise => { + return await dbaasApiClient.updateDatabaseInstance( + clusterId, + instanceId, + data + ); +}; diff --git a/src/actions/update-database.action.ts b/src/actions/update-database.action.ts new file mode 100644 index 0000000..c9d9573 --- /dev/null +++ b/src/actions/update-database.action.ts @@ -0,0 +1,10 @@ +import { dbaasApiClient } from "../api"; +import { Database } from "../types/database.type"; +import { UpdateDatabaseRequestDto } from "../types/dto/update-database-request.dto"; + +export const updateDatabaseAction = async ( + dbId: number, + data: UpdateDatabaseRequestDto +): Promise => { + return await dbaasApiClient.updateDatabase(dbId, data); +}; diff --git a/src/actions/update-dedicated-server.action.ts b/src/actions/update-dedicated-server.action.ts new file mode 100644 index 0000000..8dd3df4 --- /dev/null +++ b/src/actions/update-dedicated-server.action.ts @@ -0,0 +1,13 @@ +import { dedicatedServersApiClient } from "../api"; +import { DedicatedServer } from "../types/dedicated-server.type"; +import { UpdateDedicatedServerRequestDto } from "../types/dto/update-dedicated-server-request.dto"; + +export const updateDedicatedServerAction = async ( + dedicatedId: number, + data: UpdateDedicatedServerRequestDto +): Promise => { + return await dedicatedServersApiClient.updateDedicatedServer( + dedicatedId, + data + ); +}; diff --git a/src/actions/update-dns-record.action.ts b/src/actions/update-dns-record.action.ts new file mode 100644 index 0000000..0a3dff3 --- /dev/null +++ b/src/actions/update-dns-record.action.ts @@ -0,0 +1,11 @@ +import { domainsApiClient } from "../api"; +import { DnsRecordV2 } from "../types/dns-record.type"; +import { CreateDnsRecordV2RequestDto } from "../types/dto/create-dns-record-request.dto"; + +export const updateDnsRecordAction = async ( + fqdn: string, + recordId: number, + data: CreateDnsRecordV2RequestDto +): Promise => { + return await domainsApiClient.updateDnsRecord(fqdn, recordId, data); +}; diff --git a/src/actions/update-domain-name-servers.action.ts b/src/actions/update-domain-name-servers.action.ts new file mode 100644 index 0000000..80b68f0 --- /dev/null +++ b/src/actions/update-domain-name-servers.action.ts @@ -0,0 +1,10 @@ +import { domainsApiClient } from "../api"; +import { DomainNameServer } from "../types/domain-name-server.type"; +import { UpdateDomainNameServersRequestDto } from "../types/dto/update-domain-name-servers-request.dto"; + +export const updateDomainNameServersAction = async ( + fqdn: string, + data: UpdateDomainNameServersRequestDto +): Promise => { + return await domainsApiClient.updateNameServers(fqdn, data); +}; diff --git a/src/actions/update-domain.action.ts b/src/actions/update-domain.action.ts new file mode 100644 index 0000000..b2be33c --- /dev/null +++ b/src/actions/update-domain.action.ts @@ -0,0 +1,10 @@ +import { domainsApiClient } from "../api"; +import { Domain } from "../types/domain.type"; +import { UpdateDomainRequestDto } from "../types/dto/update-domain-request.dto"; + +export const updateDomainAction = async ( + fqdn: string, + data: UpdateDomainRequestDto +): Promise => { + return await domainsApiClient.updateDomain(fqdn, data); +}; diff --git a/src/actions/update-firewall-group.action.ts b/src/actions/update-firewall-group.action.ts new file mode 100644 index 0000000..7f0d751 --- /dev/null +++ b/src/actions/update-firewall-group.action.ts @@ -0,0 +1,13 @@ +import { firewallApiClient } from "../api"; +import { FirewallGroup } from "../types/firewall-group.type"; + +export const updateFirewallGroupAction = async ( + groupId: string, + name: string, + description?: string +): Promise => { + return await firewallApiClient.updateFirewallGroup(groupId, { + name, + description, + }); +}; diff --git a/src/actions/update-firewall-rule.action.ts b/src/actions/update-firewall-rule.action.ts new file mode 100644 index 0000000..1e82e6f --- /dev/null +++ b/src/actions/update-firewall-rule.action.ts @@ -0,0 +1,11 @@ +import { firewallApiClient } from "../api"; +import { UpdateFirewallRuleRequestDto } from "../types/dto/update-firewall-rule-request.dto"; +import { FirewallRule } from "../types/firewall-rule.type"; + +export const updateFirewallRuleAction = async ( + groupId: string, + ruleId: string, + data: UpdateFirewallRuleRequestDto +): Promise => { + return await firewallApiClient.updateFirewallRule(groupId, ruleId, data); +}; diff --git a/src/actions/update-floating-ip.action.ts b/src/actions/update-floating-ip.action.ts new file mode 100644 index 0000000..b7d1a60 --- /dev/null +++ b/src/actions/update-floating-ip.action.ts @@ -0,0 +1,10 @@ +import { dbaasApiClient } from "../api"; +import { FloatingIp } from "../types/floating-ip.type"; +import { UpdateFloatingIpRequestDto } from "../types/dto/update-floating-ip-request.dto"; + +export const updateFloatingIpAction = async ( + floatingIpId: string, + data: UpdateFloatingIpRequestDto +): Promise => { + return await dbaasApiClient.updateFloatingIp(floatingIpId, data); +}; diff --git a/src/actions/update-image.action.ts b/src/actions/update-image.action.ts new file mode 100644 index 0000000..3759a55 --- /dev/null +++ b/src/actions/update-image.action.ts @@ -0,0 +1,10 @@ +import { imagesApiClient } from "../api"; +import { Image } from "../types/image.type"; +import { UpdateImageRequestDto } from "../types/dto/update-image-request.dto"; + +export const updateImageAction = async ( + imageId: string, + data: UpdateImageRequestDto +): Promise => { + return await imagesApiClient.updateImage(imageId, data); +}; diff --git a/src/actions/update-k8s-addon.action.ts b/src/actions/update-k8s-addon.action.ts new file mode 100644 index 0000000..86c2b0c --- /dev/null +++ b/src/actions/update-k8s-addon.action.ts @@ -0,0 +1,10 @@ +import { kubernetesApiClient } from "../api"; +import { InstallK8sAddonRequestDto } from "../types/dto/install-k8s-addon-request.dto"; + +export const updateK8sAddonAction = async ( + clusterId: number, + addonId: number, + data: InstallK8sAddonRequestDto +): Promise => { + await kubernetesApiClient.updateAddon(clusterId, addonId, data); +}; diff --git a/src/actions/update-k8s-cluster-version.action.ts b/src/actions/update-k8s-cluster-version.action.ts new file mode 100644 index 0000000..aa39028 --- /dev/null +++ b/src/actions/update-k8s-cluster-version.action.ts @@ -0,0 +1,10 @@ +import { kubernetesApiClient } from "../api"; + +export const updateK8sClusterVersionAction = async ( + clusterId: number, + k8sVersion?: string +): Promise => { + await kubernetesApiClient.updateClusterVersion(clusterId, { + k8s_version: k8sVersion, + }); +}; diff --git a/src/actions/update-knowledge-base.action.ts b/src/actions/update-knowledge-base.action.ts new file mode 100644 index 0000000..6515b61 --- /dev/null +++ b/src/actions/update-knowledge-base.action.ts @@ -0,0 +1,10 @@ +import { knowledgeBasesApiClient } from "../api"; +import { KnowledgeBase } from "../types/knowledge-base.type"; +import { UpdateKnowledgeBaseRequestDto } from "../types/dto/update-knowledge-base-request.dto"; + +export const updateKnowledgeBaseAction = async ( + id: number, + data: UpdateKnowledgeBaseRequestDto +): Promise => { + return await knowledgeBasesApiClient.updateKnowledgeBase(id, data); +}; diff --git a/src/actions/update-mail-domain-info.action.ts b/src/actions/update-mail-domain-info.action.ts new file mode 100644 index 0000000..a3303cf --- /dev/null +++ b/src/actions/update-mail-domain-info.action.ts @@ -0,0 +1,9 @@ +import { mailApiClient } from "../api"; +import { MailDomainInfo } from "../types/mailbox.type"; + +export const updateMailDomainInfoAction = async ( + domain: string, + email: string +): Promise => { + return await mailApiClient.updateMailDomainInfo(domain, { email }); +}; diff --git a/src/actions/update-mailbox-v1.action.ts b/src/actions/update-mailbox-v1.action.ts new file mode 100644 index 0000000..ec2ebd8 --- /dev/null +++ b/src/actions/update-mailbox-v1.action.ts @@ -0,0 +1,11 @@ +import { mailApiClient } from "../api"; +import { Mailbox } from "../types/mailbox.type"; +import { UpdateMailboxV1RequestDto } from "../types/dto/update-mailbox-request.dto"; + +export const updateMailboxV1Action = async ( + domain: string, + mailbox: string, + data: UpdateMailboxV1RequestDto +): Promise => { + return await mailApiClient.updateMailboxV1(domain, mailbox, data); +}; diff --git a/src/actions/update-mailbox.action.ts b/src/actions/update-mailbox.action.ts new file mode 100644 index 0000000..338e66a --- /dev/null +++ b/src/actions/update-mailbox.action.ts @@ -0,0 +1,10 @@ +import { mailApiClient } from "../api"; +import { UpdateMailboxV2RequestDto } from "../types/dto/update-mailbox-request.dto"; + +export const updateMailboxAction = async ( + domain: string, + mailbox: string, + data: UpdateMailboxV2RequestDto +): Promise> => { + return await mailApiClient.updateMailboxV2(domain, mailbox, data); +}; diff --git a/src/actions/update-network-drive.action.ts b/src/actions/update-network-drive.action.ts new file mode 100644 index 0000000..8255206 --- /dev/null +++ b/src/actions/update-network-drive.action.ts @@ -0,0 +1,10 @@ +import { networkDrivesApiClient } from "../api/network-drives"; +import { NetworkDrive } from "../types/network-drive.type"; +import { UpdateNetworkDriveRequestDto } from "../types/dto/update-network-drive-request.dto"; + +export const updateNetworkDriveAction = async ( + networkDriveId: string, + data: UpdateNetworkDriveRequestDto +): Promise => { + return await networkDrivesApiClient.updateNetworkDrive(networkDriveId, data); +}; diff --git a/src/actions/update-project.action.ts b/src/actions/update-project.action.ts new file mode 100644 index 0000000..aaa9151 --- /dev/null +++ b/src/actions/update-project.action.ts @@ -0,0 +1,10 @@ +import { projectsApiClient } from "../api/projects"; +import { Project } from "../types/project.type"; +import { UpdateProjectRequestDto } from "../types/dto/update-project-request.dto"; + +export const updateProjectAction = async ( + projectId: number, + data: UpdateProjectRequestDto +): Promise => { + return await projectsApiClient.updateProject(projectId, data); +}; diff --git a/src/actions/update-server-disk-auto-backups.action.ts b/src/actions/update-server-disk-auto-backups.action.ts new file mode 100644 index 0000000..9b726c3 --- /dev/null +++ b/src/actions/update-server-disk-auto-backups.action.ts @@ -0,0 +1,14 @@ +import { serversApiClient } from "../api"; +import { AutoBackupSettings } from "../types/auto-backup.type"; + +export const updateServerDiskAutoBackupsAction = async ( + serverId: number, + diskId: number, + settings: AutoBackupSettings +): Promise => { + return await serversApiClient.updateServerDiskAutoBackups( + serverId, + diskId, + settings + ); +}; diff --git a/src/actions/update-server-disk-backup.action.ts b/src/actions/update-server-disk-backup.action.ts new file mode 100644 index 0000000..c944825 --- /dev/null +++ b/src/actions/update-server-disk-backup.action.ts @@ -0,0 +1,16 @@ +import { serversApiClient } from "../api"; +import { ServerBackup } from "../types/server-backup.type"; + +export const updateServerDiskBackupAction = async ( + serverId: number, + diskId: number, + backupId: number, + comment: string +): Promise => { + return await serversApiClient.updateServerDiskBackup( + serverId, + diskId, + backupId, + comment + ); +}; diff --git a/src/actions/update-server-disk.action.ts b/src/actions/update-server-disk.action.ts new file mode 100644 index 0000000..b101b41 --- /dev/null +++ b/src/actions/update-server-disk.action.ts @@ -0,0 +1,10 @@ +import { serversApiClient } from "../api"; +import { ServerDisk } from "../types/server-disk.type"; + +export const updateServerDiskAction = async ( + serverId: number, + diskId: number, + size: number +): Promise => { + return await serversApiClient.updateServerDisk(serverId, diskId, size); +}; diff --git a/src/actions/update-server-ip.action.ts b/src/actions/update-server-ip.action.ts new file mode 100644 index 0000000..aeff19a --- /dev/null +++ b/src/actions/update-server-ip.action.ts @@ -0,0 +1,10 @@ +import { serversApiClient } from "../api"; +import { ServerIp } from "../types/server-ip.type"; + +export const updateServerIpAction = async ( + serverId: number, + ip: string, + ptr: string +): Promise => { + return await serversApiClient.updateServerIp(serverId, { ip, ptr }); +}; diff --git a/src/actions/update-server.action.ts b/src/actions/update-server.action.ts new file mode 100644 index 0000000..9cbe18c --- /dev/null +++ b/src/actions/update-server.action.ts @@ -0,0 +1,10 @@ +import { serversApiClient } from "../api"; +import { UpdateServerRequestDto } from "../types/dto/update-server-request.dto"; +import { Server } from "../types/server.type"; + +export const updateServerAction = async ( + serverId: number, + data: UpdateServerRequestDto +): Promise => { + return await serversApiClient.updateServer(serverId, data); +}; diff --git a/src/actions/update-ssh-key.action.ts b/src/actions/update-ssh-key.action.ts new file mode 100644 index 0000000..d2944a5 --- /dev/null +++ b/src/actions/update-ssh-key.action.ts @@ -0,0 +1,10 @@ +import { sshKeysApiClient } from "../api"; +import { SshKey } from "../types/ssh-key.type"; +import { UpdateSshKeyRequestDto } from "../types/dto/update-ssh-key-request.dto"; + +export const updateSshKeyAction = async ( + sshKeyId: number, + data: UpdateSshKeyRequestDto +): Promise => { + return await sshKeysApiClient.updateSshKey(sshKeyId, data); +}; diff --git a/src/actions/update-vpc.action.ts b/src/actions/update-vpc.action.ts new file mode 100644 index 0000000..748afdd --- /dev/null +++ b/src/actions/update-vpc.action.ts @@ -0,0 +1,10 @@ +import { dbaasApiClient } from "../api"; +import { Vpc } from "../types/vpc.type"; +import { UpdateVpcRequestDto } from "../types/dto/update-vpc-request.dto"; + +export const updateVpcAction = async ( + vpcId: string, + data: UpdateVpcRequestDto +): Promise => { + return await dbaasApiClient.updateVpc(vpcId, data); +}; diff --git a/src/api/account.ts b/src/api/account.ts new file mode 100644 index 0000000..4f86181 --- /dev/null +++ b/src/api/account.ts @@ -0,0 +1,40 @@ +import { BaseApiClient } from "./client"; +import { AccountStatus, Finances } from "../types/finances.type"; +import { ServicePrice } from "../types/service-price.type"; +import { GetFinancesResponseDto } from "../types/dto/get-finances-response.dto"; +import { GetAccountStatusResponseDto } from "../types/dto/get-account-status-response.dto"; +import { GetServicesCostResponseDto } from "../types/dto/get-services-cost-response.dto"; + +export class AccountApiClient extends BaseApiClient { + /** + * Получает платёжную информацию аккаунта (баланс, тариф, автоплатёж) + */ + async getFinances(): Promise { + const response = await this.get( + "/api/v1/account/finances" + ); + return response.finances; + } + + /** + * Получает статус аккаунта (блокировка, уведомления, смена пароля) + */ + async getStatus(): Promise { + const response = await this.get( + "/api/v1/account/status" + ); + return response.status; + } + + /** + * Получает детализацию стоимости сервисов (какой VPS/БД/S3 сколько стоит) + */ + async getServicesCost(): Promise { + const response = await this.get( + "/api/v1/account/services/cost" + ); + return response.services_costs; + } +} + +export const accountApiClient: AccountApiClient = new AccountApiClient(); diff --git a/src/api/ai-agents.ts b/src/api/ai-agents.ts new file mode 100644 index 0000000..7c109f3 --- /dev/null +++ b/src/api/ai-agents.ts @@ -0,0 +1,137 @@ +import { BaseApiClient } from "./client"; +import { AiAgent } from "../types/ai-agent.type"; +import { AiModel } from "../types/ai-model.type"; +import { TokenPackage } from "../types/token-package.type"; +import { TokenStatistic } from "../types/token-statistic.type"; +import { ListAiAgentsResponseDto } from "../types/dto/list-ai-agents-response.dto"; +import { GetAiAgentResponseDto } from "../types/dto/get-ai-agent-response.dto"; +import { CreateAiAgentRequestDto } from "../types/dto/create-ai-agent-request.dto"; +import { UpdateAiAgentRequestDto } from "../types/dto/update-ai-agent-request.dto"; +import { GetAgentStatisticResponseDto } from "../types/dto/get-agent-statistic-response.dto"; +import { AddTokenPackageRequestDto } from "../types/dto/add-token-package-request.dto"; +import { ListAiModelsResponseDto } from "../types/dto/list-ai-models-response.dto"; +import { ListTokenPackagesResponseDto } from "../types/dto/list-token-packages-response.dto"; + +export type AgentStatisticQuery = { + startTime?: string; + endTime?: string; + interval?: number; +}; + +export class AiAgentsApiClient extends BaseApiClient { + /** + * Получает список AI агентов + */ + async listAgents(): Promise { + const response = await this.get( + "/api/v1/cloud-ai/agents" + ); + return response.agents; + } + + /** + * Получает данные AI агента по ID + */ + async getAgent(agentId: number): Promise { + const response = await this.get( + `/api/v1/cloud-ai/agents/${agentId}` + ); + return response.agent; + } + + /** + * Создаёт AI агента + */ + async createAgent(data: CreateAiAgentRequestDto): Promise { + const response = await this.post( + "/api/v1/cloud-ai/agents", + data + ); + return response.agent; + } + + /** + * Обновляет AI агента + */ + async updateAgent( + agentId: number, + data: UpdateAiAgentRequestDto + ): Promise { + const response = await this.patch( + `/api/v1/cloud-ai/agents/${agentId}`, + data + ); + return response.agent; + } + + /** + * Удаляет AI агента + */ + async deleteAgent(agentId: number): Promise { + await this.delete(`/api/v1/cloud-ai/agents/${agentId}`); + } + + /** + * Получает статистику использования токенов агента + */ + async getAgentStatistic( + agentId: number, + query: AgentStatisticQuery = {} + ): Promise { + const qs = new URLSearchParams(); + if (query.startTime) qs.append("startTime", query.startTime); + if (query.endTime) qs.append("endTime", query.endTime); + if (query.interval !== undefined) + qs.append("interval", String(query.interval)); + const suffix = qs.toString() ? `?${qs.toString()}` : ""; + const response = await this.get( + `/api/v1/cloud-ai/agents/${agentId}/statistic${suffix}` + ); + return response.agent_statistics; + } + + /** + * Добавляет дополнительный пакет токенов к агенту + */ + async addAgentTokenPackage( + agentId: number, + data: AddTokenPackageRequestDto + ): Promise { + await this.post( + `/api/v1/cloud-ai/agents/${agentId}/add-additional-token-package`, + data + ); + } + + /** + * Получает список доступных AI моделей + */ + async listModels(): Promise { + const response = await this.get( + "/api/v1/cloud-ai/models" + ); + return response.models; + } + + /** + * Получает список пакетов токенов для агентов + */ + async listAgentTokenPackages(): Promise { + const response = await this.get( + "/api/v1/cloud-ai/token-packages/agents" + ); + return response.token_packages; + } + + /** + * Получает список пакетов токенов для баз знаний + */ + async listKnowledgeBaseTokenPackages(): Promise { + const response = await this.get( + "/api/v1/cloud-ai/token-packages/knowledge-bases" + ); + return response.token_packages; + } +} + +export const aiAgentsApiClient: AiAgentsApiClient = new AiAgentsApiClient(); diff --git a/src/api/auth.ts b/src/api/auth.ts new file mode 100644 index 0000000..3071b4e --- /dev/null +++ b/src/api/auth.ts @@ -0,0 +1,69 @@ +import { BaseApiClient } from "./client"; +import { ApiKey, CreatedApiKey } from "../types/api-key.type"; +import { ListApiKeysResponseDto } from "../types/dto/list-api-keys-response.dto"; +import { CreateApiKeyRequestDto } from "../types/dto/create-api-key-request.dto"; +import { CreateApiKeyResponseDto } from "../types/dto/create-api-key-response.dto"; +import { EditApiKeyRequestDto } from "../types/dto/edit-api-key-request.dto"; +import { EditApiKeyResponseDto } from "../types/dto/edit-api-key-response.dto"; +import { RefreshApiKeyRequestDto } from "../types/dto/refresh-api-key-request.dto"; +import { RefreshApiKeyResponseDto } from "../types/dto/refresh-api-key-response.dto"; + +export class AuthApiClient extends BaseApiClient { + /** + * Получает список всех выпущенных API-токенов аккаунта + */ + async listApiKeys(): Promise { + const response = await this.get( + "/api/v1/auth/api-keys" + ); + return response.api_keys; + } + + /** + * Создает новый API-токен. Токен показывается только один раз + */ + async createApiKey(data: CreateApiKeyRequestDto): Promise { + const response = await this.post( + "/api/v1/auth/api-keys", + data + ); + return response.api_key; + } + + /** + * Изменяет API-токен (имя и/или флаг is_able_to_delete) + */ + async editApiKey( + tokenId: string, + data: EditApiKeyRequestDto + ): Promise { + const response = await this.patch( + `/api/v1/auth/api-keys/${tokenId}`, + data + ); + return response.api_key; + } + + /** + * Перевыпускает API-токен. Возвращает новое значение токена (показывается один раз) + */ + async refreshApiKey( + tokenId: string, + data: RefreshApiKeyRequestDto = {} + ): Promise { + const response = await this.put( + `/api/v1/auth/api-keys/${tokenId}`, + data + ); + return response.api_key; + } + + /** + * Удаляет API-токен по ID + */ + async deleteApiKey(tokenId: string): Promise { + await this.delete(`/api/v1/auth/api-keys/${tokenId}`); + } +} + +export const authApiClient: AuthApiClient = new AuthApiClient(); diff --git a/src/api/balancers.ts b/src/api/balancers.ts new file mode 100644 index 0000000..a8ce116 --- /dev/null +++ b/src/api/balancers.ts @@ -0,0 +1,189 @@ +import { BaseApiClient } from "./client"; +import { + Balancer, + BalancerPreset, + BalancerRule, + DeleteBalancerResult, +} from "../types/balancer.type"; +import { ListBalancersResponseDto } from "../types/dto/list-balancers-response.dto"; +import { GetBalancerResponseDto } from "../types/dto/get-balancer-response.dto"; +import { CreateBalancerRequestDto } from "../types/dto/create-balancer-request.dto"; +import { UpdateBalancerRequestDto } from "../types/dto/update-balancer-request.dto"; +import { DeleteBalancerResponseDto } from "../types/dto/delete-balancer-response.dto"; +import { ListBalancerIpsResponseDto } from "../types/dto/list-balancer-ips-response.dto"; +import { ListBalancerRulesResponseDto } from "../types/dto/list-balancer-rules-response.dto"; +import { BalancerRuleResponseDto } from "../types/dto/balancer-rule-response.dto"; +import { + CreateBalancerRuleRequestDto, + UpdateBalancerRuleRequestDto, +} from "../types/dto/create-balancer-rule-request.dto"; +import { ListBalancerPresetsResponseDto } from "../types/dto/list-balancer-presets-response.dto"; + +export class BalancersApiClient extends BaseApiClient { + /** + * Получает список всех балансировщиков аккаунта + */ + async listBalancers(limit?: number, offset?: number): Promise { + const query: string[] = []; + if (typeof limit === "number") query.push(`limit=${limit}`); + if (typeof offset === "number") query.push(`offset=${offset}`); + const qs = query.length ? `?${query.join("&")}` : ""; + const response = await this.get( + `/api/v1/balancers${qs}` + ); + return response.balancers; + } + + /** + * Получает детальную информацию о балансировщике + */ + async getBalancer(balancerId: number): Promise { + const response = await this.get( + `/api/v1/balancers/${balancerId}` + ); + return response.balancer; + } + + /** + * Создаёт новый балансировщик + */ + async createBalancer(data: CreateBalancerRequestDto): Promise { + const response = await this.post( + `/api/v1/balancers`, + data + ); + return response.balancer; + } + + /** + * Обновляет параметры существующего балансировщика + */ + async updateBalancer( + balancerId: number, + data: UpdateBalancerRequestDto + ): Promise { + const response = await this.patch( + `/api/v1/balancers/${balancerId}`, + data + ); + return response.balancer; + } + + /** + * Удаляет балансировщик. Поддерживает 2FA через hash и code + */ + async deleteBalancer( + balancerId: number, + hash?: string, + code?: string + ): Promise { + const query: string[] = []; + if (hash) query.push(`hash=${encodeURIComponent(hash)}`); + if (code) query.push(`code=${encodeURIComponent(code)}`); + const qs = query.length ? `?${query.join("&")}` : ""; + const response = await this.delete( + `/api/v1/balancers/${balancerId}${qs}` + ); + if (response && typeof response === "object" && "balancer_delete" in response) { + return response.balancer_delete; + } + return null; + } + + /** + * Получает список IP-адресов балансировщика + */ + async listBalancerIps(balancerId: number): Promise { + const response = await this.get( + `/api/v1/balancers/${balancerId}/ips` + ); + return response.ips; + } + + /** + * Добавляет IP-адреса к балансировщику + */ + async addBalancerIps(balancerId: number, ips: string[]): Promise { + await this.post(`/api/v1/balancers/${balancerId}/ips`, { ips }); + } + + /** + * Удаляет IP-адреса из балансировщика. + * DELETE с телом — используем makeRequest через post в данной базе не подходит; + * BaseApiClient.delete не принимает body, поэтому используем axios через makeRequest напрямую. + */ + async removeBalancerIps(balancerId: number, ips: string[]): Promise { + await this.deleteWithBody( + `/api/v1/balancers/${balancerId}/ips`, + { ips } + ); + } + + /** + * DELETE-запрос с телом через базовый makeRequest (axios поддерживает тело в DELETE). + * protected makeRequest доступен в подклассе напрямую. + */ + private async deleteWithBody(endpoint: string, data: any): Promise { + return this.makeRequest("DELETE", endpoint, data); + } + + /** + * Получает правила балансировщика + */ + async listBalancerRules(balancerId: number): Promise { + const response = await this.get( + `/api/v1/balancers/${balancerId}/rules` + ); + return response.rules; + } + + /** + * Создаёт правило для балансировщика + */ + async createBalancerRule( + balancerId: number, + data: CreateBalancerRuleRequestDto + ): Promise { + const response = await this.post( + `/api/v1/balancers/${balancerId}/rules`, + data + ); + return response.rule; + } + + /** + * Обновляет правило для балансировщика + */ + async updateBalancerRule( + balancerId: number, + ruleId: number, + data: UpdateBalancerRuleRequestDto + ): Promise { + const response = await this.patch( + `/api/v1/balancers/${balancerId}/rules/${ruleId}`, + data + ); + return response.rule; + } + + /** + * Удаляет правило для балансировщика + */ + async deleteBalancerRule(balancerId: number, ruleId: number): Promise { + await this.delete( + `/api/v1/balancers/${balancerId}/rules/${ruleId}` + ); + } + + /** + * Получает список тарифов для балансировщиков + */ + async listBalancerPresets(): Promise { + const response = await this.get( + `/api/v1/presets/balancers` + ); + return response.balancers_presets; + } +} + +export const balancersApiClient: BalancersApiClient = new BalancersApiClient(); diff --git a/src/api/catalogs.ts b/src/api/catalogs.ts new file mode 100644 index 0000000..aa365e1 --- /dev/null +++ b/src/api/catalogs.ts @@ -0,0 +1,69 @@ +import { BaseApiClient } from "./client"; +import { ServerPreset } from "../types/server-preset.type"; +import { ServerOs } from "../types/server-os.type"; +import { ServerConfigurator } from "../types/server-configurator.type"; +import { ServerSoftware } from "../types/server-software.type"; +import { Location } from "../types/location.type"; +import { ListServerPresetsResponseDto } from "../types/dto/list-server-presets-response.dto"; +import { ListServerOsResponseDto } from "../types/dto/list-server-os-response.dto"; +import { ListServerConfiguratorsResponseDto } from "../types/dto/list-server-configurators-response.dto"; +import { ListServerSoftwareResponseDto } from "../types/dto/list-server-software-response.dto"; +import { ListLocationsResponseDto } from "../types/dto/list-locations-response.dto"; + +/** + * API-клиент для справочных каталогов, необходимых перед созданием VPS: + * тарифы, ОС, конфигураторы, ПО из маркетплейса и локации. + */ +export class CatalogsApiClient extends BaseApiClient { + /** + * Список тарифов (пресетов) для VPS-серверов. + */ + async listServerPresets(): Promise { + const response = await this.get( + "/api/v1/presets/servers" + ); + return response.server_presets; + } + + /** + * Список операционных систем, доступных для установки на VPS. + */ + async listServerOs(): Promise { + const response = await this.get( + "/api/v1/os/servers" + ); + return response.servers_os; + } + + /** + * Список конфигураторов серверов (диапазоны CPU/RAM/Disk/Bandwidth/GPU). + */ + async listServerConfigurators(): Promise { + const response = await this.get( + "/api/v1/configurator/servers" + ); + return response.server_configurators; + } + + /** + * Список ПО из маркетплейса, доступного при создании VPS. + */ + async listServerSoftware(): Promise { + const response = await this.get( + "/api/v1/software/servers" + ); + return response.servers_software; + } + + /** + * Список локаций и зон доступности. + */ + async listLocations(): Promise { + const response = await this.get( + "/api/v2/locations" + ); + return response.locations; + } +} + +export const catalogsApiClient: CatalogsApiClient = new CatalogsApiClient(); diff --git a/src/api/container-registry.ts b/src/api/container-registry.ts new file mode 100644 index 0000000..3d4e693 --- /dev/null +++ b/src/api/container-registry.ts @@ -0,0 +1,94 @@ +import { BaseApiClient } from "./client"; +import { + ContainerRegistry, + ContainerRegistryPreset, + ContainerRegistryRepository, +} from "../types/container-registry.type"; +import { ListContainerRegistriesResponseDto } from "../types/dto/list-container-registries-response.dto"; +import { GetContainerRegistryResponseDto } from "../types/dto/get-container-registry-response.dto"; +import { CreateContainerRegistryRequestDto } from "../types/dto/create-container-registry-request.dto"; +import { UpdateContainerRegistryRequestDto } from "../types/dto/update-container-registry-request.dto"; +import { ListContainerRegistryPresetsResponseDto } from "../types/dto/list-container-registry-presets-response.dto"; +import { ListContainerRegistryRepositoriesResponseDto } from "../types/dto/list-container-registry-repositories-response.dto"; + +export class ContainerRegistryApiClient extends BaseApiClient { + /** + * Получает список всех реестров контейнеров аккаунта + */ + async listContainerRegistries(): Promise { + const response = await this.get( + "/api/v1/container-registry" + ); + return response.container_registry_list; + } + + /** + * Создаёт новый реестр контейнеров + */ + async createContainerRegistry( + data: CreateContainerRegistryRequestDto + ): Promise { + const response = await this.post( + "/api/v1/container-registry", + data + ); + return response.container_registry; + } + + /** + * Получает информацию о реестре по ID + */ + async getContainerRegistry(registryId: number): Promise { + const response = await this.get( + `/api/v1/container-registry/${registryId}` + ); + return response.container_registry; + } + + /** + * Обновляет информацию о реестре + */ + async updateContainerRegistry( + registryId: number, + data: UpdateContainerRegistryRequestDto + ): Promise { + const response = await this.patch( + `/api/v1/container-registry/${registryId}`, + data + ); + return response.container_registry; + } + + /** + * Удаляет реестр контейнеров + */ + async deleteContainerRegistry(registryId: number): Promise { + await this.delete(`/api/v1/container-registry/${registryId}`); + } + + /** + * Получает список тарифов реестров контейнеров + */ + async listContainerRegistryPresets(): Promise { + const response = await this.get( + "/api/v1/container-registry/presets" + ); + return response.container_registry_presets; + } + + /** + * Получает список репозиториев внутри реестра + */ + async listContainerRegistryRepositories( + registryId: number + ): Promise { + const response = + await this.get( + `/api/v1/container-registry/${registryId}/repositories` + ); + return response.container_registries_repositories; + } +} + +export const containerRegistryApiClient: ContainerRegistryApiClient = + new ContainerRegistryApiClient(); diff --git a/src/api/dbaas.ts b/src/api/dbaas.ts index 59beeee..644ec87 100644 --- a/src/api/dbaas.ts +++ b/src/api/dbaas.ts @@ -15,6 +15,50 @@ import { CreateDbParams } from "../types/create-db-params.type"; import { Vpc } from "../types/vpc.type"; import { FloatingIp } from "../types/floating-ip.type"; import { GetVpcsResponseDto } from "../types/dto/get-vpcs-response.dto"; +import { + DatabaseCluster, + DatabaseAdminEntity, + DatabaseInstanceEntity, + DatabaseType, + DatabaseBackup, + DatabaseAutoBackupSettings, +} from "../types/database-cluster.type"; +import { ListDatabaseClustersResponseDto } from "../types/dto/list-database-clusters-response.dto"; +import { GetDatabaseClusterResponseDto } from "../types/dto/get-database-cluster-response.dto"; +import { UpdateDatabaseClusterRequestDto } from "../types/dto/update-database-cluster-request.dto"; +import { + DeleteDatabaseClusterResponseDto, + DeleteDatabaseResponseDto, +} from "../types/dto/delete-database-response.dto"; +import { ListDatabaseAdminsResponseDto } from "../types/dto/list-database-admins-response.dto"; +import { DatabaseAdminResponseDto } from "../types/dto/database-admin-response.dto"; +import { CreateDatabaseAdminRequestDto } from "../types/dto/create-database-admin-request.dto"; +import { UpdateDatabaseAdminRequestDto } from "../types/dto/update-database-admin-request.dto"; +import { ListDatabaseInstancesResponseDto } from "../types/dto/list-database-instances-response.dto"; +import { DatabaseInstanceResponseDto } from "../types/dto/database-instance-response.dto"; +import { CreateDatabaseInstanceRequestDto } from "../types/dto/create-database-instance-request.dto"; +import { UpdateDatabaseInstanceRequestDto } from "../types/dto/update-database-instance-request.dto"; +import { ListDatabaseTypesResponseDto } from "../types/dto/list-database-types-response.dto"; +import { GetDatabaseParametersResponseDto } from "../types/dto/get-database-parameters-response.dto"; +import { ListDatabasesResponseDto } from "../types/dto/list-databases-response.dto"; +import { GetDatabaseResponseDto } from "../types/dto/get-database-response.dto"; +import { UpdateDatabaseRequestDto } from "../types/dto/update-database-request.dto"; +import { DatabaseAutoBackupsResponseDto } from "../types/dto/database-auto-backups-response.dto"; +import { UpdateDatabaseAutoBackupsRequestDto } from "../types/dto/update-database-auto-backups-request.dto"; +import { ListDatabaseBackupsResponseDto } from "../types/dto/list-database-backups-response.dto"; +import { DatabaseBackupResponseDto } from "../types/dto/database-backup-response.dto"; +import { ListFloatingIpsResponseDto } from "../types/dto/list-floating-ips-response.dto"; +import { GetFloatingIpResponseDto } from "../types/dto/get-floating-ip-response.dto"; +import { UpdateFloatingIpRequestDto } from "../types/dto/update-floating-ip-request.dto"; +import { UpdateFloatingIpResponseDto } from "../types/dto/update-floating-ip-response.dto"; +import { BindFloatingIpRequestDto } from "../types/dto/bind-floating-ip-request.dto"; +import { GetVpcResponseDto } from "../types/dto/get-vpc-response.dto"; +import { UpdateVpcRequestDto } from "../types/dto/update-vpc-request.dto"; +import { UpdateVpcResponseDto } from "../types/dto/update-vpc-response.dto"; +import { ListVpcServicesResponseDto } from "../types/dto/list-vpc-services-response.dto"; +import { ListVpcPortsResponseDto } from "../types/dto/list-vpc-ports-response.dto"; +import { VpcService } from "../types/vpc-service.type"; +import { VpcPort } from "../types/vpc-port.type"; export class DbaasApiClient extends BaseApiClient { /** @@ -36,6 +80,61 @@ export class DbaasApiClient extends BaseApiClient { return response.ip; } + /** + * Получает список всех плавающих IP пользователя + */ + async listFloatingIps(): Promise { + return this.get("/api/v1/floating-ips"); + } + + /** + * Получает информацию о плавающем IP по ID + */ + async getFloatingIp(floatingIpId: string): Promise { + const response = await this.get( + `/api/v1/floating-ips/${floatingIpId}` + ); + return response.ip; + } + + /** + * Изменяет плавающий IP по ID (комментарий и/или PTR-запись) + */ + async updateFloatingIp( + floatingIpId: string, + data: UpdateFloatingIpRequestDto + ): Promise { + const response = await this.patch( + `/api/v1/floating-ips/${floatingIpId}`, + data + ); + return response.ip; + } + + /** + * Удаляет плавающий IP по ID + */ + async deleteFloatingIp(floatingIpId: string): Promise { + await this.delete(`/api/v1/floating-ips/${floatingIpId}`); + } + + /** + * Привязывает плавающий IP к сервису (server/balancer/database/network) + */ + async bindFloatingIp( + floatingIpId: string, + data: BindFloatingIpRequestDto + ): Promise { + await this.post(`/api/v1/floating-ips/${floatingIpId}/bind`, data); + } + + /** + * Отвязывает плавающий IP от сервиса + */ + async unbindFloatingIp(floatingIpId: string): Promise { + await this.post(`/api/v1/floating-ips/${floatingIpId}/unbind`); + } + /** * Получить список VPC пользователя */ @@ -64,6 +163,52 @@ export class DbaasApiClient extends BaseApiClient { return response.vpc; } + /** + * Получает VPC по ID + */ + async getVpc(vpcId: string): Promise { + const response = await this.get(`/api/v2/vpcs/${vpcId}`); + return response.vpc; + } + + /** + * Изменяет VPC по ID (имя и/или описание) + */ + async updateVpc(vpcId: string, data: UpdateVpcRequestDto): Promise { + const response = await this.patch( + `/api/v2/vpcs/${vpcId}`, + data + ); + return response.vpc; + } + + /** + * Удаляет VPC по ID + */ + async deleteVpc(vpcId: string): Promise { + await this.delete(`/api/v1/vpcs/${vpcId}`); + } + + /** + * Получает список сервисов в VPC + */ + async listVpcServices(vpcId: string): Promise { + const response = await this.get( + `/api/v2/vpcs/${vpcId}/services` + ); + return response.services; + } + + /** + * Получает список портов VPC + */ + async listVpcPorts(vpcId: string): Promise { + const response = await this.get( + `/api/v1/vpcs/${vpcId}/ports` + ); + return response.vpc_ports; + } + /** * Создает новую базу данных */ @@ -115,6 +260,312 @@ export class DbaasApiClient extends BaseApiClient { ); return response.databases_presets; } + + // ========================================================================== + // Кластеры баз данных (/api/v1/databases) + // ========================================================================== + + /** + * Получает список кластеров баз данных + */ + async listDatabaseClusters( + limit?: number, + offset?: number + ): Promise { + const qs = this.buildQuery({ limit, offset }); + const response = await this.get( + `/api/v1/databases${qs}` + ); + return response.dbs; + } + + /** + * Получает информацию о кластере баз данных + */ + async getDatabaseCluster(clusterId: number): Promise { + const response = await this.get( + `/api/v1/databases/${clusterId}` + ); + return response.db; + } + + /** + * Обновляет кластер баз данных + */ + async updateDatabaseCluster( + clusterId: number, + data: UpdateDatabaseClusterRequestDto + ): Promise { + const response = await this.patch( + `/api/v1/databases/${clusterId}`, + data + ); + return response.db; + } + + /** + * Удаляет кластер баз данных (поддерживает 2FA через hash+code) + */ + async deleteDatabaseCluster( + clusterId: number, + hash?: string, + code?: string + ): Promise { + const qs = this.buildQuery({ hash, code }); + return await this.delete( + `/api/v1/databases/${clusterId}${qs}` + ); + } + + // ========================================================================== + // Пользователи кластера (/admins) + // ========================================================================== + + async listDatabaseAdmins(clusterId: number): Promise { + const response = await this.get( + `/api/v1/databases/${clusterId}/admins` + ); + return response.admins; + } + + async getDatabaseAdmin( + clusterId: number, + adminId: number + ): Promise { + const response = await this.get( + `/api/v1/databases/${clusterId}/admins/${adminId}` + ); + return response.admin; + } + + async createDatabaseAdmin( + clusterId: number, + data: CreateDatabaseAdminRequestDto + ): Promise { + const response = await this.post( + `/api/v1/databases/${clusterId}/admins`, + data + ); + return response?.admin ?? null; + } + + async updateDatabaseAdmin( + clusterId: number, + adminId: number, + data: UpdateDatabaseAdminRequestDto + ): Promise { + const response = await this.patch( + `/api/v1/databases/${clusterId}/admins/${adminId}`, + data + ); + return response.admin; + } + + async deleteDatabaseAdmin(clusterId: number, adminId: number): Promise { + await this.delete( + `/api/v1/databases/${clusterId}/admins/${adminId}` + ); + } + + // ========================================================================== + // Инстансы кластера (/instances) + // ========================================================================== + + async listDatabaseInstances( + clusterId: number + ): Promise { + const response = await this.get( + `/api/v1/databases/${clusterId}/instances` + ); + return response.instances; + } + + async getDatabaseInstance( + clusterId: number, + instanceId: number + ): Promise { + const response = await this.get( + `/api/v1/databases/${clusterId}/instances/${instanceId}` + ); + return response.instance; + } + + async createDatabaseInstance( + clusterId: number, + data: CreateDatabaseInstanceRequestDto + ): Promise { + const response = await this.post( + `/api/v1/databases/${clusterId}/instances`, + data + ); + return response?.instance ?? null; + } + + async updateDatabaseInstance( + clusterId: number, + instanceId: number, + data: UpdateDatabaseInstanceRequestDto + ): Promise { + const response = await this.patch( + `/api/v1/databases/${clusterId}/instances/${instanceId}`, + data + ); + return response.instance; + } + + async deleteDatabaseInstance( + clusterId: number, + instanceId: number + ): Promise { + await this.delete( + `/api/v1/databases/${clusterId}/instances/${instanceId}` + ); + } + + // ========================================================================== + // Типы и параметры + // ========================================================================== + + async listDatabaseTypes(): Promise { + const response = await this.get( + "/api/v1/database-types" + ); + return response.types; + } + + async getDatabaseParameters(): Promise { + return await this.get( + "/api/v1/dbs/parameters" + ); + } + + // ========================================================================== + // Базы данных (/api/v1/dbs) — legacy API + // ========================================================================== + + async listDatabases(limit?: number, offset?: number): Promise { + const qs = this.buildQuery({ limit, offset }); + const response = await this.get( + `/api/v1/dbs${qs}` + ); + return response.dbs; + } + + async getDatabase(dbId: number): Promise { + const response = await this.get( + `/api/v1/dbs/${dbId}` + ); + return response.db; + } + + async updateDatabase( + dbId: number, + data: UpdateDatabaseRequestDto + ): Promise { + const response = await this.patch( + `/api/v1/dbs/${dbId}`, + data + ); + return response.db; + } + + async deleteDatabase( + dbId: number, + hash?: string, + code?: string + ): Promise { + const qs = this.buildQuery({ hash, code }); + return await this.delete( + `/api/v1/dbs/${dbId}${qs}` + ); + } + + // ========================================================================== + // Автобэкапы (/auto-backups) + // ========================================================================== + + async getDatabaseAutoBackups( + dbId: number + ): Promise { + const response = await this.get( + `/api/v1/dbs/${dbId}/auto-backups` + ); + return response.auto_backups_settings; + } + + async updateDatabaseAutoBackups( + dbId: number, + data: UpdateDatabaseAutoBackupsRequestDto + ): Promise { + const response = await this.patch( + `/api/v1/dbs/${dbId}/auto-backups`, + data + ); + return response.auto_backups_settings; + } + + // ========================================================================== + // Бэкапы (/backups) + // ========================================================================== + + async listDatabaseBackups( + dbId: number, + limit?: number, + offset?: number + ): Promise { + const qs = this.buildQuery({ limit, offset }); + const response = await this.get( + `/api/v1/dbs/${dbId}/backups${qs}` + ); + return response.backups; + } + + async createDatabaseBackup( + dbId: number, + comment?: string + ): Promise { + const qs = this.buildQuery({ comment }); + const response = await this.post( + `/api/v1/dbs/${dbId}/backups${qs}` + ); + return response?.backup ?? null; + } + + async getDatabaseBackup( + dbId: number, + backupId: number + ): Promise { + const response = await this.get( + `/api/v1/dbs/${dbId}/backups/${backupId}` + ); + return response.backup; + } + + async deleteDatabaseBackup(dbId: number, backupId: number): Promise { + await this.delete(`/api/v1/dbs/${dbId}/backups/${backupId}`); + } + + async restoreDatabaseBackup(dbId: number, backupId: number): Promise { + await this.put(`/api/v1/dbs/${dbId}/backups/${backupId}`); + } + + // ========================================================================== + // Helpers + // ========================================================================== + + private buildQuery(params: Record): string { + const entries = Object.entries(params).filter( + ([, v]) => v !== undefined && v !== null && v !== "" + ); + if (entries.length === 0) return ""; + const qs = entries + .map( + ([k, v]) => + `${encodeURIComponent(k)}=${encodeURIComponent(String(v))}` + ) + .join("&"); + return `?${qs}`; + } } export const dbaasApiClient: DbaasApiClient = new DbaasApiClient(); diff --git a/src/api/dedicated-servers.ts b/src/api/dedicated-servers.ts new file mode 100644 index 0000000..754ef33 --- /dev/null +++ b/src/api/dedicated-servers.ts @@ -0,0 +1,99 @@ +import { BaseApiClient } from "./client"; +import { + DedicatedServer, + DedicatedServerPreset, + DedicatedServerAdditionalService, + DedicatedServerLocation, +} from "../types/dedicated-server.type"; +import { ListDedicatedServersResponseDto } from "../types/dto/list-dedicated-servers-response.dto"; +import { GetDedicatedServerResponseDto } from "../types/dto/get-dedicated-server-response.dto"; +import { CreateDedicatedServerRequestDto } from "../types/dto/create-dedicated-server-request.dto"; +import { UpdateDedicatedServerRequestDto } from "../types/dto/update-dedicated-server-request.dto"; +import { ListDedicatedServerPresetsResponseDto } from "../types/dto/list-dedicated-server-presets-response.dto"; +import { ListDedicatedServerAdditionalServicesResponseDto } from "../types/dto/list-dedicated-server-additional-services-response.dto"; + +export class DedicatedServersApiClient extends BaseApiClient { + /** + * Получает список всех выделенных серверов аккаунта + */ + async listDedicatedServers(): Promise { + const response = await this.get( + "/api/v1/dedicated-servers" + ); + return response.dedicated_servers; + } + + /** + * Создаёт новый выделенный сервер + */ + async createDedicatedServer( + data: CreateDedicatedServerRequestDto + ): Promise { + const response = await this.post( + "/api/v1/dedicated-servers", + data + ); + return response.dedicated_server; + } + + /** + * Получает детальную информацию по одному выделенному серверу + */ + async getDedicatedServer(dedicatedId: number): Promise { + const response = await this.get( + `/api/v1/dedicated-servers/${dedicatedId}` + ); + return response.dedicated_server; + } + + /** + * Обновляет параметры выделенного сервера (имя, комментарий) + */ + async updateDedicatedServer( + dedicatedId: number, + data: UpdateDedicatedServerRequestDto + ): Promise { + const response = await this.patch( + `/api/v1/dedicated-servers/${dedicatedId}`, + data + ); + return response.dedicated_server; + } + + /** + * Удаляет выделенный сервер + */ + async deleteDedicatedServer(dedicatedId: number): Promise { + await this.delete(`/api/v1/dedicated-servers/${dedicatedId}`); + } + + /** + * Получает список тарифов выделенных серверов (опционально по локации) + */ + async listDedicatedServerPresets( + location?: DedicatedServerLocation + ): Promise { + const path = location + ? `/api/v1/presets/dedicated-servers?location=${location}` + : "/api/v1/presets/dedicated-servers"; + const response = + await this.get(path); + return response.dedicated_servers_presets; + } + + /** + * Получает список дополнительных услуг для указанного тарифа выделенного сервера + */ + async listDedicatedServerAdditionalServices( + presetId: number + ): Promise { + const response = + await this.get( + `/api/v1/presets/dedicated-servers/${presetId}/additional-services` + ); + return response.dedicated_server_additional_services; + } +} + +export const dedicatedServersApiClient: DedicatedServersApiClient = + new DedicatedServersApiClient(); diff --git a/src/api/domains.ts b/src/api/domains.ts new file mode 100644 index 0000000..8101f10 --- /dev/null +++ b/src/api/domains.ts @@ -0,0 +1,315 @@ +import { BaseApiClient } from "./client"; +import { Domain, DomainSubdomain } from "../types/domain.type"; +import { DnsRecord, DnsRecordV2 } from "../types/dns-record.type"; +import { DomainNameServer } from "../types/domain-name-server.type"; +import { DomainRequest } from "../types/domain-request.type"; +import { TopLevelDomain } from "../types/top-level-domain.type"; +import { ListDomainsResponseDto } from "../types/dto/list-domains-response.dto"; +import { GetDomainResponseDto } from "../types/dto/get-domain-response.dto"; +import { UpdateDomainRequestDto } from "../types/dto/update-domain-request.dto"; +import { CheckDomainResponseDto } from "../types/dto/check-domain-response.dto"; +import { ListDnsRecordsResponseDto } from "../types/dto/list-dns-records-response.dto"; +import { + CreateDnsRecordRequestDto, + CreateDnsRecordV2RequestDto, +} from "../types/dto/create-dns-record-request.dto"; +import { + CreateDnsRecordResponseDto, + CreateDnsRecordV2ResponseDto, +} from "../types/dto/create-dns-record-response.dto"; +import { AddSubdomainResponseDto } from "../types/dto/add-subdomain-response.dto"; +import { DomainNameServersResponseDto } from "../types/dto/domain-name-servers-response.dto"; +import { UpdateDomainNameServersRequestDto } from "../types/dto/update-domain-name-servers-request.dto"; +import { + ListDomainRequestsResponseDto, + GetDomainRequestResponseDto, +} from "../types/dto/list-domain-requests-response.dto"; +import { + CreateDomainRequestRequestDto, + UpdateDomainRequestBodyDto, +} from "../types/dto/create-domain-request-request.dto"; +import { + ListTldsResponseDto, + GetTldResponseDto, +} from "../types/dto/list-tlds-response.dto"; + +export class DomainsApiClient extends BaseApiClient { + /** + * Получает список всех доменов аккаунта + */ + async listDomains(): Promise { + const response = await this.get("/api/v1/domains"); + return response.domains; + } + + /** + * Получает детальную информацию по домену + */ + async getDomain(fqdn: string): Promise { + const response = await this.get( + `/api/v1/domains/${encodeURIComponent(fqdn)}` + ); + return response.domain; + } + + /** + * Обновляет параметры домена (в т.ч. автопродление) + */ + async updateDomain( + fqdn: string, + data: UpdateDomainRequestDto + ): Promise { + const response = await this.patch( + `/api/v1/domains/${encodeURIComponent(fqdn)}`, + data + ); + return response.domain; + } + + /** + * Удаляет домен с аккаунта + */ + async deleteDomain(fqdn: string): Promise { + await this.delete(`/api/v1/domains/${encodeURIComponent(fqdn)}`); + } + + /** + * Добавляет домен на аккаунт + */ + async addDomain(fqdn: string): Promise { + await this.post(`/api/v1/add-domain/${encodeURIComponent(fqdn)}`); + } + + /** + * Проверяет, доступен ли домен для регистрации + */ + async checkDomain(fqdn: string): Promise { + const response = await this.get( + `/api/v1/check-domain/${encodeURIComponent(fqdn)}` + ); + return response.is_domain_available; + } + + // ===== DNS records (v1) ===== + + /** + * Получает список пользовательских DNS-записей домена + */ + async listDnsRecords(fqdn: string): Promise { + const response = await this.get( + `/api/v1/domains/${encodeURIComponent(fqdn)}/dns-records` + ); + return response.dns_records; + } + + /** + * Получает DNS-записи домена по умолчанию + */ + async listDefaultDnsRecords(fqdn: string): Promise { + const response = await this.get( + `/api/v1/domains/${encodeURIComponent(fqdn)}/default-dns-records` + ); + return response.dns_records; + } + + // ===== DNS records (v2 — предпочтительные для CRUD) ===== + + /** + * Создаёт DNS-запись (v2) + */ + async createDnsRecord( + fqdn: string, + data: CreateDnsRecordV2RequestDto + ): Promise { + const response = await this.post( + `/api/v2/domains/${encodeURIComponent(fqdn)}/dns-records`, + data + ); + return response.dns_record; + } + + /** + * Обновляет DNS-запись по ID (v2) + */ + async updateDnsRecord( + fqdn: string, + recordId: number, + data: CreateDnsRecordV2RequestDto + ): Promise { + const response = await this.patch( + `/api/v2/domains/${encodeURIComponent(fqdn)}/dns-records/${recordId}`, + data + ); + return response.dns_record; + } + + /** + * Удаляет DNS-запись по ID (v2) + */ + async deleteDnsRecord(fqdn: string, recordId: number): Promise { + await this.delete( + `/api/v2/domains/${encodeURIComponent(fqdn)}/dns-records/${recordId}` + ); + } + + // ===== DNS records (v1 legacy, оставлены для совместимости) ===== + + /** + * Создаёт DNS-запись (v1, устаревший вариант) + */ + async createDnsRecordV1( + fqdn: string, + data: CreateDnsRecordRequestDto + ): Promise { + const response = await this.post( + `/api/v1/domains/${encodeURIComponent(fqdn)}/dns-records`, + data + ); + return response.dns_record; + } + + /** + * Обновляет DNS-запись по ID (v1, устаревший вариант) + */ + async updateDnsRecordV1( + fqdn: string, + recordId: number, + data: CreateDnsRecordRequestDto + ): Promise { + const response = await this.patch( + `/api/v1/domains/${encodeURIComponent(fqdn)}/dns-records/${recordId}`, + data + ); + return response.dns_record; + } + + /** + * Удаляет DNS-запись по ID (v1, устаревший вариант) + */ + async deleteDnsRecordV1(fqdn: string, recordId: number): Promise { + await this.delete( + `/api/v1/domains/${encodeURIComponent(fqdn)}/dns-records/${recordId}` + ); + } + + // ===== Поддомены ===== + + /** + * Добавляет поддомен + */ + async addSubdomain( + fqdn: string, + subdomainFqdn: string + ): Promise { + const response = await this.post( + `/api/v1/domains/${encodeURIComponent(fqdn)}/subdomains/${encodeURIComponent(subdomainFqdn)}` + ); + return response.subdomain; + } + + /** + * Удаляет поддомен + */ + async deleteSubdomain(fqdn: string, subdomainFqdn: string): Promise { + await this.delete( + `/api/v1/domains/${encodeURIComponent(fqdn)}/subdomains/${encodeURIComponent(subdomainFqdn)}` + ); + } + + // ===== Name servers ===== + + /** + * Получает список name-серверов домена + */ + async getNameServers(fqdn: string): Promise { + const response = await this.get( + `/api/v1/domains/${encodeURIComponent(fqdn)}/name-servers` + ); + return response.name_servers; + } + + /** + * Обновляет name-серверы домена + */ + async updateNameServers( + fqdn: string, + data: UpdateDomainNameServersRequestDto + ): Promise { + const response = await this.put( + `/api/v1/domains/${encodeURIComponent(fqdn)}/name-servers`, + data + ); + return response.name_servers; + } + + // ===== Заявки на регистрацию/продление/трансфер ===== + + /** + * Получает список заявок + */ + async listDomainRequests(): Promise { + const response = await this.get( + "/api/v1/domains-requests" + ); + return response.requests; + } + + /** + * Получает заявку по ID + */ + async getDomainRequest(requestId: number): Promise { + const response = await this.get( + `/api/v1/domains-requests/${requestId}` + ); + return response.request; + } + + /** + * Создаёт заявку (register / prolong / transfer) + */ + async createDomainRequest( + data: CreateDomainRequestRequestDto + ): Promise { + const response = await this.post( + "/api/v1/domains-requests", + data + ); + return response.request; + } + + /** + * Обновляет/оплачивает заявку (use / invoice / free / bonus) + */ + async updateDomainRequest( + requestId: number, + data: UpdateDomainRequestBodyDto + ): Promise { + const response = await this.patch( + `/api/v1/domains-requests/${requestId}`, + data + ); + return response.request; + } + + // ===== TLDs ===== + + /** + * Получает информацию обо всех доменных зонах + */ + async listTlds(): Promise { + const response = await this.get("/api/v1/tlds"); + return response.top_level_domains; + } + + /** + * Получает информацию о доменной зоне по ID + */ + async getTld(tldId: number): Promise { + const response = await this.get( + `/api/v1/tlds/${tldId}` + ); + return response.top_level_domain; + } +} + +export const domainsApiClient: DomainsApiClient = new DomainsApiClient(); diff --git a/src/api/firewall.ts b/src/api/firewall.ts new file mode 100644 index 0000000..7f9f429 --- /dev/null +++ b/src/api/firewall.ts @@ -0,0 +1,195 @@ +import { BaseApiClient } from "./client"; +import { + FirewallGroup, + FirewallPolicy, +} from "../types/firewall-group.type"; +import { FirewallRule } from "../types/firewall-rule.type"; +import { + FirewallGroupResource, + FirewallResourceType, +} from "../types/firewall-resource.type"; +import { ListFirewallGroupsResponseDto } from "../types/dto/list-firewall-groups-response.dto"; +import { GetFirewallGroupResponseDto } from "../types/dto/get-firewall-group-response.dto"; +import { CreateFirewallGroupRequestDto } from "../types/dto/create-firewall-group-request.dto"; +import { UpdateFirewallGroupRequestDto } from "../types/dto/update-firewall-group-request.dto"; +import { ListFirewallGroupResourcesResponseDto } from "../types/dto/list-firewall-group-resources-response.dto"; +import { LinkFirewallResourceResponseDto } from "../types/dto/link-firewall-resource-response.dto"; +import { ListFirewallRulesResponseDto } from "../types/dto/list-firewall-rules-response.dto"; +import { GetFirewallRuleResponseDto } from "../types/dto/get-firewall-rule-response.dto"; +import { CreateFirewallRuleRequestDto } from "../types/dto/create-firewall-rule-request.dto"; +import { UpdateFirewallRuleRequestDto } from "../types/dto/update-firewall-rule-request.dto"; + +export class FirewallApiClient extends BaseApiClient { + /** + * Получает список всех групп правил firewall + */ + async listFirewallGroups(): Promise { + const response = await this.get( + "/api/v1/firewall/groups" + ); + return response.groups; + } + + /** + * Создаёт новую группу правил firewall + */ + async createFirewallGroup( + data: CreateFirewallGroupRequestDto, + policy?: FirewallPolicy + ): Promise { + const endpoint = policy + ? `/api/v1/firewall/groups?policy=${encodeURIComponent(policy)}` + : "/api/v1/firewall/groups"; + const response = await this.post( + endpoint, + data + ); + return response.group; + } + + /** + * Получает информацию о конкретной группе правил + */ + async getFirewallGroup(groupId: string): Promise { + const response = await this.get( + `/api/v1/firewall/groups/${groupId}` + ); + return response.group; + } + + /** + * Обновляет имя и/или описание группы правил + */ + async updateFirewallGroup( + groupId: string, + data: UpdateFirewallGroupRequestDto + ): Promise { + const response = await this.patch( + `/api/v1/firewall/groups/${groupId}`, + data + ); + return response.group; + } + + /** + * Удаляет группу правил firewall + */ + async deleteFirewallGroup(groupId: string): Promise { + await this.delete(`/api/v1/firewall/groups/${groupId}`); + } + + /** + * Получает список слинкованных с группой правил ресурсов + */ + async listFirewallGroupResources( + groupId: string + ): Promise { + const response = await this.get( + `/api/v1/firewall/groups/${groupId}/resources` + ); + return response.resources; + } + + /** + * Линкует ресурс (сервер) к группе правил firewall + */ + async linkFirewallResource( + groupId: string, + resourceId: string, + resourceType: FirewallResourceType = "server" + ): Promise { + const response = await this.post( + `/api/v1/firewall/groups/${groupId}/resources/${resourceId}?resource_type=${encodeURIComponent(resourceType)}` + ); + return response.resource; + } + + /** + * Отлинковывает ресурс от группы правил firewall + */ + async unlinkFirewallResource( + groupId: string, + resourceId: string, + resourceType: FirewallResourceType = "server" + ): Promise { + await this.delete( + `/api/v1/firewall/groups/${groupId}/resources/${resourceId}?resource_type=${encodeURIComponent(resourceType)}` + ); + } + + /** + * Получает список правил в группе + */ + async listFirewallRules(groupId: string): Promise { + const response = await this.get( + `/api/v1/firewall/groups/${groupId}/rules` + ); + return response.rules; + } + + /** + * Создаёт новое правило в группе + */ + async createFirewallRule( + groupId: string, + data: CreateFirewallRuleRequestDto + ): Promise { + const response = await this.post( + `/api/v1/firewall/groups/${groupId}/rules`, + data + ); + return response.rule; + } + + /** + * Получает детальную информацию о правиле + */ + async getFirewallRule( + groupId: string, + ruleId: string + ): Promise { + const response = await this.get( + `/api/v1/firewall/groups/${groupId}/rules/${ruleId}` + ); + return response.rule; + } + + /** + * Обновляет правило в группе + */ + async updateFirewallRule( + groupId: string, + ruleId: string, + data: UpdateFirewallRuleRequestDto + ): Promise { + const response = await this.patch( + `/api/v1/firewall/groups/${groupId}/rules/${ruleId}`, + data + ); + return response.rule; + } + + /** + * Удаляет правило из группы + */ + async deleteFirewallRule(groupId: string, ruleId: string): Promise { + await this.delete( + `/api/v1/firewall/groups/${groupId}/rules/${ruleId}` + ); + } + + /** + * Получает список групп правил, привязанных к конкретному ресурсу + */ + async listFirewallGroupsByResource( + resourceType: FirewallResourceType, + resourceId: string + ): Promise { + const response = await this.get( + `/api/v1/firewall/service/${encodeURIComponent(resourceType)}/${resourceId}` + ); + return response.groups; + } +} + +export const firewallApiClient: FirewallApiClient = new FirewallApiClient(); diff --git a/src/api/images.ts b/src/api/images.ts new file mode 100644 index 0000000..ef09f08 --- /dev/null +++ b/src/api/images.ts @@ -0,0 +1,127 @@ +import { BaseApiClient } from "./client"; +import { Image } from "../types/image.type"; +import { ImageDownload } from "../types/image-download.type"; +import { ListImagesResponseDto } from "../types/dto/list-images-response.dto"; +import { GetImageResponseDto } from "../types/dto/get-image-response.dto"; +import { CreateImageRequestDto } from "../types/dto/create-image-request.dto"; +import { UpdateImageRequestDto } from "../types/dto/update-image-request.dto"; +import { ListImageDownloadsResponseDto } from "../types/dto/list-image-downloads-response.dto"; +import { GetImageDownloadResponseDto } from "../types/dto/get-image-download-response.dto"; +import { CreateImageDownloadRequestDto } from "../types/dto/create-image-download-request.dto"; + +export class ImagesApiClient extends BaseApiClient { + /** + * Получает список образов аккаунта + */ + async listImages(limit?: number, offset?: number): Promise { + const query: string[] = []; + if (typeof limit === "number") query.push(`limit=${limit}`); + if (typeof offset === "number") query.push(`offset=${offset}`); + const qs = query.length > 0 ? `?${query.join("&")}` : ""; + const response = await this.get( + `/api/v1/images${qs}` + ); + return response.images; + } + + /** + * Создаёт образ (из диска либо пустой для последующей загрузки) + */ + async createImage(data: CreateImageRequestDto): Promise { + const response = await this.post( + "/api/v1/images", + data + ); + return response.image; + } + + /** + * Получает детальную информацию по образу + */ + async getImage(imageId: string): Promise { + const response = await this.get( + `/api/v1/images/${imageId}` + ); + return response.image; + } + + /** + * Обновляет имя/описание образа + */ + async updateImage( + imageId: string, + data: UpdateImageRequestDto + ): Promise { + const response = await this.patch( + `/api/v1/images/${imageId}`, + data + ); + return response.image; + } + + /** + * Удаляет образ + */ + async deleteImage(imageId: string): Promise { + await this.delete(`/api/v1/images/${imageId}`); + } + + /** + * Получает список ссылок на скачивание образа + */ + async listImageDownloads( + imageId: string, + limit?: number, + offset?: number + ): Promise { + const query: string[] = []; + if (typeof limit === "number") query.push(`limit=${limit}`); + if (typeof offset === "number") query.push(`offset=${offset}`); + const qs = query.length > 0 ? `?${query.join("&")}` : ""; + const response = await this.get( + `/api/v1/images/${imageId}/download-url${qs}` + ); + return response.downloads; + } + + /** + * Создаёт ссылку на скачивание образа (в том числе в облачные хранилища) + */ + async createImageDownload( + imageId: string, + data: CreateImageDownloadRequestDto + ): Promise { + const response = await this.post( + `/api/v1/images/${imageId}/download-url`, + data + ); + return response.download; + } + + /** + * Получает информацию о конкретной ссылке на скачивание + */ + async getImageDownload( + imageId: string, + imageUrlId: string + ): Promise { + const response = await this.get( + `/api/v1/images/${imageId}/download-url/${imageUrlId}` + ); + return response.download; + } + + /** + * Удаляет ссылку на скачивание образа + */ + async deleteImageDownload( + imageId: string, + imageUrlId: string + ): Promise { + await this.delete( + `/api/v1/images/${imageId}/download-url/${imageUrlId}` + ); + } +} + +export const imagesApiClient: ImagesApiClient = new ImagesApiClient(); diff --git a/src/api/index.ts b/src/api/index.ts index f9db26e..3e29179 100644 --- a/src/api/index.ts +++ b/src/api/index.ts @@ -1,2 +1,20 @@ export { appsApiClient } from "./apps"; export { dbaasApiClient } from "./dbaas"; +export { serversApiClient } from "./servers"; +export { accountApiClient } from "./account"; +export { catalogsApiClient } from "./catalogs"; +export { sshKeysApiClient } from "./ssh-keys"; +export { s3BucketsApiClient } from "./s3-buckets"; +export { domainsApiClient } from "./domains"; +export { imagesApiClient } from "./images"; +export { firewallApiClient } from "./firewall"; +export { authApiClient } from "./auth"; +export { networkDrivesApiClient } from "./network-drives"; +export { projectsApiClient } from "./projects"; +export { kubernetesApiClient } from "./kubernetes"; +export { balancersApiClient } from "./balancers"; +export { containerRegistryApiClient } from "./container-registry"; +export { dedicatedServersApiClient } from "./dedicated-servers"; +export { mailApiClient } from "./mail"; +export { aiAgentsApiClient } from "./ai-agents"; +export { knowledgeBasesApiClient } from "./knowledge-bases"; diff --git a/src/api/knowledge-bases.ts b/src/api/knowledge-bases.ts new file mode 100644 index 0000000..7edcf8d --- /dev/null +++ b/src/api/knowledge-bases.ts @@ -0,0 +1,206 @@ +import { BaseApiClient } from "./client"; +import { + KnowledgeBase, + KnowledgeBaseDocument, +} from "../types/knowledge-base.type"; +import { TokenStatistic } from "../types/token-statistic.type"; +import { ListKnowledgeBasesResponseDto } from "../types/dto/list-knowledge-bases-response.dto"; +import { GetKnowledgeBaseResponseDto } from "../types/dto/get-knowledge-base-response.dto"; +import { CreateKnowledgeBaseRequestDto } from "../types/dto/create-knowledge-base-request.dto"; +import { UpdateKnowledgeBaseRequestDto } from "../types/dto/update-knowledge-base-request.dto"; +import { ListKnowledgeBaseDocumentsResponseDto } from "../types/dto/list-knowledge-base-documents-response.dto"; +import { GetKnowledgeBaseStatisticResponseDto } from "../types/dto/get-knowledge-base-statistic-response.dto"; +import { AddTokenPackageRequestDto } from "../types/dto/add-token-package-request.dto"; + +export type ListKnowledgeBaseDocumentsQuery = { + limit?: number; + offset?: number; + sort_by?: "name" | "size" | "status" | "indexing_timestamp"; + sort_order?: "ASC" | "DESC"; +}; + +export type KnowledgeBaseStatisticQuery = { + startTime?: string; + endTime?: string; + interval?: number; +}; + +export class KnowledgeBasesApiClient extends BaseApiClient { + /** + * Получает список баз знаний (v2 - с полем documents_count) + */ + async listKnowledgeBasesV2(): Promise { + const response = await this.get( + "/api/v2/cloud-ai/knowledge-bases" + ); + return response.knowledgebases; + } + + /** + * Получает список баз знаний (v1 - с массивом documents) + */ + async listKnowledgeBases(): Promise { + const response = await this.get( + "/api/v1/cloud-ai/knowledge-bases" + ); + return response.knowledgebases; + } + + /** + * Получает базу знаний по ID + */ + async getKnowledgeBase(id: number): Promise { + const response = await this.get( + `/api/v1/cloud-ai/knowledge-bases/${id}` + ); + return response.knowledgebase; + } + + /** + * Создаёт базу знаний + */ + async createKnowledgeBase( + data: CreateKnowledgeBaseRequestDto + ): Promise { + const response = await this.post( + "/api/v1/cloud-ai/knowledge-bases", + data + ); + return response.knowledgebase; + } + + /** + * Обновляет базу знаний + */ + async updateKnowledgeBase( + id: number, + data: UpdateKnowledgeBaseRequestDto + ): Promise { + const response = await this.patch( + `/api/v1/cloud-ai/knowledge-bases/${id}`, + data + ); + return response.knowledgebase; + } + + /** + * Удаляет базу знаний + */ + async deleteKnowledgeBase(id: number): Promise { + await this.delete(`/api/v1/cloud-ai/knowledge-bases/${id}`); + } + + /** + * Привязывает базу знаний к агенту + */ + async linkKnowledgeBaseToAgent(id: number, agentId: number): Promise { + await this.post( + `/api/v1/cloud-ai/knowledge-bases/${id}/link/${agentId}` + ); + } + + /** + * Отвязывает базу знаний от агента + */ + async unlinkKnowledgeBaseFromAgent( + id: number, + agentId: number + ): Promise { + await this.delete( + `/api/v1/cloud-ai/knowledge-bases/${id}/link/${agentId}` + ); + } + + /** + * Добавляет дополнительный пакет токенов к базе знаний + */ + async addKnowledgeBaseTokenPackage( + id: number, + data: AddTokenPackageRequestDto + ): Promise { + await this.post( + `/api/v1/cloud-ai/knowledge-bases/${id}/add-additional-token-package`, + data + ); + } + + /** + * Получает список документов базы знаний + */ + async listKnowledgeBaseDocuments( + id: number, + query: ListKnowledgeBaseDocumentsQuery = {} + ): Promise<{ documents: KnowledgeBaseDocument[]; total: number }> { + const qs = new URLSearchParams(); + if (query.limit !== undefined) qs.append("limit", String(query.limit)); + if (query.offset !== undefined) qs.append("offset", String(query.offset)); + if (query.sort_by) qs.append("sort_by", query.sort_by); + if (query.sort_order) qs.append("sort_order", query.sort_order); + const suffix = qs.toString() ? `?${qs.toString()}` : ""; + const response = await this.get( + `/api/v2/cloud-ai/knowledge-bases/${id}/documents${suffix}` + ); + return { + documents: response.knowledgebase_documents, + total: response.meta.total, + }; + } + + /** + * Удаляет документ из базы знаний + */ + async deleteKnowledgeBaseDocument( + id: number, + documentId: number + ): Promise { + await this.delete( + `/api/v1/cloud-ai/knowledge-bases/${id}/documents/${documentId}` + ); + } + + /** + * Получает прямую ссылку для скачивания документа из базы знаний + */ + async downloadKnowledgeBaseDocument( + id: number, + documentId: number + ): Promise { + return await this.get( + `/api/v1/cloud-ai/knowledge-bases/${id}/documents/${documentId}/download` + ); + } + + /** + * Запускает переиндексацию документа + */ + async reindexKnowledgeBaseDocument( + id: number, + documentId: number + ): Promise { + await this.post( + `/api/v1/cloud-ai/knowledge-bases/${id}/documents/${documentId}/reindex` + ); + } + + /** + * Получает статистику использования токенов базы знаний + */ + async getKnowledgeBaseStatistic( + id: number, + query: KnowledgeBaseStatisticQuery = {} + ): Promise { + const qs = new URLSearchParams(); + if (query.startTime) qs.append("startTime", query.startTime); + if (query.endTime) qs.append("endTime", query.endTime); + if (query.interval !== undefined) + qs.append("interval", String(query.interval)); + const suffix = qs.toString() ? `?${qs.toString()}` : ""; + const response = await this.get( + `/api/v1/cloud-ai/knowledge-bases/${id}/statistic${suffix}` + ); + return response.knowledgebase_statistics; + } +} + +export const knowledgeBasesApiClient: KnowledgeBasesApiClient = + new KnowledgeBasesApiClient(); diff --git a/src/api/kubernetes.ts b/src/api/kubernetes.ts new file mode 100644 index 0000000..f911d1d --- /dev/null +++ b/src/api/kubernetes.ts @@ -0,0 +1,340 @@ +import { BaseApiClient } from "./client"; +import { K8sCluster } from "../types/k8s-cluster.type"; +import { K8sNodeGroup } from "../types/k8s-node-group.type"; +import { K8sNode } from "../types/k8s-node.type"; +import { K8sAddon, K8sAddonConfig } from "../types/k8s-addon.type"; +import { K8sPreset } from "../types/k8s-preset.type"; +import { K8sResources } from "../types/k8s-resources.type"; +import { ListK8sClustersResponseDto } from "../types/dto/list-k8s-clusters-response.dto"; +import { GetK8sClusterResponseDto } from "../types/dto/get-k8s-cluster-response.dto"; +import { CreateK8sClusterRequestDto } from "../types/dto/create-k8s-cluster-request.dto"; +import { EditK8sClusterRequestDto } from "../types/dto/edit-k8s-cluster-request.dto"; +import { DeleteK8sClusterResponseDto } from "../types/dto/delete-k8s-cluster-response.dto"; +import { GetK8sResourcesResponseDto } from "../types/dto/get-k8s-resources-response.dto"; +import { ListK8sNodeGroupsResponseDto } from "../types/dto/list-k8s-node-groups-response.dto"; +import { GetK8sNodeGroupResponseDto } from "../types/dto/get-k8s-node-group-response.dto"; +import { CreateK8sNodeGroupRequestDto } from "../types/dto/create-k8s-node-group-request.dto"; +import { ListK8sNodesResponseDto } from "../types/dto/list-k8s-nodes-response.dto"; +import { IncreaseK8sNodesRequestDto } from "../types/dto/increase-k8s-nodes-request.dto"; +import { ReduceK8sNodesRequestDto } from "../types/dto/reduce-k8s-nodes-request.dto"; +import { ListK8sVersionsResponseDto } from "../types/dto/list-k8s-versions-response.dto"; +import { ListK8sNetworkDriversResponseDto } from "../types/dto/list-k8s-network-drivers-response.dto"; +import { ListK8sPresetsResponseDto } from "../types/dto/list-k8s-presets-response.dto"; +import { ListK8sAddonConfigsResponseDto } from "../types/dto/list-k8s-addon-configs-response.dto"; +import { ListK8sAddonsResponseDto } from "../types/dto/list-k8s-addons-response.dto"; +import { InstallK8sAddonRequestDto } from "../types/dto/install-k8s-addon-request.dto"; +import { UpdateK8sClusterVersionRequestDto } from "../types/dto/update-k8s-cluster-version-request.dto"; + +export type DeleteK8sClusterResult = { + hash?: string; + is_moved_in_quarantine?: boolean; +}; + +export class KubernetesApiClient extends BaseApiClient { + /** + * Получает список кластеров Kubernetes + */ + async listClusters(limit?: number, offset?: number): Promise { + const qs: string[] = []; + if (typeof limit === "number") qs.push(`limit=${limit}`); + if (typeof offset === "number") qs.push(`offset=${offset}`); + const query = qs.length ? `?${qs.join("&")}` : ""; + const response = await this.get( + `/api/v1/k8s/clusters${query}` + ); + return response.clusters; + } + + /** + * Создаёт новый кластер Kubernetes + */ + async createCluster(data: CreateK8sClusterRequestDto): Promise { + const response = await this.post( + "/api/v1/k8s/clusters", + data + ); + return response.cluster; + } + + /** + * Получает информацию о кластере + */ + async getCluster(clusterId: number): Promise { + const response = await this.get( + `/api/v1/k8s/clusters/${clusterId}` + ); + return response.cluster; + } + + /** + * Удаляет кластер. Для аккаунтов с 2FA поддерживает подтверждение через hash и code + */ + async deleteCluster( + clusterId: number, + hash?: string, + code?: string + ): Promise { + const qs: string[] = []; + if (hash) qs.push(`hash=${encodeURIComponent(hash)}`); + if (code) qs.push(`code=${encodeURIComponent(code)}`); + const query = qs.length ? `?${qs.join("&")}` : ""; + const response = await this.delete( + `/api/v1/k8s/clusters/${clusterId}${query}` + ); + return response.cluster_delete; + } + + /** + * Обновляет имя/описание/OIDC-провайдера кластера + */ + async editCluster( + clusterId: number, + data: EditK8sClusterRequestDto + ): Promise { + const response = await this.patch( + `/api/v1/k8s/clusters/${clusterId}`, + data + ); + return response.cluster; + } + + /** + * Получает сводку ресурсов кластера (cpu, memory, pods, nodes) + */ + async getClusterResources(clusterId: number): Promise { + const response = await this.get( + `/api/v1/k8s/clusters/${clusterId}/resources` + ); + return response.resources; + } + + /** + * Получает файл kubeconfig (YAML) для кластера + */ + async getKubeconfig(clusterId: number): Promise { + const response = await this.get( + `/api/v1/k8s/clusters/${clusterId}/kubeconfig` + ); + if (typeof response === "string") { + return response; + } + return JSON.stringify(response); + } + + /** + * Обновляет версию Kubernetes в кластере + */ + async updateClusterVersion( + clusterId: number, + data: UpdateK8sClusterVersionRequestDto + ): Promise { + await this.patch( + `/api/v1/k8s/clusters/${clusterId}/versions/update`, + data + ); + } + + /** + * Получает список групп нод кластера + */ + async listNodeGroups(clusterId: number): Promise { + const response = await this.get( + `/api/v1/k8s/clusters/${clusterId}/groups` + ); + return response.node_groups; + } + + /** + * Создаёт новую группу нод в кластере + */ + async createNodeGroup( + clusterId: number, + data: CreateK8sNodeGroupRequestDto + ): Promise { + const response = await this.post( + `/api/v1/k8s/clusters/${clusterId}/groups`, + data + ); + return response.node_group; + } + + /** + * Получает информацию о группе нод + */ + async getNodeGroup( + clusterId: number, + groupId: number + ): Promise { + const response = await this.get( + `/api/v1/k8s/clusters/${clusterId}/groups/${groupId}` + ); + return response.node_group; + } + + /** + * Удаляет группу нод + */ + async deleteNodeGroup(clusterId: number, groupId: number): Promise { + await this.delete( + `/api/v1/k8s/clusters/${clusterId}/groups/${groupId}` + ); + } + + /** + * Получает список нод, принадлежащих группе + */ + async listNodeGroupNodes( + clusterId: number, + groupId: number, + limit?: number, + offset?: number + ): Promise { + const qs: string[] = []; + if (typeof limit === "number") qs.push(`limit=${limit}`); + if (typeof offset === "number") qs.push(`offset=${offset}`); + const query = qs.length ? `?${qs.join("&")}` : ""; + const response = await this.get( + `/api/v1/k8s/clusters/${clusterId}/groups/${groupId}/nodes${query}` + ); + return response.nodes; + } + + /** + * Увеличивает количество нод в группе на указанное количество + */ + async increaseNodeGroupNodes( + clusterId: number, + groupId: number, + data: IncreaseK8sNodesRequestDto + ): Promise { + const response = await this.post( + `/api/v1/k8s/clusters/${clusterId}/groups/${groupId}/nodes`, + data + ); + return response.nodes; + } + + /** + * Уменьшает количество нод в группе на указанное количество. + * DELETE с телом запроса (поддерживается через базовый makeRequest). + */ + async reduceNodeGroupNodes( + clusterId: number, + groupId: number, + data: ReduceK8sNodesRequestDto + ): Promise { + await this.makeRequest( + "DELETE", + `/api/v1/k8s/clusters/${clusterId}/groups/${groupId}/nodes`, + data + ); + } + + /** + * Получает список всех нод кластера + */ + async listClusterNodes(clusterId: number): Promise { + const response = await this.get( + `/api/v1/k8s/clusters/${clusterId}/nodes` + ); + return response.nodes; + } + + /** + * Удаляет конкретную ноду из кластера + */ + async deleteClusterNode(clusterId: number, nodeId: number): Promise { + await this.delete( + `/api/v1/k8s/clusters/${clusterId}/nodes/${nodeId}` + ); + } + + /** + * Получает список доступных версий Kubernetes + */ + async listK8sVersions(): Promise { + const response = await this.get( + "/api/v1/k8s/k8s-versions" + ); + return response.k8s_versions; + } + + /** + * Получает список сетевых драйверов + */ + async listNetworkDrivers(): Promise { + const response = await this.get( + "/api/v1/k8s/network-drivers" + ); + return response.network_drivers; + } + + /** + * Получает список тарифов (мастер/воркер) для Kubernetes + */ + async listK8sPresets(): Promise { + const response = await this.get( + "/api/v1/presets/k8s" + ); + return response.k8s_presets; + } + + /** + * Получает список конфигураций дополнений (каталог доступных аддонов) + */ + async listAddonConfigs(clusterId: number): Promise { + const response = await this.get( + `/api/v1/k8s/clusters/${clusterId}/addons-configs` + ); + return response.k8s_addons; + } + + /** + * Получает список установленных в кластере дополнений + */ + async listInstalledAddons(clusterId: number): Promise { + const response = await this.get( + `/api/v1/k8s/clusters/${clusterId}/addons` + ); + return response.addons; + } + + /** + * Устанавливает дополнение в кластере + */ + async installAddon( + clusterId: number, + data: InstallK8sAddonRequestDto + ): Promise { + await this.post( + `/api/v1/k8s/clusters/${clusterId}/addons`, + data + ); + } + + /** + * Изменяет конфигурацию установленного дополнения + */ + async updateAddon( + clusterId: number, + addonId: number, + data: InstallK8sAddonRequestDto + ): Promise { + await this.post( + `/api/v1/k8s/clusters/${clusterId}/addons/${addonId}`, + data + ); + } + + /** + * Удаляет установленное дополнение + */ + async uninstallAddon(clusterId: number, addonId: number): Promise { + await this.delete( + `/api/v1/k8s/clusters/${clusterId}/addons/${addonId}` + ); + } +} + +export const kubernetesApiClient: KubernetesApiClient = + new KubernetesApiClient(); diff --git a/src/api/mail.ts b/src/api/mail.ts new file mode 100644 index 0000000..1a1623b --- /dev/null +++ b/src/api/mail.ts @@ -0,0 +1,214 @@ +import { BaseApiClient } from "./client"; +import { Mailbox, MailboxV2, MailDomainInfo } from "../types/mailbox.type"; +import { + ListMailboxesV1ResponseDto, + ListMailboxesV2ResponseDto, +} from "../types/dto/list-mailboxes-response.dto"; +import { + GetMailboxV1ResponseDto, + GetMailboxV2ResponseDto, +} from "../types/dto/get-mailbox-response.dto"; +import { + CreateMailboxV1RequestDto, + CreateMailboxV2RequestDto, +} from "../types/dto/create-mailbox-request.dto"; +import { + CreateMailboxV1ResponseDto, + CreateMailboxV2ResponseDto, +} from "../types/dto/create-mailbox-response.dto"; +import { + BatchCreateMailboxesV1RequestDto, + BatchCreateMailboxesV2RequestDto, +} from "../types/dto/batch-create-mailboxes-request.dto"; +import { + BatchCreateMailboxesV1ResponseDto, + BatchCreateMailboxesV2ResponseDto, +} from "../types/dto/batch-create-mailboxes-response.dto"; +import { + UpdateMailboxV1RequestDto, + UpdateMailboxV2RequestDto, +} from "../types/dto/update-mailbox-request.dto"; +import { + UpdateMailboxV1ResponseDto, + UpdateMailboxV2ResponseDto, +} from "../types/dto/update-mailbox-response.dto"; +import { GetMailDomainInfoResponseDto } from "../types/dto/get-mail-domain-info-response.dto"; +import { UpdateMailDomainInfoRequestDto } from "../types/dto/update-mail-domain-info-request.dto"; +import { UpdateMailDomainInfoResponseDto } from "../types/dto/update-mail-domain-info-response.dto"; + +export class MailApiClient extends BaseApiClient { + // ───── v2 (приоритетная версия API) ───── + + /** + * Список всех почтовых ящиков аккаунта (API v2). + */ + async listMailboxesV2(): Promise { + const response = await this.get( + "/api/v2/mail" + ); + return response.mailboxes; + } + + /** + * Получение одного почтового ящика (API v2). + */ + async getMailboxV2(domain: string, mailbox: string): Promise { + const response = await this.get( + `/api/v2/mail/domains/${encodeURIComponent(domain)}/mailboxes/${encodeURIComponent(mailbox)}` + ); + return response.mailbox; + } + + /** + * Создание почтового ящика (API v2). + */ + async createMailboxV2( + domain: string, + data: CreateMailboxV2RequestDto + ): Promise { + const response = await this.post( + `/api/v2/mail/domains/${encodeURIComponent(domain)}`, + data + ); + return response.mailbox; + } + + /** + * Массовое создание почтовых ящиков (API v2). Тело — массив. + */ + async batchCreateMailboxesV2( + domain: string, + data: BatchCreateMailboxesV2RequestDto + ): Promise { + const response = await this.post( + `/api/v2/mail/domains/${encodeURIComponent(domain)}/batch`, + data + ); + return response.mailboxes_batch; + } + + /** + * Изменение почтового ящика (API v2). + */ + async updateMailboxV2( + domain: string, + mailbox: string, + data: UpdateMailboxV2RequestDto + ): Promise> { + const response = await this.patch( + `/api/v2/mail/domains/${encodeURIComponent(domain)}/mailboxes/${encodeURIComponent(mailbox)}`, + data + ); + return response.mailbox; + } + + // ───── v1 (legacy, но всё ещё нужна для delete и domain info) ───── + + /** + * Список всех почтовых ящиков аккаунта (API v1). + */ + async listMailboxesV1(): Promise { + const response = await this.get( + "/api/v1/mail" + ); + return response.mailboxes; + } + + /** + * Список почтовых ящиков одного домена (только v1). + */ + async listMailboxesByDomain(domain: string): Promise { + const response = await this.get( + `/api/v1/mail/domains/${encodeURIComponent(domain)}` + ); + return response.mailboxes; + } + + /** + * Получение одного почтового ящика (API v1). + */ + async getMailboxV1(domain: string, mailbox: string): Promise { + const response = await this.get( + `/api/v1/mail/domains/${encodeURIComponent(domain)}/mailboxes/${encodeURIComponent(mailbox)}` + ); + return response.mailbox; + } + + /** + * Создание почтового ящика (API v1). + */ + async createMailboxV1( + domain: string, + data: CreateMailboxV1RequestDto + ): Promise { + const response = await this.post( + `/api/v1/mail/domains/${encodeURIComponent(domain)}`, + data + ); + return response.mailbox; + } + + /** + * Массовое создание почтовых ящиков (API v1). + */ + async batchCreateMailboxesV1( + domain: string, + data: BatchCreateMailboxesV1RequestDto + ): Promise { + const response = await this.post( + `/api/v1/mail/domains/${encodeURIComponent(domain)}/batch`, + data + ); + return response.mailboxes; + } + + /** + * Изменение почтового ящика (API v1). + */ + async updateMailboxV1( + domain: string, + mailbox: string, + data: UpdateMailboxV1RequestDto + ): Promise { + const response = await this.patch( + `/api/v1/mail/domains/${encodeURIComponent(domain)}/mailboxes/${encodeURIComponent(mailbox)}`, + data + ); + return response.mailbox; + } + + /** + * Удаление почтового ящика (только v1). + */ + async deleteMailbox(domain: string, mailbox: string): Promise { + await this.delete( + `/api/v1/mail/domains/${encodeURIComponent(domain)}/mailboxes/${encodeURIComponent(mailbox)}` + ); + } + + /** + * Получение почтовой информации о домене. + */ + async getMailDomainInfo(domain: string): Promise { + const response = await this.get( + `/api/v1/mail/domains/${encodeURIComponent(domain)}/info` + ); + return response.domain_info; + } + + /** + * Изменение почтовой информации о домене. + */ + async updateMailDomainInfo( + domain: string, + data: UpdateMailDomainInfoRequestDto + ): Promise { + const response = await this.patch( + `/api/v1/mail/domains/${encodeURIComponent(domain)}/info`, + data + ); + return response.domain_info; + } +} + +export const mailApiClient: MailApiClient = new MailApiClient(); diff --git a/src/api/network-drives.ts b/src/api/network-drives.ts new file mode 100644 index 0000000..372d415 --- /dev/null +++ b/src/api/network-drives.ts @@ -0,0 +1,115 @@ +import { BaseApiClient } from "./client"; +import { NetworkDrive } from "../types/network-drive.type"; +import { NetworkDrivePreset } from "../types/network-drive-preset.type"; +import { NetworkDriveAvailableResource } from "../types/network-drive-available-resource.type"; +import { ListNetworkDrivesResponseDto } from "../types/dto/list-network-drives-response.dto"; +import { GetNetworkDriveResponseDto } from "../types/dto/get-network-drive-response.dto"; +import { CreateNetworkDriveRequestDto } from "../types/dto/create-network-drive-request.dto"; +import { CreateNetworkDriveResponseDto } from "../types/dto/create-network-drive-response.dto"; +import { UpdateNetworkDriveRequestDto } from "../types/dto/update-network-drive-request.dto"; +import { UpdateNetworkDriveResponseDto } from "../types/dto/update-network-drive-response.dto"; +import { MountNetworkDriveRequestDto } from "../types/dto/mount-network-drive-request.dto"; +import { ListNetworkDriveAvailableResourcesResponseDto } from "../types/dto/list-network-drive-available-resources-response.dto"; +import { ListNetworkDrivePresetsResponseDto } from "../types/dto/list-network-drive-presets-response.dto"; + +export class NetworkDrivesApiClient extends BaseApiClient { + /** + * Получает список всех сетевых дисков аккаунта + */ + async listNetworkDrives(): Promise { + const response = await this.get( + "/api/v1/network-drives" + ); + return response.network_drives; + } + + /** + * Создаёт новый сетевой диск + */ + async createNetworkDrive( + data: CreateNetworkDriveRequestDto + ): Promise { + const response = await this.post( + "/api/v1/network-drives", + data + ); + return response.network_drive; + } + + /** + * Получает информацию о сетевом диске по ID + */ + async getNetworkDrive(networkDriveId: string): Promise { + const response = await this.get( + `/api/v1/network-drives/${networkDriveId}` + ); + return response.network_drive; + } + + /** + * Изменяет параметры сетевого диска (name, comment, size) + */ + async updateNetworkDrive( + networkDriveId: string, + data: UpdateNetworkDriveRequestDto + ): Promise { + const response = await this.patch( + `/api/v1/network-drives/${networkDriveId}`, + data + ); + return response.network_drive; + } + + /** + * Удаляет сетевой диск по ID + */ + async deleteNetworkDrive(networkDriveId: string): Promise { + await this.delete(`/api/v1/network-drives/${networkDriveId}`); + } + + /** + * Подключает сетевой диск к сервису (например, к серверу) + */ + async mountNetworkDrive( + networkDriveId: string, + data: MountNetworkDriveRequestDto + ): Promise { + await this.post( + `/api/v1/network-drives/${networkDriveId}/mount`, + data + ); + } + + /** + * Отключает сетевой диск от сервиса + */ + async unmountNetworkDrive(networkDriveId: string): Promise { + await this.post(`/api/v1/network-drives/${networkDriveId}/unmount`); + } + + /** + * Получает список сервисов, доступных для подключения сетевого диска + */ + async listNetworkDriveAvailableResources(): Promise< + NetworkDriveAvailableResource[] + > { + const response = + await this.get( + "/api/v1/network-drives/available-resources" + ); + return response.available_resources; + } + + /** + * Получает список доступных тарифов для сетевого диска + */ + async listNetworkDrivePresets(): Promise { + const response = await this.get( + "/api/v1/presets/network-drives" + ); + return response.network_drive_presets; + } +} + +export const networkDrivesApiClient: NetworkDrivesApiClient = + new NetworkDrivesApiClient(); diff --git a/src/api/projects.ts b/src/api/projects.ts new file mode 100644 index 0000000..7b86bb7 --- /dev/null +++ b/src/api/projects.ts @@ -0,0 +1,270 @@ +import { BaseApiClient } from "./client"; +import { Project, ProjectResource } from "../types/project.type"; +import { ProjectResourceTypeEnum } from "../types/project-resource-type.enum"; +import { ListProjectsResponseDto } from "../types/dto/list-projects-response.dto"; +import { GetProjectResponseDto } from "../types/dto/get-project-response.dto"; +import { CreateProjectRequestDto } from "../types/dto/create-project-request.dto"; +import { UpdateProjectRequestDto } from "../types/dto/update-project-request.dto"; +import { ProjectResourceResponseDto } from "../types/dto/project-resource-response.dto"; +import { ListProjectResourcesResponseDto } from "../types/dto/list-project-resources-response.dto"; +import { + ListResourceServersResponseDto, + ListResourceBalancersResponseDto, + ListResourceBucketsResponseDto, + ListResourceClustersResponseDto, + ListResourceDatabasesResponseDto, + ListResourceDedicatedResponseDto, +} from "../types/dto/list-resources-response.dto"; +import { AddResourceToProjectRequestDto } from "../types/dto/add-resource-to-project-request.dto"; +import { TransferProjectResourceRequestDto } from "../types/dto/transfer-project-resource-request.dto"; + +export class ProjectsApiClient extends BaseApiClient { + /** + * Получить список проектов аккаунта + */ + async listProjects(): Promise { + const response = await this.get( + "/api/v1/projects" + ); + return response.projects; + } + + /** + * Получить проект по ID + */ + async getProject(projectId: number): Promise { + const response = await this.get( + `/api/v1/projects/${projectId}` + ); + return response.project; + } + + /** + * Создать новый проект + */ + async createProject(data: CreateProjectRequestDto): Promise { + const response = await this.post( + "/api/v1/projects", + data + ); + return response.project; + } + + /** + * Изменить проект + */ + async updateProject( + projectId: number, + data: UpdateProjectRequestDto + ): Promise { + const response = await this.put( + `/api/v1/projects/${projectId}`, + data + ); + return response.project; + } + + /** + * Удалить проект + */ + async deleteProject(projectId: number): Promise { + await this.delete(`/api/v1/projects/${projectId}`); + } + + /** + * Получить все ресурсы проекта (комбинированный ответ) + */ + async listProjectResources( + projectId: number + ): Promise { + return await this.get( + `/api/v1/projects/${projectId}/resources` + ); + } + + // ---------- Балансировщики ---------- + async listProjectBalancers(projectId: number): Promise { + const response = await this.get( + `/api/v1/projects/${projectId}/resources/balancers` + ); + return response.balancers; + } + + async addBalancerToProject( + projectId: number, + resourceId: number + ): Promise { + const body: AddResourceToProjectRequestDto = { resource_id: resourceId }; + const response = await this.post( + `/api/v1/projects/${projectId}/resources/balancers`, + body + ); + return response.resource; + } + + // ---------- Хранилища (buckets) ---------- + async listProjectBuckets(projectId: number): Promise { + const response = await this.get( + `/api/v1/projects/${projectId}/resources/buckets` + ); + return response.buckets; + } + + async addBucketToProject( + projectId: number, + resourceId: number + ): Promise { + const body: AddResourceToProjectRequestDto = { resource_id: resourceId }; + const response = await this.post( + `/api/v1/projects/${projectId}/resources/buckets`, + body + ); + return response.resource; + } + + // ---------- Кластеры (k8s) ---------- + async listProjectClusters(projectId: number): Promise { + const response = await this.get( + `/api/v1/projects/${projectId}/resources/clusters` + ); + return response.clusters; + } + + async addClusterToProject( + projectId: number, + resourceId: number + ): Promise { + const body: AddResourceToProjectRequestDto = { resource_id: resourceId }; + const response = await this.post( + `/api/v1/projects/${projectId}/resources/clusters`, + body + ); + return response.resource; + } + + // ---------- Серверы ---------- + async listProjectServers(projectId: number): Promise { + const response = await this.get( + `/api/v1/projects/${projectId}/resources/servers` + ); + return response.servers; + } + + async addServerToProject( + projectId: number, + resourceId: number + ): Promise { + const body: AddResourceToProjectRequestDto = { resource_id: resourceId }; + const response = await this.post( + `/api/v1/projects/${projectId}/resources/servers`, + body + ); + return response.resource; + } + + // ---------- Базы данных ---------- + async listProjectDatabases(projectId: number): Promise { + const response = await this.get( + `/api/v1/projects/${projectId}/resources/databases` + ); + return response.databases; + } + + async addDatabaseToProject( + projectId: number, + resourceId: number + ): Promise { + const body: AddResourceToProjectRequestDto = { resource_id: resourceId }; + const response = await this.post( + `/api/v1/projects/${projectId}/resources/databases`, + body + ); + return response.resource; + } + + // ---------- Выделенные серверы ---------- + async listProjectDedicated(projectId: number): Promise { + const response = await this.get( + `/api/v1/projects/${projectId}/resources/dedicated` + ); + return response.dedicated_servers; + } + + async addDedicatedToProject( + projectId: number, + resourceId: number + ): Promise { + const body: AddResourceToProjectRequestDto = { resource_id: resourceId }; + const response = await this.post( + `/api/v1/projects/${projectId}/resources/dedicated`, + body + ); + return response.resource; + } + + // ---------- Ресурсы всего аккаунта с project_id ---------- + async listAllResourceBalancers(): Promise { + const response = await this.get( + "/api/v1/projects/resources/balancers" + ); + return response.balancers; + } + + async listAllResourceServers(): Promise { + const response = await this.get( + "/api/v1/projects/resources/servers" + ); + return response.servers; + } + + async listAllResourceBuckets(): Promise { + const response = await this.get( + "/api/v1/projects/resources/buckets" + ); + return response.buckets; + } + + async listAllResourceClusters(): Promise { + const response = await this.get( + "/api/v1/projects/resources/clusters" + ); + return response.clusters; + } + + async listAllResourceDatabases(): Promise { + const response = await this.get( + "/api/v1/projects/resources/databases" + ); + return response.databases; + } + + async listAllResourceDedicated(): Promise { + const response = await this.get( + "/api/v1/projects/resources/dedicated" + ); + return response.dedicated_servers; + } + + /** + * Перенести ресурс в другой проект + */ + async transferProjectResource( + fromProjectId: number, + toProjectId: number, + resourceId: number, + resourceType: ProjectResourceTypeEnum + ): Promise { + const body: TransferProjectResourceRequestDto = { + to_project: toProjectId, + resource_id: resourceId, + resource_type: resourceType, + }; + const response = await this.put( + `/api/v1/projects/${fromProjectId}/resources/transfer`, + body + ); + return response.resource; + } +} + +export const projectsApiClient: ProjectsApiClient = new ProjectsApiClient(); diff --git a/src/api/s3-buckets.ts b/src/api/s3-buckets.ts new file mode 100644 index 0000000..97a20d8 --- /dev/null +++ b/src/api/s3-buckets.ts @@ -0,0 +1,203 @@ +import { BaseApiClient } from "./client"; +import { Bucket } from "../types/bucket.type"; +import { BucketPreset } from "../types/bucket-preset.type"; +import { BucketUser } from "../types/bucket-user.type"; +import { + BucketSubdomain, + AddedBucketSubdomain, +} from "../types/bucket-subdomain.type"; +import { BucketTransferStatus } from "../types/bucket-transfer-status.type"; +import { BucketDeleteResponse } from "../types/bucket-delete-response.type"; + +import { ListBucketsResponseDto } from "../types/dto/list-buckets-response.dto"; +import { CreateBucketRequestDto } from "../types/dto/create-bucket-request.dto"; +import { CreateBucketResponseDto } from "../types/dto/create-bucket-response.dto"; +import { GetBucketResponseDto } from "../types/dto/get-bucket-response.dto"; +import { UpdateBucketRequestDto } from "../types/dto/update-bucket-request.dto"; +import { UpdateBucketResponseDto } from "../types/dto/update-bucket-response.dto"; +import { DeleteBucketResponseDto } from "../types/dto/delete-bucket-response.dto"; +import { GetBucketPresetsResponseDto } from "../types/dto/get-bucket-presets-response.dto"; +import { ListBucketUsersResponseDto } from "../types/dto/list-bucket-users-response.dto"; +import { UpdateBucketUserRequestDto } from "../types/dto/update-bucket-user-request.dto"; +import { UpdateBucketUserResponseDto } from "../types/dto/update-bucket-user-response.dto"; +import { GetBucketTransferStatusResponseDto } from "../types/dto/get-bucket-transfer-status-response.dto"; +import { TransferBucketRequestDto } from "../types/dto/transfer-bucket-request.dto"; +import { ListBucketSubdomainsResponseDto } from "../types/dto/list-bucket-subdomains-response.dto"; +import { AddBucketSubdomainsRequestDto } from "../types/dto/add-bucket-subdomains-request.dto"; +import { AddBucketSubdomainsResponseDto } from "../types/dto/add-bucket-subdomains-response.dto"; +import { DeleteBucketSubdomainsRequestDto } from "../types/dto/delete-bucket-subdomains-request.dto"; +import { DeleteBucketSubdomainsResponseDto } from "../types/dto/delete-bucket-subdomains-response.dto"; +import { AddBucketCertificateRequestDto } from "../types/dto/add-bucket-certificate-request.dto"; + +export class S3BucketsApiClient extends BaseApiClient { + /** + * Получает список всех S3-хранилищ аккаунта + */ + async listBuckets(): Promise { + const response = await this.get( + "/api/v1/storages/buckets" + ); + return response.buckets; + } + + /** + * Создаёт новое S3-хранилище. Нужно передать либо preset_id, либо configurator. + */ + async createBucket(data: CreateBucketRequestDto): Promise { + const response = await this.post( + "/api/v1/storages/buckets", + data + ); + return response.bucket; + } + + /** + * Получает детальную информацию по одному S3-хранилищу + */ + async getBucket(bucketId: number): Promise { + const response = await this.get( + `/api/v1/storages/buckets/${bucketId}` + ); + return response.bucket; + } + + /** + * Изменяет параметры S3-хранилища (тариф, конфигуратор, тип, описание) + */ + async updateBucket( + bucketId: number, + data: UpdateBucketRequestDto + ): Promise { + const response = await this.patch( + `/api/v1/storages/buckets/${bucketId}`, + data + ); + return response.bucket; + } + + /** + * Удаляет S3-хранилище. Поддерживает 2FA через hash+code query params. + */ + async deleteBucket( + bucketId: number, + hash?: string, + code?: string + ): Promise { + const params = new URLSearchParams(); + if (hash) params.append("hash", hash); + if (code) params.append("code", code); + const qs = params.toString(); + const endpoint = + qs.length > 0 + ? `/api/v1/storages/buckets/${bucketId}?${qs}` + : `/api/v1/storages/buckets/${bucketId}`; + + const response = await this.delete(endpoint); + return response?.bucket_delete ?? {}; + } + + /** + * Получает список тарифов для S3-хранилищ + */ + async getBucketPresets(): Promise { + const response = await this.get( + "/api/v1/presets/storages" + ); + return response.storages_presets; + } + + /** + * Получает список пользователей S3-хранилищ аккаунта + */ + async listBucketUsers(): Promise { + const response = await this.get( + "/api/v1/storages/users" + ); + return response.users; + } + + /** + * Изменяет пароль пользователя-администратора S3-хранилища + */ + async updateBucketUser( + userId: number, + secretKey: string + ): Promise { + const data: UpdateBucketUserRequestDto = { secret_key: secretKey }; + const response = await this.patch( + `/api/v1/storages/users/${userId}`, + data + ); + return response.user; + } + + /** + * Получает статус переноса хранилища от стороннего S3 в Timeweb Cloud + */ + async getBucketTransferStatus( + bucketId: number + ): Promise { + const response = await this.get( + `/api/v1/storages/buckets/${bucketId}/transfer-status` + ); + return response.transfer_status; + } + + /** + * Запускает перенос хранилища от стороннего провайдера S3 в Timeweb Cloud + */ + async transferBucket(data: TransferBucketRequestDto): Promise { + await this.post("/api/v1/storages/transfer", data); + } + + /** + * Получает список поддоменов хранилища + */ + async listBucketSubdomains(bucketId: number): Promise { + const response = await this.get( + `/api/v1/storages/buckets/${bucketId}/subdomains` + ); + return response.subdomains; + } + + /** + * Добавляет поддомены для хранилища + */ + async addBucketSubdomains( + bucketId: number, + subdomains: string[] + ): Promise { + const data: AddBucketSubdomainsRequestDto = { subdomains }; + const response = await this.post( + `/api/v1/storages/buckets/${bucketId}/subdomains`, + data + ); + return response.subdomains; + } + + /** + * Удаляет поддомены хранилища. Axios поддерживает body в DELETE запросах. + */ + async deleteBucketSubdomains( + bucketId: number, + subdomains: string[] + ): Promise { + const data: DeleteBucketSubdomainsRequestDto = { subdomains }; + const response = await this.makeRequest( + "DELETE", + `/api/v1/storages/buckets/${bucketId}/subdomains`, + data + ); + return response.subdomains; + } + + /** + * Добавляет SSL-сертификат для поддомена хранилища + */ + async addBucketSubdomainCertificate(subdomain: string): Promise { + const data: AddBucketCertificateRequestDto = { subdomain }; + await this.post("/api/v1/storages/certificates/generate", data); + } +} + +export const s3BucketsApiClient: S3BucketsApiClient = new S3BucketsApiClient(); diff --git a/src/api/servers.ts b/src/api/servers.ts new file mode 100644 index 0000000..514cf4b --- /dev/null +++ b/src/api/servers.ts @@ -0,0 +1,465 @@ +import { BaseApiClient } from "./client"; +import { Server } from "../types/server.type"; +import { ServerLog } from "../types/server-log.type"; +import { ServerBackup } from "../types/server-backup.type"; +import { ServerDisk } from "../types/server-disk.type"; +import { ServerIp } from "../types/server-ip.type"; +import { AutoBackupSettings } from "../types/auto-backup.type"; +import { ListServersResponseDto } from "../types/dto/list-servers-response.dto"; +import { GetServerResponseDto } from "../types/dto/get-server-response.dto"; +import { GetServerLogsResponseDto } from "../types/dto/get-server-logs-response.dto"; +import { ListServerDiskBackupsResponseDto } from "../types/dto/list-server-disk-backups-response.dto"; +import { CreateServerDiskBackupResponseDto } from "../types/dto/create-server-disk-backup-response.dto"; +import { ListServerDisksResponseDto } from "../types/dto/list-server-disks-response.dto"; +import { CreateServerRequestDto } from "../types/dto/create-server-request.dto"; +import { CreateServerResponseDto } from "../types/dto/create-server-response.dto"; +import { DeleteServerResponseDto } from "../types/dto/delete-server-response.dto"; +import { UpdateServerRequestDto } from "../types/dto/update-server-request.dto"; +import { ListServerIpsResponseDto } from "../types/dto/list-server-ips-response.dto"; +import { ServerIpResponseDto } from "../types/dto/server-ip-response.dto"; +import { ServerDiskResponseDto } from "../types/dto/server-disk-response.dto"; +import { AutoBackupResponseDto } from "../types/dto/auto-backup-response.dto"; +import { ServerDiskBackupResponseDto } from "../types/dto/server-disk-backup-response.dto"; + +export type ServerLogsOrder = "asc" | "desc"; + +export type ResizeServerParams = + | { preset_id: number } + | { + configurator: { + configurator_id: number; + cpu?: number; + ram?: number; + disk?: number; + gpu?: number; + }; + }; + +export type DeleteServerParams = { + hash?: string; + code?: string; +}; + +export type AddServerIpParams = { + type: "ipv4" | "ipv6"; + ptr?: string; +}; + +export type UpdateServerIpParams = { + ip: string; + ptr: string; +}; + +export type DeleteServerIpParams = { + ip: string; +}; + +export type ServerBootMode = "default" | "single" | "recovery_disk"; +export type ServerNatMode = "dnat_and_snat" | "snat" | "no_nat"; +export type ServerDiskBackupAction = "restore" | "mount" | "unmount"; + +export class ServersApiClient extends BaseApiClient { + /** + * Получает список всех серверов аккаунта + */ + async listServers(): Promise { + const response = await this.get("/api/v1/servers"); + return response.servers; + } + + /** + * Получает детальную информацию по одному серверу + */ + async getServer(serverId: number): Promise { + const response = await this.get( + `/api/v1/servers/${serverId}` + ); + return response.server; + } + + /** + * Запускает выключенный сервер + */ + async startServer(serverId: number): Promise { + await this.post(`/api/v1/servers/${serverId}/start`); + } + + /** + * Выполняет мягкое выключение сервера через ACPI shutdown + */ + async shutdownServer(serverId: number): Promise { + await this.post(`/api/v1/servers/${serverId}/shutdown`); + } + + /** + * Принудительно выключает сервер (аналог выдергивания кабеля) + */ + async hardShutdownServer(serverId: number): Promise { + await this.post(`/api/v1/servers/${serverId}/hard-shutdown`); + } + + /** + * Перезагружает сервер через ACPI (мягкая перезагрузка) + */ + async rebootServer(serverId: number): Promise { + await this.post(`/api/v1/servers/${serverId}/reboot`); + } + + /** + * Принудительная перезагрузка (reset power) + */ + async hardRebootServer(serverId: number): Promise { + await this.post(`/api/v1/servers/${serverId}/hard-reboot`); + } + + /** + * Клонирует сервер в отдельный VPS + */ + async cloneServer(serverId: number): Promise { + const response = await this.post( + `/api/v1/servers/${serverId}/clone` + ); + return response.server; + } + + /** + * Изменяет тариф или конфигурацию сервера + */ + async resizeServer( + serverId: number, + params: ResizeServerParams + ): Promise { + const response = await this.patch( + `/api/v1/servers/${serverId}`, + params + ); + return response.server; + } + + /** + * Получает список событий жизненного цикла сервера + */ + async getServerLogs( + serverId: number, + order: ServerLogsOrder = "desc" + ): Promise { + const response = await this.get( + `/api/v1/servers/${serverId}/logs?order=${order}` + ); + return response.server_logs; + } + + /** + * Получает список дисков сервера + */ + async listServerDisks(serverId: number): Promise { + const response = await this.get( + `/api/v1/servers/${serverId}/disks` + ); + return response.server_disks; + } + + /** + * Получает список бэкапов диска сервера + */ + async listServerDiskBackups( + serverId: number, + diskId: number + ): Promise { + const response = await this.get( + `/api/v1/servers/${serverId}/disks/${diskId}/backups` + ); + return response.backups; + } + + /** + * Создаёт ручной бэкап диска сервера + */ + async createServerDiskBackup( + serverId: number, + diskId: number, + comment?: string + ): Promise { + const response = await this.post( + `/api/v1/servers/${serverId}/disks/${diskId}/backups`, + comment ? { comment } : {} + ); + return response.backup; + } + + /** + * Удаляет бэкап диска сервера + */ + async deleteServerDiskBackup( + serverId: number, + diskId: number, + backupId: number + ): Promise { + await this.delete( + `/api/v1/servers/${serverId}/disks/${diskId}/backups/${backupId}` + ); + } + + /** + * Создаёт новый облачный сервер + */ + async createServer(data: CreateServerRequestDto): Promise { + const response = await this.post( + "/api/v1/servers", + data + ); + return response.server; + } + + /** + * Удаляет сервер (для аккаунтов с 2FA — поддерживает hash и code как query-параметры) + */ + async deleteServer( + serverId: number, + params: DeleteServerParams = {} + ): Promise { + const query: string[] = []; + if (params.hash) query.push(`hash=${encodeURIComponent(params.hash)}`); + if (params.code) query.push(`code=${encodeURIComponent(params.code)}`); + const qs = query.length > 0 ? `?${query.join("&")}` : ""; + const response = await this.delete( + `/api/v1/servers/${serverId}${qs}` + ); + return response?.server_delete ?? { is_moved_in_quarantine: true }; + } + + /** + * Обновляет метаданные сервера (имя, комментарий, avatar_id, cloud_init) + */ + async updateServer( + serverId: number, + data: UpdateServerRequestDto + ): Promise { + const response = await this.patch( + `/api/v1/servers/${serverId}`, + data + ); + return response.server; + } + + /** + * Сбрасывает пароль root сервера. Новый пароль будет отправлен на email. + */ + async resetServerPassword(serverId: number): Promise { + await this.post(`/api/v1/servers/${serverId}/reset-password`); + } + + /** + * Устанавливает тип загрузки ОС сервера + */ + async setServerBootMode( + serverId: number, + bootMode: ServerBootMode + ): Promise { + await this.post(`/api/v1/servers/${serverId}/boot-mode`, { + boot_mode: bootMode, + }); + } + + /** + * Отмонтирует ISO-образ и перезагружает сервер + */ + async unmountServerImage(serverId: number): Promise { + await this.post(`/api/v1/servers/${serverId}/image-unmount`); + } + + /** + * Изменяет правила маршрутизации (NAT) для сервера в локальной сети + */ + async setServerNatMode( + serverId: number, + natMode: ServerNatMode + ): Promise { + await this.patch( + `/api/v1/servers/${serverId}/local-networks/nat-mode`, + { nat_mode: natMode } + ); + } + + /** + * Получает список IP-адресов сервера + */ + async listServerIps(serverId: number): Promise { + const response = await this.get( + `/api/v1/servers/${serverId}/ips` + ); + return response.server_ips; + } + + /** + * Добавляет IP-адрес сервера + */ + async addServerIp( + serverId: number, + params: AddServerIpParams + ): Promise { + const response = await this.post( + `/api/v1/servers/${serverId}/ips`, + params + ); + return response.server_ip; + } + + /** + * Удаляет IP-адрес сервера. API принимает тело запроса с полем `ip`. + */ + async deleteServerIp( + serverId: number, + params: DeleteServerIpParams + ): Promise { + await this.makeRequest( + "DELETE", + `/api/v1/servers/${serverId}/ips`, + params + ); + } + + /** + * Изменяет PTR-запись для IP-адреса сервера + */ + async updateServerIp( + serverId: number, + params: UpdateServerIpParams + ): Promise { + const response = await this.patch( + `/api/v1/servers/${serverId}/ips`, + params + ); + return response.server_ip; + } + + /** + * Создаёт дополнительный диск для сервера + */ + async createServerDisk( + serverId: number, + size: number + ): Promise { + const response = await this.post( + `/api/v1/servers/${serverId}/disks`, + { size } + ); + return response.server_disk; + } + + /** + * Получает информацию по конкретному диску сервера + */ + async getServerDisk( + serverId: number, + diskId: number + ): Promise { + const response = await this.get( + `/api/v1/servers/${serverId}/disks/${diskId}` + ); + return response.server_disk; + } + + /** + * Изменяет размер диска сервера + */ + async updateServerDisk( + serverId: number, + diskId: number, + size: number + ): Promise { + const response = await this.patch( + `/api/v1/servers/${serverId}/disks/${diskId}`, + { size } + ); + return response.server_disk; + } + + /** + * Удаляет диск сервера + */ + async deleteServerDisk( + serverId: number, + diskId: number + ): Promise { + await this.delete( + `/api/v1/servers/${serverId}/disks/${diskId}` + ); + } + + /** + * Получает настройки автобэкапов диска + */ + async getServerDiskAutoBackups( + serverId: number, + diskId: number + ): Promise { + const response = await this.get( + `/api/v1/servers/${serverId}/disks/${diskId}/auto-backups` + ); + return response.auto_backups_settings; + } + + /** + * Изменяет настройки автобэкапов диска + */ + async updateServerDiskAutoBackups( + serverId: number, + diskId: number, + settings: AutoBackupSettings + ): Promise { + const response = await this.patch( + `/api/v1/servers/${serverId}/disks/${diskId}/auto-backups`, + settings + ); + return response.auto_backups_settings; + } + + /** + * Получает информацию по конкретному бэкапу диска + */ + async getServerDiskBackup( + serverId: number, + diskId: number, + backupId: number + ): Promise { + const response = await this.get( + `/api/v1/servers/${serverId}/disks/${diskId}/backups/${backupId}` + ); + return response.backup; + } + + /** + * Изменяет комментарий к бэкапу диска + */ + async updateServerDiskBackup( + serverId: number, + diskId: number, + backupId: number, + comment: string + ): Promise { + const response = await this.patch( + `/api/v1/servers/${serverId}/disks/${diskId}/backups/${backupId}`, + { comment } + ); + return response.backup; + } + + /** + * Выполняет действие над бэкапом: restore / mount / unmount + */ + async serverDiskBackupAction( + serverId: number, + diskId: number, + backupId: number, + action: ServerDiskBackupAction + ): Promise { + await this.post( + `/api/v1/servers/${serverId}/disks/${diskId}/backups/${backupId}/action`, + { action } + ); + } + +} + +export const serversApiClient: ServersApiClient = new ServersApiClient(); diff --git a/src/api/ssh-keys.ts b/src/api/ssh-keys.ts new file mode 100644 index 0000000..c9f0148 --- /dev/null +++ b/src/api/ssh-keys.ts @@ -0,0 +1,88 @@ +import { BaseApiClient } from "./client"; +import { SshKey } from "../types/ssh-key.type"; +import { ListSshKeysResponseDto } from "../types/dto/list-ssh-keys-response.dto"; +import { CreateSshKeyRequestDto } from "../types/dto/create-ssh-key-request.dto"; +import { CreateSshKeyResponseDto } from "../types/dto/create-ssh-key-response.dto"; +import { GetSshKeyResponseDto } from "../types/dto/get-ssh-key-response.dto"; +import { UpdateSshKeyRequestDto } from "../types/dto/update-ssh-key-request.dto"; +import { UpdateSshKeyResponseDto } from "../types/dto/update-ssh-key-response.dto"; +import { AddSshKeysToServerRequestDto } from "../types/dto/add-ssh-keys-to-server-request.dto"; + +export class SshKeysApiClient extends BaseApiClient { + /** + * Получает список всех SSH-ключей аккаунта + */ + async listSshKeys(): Promise { + const response = await this.get( + "/api/v1/ssh-keys" + ); + return response.ssh_keys; + } + + /** + * Создаёт новый SSH-ключ в аккаунте + */ + async createSshKey(data: CreateSshKeyRequestDto): Promise { + const response = await this.post( + "/api/v1/ssh-keys", + data + ); + return response.ssh_key; + } + + /** + * Получает SSH-ключ по ID + */ + async getSshKey(sshKeyId: number): Promise { + const response = await this.get( + `/api/v1/ssh-keys/${sshKeyId}` + ); + return response.ssh_key; + } + + /** + * Изменяет SSH-ключ по ID + */ + async updateSshKey( + sshKeyId: number, + data: UpdateSshKeyRequestDto + ): Promise { + const response = await this.patch( + `/api/v1/ssh-keys/${sshKeyId}`, + data + ); + return response.ssh_key; + } + + /** + * Удаляет SSH-ключ по ID + */ + async deleteSshKey(sshKeyId: number): Promise { + await this.delete(`/api/v1/ssh-keys/${sshKeyId}`); + } + + /** + * Добавляет SSH-ключи на сервер + */ + async addSshKeysToServer( + serverId: number, + sshKeyIds: number[] + ): Promise { + const data: AddSshKeysToServerRequestDto = { ssh_key_ids: sshKeyIds }; + await this.post(`/api/v1/servers/${serverId}/ssh-keys`, data); + } + + /** + * Удаляет SSH-ключ с сервера + */ + async removeSshKeyFromServer( + serverId: number, + sshKeyId: number + ): Promise { + await this.delete( + `/api/v1/servers/${serverId}/ssh-keys/${sshKeyId}` + ); + } +} + +export const sshKeysApiClient: SshKeysApiClient = new SshKeysApiClient(); diff --git a/src/index.ts b/src/index.ts index 2f76d8b..f8df204 100644 --- a/src/index.ts +++ b/src/index.ts @@ -22,7 +22,7 @@ const startServer = async () => { } ); - Object.values(tools).forEach((tool) => { + Object.values(tools).forEach((tool: any) => { server.registerTool( tool.name, { @@ -41,7 +41,7 @@ const startServer = async () => { ); }); - Object.values(resources).forEach((resource) => { + Object.values(resources).forEach((resource: any) => { server.registerResource( resource.name, resource.uri, @@ -53,7 +53,7 @@ const startServer = async () => { ); }); - Object.values(prompts).forEach((prompt) => { + Object.values(prompts).forEach((prompt: any) => { server.registerPrompt(prompt.name, prompt.config, prompt.handler); }); diff --git a/src/tools/add-balancer-ips.tool.ts b/src/tools/add-balancer-ips.tool.ts new file mode 100644 index 0000000..9d0d237 --- /dev/null +++ b/src/tools/add-balancer-ips.tool.ts @@ -0,0 +1,45 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { addBalancerIpsAction } from "../actions/add-balancer-ips.action"; + +const inputSchema = { + balancer_id: z + .number() + .int() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID балансировщика"), + ips: z + .array(z.string()) + .min(1) + .describe( + "ОБЯЗАТЕЛЬНОЕ ПОЛЕ - массив backend IP-адресов для добавления (например ['192.168.0.1', '192.168.0.2'])" + ), +}; + +const handler = async (params: { balancer_id: number; ips: string[] }) => { + try { + await addBalancerIpsAction(params.balancer_id, params.ips); + + return createToolResponse( + `✅ Добавлено IP к балансировщику ${params.balancer_id} (${params.ips.length}):\n${params.ips.map((i) => `• ${i}`).join("\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка добавления IP к балансировщику ${params.balancer_id}. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при добавлении IP к балансировщику" + ); + } +}; + +export const addBalancerIpsTool = { + name: ToolNames.ADD_BALANCER_IPS, + title: "Добавление IP к балансировщику", + description: + "Добавляет backend IP-адреса к балансировщику. На эти IP будет распределяться входящий трафик.", + inputSchema, + handler, +}; diff --git a/src/tools/add-balancer-to-project.tool.ts b/src/tools/add-balancer-to-project.tool.ts new file mode 100644 index 0000000..e1a2bbe --- /dev/null +++ b/src/tools/add-balancer-to-project.tool.ts @@ -0,0 +1,47 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { addBalancerToProjectAction } from "../actions/add-balancer-to-project.action"; + +const inputSchema = { + project_id: z + .number() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID проекта, куда добавить балансировщик"), + resource_id: z + .number() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID балансировщика"), +}; + +const handler = async (params: { + project_id: number; + resource_id: number; +}) => { + try { + const r = await addBalancerToProjectAction( + params.project_id, + params.resource_id + ); + return createToolResponse( + `✅ Балансировщик ${params.resource_id} добавлен в проект ${params.project_id}.\n` + + `• ID связи: ${r.id}, тип: ${r.type}, создан: ${new Date(r.created_at).toLocaleString("ru-RU")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось добавить балансировщик. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при добавлении балансировщика" + ); + } +}; + +export const addBalancerToProjectTool = { + name: ToolNames.ADD_BALANCER_TO_PROJECT, + title: "Добавление балансировщика в проект", + description: + "Привязывает существующий балансировщик к проекту. Для переноса между проектами используй transfer_project_resource.", + inputSchema, + handler, +}; diff --git a/src/tools/add-bucket-subdomain-certificate.tool.ts b/src/tools/add-bucket-subdomain-certificate.tool.ts new file mode 100644 index 0000000..169200f --- /dev/null +++ b/src/tools/add-bucket-subdomain-certificate.tool.ts @@ -0,0 +1,40 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { addBucketSubdomainCertificateAction } from "../actions/add-bucket-subdomain-certificate.action"; + +const inputSchema = { + subdomain: z + .string() + .describe( + "ОБЯЗАТЕЛЬНОЕ ПОЛЕ - поддомен, для которого нужно выпустить SSL-сертификат" + ), +}; + +const handler = async (params: { subdomain: string }) => { + try { + await addBucketSubdomainCertificateAction(params.subdomain); + + return createToolResponse( + `✅ Запущен выпуск SSL-сертификата для поддомена '${params.subdomain}'.\n\nСтатус можно проверить через list_bucket_subdomains (поле status).` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка выпуска SSL-сертификата для '${params.subdomain}'. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при выпуске SSL-сертификата" + ); + } +}; + +export const addBucketSubdomainCertificateTool = { + name: ToolNames.ADD_BUCKET_SUBDOMAIN_CERTIFICATE, + title: "Выпуск SSL-сертификата для поддомена S3-хранилища", + description: + "Выпускает SSL-сертификат (Let's Encrypt) для поддомена, привязанного к S3-хранилищу. Поддомен должен быть предварительно добавлен через add_bucket_subdomains и иметь корректную CNAME-запись.", + inputSchema, + handler, +}; diff --git a/src/tools/add-bucket-subdomains.tool.ts b/src/tools/add-bucket-subdomains.tool.ts new file mode 100644 index 0000000..2a8c456 --- /dev/null +++ b/src/tools/add-bucket-subdomains.tool.ts @@ -0,0 +1,50 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { addBucketSubdomainsAction } from "../actions/add-bucket-subdomains.action"; + +const inputSchema = { + bucket_id: z.number().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID S3-хранилища"), + subdomains: z + .array(z.string()) + .min(1) + .describe( + "ОБЯЗАТЕЛЬНОЕ ПОЛЕ - массив поддоменов для добавления, например ['test.example.com']" + ), +}; + +const handler = async (params: { + bucket_id: number; + subdomains: string[]; +}) => { + try { + const result = await addBucketSubdomainsAction( + params.bucket_id, + params.subdomains + ); + + const lines = result.map((s) => `• ${s.subdomain} — ${s.status}`); + + return createToolResponse( + `📋 Результат добавления поддоменов к хранилищу ${params.bucket_id}:\n\n${lines.join("\n")}\n\nДля выпуска SSL-сертификата используй add_bucket_subdomain_certificate.` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка добавления поддоменов к хранилищу ${params.bucket_id}. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при добавлении поддоменов" + ); + } +}; + +export const addBucketSubdomainsTool = { + name: ToolNames.ADD_BUCKET_SUBDOMAINS, + title: "Добавление поддоменов к S3-хранилищу", + description: + "Добавляет один или несколько поддоменов к S3-хранилищу. Для каждого возвращает статус: success, empty_cname (нет CNAME-записи), duplicate или failed. После добавления выпускай SSL через add_bucket_subdomain_certificate.", + inputSchema, + handler, +}; diff --git a/src/tools/add-bucket-to-project.tool.ts b/src/tools/add-bucket-to-project.tool.ts new file mode 100644 index 0000000..54de067 --- /dev/null +++ b/src/tools/add-bucket-to-project.tool.ts @@ -0,0 +1,42 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { addBucketToProjectAction } from "../actions/add-bucket-to-project.action"; + +const inputSchema = { + project_id: z + .number() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID проекта, куда добавить хранилище"), + resource_id: z.number().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID хранилища"), +}; + +const handler = async (params: { + project_id: number; + resource_id: number; +}) => { + try { + const r = await addBucketToProjectAction( + params.project_id, + params.resource_id + ); + return createToolResponse( + `✅ Хранилище ${params.resource_id} добавлено в проект ${params.project_id}.\n` + + `• ID связи: ${r.id}, тип: ${r.type}, создан: ${new Date(r.created_at).toLocaleString("ru-RU")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось добавить хранилище. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при добавлении хранилища"); + } +}; + +export const addBucketToProjectTool = { + name: ToolNames.ADD_BUCKET_TO_PROJECT, + title: "Добавление хранилища в проект", + description: "Привязывает существующее S3-хранилище к проекту.", + inputSchema, + handler, +}; diff --git a/src/tools/add-cluster-to-project.tool.ts b/src/tools/add-cluster-to-project.tool.ts new file mode 100644 index 0000000..b46ad8e --- /dev/null +++ b/src/tools/add-cluster-to-project.tool.ts @@ -0,0 +1,42 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { addClusterToProjectAction } from "../actions/add-cluster-to-project.action"; + +const inputSchema = { + project_id: z + .number() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID проекта, куда добавить кластер"), + resource_id: z.number().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID кластера"), +}; + +const handler = async (params: { + project_id: number; + resource_id: number; +}) => { + try { + const r = await addClusterToProjectAction( + params.project_id, + params.resource_id + ); + return createToolResponse( + `✅ Кластер ${params.resource_id} добавлен в проект ${params.project_id}.\n` + + `• ID связи: ${r.id}, тип: ${r.type}, создан: ${new Date(r.created_at).toLocaleString("ru-RU")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось добавить кластер. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при добавлении кластера"); + } +}; + +export const addClusterToProjectTool = { + name: ToolNames.ADD_CLUSTER_TO_PROJECT, + title: "Добавление кластера в проект", + description: "Привязывает существующий Kubernetes-кластер к проекту.", + inputSchema, + handler, +}; diff --git a/src/tools/add-database-to-project.tool.ts b/src/tools/add-database-to-project.tool.ts new file mode 100644 index 0000000..ab3c7f5 --- /dev/null +++ b/src/tools/add-database-to-project.tool.ts @@ -0,0 +1,42 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { addDatabaseToProjectAction } from "../actions/add-database-to-project.action"; + +const inputSchema = { + project_id: z + .number() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID проекта, куда добавить БД"), + resource_id: z.number().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID базы данных"), +}; + +const handler = async (params: { + project_id: number; + resource_id: number; +}) => { + try { + const r = await addDatabaseToProjectAction( + params.project_id, + params.resource_id + ); + return createToolResponse( + `✅ База данных ${params.resource_id} добавлена в проект ${params.project_id}.\n` + + `• ID связи: ${r.id}, тип: ${r.type}, создан: ${new Date(r.created_at).toLocaleString("ru-RU")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось добавить БД. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при добавлении БД"); + } +}; + +export const addDatabaseToProjectTool = { + name: ToolNames.ADD_DATABASE_TO_PROJECT, + title: "Добавление БД в проект", + description: "Привязывает существующую managed-БД к проекту.", + inputSchema, + handler, +}; diff --git a/src/tools/add-dedicated-to-project.tool.ts b/src/tools/add-dedicated-to-project.tool.ts new file mode 100644 index 0000000..8fc09cc --- /dev/null +++ b/src/tools/add-dedicated-to-project.tool.ts @@ -0,0 +1,48 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { addDedicatedToProjectAction } from "../actions/add-dedicated-to-project.action"; + +const inputSchema = { + project_id: z + .number() + .describe( + "ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID проекта, куда добавить выделенный сервер" + ), + resource_id: z + .number() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID выделенного сервера"), +}; + +const handler = async (params: { + project_id: number; + resource_id: number; +}) => { + try { + const r = await addDedicatedToProjectAction( + params.project_id, + params.resource_id + ); + return createToolResponse( + `✅ Выделенный сервер ${params.resource_id} добавлен в проект ${params.project_id}.\n` + + `• ID связи: ${r.id}, тип: ${r.type}, создан: ${new Date(r.created_at).toLocaleString("ru-RU")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось добавить выделенный сервер. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при добавлении выделенного сервера" + ); + } +}; + +export const addDedicatedToProjectTool = { + name: ToolNames.ADD_DEDICATED_TO_PROJECT, + title: "Добавление выделенного сервера в проект", + description: "Привязывает существующий выделенный сервер к проекту.", + inputSchema, + handler, +}; diff --git a/src/tools/add-domain.tool.ts b/src/tools/add-domain.tool.ts new file mode 100644 index 0000000..a49390c --- /dev/null +++ b/src/tools/add-domain.tool.ts @@ -0,0 +1,37 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { addDomainAction } from "../actions/add-domain.action"; + +const inputSchema = { + fqdn: z + .string() + .describe( + "ОБЯЗАТЕЛЬНОЕ ПОЛЕ - полное имя домена, который уже зарегистрирован у другого регистратора и его нужно добавить на аккаунт" + ), +}; + +const handler = async (params: { fqdn: string }) => { + try { + await addDomainAction(params.fqdn); + return createToolResponse( + `✅ Домен ${params.fqdn} добавлен на аккаунт. Управление DNS/NS теперь доступно в Timeweb Cloud.` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка добавления домена "${params.fqdn}". Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при добавлении домена"); + } +}; + +export const addDomainTool = { + name: ToolNames.ADD_DOMAIN, + title: "Добавление домена на аккаунт", + description: + "Добавляет уже зарегистрированный в другом месте домен на аккаунт Timeweb Cloud для управления DNS и name-серверами. Не выполняет регистрацию — для регистрации используй create_domain_request.", + inputSchema, + handler, +}; diff --git a/src/tools/add-server-ip.tool.ts b/src/tools/add-server-ip.tool.ts new file mode 100644 index 0000000..abab62a --- /dev/null +++ b/src/tools/add-server-ip.tool.ts @@ -0,0 +1,47 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { addServerIpAction } from "../actions/add-server-ip.action"; + +const inputSchema = { + server_id: z.number().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID сервера"), + type: z + .enum(["ipv4", "ipv6"]) + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - тип IP-адреса: ipv4 или ipv6"), + ptr: z.string().optional().describe("PTR-запись для нового IP (опц.)"), +}; + +const handler = async (params: { + server_id: number; + type: "ipv4" | "ipv6"; + ptr?: string; +}) => { + try { + const ip = await addServerIpAction(params.server_id, { + type: params.type, + ...(params.ptr !== undefined && { ptr: params.ptr }), + }); + return createToolResponse( + `✅ IP-адрес добавлен на сервер ${params.server_id}.\n` + + `• ${ip.type.toUpperCase()} ${ip.ip}\n` + + `• PTR: ${ip.ptr || "—"}\n` + + `• Основной: ${ip.is_main ? "да" : "нет"}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось добавить IP на сервер ${params.server_id}. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при добавлении IP"); + } +}; + +export const addServerIpTool = { + name: ToolNames.ADD_SERVER_IP, + title: "Добавление IP-адреса сервера", + description: + "Выделяет новый IPv4 или IPv6 адрес для сервера. Опционально можно задать PTR-запись.", + inputSchema, + handler, +}; diff --git a/src/tools/add-server-to-project.tool.ts b/src/tools/add-server-to-project.tool.ts new file mode 100644 index 0000000..7aeccd9 --- /dev/null +++ b/src/tools/add-server-to-project.tool.ts @@ -0,0 +1,43 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { addServerToProjectAction } from "../actions/add-server-to-project.action"; + +const inputSchema = { + project_id: z + .number() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID проекта, куда добавить сервер"), + resource_id: z.number().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID сервера"), +}; + +const handler = async (params: { + project_id: number; + resource_id: number; +}) => { + try { + const r = await addServerToProjectAction( + params.project_id, + params.resource_id + ); + return createToolResponse( + `✅ Сервер ${params.resource_id} добавлен в проект ${params.project_id}.\n` + + `• ID связи: ${r.id}, тип: ${r.type}, создан: ${new Date(r.created_at).toLocaleString("ru-RU")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось добавить сервер. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при добавлении сервера"); + } +}; + +export const addServerToProjectTool = { + name: ToolNames.ADD_SERVER_TO_PROJECT, + title: "Добавление сервера в проект", + description: + "Привязывает существующий VPS-сервер к проекту. Для переноса между проектами — transfer_project_resource.", + inputSchema, + handler, +}; diff --git a/src/tools/add-ssh-keys-to-server.tool.ts b/src/tools/add-ssh-keys-to-server.tool.ts new file mode 100644 index 0000000..82dabe9 --- /dev/null +++ b/src/tools/add-ssh-keys-to-server.tool.ts @@ -0,0 +1,51 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { addSshKeysToServerAction } from "../actions/add-ssh-keys-to-server.action"; + +const inputSchema = { + server_id: z.number().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID сервера"), + ssh_key_ids: z + .array(z.number()) + .min(1) + .describe( + "ОБЯЗАТЕЛЬНОЕ ПОЛЕ - массив ID SSH-ключей, которые нужно добавить на сервер" + ), +}; + +const handler = async (params: { + server_id: number; + ssh_key_ids: number[]; +}) => { + try { + if (!params.ssh_key_ids || params.ssh_key_ids.length === 0) { + return createToolResponse( + "❌ Нужно передать хотя бы один ID SSH-ключа." + ); + } + + await addSshKeysToServerAction(params.server_id, params.ssh_key_ids); + + return createToolResponse( + `✅ SSH-ключи [${params.ssh_key_ids.join(", ")}] добавлены на сервер ${params.server_id}.` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось добавить SSH-ключи на сервер ${params.server_id}. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при добавлении SSH-ключей на сервер" + ); + } +}; + +export const addSshKeysToServerTool = { + name: ToolNames.ADD_SSH_KEYS_TO_SERVER, + title: "Добавление SSH-ключей на сервер", + description: + "Добавляет один или несколько существующих SSH-ключей на сервер по массиву ID. Получить ID ключей можно через list_ssh_keys, ID сервера — через list_servers.", + inputSchema, + handler, +}; diff --git a/src/tools/add-subdomain.tool.ts b/src/tools/add-subdomain.tool.ts new file mode 100644 index 0000000..8e5d5b3 --- /dev/null +++ b/src/tools/add-subdomain.tool.ts @@ -0,0 +1,41 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { addSubdomainAction } from "../actions/add-subdomain.action"; + +const inputSchema = { + fqdn: z + .string() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - полное имя основного домена"), + subdomain_fqdn: z + .string() + .describe( + "ОБЯЗАТЕЛЬНОЕ ПОЛЕ - полное имя создаваемого поддомена (например: sub.example.com)" + ), +}; + +const handler = async (params: { fqdn: string; subdomain_fqdn: string }) => { + try { + const sub = await addSubdomainAction(params.fqdn, params.subdomain_fqdn); + return createToolResponse(`✅ Поддомен создан! +• ID: ${sub.id} +• FQDN: ${sub.fqdn} +• Привязанный IP: ${sub.linked_ip ?? "—"}`); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка создания поддомена "${params.subdomain_fqdn}" для "${params.fqdn}". Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при создании поддомена"); + } +}; + +export const addSubdomainTool = { + name: ToolNames.ADD_SUBDOMAIN, + title: "Добавление поддомена", + description: + "Создаёт поддомен у указанного основного домена. Нужны FQDN основного домена и FQDN поддомена.", + inputSchema, + handler, +}; diff --git a/src/tools/batch-create-mailboxes-v1.tool.ts b/src/tools/batch-create-mailboxes-v1.tool.ts new file mode 100644 index 0000000..69dfecc --- /dev/null +++ b/src/tools/batch-create-mailboxes-v1.tool.ts @@ -0,0 +1,63 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { batchCreateMailboxesV1Action } from "../actions/batch-create-mailboxes-v1.action"; + +const mailboxItemSchema = z.object({ + login: z.string().describe("Имя ящика (часть до @)"), + password: z.string().describe("Пароль ящика"), + owner_full_name: z.string().optional().describe("ФИО владельца (опц.)"), + comment: z.string().optional().describe("Комментарий (опц.)"), +}); + +const inputSchema = { + domain: z.string().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - имя домена"), + mailboxes: z + .array(mailboxItemSchema) + .min(1) + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - массив объектов с настройками ящиков"), +}; + +const handler = async (params: { + domain: string; + mailboxes: Array<{ + login: string; + password: string; + owner_full_name?: string; + comment?: string; + }>; +}) => { + try { + const created = await batchCreateMailboxesV1Action(params.domain, { + mailboxes: params.mailboxes, + }); + + const lines = created.map((m) => { + const full = + m.mailbox && m.fqdn ? `${m.mailbox}@${m.fqdn}` : (m.mailbox ?? "—"); + return ` • ${full}`; + }); + + return createToolResponse( + `✅ Массовое создание (API v1) завершено. Создано: ${created.length}\n${lines.join("\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка массового создания (v1). Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при массовом создании ящиков (v1)" + ); + } +}; + +export const batchCreateMailboxesV1Tool = { + name: ToolNames.BATCH_CREATE_MAILBOXES_V1, + title: "Массовое создание почтовых ящиков (API v1)", + description: + "Создаёт несколько ящиков на домене через API v1. Предпочитай batch_create_mailboxes (v2).", + inputSchema, + handler, +}; diff --git a/src/tools/batch-create-mailboxes.tool.ts b/src/tools/batch-create-mailboxes.tool.ts new file mode 100644 index 0000000..5b0c722 --- /dev/null +++ b/src/tools/batch-create-mailboxes.tool.ts @@ -0,0 +1,79 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { batchCreateMailboxesAction } from "../actions/batch-create-mailboxes.action"; + +const mailboxItemSchema = z.object({ + login: z.string().describe("Имя ящика (часть до @)"), + password: z.string().describe("Пароль ящика"), + owner_full_name: z.string().optional().describe("ФИО владельца (опц.)"), + comment: z.string().optional().describe("Комментарий (опц.)"), + filter_status: z.boolean().optional().describe("Спам-фильтр включён (опц.)"), + filter_action: z + .enum(["directory", "label"]) + .optional() + .describe("Действие спам-фильтра, только если filter_status=true"), +}); + +const inputSchema = { + domain: z.string().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - имя домена"), + mailboxes: z + .array(mailboxItemSchema) + .min(1) + .describe( + "ОБЯЗАТЕЛЬНОЕ ПОЛЕ - массив объектов с настройками ящиков для массового создания" + ), +}; + +const handler = async (params: { + domain: string; + mailboxes: Array<{ + login: string; + password: string; + owner_full_name?: string; + comment?: string; + filter_status?: boolean; + filter_action?: "directory" | "label"; + }>; +}) => { + try { + const batch = await batchCreateMailboxesAction( + params.domain, + params.mailboxes + ); + + const createdLines = batch.mailboxes.map((m) => { + const full = m.mailbox && m.fqdn ? `${m.mailbox}@${m.fqdn}` : (m.mailbox ?? "—"); + return ` • ${full}`; + }); + + const errorsBlock = + batch.errors.length > 0 + ? `\n\n⚠️ Ошибки (${batch.errors.length}):\n${batch.errors + .map((e) => ` • ${JSON.stringify(e)}`) + .join("\n")}` + : ""; + + return createToolResponse( + `✅ Массовое создание завершено. Создано: ${batch.mailboxes.length}\n${createdLines.join("\n")}${errorsBlock}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка массового создания ящиков. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при массовом создании ящиков" + ); + } +}; + +export const batchCreateMailboxesTool = { + name: ToolNames.BATCH_CREATE_MAILBOXES, + title: "Массовое создание почтовых ящиков", + description: + "Создаёт сразу несколько почтовых ящиков на одном домене (API v2). Возвращает список созданных ящиков и массив ошибок.", + inputSchema, + handler, +}; diff --git a/src/tools/bind-floating-ip.tool.ts b/src/tools/bind-floating-ip.tool.ts new file mode 100644 index 0000000..659df23 --- /dev/null +++ b/src/tools/bind-floating-ip.tool.ts @@ -0,0 +1,67 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { bindFloatingIpAction } from "../actions/bind-floating-ip.action"; +import { FloatingIpResourceType } from "../types/floating-ip.type"; + +const RESOURCE_TYPES: FloatingIpResourceType[] = [ + "server", + "balancer", + "database", + "network", +]; + +const inputSchema = { + floating_ip_id: z + .string() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID плавающего IP"), + resource_type: z + .enum(["server", "balancer", "database", "network"] as const) + .describe( + "ОБЯЗАТЕЛЬНОЕ ПОЛЕ - тип ресурса: server | balancer | database | network" + ), + resource_id: z + .union([z.string(), z.number()]) + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID ресурса (число или строка)"), +}; + +const handler = async (params: { + floating_ip_id: string; + resource_type: FloatingIpResourceType; + resource_id: string | number; +}) => { + try { + if (!RESOURCE_TYPES.includes(params.resource_type)) { + return createToolResponse( + `❌ Неверный resource_type: ${params.resource_type}. Допустимо: ${RESOURCE_TYPES.join(", ")}` + ); + } + + await bindFloatingIpAction(params.floating_ip_id, { + resource_type: params.resource_type, + resource_id: params.resource_id, + }); + + return createToolResponse( + `✅ Плавающий IP ${params.floating_ip_id} привязан к ${params.resource_type} #${params.resource_id}.` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка при привязке плавающего IP. Причина: ${error.message}` + ); + } + return createToolResponse( + `❌ Неизвестная ошибка при привязке плавающего IP` + ); + } +}; + +export const bindFloatingIpTool = { + name: ToolNames.BIND_FLOATING_IP, + title: "Привязка плавающего IP к сервису", + description: + "Привязывает плавающий IP к сервису (server / balancer / database / network) по ID ресурса", + inputSchema, + handler, +}; diff --git a/src/tools/check-domain.tool.ts b/src/tools/check-domain.tool.ts new file mode 100644 index 0000000..a3b32be --- /dev/null +++ b/src/tools/check-domain.tool.ts @@ -0,0 +1,40 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { checkDomainAction } from "../actions/check-domain.action"; + +const inputSchema = { + fqdn: z + .string() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - полное имя домена для проверки доступности"), +}; + +const handler = async (params: { fqdn: string }) => { + try { + const available = await checkDomainAction(params.fqdn); + if (available) { + return createToolResponse( + `✅ Домен ${params.fqdn} свободен и доступен для регистрации.` + ); + } + return createToolResponse( + `⚠️ Домен ${params.fqdn} уже занят — зарегистрировать нельзя.` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка проверки домена "${params.fqdn}". Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при проверке домена"); + } +}; + +export const checkDomainTool = { + name: ToolNames.CHECK_DOMAIN, + title: "Проверка доступности домена для регистрации", + description: + "Проверяет, свободен ли домен и можно ли его зарегистрировать. Возвращает булево значение.", + inputSchema, + handler, +}; diff --git a/src/tools/clone-server.tool.ts b/src/tools/clone-server.tool.ts new file mode 100644 index 0000000..1be8ad7 --- /dev/null +++ b/src/tools/clone-server.tool.ts @@ -0,0 +1,38 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { cloneServerAction } from "../actions/clone-server.action"; + +const inputSchema = { + server_id: z + .number() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID исходного сервера для клонирования"), +}; + +const handler = async (params: { server_id: number }) => { + try { + const server = await cloneServerAction(params.server_id); + return createToolResponse( + `✅ Сервер ${params.server_id} клонирован.\n\n` + + `Новый сервер: ID ${server.id}, имя "${server.name}", статус ${server.status}.\n` + + `Локация: ${server.location}, CPU: ${server.cpu}, RAM: ${server.ram} MB.\n` + + `Создание идёт асинхронно — повторно проверь статус через get_server.` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось клонировать сервер ${params.server_id}. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при клонировании"); + } +}; + +export const cloneServerTool = { + name: ToolNames.CLONE_SERVER, + title: "Клонирование сервера", + description: + "Создаёт полную копию сервера в отдельный VPS с такой же конфигурацией и данными. Использовать для миграций, blue-green deploy или тестирования рискованных операций на копии.", + inputSchema, + handler, +}; diff --git a/src/tools/create-ai-agent.tool.ts b/src/tools/create-ai-agent.tool.ts new file mode 100644 index 0000000..8b6091c --- /dev/null +++ b/src/tools/create-ai-agent.tool.ts @@ -0,0 +1,106 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { createAiAgentAction } from "../actions/create-ai-agent.action"; +import { CreateAiAgentRequestDto } from "../types/dto/create-ai-agent-request.dto"; + +const inputSchema = { + name: z.string().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - название агента"), + description: z.string().optional().describe("Описание агента"), + access_type: z + .enum(["public", "private"]) + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - тип доступа: public или private"), + model_id: z.number().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID модели (см. list_ai_models)"), + token_package_id: z + .number() + .describe( + "ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID пакета токенов (см. list_ai_agent_token_packages)" + ), + system_prompt: z + .string() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - системный промпт агента"), + refine_query: z + .boolean() + .optional() + .describe("Уточнять ли запрос перед обработкой (по умолчанию false)"), + temperature: z.number().optional().describe("temperature модели"), + top_p: z.number().optional().describe("top_p модели"), + max_tokens: z.number().optional().describe("Максимум токенов в ответе"), + frequency_penalty: z.number().optional().describe("frequency_penalty"), + presence_penalty: z.number().optional().describe("presence_penalty"), + project_id: z.number().optional().describe("ID проекта"), +}; + +const handler = async (params: { + name: string; + description?: string; + access_type: "public" | "private"; + model_id: number; + token_package_id: number; + system_prompt: string; + refine_query?: boolean; + temperature?: number; + top_p?: number; + max_tokens?: number; + frequency_penalty?: number; + presence_penalty?: number; + project_id?: number; +}) => { + try { + const body: CreateAiAgentRequestDto = { + name: params.name, + description: params.description, + access_type: params.access_type, + model_id: params.model_id, + token_package_id: params.token_package_id, + settings: { + model: { + ...(params.temperature !== undefined && { + temperature: params.temperature, + }), + ...(params.top_p !== undefined && { top_p: params.top_p }), + ...(params.max_tokens !== undefined && { + max_tokens: params.max_tokens, + }), + ...(params.frequency_penalty !== undefined && { + frequency_penalty: params.frequency_penalty, + }), + ...(params.presence_penalty !== undefined && { + presence_penalty: params.presence_penalty, + }), + }, + system_prompt: params.system_prompt, + refine_query: params.refine_query ?? false, + }, + ...(params.project_id !== undefined && { project_id: params.project_id }), + }; + + const agent = await createAiAgentAction(body); + + return createToolResponse(`✅ AI-агент создан! + +📋 Детали: +• ID: ${agent.id} +• Название: ${agent.name} +• Статус: ${agent.status} +• Тип доступа: ${agent.access_type} +• Модель ID: ${agent.model_id} +${agent.total_tokens !== undefined ? `• Всего токенов: ${agent.total_tokens}` : ""}`); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка создания AI-агента. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при создании агента"); + } +}; + +export const createAiAgentTool = { + name: ToolNames.CREATE_AI_AGENT, + title: "Создание AI-агента", + description: + "Создаёт нового AI-агента. Обязательны: name, access_type, model_id, token_package_id, system_prompt. Перед вызовом получи model_id через list_ai_models и token_package_id через list_ai_agent_token_packages.", + inputSchema, + handler, +}; diff --git a/src/tools/create-api-key.tool.ts b/src/tools/create-api-key.tool.ts new file mode 100644 index 0000000..e836497 --- /dev/null +++ b/src/tools/create-api-key.tool.ts @@ -0,0 +1,79 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { createApiKeyAction } from "../actions/create-api-key.action"; +import { CreateApiKeyRequestDto } from "../types/dto/create-api-key-request.dto"; + +const inputSchema = { + name: z + .string() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - имя для создаваемого API-токена"), + expire: z + .string() + .optional() + .describe( + "Дата и время истечения токена в ISO8601 (например 2026-12-31T23:59:59Z). Если не указано — токен без срока" + ), + is_able_to_delete: z + .boolean() + .optional() + .describe( + "Разрешить удаление сервисов этим токеном без подтверждения через Telegram (по умолчанию — политика аккаунта)" + ), + projects: z + .array(z.number()) + .optional() + .describe( + "Список ID проектов, к которым ограничивается токен. Пусто/не указано — доступ ко всем проектам" + ), +}; + +const handler = async (params: { + name: string; + expire?: string; + is_able_to_delete?: boolean; + projects?: number[]; +}) => { + try { + const data: CreateApiKeyRequestDto = { name: params.name }; + if (params.expire !== undefined) data.expire = params.expire; + if (params.is_able_to_delete !== undefined) + data.is_able_to_delete = params.is_able_to_delete; + if (params.projects !== undefined) data.projects = params.projects; + + const apiKey = await createApiKeyAction(data); + + const created = new Date(apiKey.created_at).toLocaleString("ru-RU"); + const expires = apiKey.expired_at + ? new Date(apiKey.expired_at).toLocaleString("ru-RU") + : "без срока"; + + return createToolResponse(`✅ API-токен создан + +⚠️ ВНИМАНИЕ: значение токена показывается только один раз. Сохраните его: + +Token: ${apiKey.token} + +📋 Детали: +• ID: ${apiKey.id} +• Имя: ${apiKey.name} +• Создан: ${created} +• Истекает: ${expires}`); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка при создании API-токена. Причина: ${error.message}` + ); + } + return createToolResponse(`❌ Неизвестная ошибка при создании API-токена`); + } +}; + +export const createApiKeyTool = { + name: ToolNames.CREATE_API_KEY, + title: "Создание API-токена", + description: + "Создает новый API-токен. Значение токена возвращается один раз и должно быть сохранено", + inputSchema, + handler, +}; diff --git a/src/tools/create-balancer-rule.tool.ts b/src/tools/create-balancer-rule.tool.ts new file mode 100644 index 0000000..c79ca5d --- /dev/null +++ b/src/tools/create-balancer-rule.tool.ts @@ -0,0 +1,68 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { createBalancerRuleAction } from "../actions/create-balancer-rule.action"; + +const BalancerProtoEnum = z.enum(["http", "http2", "https", "tcp"]); + +const inputSchema = { + balancer_id: z + .number() + .int() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID балансировщика"), + balancer_proto: BalancerProtoEnum.describe( + "ОБЯЗАТЕЛЬНОЕ ПОЛЕ - протокол балансировщика: http | http2 | https | tcp" + ), + balancer_port: z + .number() + .int() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - порт балансировщика"), + server_proto: BalancerProtoEnum.describe( + "ОБЯЗАТЕЛЬНОЕ ПОЛЕ - протокол backend-сервера" + ), + server_port: z + .number() + .int() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - порт backend-сервера"), +}; + +const handler = async (params: { + balancer_id: number; + balancer_proto: "http" | "http2" | "https" | "tcp"; + balancer_port: number; + server_proto: "http" | "http2" | "https" | "tcp"; + server_port: number; +}) => { + try { + const rule = await createBalancerRuleAction(params.balancer_id, { + balancer_proto: params.balancer_proto, + balancer_port: params.balancer_port, + server_proto: params.server_proto, + server_port: params.server_port, + }); + + return createToolResponse(`✅ Правило создано для балансировщика ${params.balancer_id}. + +• ID правила: ${rule.id} +• Вход: ${rule.balancer_proto}:${rule.balancer_port} +• На backend: ${rule.server_proto}:${rule.server_port}`); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка создания правила для балансировщика ${params.balancer_id}. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при создании правила балансировщика" + ); + } +}; + +export const createBalancerRuleTool = { + name: ToolNames.CREATE_BALANCER_RULE, + title: "Создание правила балансировщика", + description: + "Создаёт правило маршрутизации для балансировщика: соответствие между парой (протокол, порт) балансировщика и (протокол, порт) backend-сервера.", + inputSchema, + handler, +}; diff --git a/src/tools/create-balancer.tool.ts b/src/tools/create-balancer.tool.ts new file mode 100644 index 0000000..c5c6e62 --- /dev/null +++ b/src/tools/create-balancer.tool.ts @@ -0,0 +1,214 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { createBalancerAction } from "../actions/create-balancer.action"; +import { CreateBalancerRequestDto } from "../types/dto/create-balancer-request.dto"; + +const BalancerProtoEnum = z.enum(["http", "http2", "https", "tcp"]); +const BalancerAlgoEnum = z.enum(["roundrobin", "leastconn"]); + +const inputSchema = { + name: z + .string() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - имя балансировщика (уникальное в аккаунте)"), + algo: BalancerAlgoEnum.describe( + "ОБЯЗАТЕЛЬНОЕ ПОЛЕ - алгоритм балансировки: roundrobin | leastconn" + ), + is_sticky: z + .boolean() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - сохранять ли сессию"), + is_use_proxy: z + .boolean() + .describe( + "ОБЯЗАТЕЛЬНОЕ ПОЛЕ - выступает ли балансировщик в роли прокси" + ), + is_ssl: z + .boolean() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - требуется ли перенаправление на SSL"), + is_keepalive: z + .boolean() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - выдавать ли сигнал keepalive"), + proto: BalancerProtoEnum.describe( + "ОБЯЗАТЕЛЬНОЕ ПОЛЕ - протокол: http | http2 | https | tcp" + ), + path: z + .string() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - путь health-check (напр. /)"), + inter: z.number().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - интервал проверки"), + timeout: z + .number() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - таймаут ответа балансировщика"), + fall: z.number().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - порог количества ошибок"), + rise: z + .number() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - порог количества успешных ответов"), + preset_id: z + .number() + .describe( + "ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID тарифа (получить через list_balancer_presets)" + ), + port: z.number().optional().describe("Порт балансировщика (опц.)"), + maxconn: z + .number() + .optional() + .describe("Максимальное количество соединений (опц.)"), + connect_timeout: z + .number() + .optional() + .describe("Таймаут подключения (опц.)"), + client_timeout: z.number().optional().describe("Таймаут клиента (опц.)"), + server_timeout: z.number().optional().describe("Таймаут сервера (опц.)"), + httprequest_timeout: z + .number() + .optional() + .describe("Таймаут HTTP-запроса (опц.)"), + availability_zone: z + .string() + .optional() + .describe( + "Зона доступности (опц.): spb-1, spb-2, spb-3, spb-4, msk-1, nsk-1, ams-1, ala-1, fra-1" + ), + project_id: z.number().optional().describe("ID проекта (опц.)"), + network_id: z + .string() + .optional() + .describe("ID приватной сети VPC (опц.)"), + network_floating_ip: z + .string() + .optional() + .describe("Плавающий IP в приватной сети (опц.)"), + network_local_ip: z + .string() + .optional() + .describe("Локальный IP в приватной сети (опц.)"), + certificate_type: z + .enum(["lets_encrypt", "custom"]) + .optional() + .describe("Тип SSL-сертификата (опц.)"), + certificate_fqdn: z + .string() + .optional() + .describe("FQDN для сертификата (опц.)"), + certificate_cert_data: z + .string() + .optional() + .describe("PEM-данные сертификата (только для custom)"), + certificate_key_data: z + .string() + .optional() + .describe("PEM-данные приватного ключа (только для custom)"), +}; + +const handler = async (params: { + name: string; + algo: "roundrobin" | "leastconn"; + is_sticky: boolean; + is_use_proxy: boolean; + is_ssl: boolean; + is_keepalive: boolean; + proto: "http" | "http2" | "https" | "tcp"; + path: string; + inter: number; + timeout: number; + fall: number; + rise: number; + preset_id: number; + port?: number; + maxconn?: number; + connect_timeout?: number; + client_timeout?: number; + server_timeout?: number; + httprequest_timeout?: number; + availability_zone?: string; + project_id?: number; + network_id?: string; + network_floating_ip?: string; + network_local_ip?: string; + certificate_type?: "lets_encrypt" | "custom"; + certificate_fqdn?: string; + certificate_cert_data?: string; + certificate_key_data?: string; +}) => { + try { + const payload: CreateBalancerRequestDto = { + name: params.name, + algo: params.algo, + is_sticky: params.is_sticky, + is_use_proxy: params.is_use_proxy, + is_ssl: params.is_ssl, + is_keepalive: params.is_keepalive, + proto: params.proto, + path: params.path, + inter: params.inter, + timeout: params.timeout, + fall: params.fall, + rise: params.rise, + preset_id: params.preset_id, + }; + + if (typeof params.port === "number") payload.port = params.port; + if (typeof params.maxconn === "number") payload.maxconn = params.maxconn; + if (typeof params.connect_timeout === "number") + payload.connect_timeout = params.connect_timeout; + if (typeof params.client_timeout === "number") + payload.client_timeout = params.client_timeout; + if (typeof params.server_timeout === "number") + payload.server_timeout = params.server_timeout; + if (typeof params.httprequest_timeout === "number") + payload.httprequest_timeout = params.httprequest_timeout; + if (params.availability_zone) + payload.availability_zone = params.availability_zone; + if (typeof params.project_id === "number") + payload.project_id = params.project_id; + + if (params.network_id) { + payload.network = { + id: params.network_id, + floating_ip: params.network_floating_ip, + local_ip: params.network_local_ip, + }; + } + + if (params.certificate_type) { + payload.certificates = { + type: params.certificate_type, + fqdn: params.certificate_fqdn, + cert_data: params.certificate_cert_data, + key_data: params.certificate_key_data, + }; + } + + const b = await createBalancerAction(payload); + + return createToolResponse(`✅ Балансировщик успешно создан! + +📋 Детали: +• ID: ${b.id} +• Имя: ${b.name} +• Статус: ${b.status} +• Протокол/Порт: ${b.proto}:${b.port} +• Алгоритм: ${b.algo} +• Локация: ${b.location}, зона: ${b.availability_zone} +• IP: ${b.ip ?? "—"} +• Preset: ${b.preset_id} +• Создан: ${new Date(b.created_at).toLocaleString("ru-RU")}`); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка создания балансировщика. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при создании балансировщика" + ); + } +}; + +export const createBalancerTool = { + name: ToolNames.CREATE_BALANCER, + title: "Создание балансировщика", + description: + "Создаёт новый балансировщик нагрузки. Обязательны: name, algo, is_sticky, is_use_proxy, is_ssl, is_keepalive, proto, path, inter, timeout, fall, rise, preset_id. preset_id получай через list_balancer_presets. Для приватной сети задай network_id. Для SSL — certificate_type.", + inputSchema, + handler, +}; diff --git a/src/tools/create-bucket.tool.ts b/src/tools/create-bucket.tool.ts new file mode 100644 index 0000000..238b316 --- /dev/null +++ b/src/tools/create-bucket.tool.ts @@ -0,0 +1,122 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { createBucketAction } from "../actions/create-bucket.action"; + +const inputSchema = { + name: z + .string() + .min(1) + .max(255) + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - название хранилища (1-255 символов)"), + type: z + .enum(["private", "public"]) + .describe( + "ОБЯЗАТЕЛЬНОЕ ПОЛЕ - тип хранилища: 'private' (приватное) или 'public' (публичное)" + ), + description: z + .string() + .min(1) + .max(255) + .optional() + .describe("Комментарий к хранилищу (1-255 символов, опц.)"), + preset_id: z + .number() + .optional() + .describe( + "ID тарифа. Нельзя передавать вместе с configurator. Список тарифов — get_bucket_presets." + ), + configurator_id: z + .number() + .optional() + .describe( + "ID конфигуратора хранилища. Нельзя передавать вместе с preset_id." + ), + configurator_disk_mb: z + .number() + .optional() + .describe("Размер диска в МБ для конфигуратора (опц.)"), + project_id: z.number().optional().describe("ID проекта (опц.)"), +}; + +const handler = async (params: { + name: string; + type: "private" | "public"; + description?: string; + preset_id?: number; + configurator_id?: number; + configurator_disk_mb?: number; + project_id?: number; +}) => { + try { + const hasPreset = params.preset_id !== undefined; + const hasConfigurator = + params.configurator_id !== undefined || + params.configurator_disk_mb !== undefined; + + if (hasPreset && hasConfigurator) { + return createToolResponse( + "❌ Нельзя передавать одновременно preset_id и конфигуратор. Выбери что-то одно." + ); + } + + if (!hasPreset && !hasConfigurator) { + return createToolResponse( + "❌ Нужно передать либо preset_id, либо configurator_id + configurator_disk_mb." + ); + } + + const body: any = { + name: params.name, + type: params.type, + }; + if (params.description) body.description = params.description; + if (params.project_id !== undefined) body.project_id = params.project_id; + if (hasPreset) body.preset_id = params.preset_id; + if (hasConfigurator) { + body.configurator = {}; + if (params.configurator_id !== undefined) + body.configurator.id = params.configurator_id; + if (params.configurator_disk_mb !== undefined) + body.configurator.disk = params.configurator_disk_mb; + } + + const bucket = await createBucketAction(body); + + return createToolResponse(`✅ S3-хранилище успешно создано! + +📋 Детали хранилища: +• ID: ${bucket.id} +• Название: ${bucket.name} +• Тип: ${bucket.type} +• Статус: ${bucket.status} +• Класс хранилища: ${bucket.storage_class} +• Локация: ${bucket.location} +• Hostname: ${bucket.hostname} +• Access key: ${bucket.access_key} +• Secret key: ${bucket.secret_key} +• Preset ID: ${bucket.preset_id ?? "—"} +• Configurator ID: ${bucket.configurator_id ?? "—"} +• Описание: ${bucket.description || "—"} + +🎉 Хранилище готово к использованию!`); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка создания S3-хранилища. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при создании S3-хранилища" + ); + } +}; + +export const createBucketTool = { + name: ToolNames.CREATE_BUCKET, + title: "Создание S3-хранилища", + description: + "Создаёт новое S3-хранилище. Нужно указать name, type (private/public) и ЛИБО preset_id, ЛИБО configurator_id + configurator_disk_mb. Возвращает access_key и secret_key для подключения.", + inputSchema, + handler, +}; diff --git a/src/tools/create-container-registry.tool.ts b/src/tools/create-container-registry.tool.ts new file mode 100644 index 0000000..f880370 --- /dev/null +++ b/src/tools/create-container-registry.tool.ts @@ -0,0 +1,112 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { createContainerRegistryAction } from "../actions/create-container-registry.action"; + +const inputSchema = { + name: z + .string() + .regex( + /^[a-z0-9][a-z0-9-]{1,46}[a-z0-9]$/, + "Имя должно быть 3-48 символов: латиница в нижнем регистре, цифры, «-», без пробелов, начинаться/заканчиваться буквой или цифрой" + ) + .describe( + "ОБЯЗАТЕЛЬНОЕ ПОЛЕ - Имя реестра. Уникальное, 3-48 символов, только [a-z0-9-], без пробелов" + ), + description: z.string().optional().describe("Описание реестра (опц.)"), + preset_id: z + .number() + .optional() + .describe( + "Режим 1: ID готового тарифа (получить через list_container_registry_presets). Нельзя вместе с configurator_id." + ), + configurator_id: z + .number() + .optional() + .describe( + "Режим 2: ID конфигуратора для кастомной конфигурации. Нельзя вместе с preset_id." + ), + disk: z + .number() + .optional() + .describe( + "Для configurator-режима: размер диска в ГБ. ОБЯЗАТЕЛЬНО если передан configurator_id." + ), + project_id: z + .number() + .optional() + .describe("ID проекта, в который добавить реестр (опц.)"), +}; + +const handler = async (params: { + name: string; + description?: string; + preset_id?: number; + configurator_id?: number; + disk?: number; + project_id?: number; +}) => { + if (params.preset_id && params.configurator_id) { + return createToolResponse( + "❌ Нельзя передавать одновременно preset_id и configurator_id. Выбери один режим." + ); + } + if (!params.preset_id && !params.configurator_id) { + return createToolResponse( + "❌ Нужен либо preset_id (готовый тариф), либо configurator_id (кастомная конфигурация)." + ); + } + if (params.configurator_id && !params.disk) { + return createToolResponse( + "❌ При использовании configurator_id обязательно укажи disk (размер диска в ГБ)." + ); + } + + try { + const body: any = { + name: params.name, + ...(params.description !== undefined && { + description: params.description, + }), + ...(params.project_id !== undefined && { project_id: params.project_id }), + }; + if (params.preset_id) { + body.preset_id = params.preset_id; + } else { + body.configuration = { + id: params.configurator_id!, + disk: params.disk!, + }; + } + + const r = await createContainerRegistryAction(body); + + return createToolResponse(`✅ Реестр контейнеров создан! + +📋 Детали: +• ID: ${r.id} +• Имя: ${r.name} +• Описание: ${r.description || "—"} +• Preset ID: ${r.preset_id} +• Configurator ID: ${r.configurator_id} +• Project ID: ${r.project_id} +• Диск: ${r.disk_stats.size} ГБ +• Создан: ${new Date(r.created_at).toLocaleString("ru-RU")}`); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось создать реестр контейнеров. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при создании реестра"); + } +}; + +export const createContainerRegistryTool = { + name: ToolNames.CREATE_CONTAINER_REGISTRY, + title: "Создание реестра контейнеров", + description: + "Создаёт новый реестр контейнеров (Container Registry). Укажи либо preset_id (готовый тариф), либо configurator_id + disk (кастомная конфигурация). Имя должно быть уникальным, 3-48 символов, только [a-z0-9-].", + inputSchema, + handler, +}; diff --git a/src/tools/create-database-admin.tool.ts b/src/tools/create-database-admin.tool.ts new file mode 100644 index 0000000..e008414 --- /dev/null +++ b/src/tools/create-database-admin.tool.ts @@ -0,0 +1,111 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { createDatabaseAdminAction } from "../actions/create-database-admin.action"; + +const PRIVILEGES = [ + "ALTER", + "CREATE_VIEW", + "CREATE", + "DELETE", + "DROP", + "EVENT", + "INDEX", + "INSERT", + "LOCK_TABLES", + "REFERENCES", + "SELECT", + "SHOW_VIEW", + "TRUNCATE", + "UPDATE", + "READ", + "WRITE", + "CONNECTION", + "FAST", + "readWrite", + "ALTER_ROUTINE", + "CREATE_ROUTINE", + "TRANSACTION", + "SLOW_LOG", + "TRIGGER", + "CREATE_TEMPORARY_TABLES", +] as const; + +const inputSchema = { + db_cluster_id: z + .number() + .int() + .positive() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID кластера базы данных"), + login: z + .string() + .min(1) + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - имя (login) пользователя"), + password: z + .string() + .min(8) + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - пароль пользователя (мин. 8 символов)"), + privileges: z + .array(z.enum(PRIVILEGES)) + .min(1) + .describe( + `ОБЯЗАТЕЛЬНОЕ ПОЛЕ - список привилегий. Допустимые: ${PRIVILEGES.join(", ")}` + ), + host: z + .string() + .optional() + .describe("НЕ ОБЯЗАТЕЛЬНОЕ ПОЛЕ - хост пользователя, напр. '%'"), + instance_id: z + .number() + .int() + .positive() + .optional() + .describe( + "НЕ ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID инстанса для применения привилегий (только MySQL). Если не передано — применится ко всем инстансам" + ), + description: z + .string() + .optional() + .describe("НЕ ОБЯЗАТЕЛЬНОЕ ПОЛЕ - описание пользователя"), +}; + +const handler = async (params: { + db_cluster_id: number; + login: string; + password: string; + privileges: string[]; + host?: string; + instance_id?: number; + description?: string; +}) => { + try { + const { db_cluster_id, ...data } = params; + const admin = await createDatabaseAdminAction(db_cluster_id, data); + + if (!admin) { + return createToolResponse( + `⚠️ Запрос на создание пользователя "${params.login}" отправлен, но API не вернул объект.` + ); + } + + return createToolResponse( + `✅ Пользователь ${admin.login} (ID ${admin.id}) создан в кластере ${db_cluster_id}.` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось создать пользователя "${params.login}". Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при создании пользователя"); + } +}; + +export const createDatabaseAdminTool = { + name: ToolNames.CREATE_DATABASE_ADMIN, + title: "Создание пользователя кластера", + description: + "Создаёт пользователя в кластере базы данных (`POST /api/v1/databases/{db_cluster_id}/admins`).", + inputSchema, + handler, +}; diff --git a/src/tools/create-database-instance.tool.ts b/src/tools/create-database-instance.tool.ts new file mode 100644 index 0000000..67bf2b0 --- /dev/null +++ b/src/tools/create-database-instance.tool.ts @@ -0,0 +1,55 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { createDatabaseInstanceAction } from "../actions/create-database-instance.action"; + +const inputSchema = { + db_cluster_id: z + .number() + .int() + .positive() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID кластера базы данных"), + name: z + .string() + .min(1) + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - название инстанса базы данных"), + description: z + .string() + .optional() + .describe("НЕ ОБЯЗАТЕЛЬНОЕ ПОЛЕ - описание инстанса"), +}; + +const handler = async (params: { + db_cluster_id: number; + name: string; + description?: string; +}) => { + try { + const { db_cluster_id, ...data } = params; + const i = await createDatabaseInstanceAction(db_cluster_id, data); + if (!i) { + return createToolResponse( + `⚠️ Запрос на создание инстанса "${params.name}" отправлен, но API не вернул объект.` + ); + } + return createToolResponse( + `✅ Инстанс ${i.name} (ID ${i.id}) создан в кластере ${db_cluster_id}.` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось создать инстанс "${params.name}". Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при создании инстанса"); + } +}; + +export const createDatabaseInstanceTool = { + name: ToolNames.CREATE_DATABASE_INSTANCE, + title: "Создание инстанса в кластере", + description: + "Создаёт новый инстанс (БД) внутри кластера (`POST /api/v1/databases/{db_cluster_id}/instances`).", + inputSchema, + handler, +}; diff --git a/src/tools/create-dedicated-server.tool.ts b/src/tools/create-dedicated-server.tool.ts new file mode 100644 index 0000000..5877d34 --- /dev/null +++ b/src/tools/create-dedicated-server.tool.ts @@ -0,0 +1,141 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { createDedicatedServerAction } from "../actions/create-dedicated-server.action"; +import { DedicatedServerPaymentPeriod } from "../types/dedicated-server.type"; + +const paymentPeriods = ["P1M", "P3M", "P6M", "P1Y"] as const; + +const inputSchema = { + preset_id: z + .number() + .describe( + "ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID тарифа выделенного сервера (получить через list_dedicated_server_presets)" + ), + payment_period: z + .enum(paymentPeriods) + .describe( + "ОБЯЗАТЕЛЬНОЕ ПОЛЕ - Период оплаты: P1M (месяц), P3M (3 мес), P6M (полгода), P1Y (год)" + ), + name: z + .string() + .max(255) + .describe( + "ОБЯЗАТЕЛЬНОЕ ПОЛЕ - Удобочитаемое имя сервера, уникальное, до 255 символов" + ), + plan_id: z + .number() + .nullable() + .optional() + .describe( + "ID списка дополнительных услуг (получить через list_dedicated_server_additional_services)" + ), + os_id: z + .number() + .nullable() + .optional() + .describe("ID операционной системы для установки"), + cp_id: z + .number() + .nullable() + .optional() + .describe("ID панели управления для установки"), + bandwidth_id: z + .number() + .nullable() + .optional() + .describe("ID интернет-канала"), + network_drive_id: z + .number() + .optional() + .describe("ID сетевого диска"), + additional_ip_addr_id: z + .number() + .nullable() + .optional() + .describe("ID дополнительного IP-адреса"), + comment: z + .string() + .max(255) + .nullable() + .optional() + .describe("Комментарий к серверу, до 255 символов"), + project_id: z + .number() + .nullable() + .optional() + .describe("ID проекта, в который добавить сервер"), +}; + +const handler = async (params: { + preset_id: number; + payment_period: DedicatedServerPaymentPeriod; + name: string; + plan_id?: number | null; + os_id?: number | null; + cp_id?: number | null; + bandwidth_id?: number | null; + network_drive_id?: number; + additional_ip_addr_id?: number | null; + comment?: string | null; + project_id?: number | null; +}) => { + try { + const body = { + preset_id: params.preset_id, + payment_period: params.payment_period, + name: params.name, + ...(params.plan_id !== undefined && { plan_id: params.plan_id }), + ...(params.os_id !== undefined && { os_id: params.os_id }), + ...(params.cp_id !== undefined && { cp_id: params.cp_id }), + ...(params.bandwidth_id !== undefined && { + bandwidth_id: params.bandwidth_id, + }), + ...(params.network_drive_id !== undefined && { + network_drive_id: params.network_drive_id, + }), + ...(params.additional_ip_addr_id !== undefined && { + additional_ip_addr_id: params.additional_ip_addr_id, + }), + ...(params.comment !== undefined && { comment: params.comment }), + ...(params.project_id !== undefined && { project_id: params.project_id }), + }; + + const s = await createDedicatedServerAction(body); + + return createToolResponse(`✅ Выделенный сервер создан! + +📋 Детали: +• ID: ${s.id} +• Имя: ${s.name} +• Статус: ${s.status} +• Preset ID: ${s.preset_id}, Plan ID: ${s.plan_id ?? "—"} +• Локация: ${s.location} +• CPU: ${s.cpu_description} +• RAM: ${s.ram_description} +• HDD: ${s.hdd_description} +• IPv4: ${s.ip ?? "—"}, IPv6: ${s.ipv6 ?? "—"} +• Цена: ${s.price} руб +• Создан: ${new Date(s.created_at).toLocaleString("ru-RU")} + +⏳ Установка выделенного сервера может занять от нескольких минут до нескольких часов.`); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось создать выделенный сервер. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при создании выделенного сервера" + ); + } +}; + +export const createDedicatedServerTool = { + name: ToolNames.CREATE_DEDICATED_SERVER, + title: "Создание выделенного сервера", + description: + "Создаёт новый выделенный (dedicated) физический сервер. Обязательные поля: preset_id (тариф), payment_period (P1M/P3M/P6M/P1Y), name. Опционально: OS, панель управления, доп. услуги, сетевой диск, IP-адрес, проект. Перед вызовом получи preset_id через list_dedicated_server_presets.", + inputSchema, + handler, +}; diff --git a/src/tools/create-dns-record.tool.ts b/src/tools/create-dns-record.tool.ts new file mode 100644 index 0000000..2dd6f0b --- /dev/null +++ b/src/tools/create-dns-record.tool.ts @@ -0,0 +1,121 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { createDnsRecordAction } from "../actions/create-dns-record.action"; +import { CreateDnsRecordV2RequestDto } from "../types/dto/create-dns-record-request.dto"; + +const DNS_TYPES = ["A", "AAAA", "TXT", "CNAME", "MX", "SRV"] as const; + +const inputSchema = { + fqdn: z + .string() + .describe( + "ОБЯЗАТЕЛЬНОЕ ПОЛЕ - полное имя домена или поддомена, к которому добавить запись" + ), + type: z + .enum(DNS_TYPES) + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - тип DNS-записи: A, AAAA, TXT, CNAME, MX, SRV"), + value: z + .string() + .optional() + .describe( + "Значение DNS-записи. Для A — IPv4, AAAA — IPv6, TXT/CNAME/MX — строка. Для SRV не используется (см. host/port/service/protocol)." + ), + ttl: z + .number() + .optional() + .describe("Время жизни записи (TTL) в секундах, например 600"), + priority: z + .number() + .optional() + .describe("Приоритет (для MX и SRV записей)"), + subdomain: z + .string() + .optional() + .describe("Имя поддомена (только префикс, без основного домена)"), + app_id: z + .number() + .optional() + .describe("ID приложения в App Platform (для A-записи с привязкой к app)"), + host: z + .string() + .optional() + .describe("SRV: каноническое имя хоста, предоставляющего сервис"), + port: z + .number() + .optional() + .describe("SRV: порт сервиса"), + service: z + .string() + .optional() + .describe("SRV: имя сервиса, например _sip"), + protocol: z + .string() + .optional() + .describe("SRV: протокол, например _TCP или _UDP"), +}; + +const handler = async (params: { + fqdn: string; + type: (typeof DNS_TYPES)[number]; + value?: string; + ttl?: number; + priority?: number; + subdomain?: string; + app_id?: number; + host?: string; + port?: number; + service?: string; + protocol?: string; +}) => { + try { + if (params.type !== "SRV" && !params.value) { + return createToolResponse( + `❌ Для записи типа ${params.type} поле value обязательно.` + ); + } + if (params.type === "SRV") { + if (!params.host || !params.port || !params.service || !params.protocol) { + return createToolResponse( + "❌ Для SRV-записи нужны все поля: host, port, service, protocol." + ); + } + } + + const body: CreateDnsRecordV2RequestDto = { type: params.type }; + if (params.value !== undefined) body.value = params.value; + if (params.ttl !== undefined) body.ttl = params.ttl; + if (params.priority !== undefined) body.priority = params.priority; + if (params.subdomain !== undefined) body.subdomain = params.subdomain; + if (params.app_id !== undefined) body.app_id = params.app_id; + if (params.host !== undefined) body.host = params.host; + if (params.port !== undefined) body.port = params.port; + if (params.service !== undefined) body.service = params.service; + if (params.protocol !== undefined) body.protocol = params.protocol; + + const record = await createDnsRecordAction(params.fqdn, body); + return createToolResponse(`✅ DNS-запись создана! +• ID: ${record.id ?? "—"} +• Тип: ${record.type} +• FQDN: ${record.fqdn ?? params.fqdn} +• Значение: ${record.data.value ?? "—"} +• TTL: ${record.ttl ?? "default"} +${record.data.subdomain ? `• Поддомен: ${record.data.subdomain}\n` : ""}${record.data.priority !== undefined ? `• Приоритет: ${record.data.priority}` : ""}`); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка создания DNS-записи для "${params.fqdn}". Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при создании DNS-записи"); + } +}; + +export const createDnsRecordTool = { + name: ToolNames.CREATE_DNS_RECORD, + title: "Создание DNS-записи", + description: + "Создаёт DNS-запись (A, AAAA, TXT, CNAME, MX, SRV) для домена или поддомена. Использует API v2. Для SRV нужны host/port/service/protocol вместо value.", + inputSchema, + handler, +}; diff --git a/src/tools/create-domain-request.tool.ts b/src/tools/create-domain-request.tool.ts new file mode 100644 index 0000000..ff6dfcd --- /dev/null +++ b/src/tools/create-domain-request.tool.ts @@ -0,0 +1,133 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { createDomainRequestAction } from "../actions/domain-requests.action"; +import { CreateDomainRequestRequestDto } from "../types/dto/create-domain-request-request.dto"; + +const inputSchema = { + action: z + .enum(["register", "prolong", "transfer"]) + .describe( + "ОБЯЗАТЕЛЬНОЕ ПОЛЕ - тип заявки: register (регистрация), prolong (продление), transfer (перенос)" + ), + fqdn: z.string().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - полное имя домена"), + person_id: z + .number() + .optional() + .describe( + "ID администратора домена. ОБЯЗАТЕЛЕН для register. Для prolong опционален." + ), + period: z + .string() + .optional() + .describe("Период регистрации/продления в формате ISO 8601, например P1Y"), + is_autoprolong_enabled: z + .boolean() + .optional() + .describe("Включить автопродление"), + is_whois_privacy_enabled: z + .boolean() + .optional() + .describe("Включить скрытие whois (недоступно для .ru и .рф)"), + is_antispam_enabled: z + .boolean() + .optional() + .describe("Антиспам (только для prolong)"), + prime: z.string().optional().describe("Prime-тип (только для prolong)"), + auth_code: z + .string() + .optional() + .describe("Код авторизации для переноса домена. ОБЯЗАТЕЛЕН для transfer."), +}; + +const handler = async (params: { + action: "register" | "prolong" | "transfer"; + fqdn: string; + person_id?: number; + period?: string; + is_autoprolong_enabled?: boolean; + is_whois_privacy_enabled?: boolean; + is_antispam_enabled?: boolean; + prime?: string; + auth_code?: string; +}) => { + try { + let body: CreateDomainRequestRequestDto; + + if (params.action === "register") { + if (params.person_id === undefined) { + return createToolResponse( + "❌ Для register заявки поле person_id обязательно." + ); + } + body = { + action: "register", + fqdn: params.fqdn, + person_id: params.person_id, + ...(params.period !== undefined && { period: params.period }), + ...(params.is_autoprolong_enabled !== undefined && { + is_autoprolong_enabled: params.is_autoprolong_enabled, + }), + ...(params.is_whois_privacy_enabled !== undefined && { + is_whois_privacy_enabled: params.is_whois_privacy_enabled, + }), + }; + } else if (params.action === "prolong") { + body = { + action: "prolong", + fqdn: params.fqdn, + ...(params.person_id !== undefined && { person_id: params.person_id }), + ...(params.period !== undefined && { period: params.period }), + ...(params.is_autoprolong_enabled !== undefined && { + is_autoprolong_enabled: params.is_autoprolong_enabled, + }), + ...(params.is_whois_privacy_enabled !== undefined && { + is_whois_privacy_enabled: params.is_whois_privacy_enabled, + }), + ...(params.is_antispam_enabled !== undefined && { + is_antispam_enabled: params.is_antispam_enabled, + }), + ...(params.prime !== undefined && { prime: params.prime }), + }; + } else { + if (!params.auth_code) { + return createToolResponse( + "❌ Для transfer заявки поле auth_code обязательно." + ); + } + body = { + action: "transfer", + fqdn: params.fqdn, + auth_code: params.auth_code, + }; + } + + const r = await createDomainRequestAction(body); + + return createToolResponse(`✅ Заявка создана! +• ID: ${r.id} +• FQDN: ${r.fqdn} +• Тип: ${r.type ?? params.action} +• Статус: ${r.status ?? "—"} +• Источник оплаты: ${r.money_source ?? "—"} +• Сообщение: ${r.message ?? "—"} + +Следующий шаг — оплатить или обновить заявку через update_domain_request.`); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка создания заявки на "${params.fqdn}". Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при создании заявки"); + } +}; + +export const createDomainRequestTool = { + name: ToolNames.CREATE_DOMAIN_REQUEST, + title: "Создание заявки на домен (регистрация/продление/трансфер)", + description: + "Создаёт заявку на операцию с доменом: регистрация (register), продление (prolong), перенос (transfer). Для register нужен person_id, для transfer — auth_code.", + inputSchema, + handler, +}; diff --git a/src/tools/create-firewall-group.tool.ts b/src/tools/create-firewall-group.tool.ts new file mode 100644 index 0000000..1148eef --- /dev/null +++ b/src/tools/create-firewall-group.tool.ts @@ -0,0 +1,62 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { createFirewallGroupAction } from "../actions/create-firewall-group.action"; +import { FirewallPolicy } from "../types/firewall-group.type"; + +const inputSchema = { + name: z + .string() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - имя группы правил firewall"), + description: z + .string() + .optional() + .describe("Описание группы правил (опц.)"), + policy: z + .enum(["ACCEPT", "DROP"]) + .optional() + .describe( + "Политика по умолчанию для группы: ACCEPT (пропускать) или DROP (блокировать). Передаётся как query-параметр при создании." + ), +}; + +const handler = async (params: { + name: string; + description?: string; + policy?: FirewallPolicy; +}) => { + try { + const g = await createFirewallGroupAction( + params.name, + params.description, + params.policy + ); + + return createToolResponse(`✅ Группа правил firewall создана! + +📋 Детали: +• ID: ${g.id} +• Имя: ${g.name} +• Описание: ${g.description || "—"} +• Политика: ${g.policy} +• Создана: ${new Date(g.created_at).toLocaleString("ru-RU")}`); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка создания группы firewall. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при создании группы firewall" + ); + } +}; + +export const createFirewallGroupTool = { + name: ToolNames.CREATE_FIREWALL_GROUP, + title: "Создание группы правил firewall", + description: + "Создаёт новую группу правил firewall. Имя обязательно, описание и политика (ACCEPT/DROP) — опциональны. После создания группу можно наполнить правилами через create_firewall_rule и привязать к серверу через link_firewall_resource.", + inputSchema, + handler, +}; diff --git a/src/tools/create-firewall-rule.tool.ts b/src/tools/create-firewall-rule.tool.ts new file mode 100644 index 0000000..75a4bf0 --- /dev/null +++ b/src/tools/create-firewall-rule.tool.ts @@ -0,0 +1,92 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { createFirewallRuleAction } from "../actions/create-firewall-rule.action"; +import { + FirewallRuleDirection, + FirewallRuleProtocol, +} from "../types/firewall-rule.type"; + +const inputSchema = { + group_id: z + .string() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID группы правил firewall"), + direction: z + .enum(["ingress", "egress"]) + .describe( + "ОБЯЗАТЕЛЬНОЕ ПОЛЕ - направление трафика: ingress (входящий) или egress (исходящий)" + ), + protocol: z + .enum(["tcp", "udp", "icmp"]) + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - протокол: tcp, udp или icmp"), + port: z + .string() + .optional() + .describe( + "Порт или диапазон портов (например: '22' или '8000-8080'). Применимо только для tcp/udp." + ), + cidr: z + .string() + .optional() + .describe( + "Сетевой адрес или подсеть в формате CIDR (IPv4 или IPv6, например: 2.2.2.2/32)" + ), + description: z + .string() + .optional() + .describe("Описание правила (опц.)"), +}; + +const handler = async (params: { + group_id: string; + direction: FirewallRuleDirection; + protocol: FirewallRuleProtocol; + port?: string; + cidr?: string; + description?: string; +}) => { + try { + if (params.protocol === "icmp" && params.port) { + return createToolResponse( + "❌ Для протокола icmp параметр port не указывается." + ); + } + + const r = await createFirewallRuleAction(params.group_id, { + direction: params.direction, + protocol: params.protocol, + port: params.port, + cidr: params.cidr, + description: params.description, + }); + + return createToolResponse(`✅ Правило firewall создано! + +📋 Детали: +• ID: ${r.id} +• Группа: ${r.group_id} +• Направление: ${r.direction} +• Протокол: ${r.protocol} +• Порт: ${r.port || "—"} +• CIDR: ${r.cidr || "—"} +• Описание: ${r.description || "—"}`); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка создания правила firewall. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при создании правила firewall" + ); + } +}; + +export const createFirewallRuleTool = { + name: ToolNames.CREATE_FIREWALL_RULE, + title: "Создание правила firewall", + description: + "Создаёт новое правило в группе firewall. Обязательны direction (ingress/egress) и protocol (tcp/udp/icmp). Для tcp/udp можно указать port и cidr.", + inputSchema, + handler, +}; diff --git a/src/tools/create-floating-ip.tool.ts b/src/tools/create-floating-ip.tool.ts index 7432fa0..0b5eb29 100644 --- a/src/tools/create-floating-ip.tool.ts +++ b/src/tools/create-floating-ip.tool.ts @@ -47,7 +47,7 @@ const handler = async (params: { • Зона доступности: ${ip.availability_zone} • DDoS Guard: ${ip.is_ddos_guard ? "✅ Включен" : "❌ Отключен"} • Комментарий: ${ip.comment || "Нет"} -• Создан: ${new Date(ip.created_at).toLocaleString("ru-RU")} +• Создан: ${ip.created_at ? new Date(ip.created_at).toLocaleString("ru-RU") : "—"} 🎉 Floating IP готов к использованию!`); } catch (error) { diff --git a/src/tools/create-image-download.tool.ts b/src/tools/create-image-download.tool.ts new file mode 100644 index 0000000..3080f3d --- /dev/null +++ b/src/tools/create-image-download.tool.ts @@ -0,0 +1,99 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { createImageDownloadAction } from "../actions/create-image-download.action"; + +const inputSchema = { + image_id: z.string().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID образа"), + type: z + .enum(["timeweb", "google_drive", "yandex"]) + .optional() + .describe( + "НЕ ОБЯЗАТЕЛЬНОЕ ПОЛЕ - тип ссылки: timeweb (по умолчанию), google_drive, yandex" + ), + filename: z + .string() + .optional() + .describe( + "НЕ ОБЯЗАТЕЛЬНОЕ ПОЛЕ - имя файла для загрузки в облачное хранилище (например, 'backup.qcow2')" + ), + access_token: z + .string() + .optional() + .describe( + "ОБЯЗАТЕЛЬНОЕ если type = google_drive или yandex - токен доступа к API облачного хранилища" + ), + refresh_token: z + .string() + .optional() + .describe( + "НЕ ОБЯЗАТЕЛЬНОЕ ПОЛЕ - refresh token для обновления access_token" + ), + expiry: z + .string() + .optional() + .describe( + "НЕ ОБЯЗАТЕЛЬНОЕ ПОЛЕ - время истечения access_token (ISO8601 date-time)" + ), + token_type: z + .string() + .optional() + .describe("НЕ ОБЯЗАТЕЛЬНОЕ ПОЛЕ - тип токена доступа (по умолчанию Bearer)"), +}; + +const handler = async (params: { + image_id: string; + type?: "timeweb" | "google_drive" | "yandex"; + filename?: string; + access_token?: string; + refresh_token?: string; + expiry?: string; + token_type?: string; +}) => { + try { + const needsAuth = + params.type === "google_drive" || params.type === "yandex"; + if (needsAuth && !params.access_token) { + return createToolResponse( + `❌ Для типа ${params.type} необходим access_token.` + ); + } + + const auth = params.access_token + ? { + access_token: params.access_token, + refresh_token: params.refresh_token, + expiry: params.expiry, + token_type: params.token_type, + } + : undefined; + + const download = await createImageDownloadAction(params.image_id, { + type: params.type, + filename: params.filename, + auth, + }); + + return createToolResponse( + `✅ Ссылка на скачивание создана: ID ${download.id}, тип ${download.type}, статус ${download.status} (progress ${download.progress}%). Отслеживай статус через get_image_download.` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось создать ссылку на скачивание. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при создании ссылки на скачивание" + ); + } +}; + +export const createImageDownloadTool = { + name: ToolNames.CREATE_IMAGE_DOWNLOAD, + title: "Создание ссылки на скачивание образа", + description: + "Создаёт ссылку на скачивание образа. type=timeweb — прямая ссылка на файл (без auth). type=google_drive или yandex — копирование в облако пользователя (нужен access_token). Процесс асинхронный.", + inputSchema, + handler, +}; diff --git a/src/tools/create-image.tool.ts b/src/tools/create-image.tool.ts new file mode 100644 index 0000000..e09063b --- /dev/null +++ b/src/tools/create-image.tool.ts @@ -0,0 +1,95 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { createImageAction } from "../actions/create-image.action"; + +const inputSchema = { + os: z + .enum([ + "centos", + "almalinux", + "debian", + "bitrix", + "ubuntu", + "brainycp", + "archlinux", + "astralinux", + "windows", + "custom_os", + "other", + ]) + .describe( + "ОБЯЗАТЕЛЬНОЕ ПОЛЕ - операционная система образа. Для кастомного образа обычно 'other' или 'custom_os'" + ), + location: z + .enum(["ru-1", "ru-2", "pl-1", "kz-1", "nl-1"]) + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - локация, в которой будет создан образ"), + name: z + .string() + .optional() + .describe("НЕ ОБЯЗАТЕЛЬНОЕ ПОЛЕ - имя образа"), + description: z + .string() + .optional() + .describe("НЕ ОБЯЗАТЕЛЬНОЕ ПОЛЕ - описание образа"), + disk_id: z + .number() + .int() + .optional() + .describe( + "НЕ ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID диска сервера, для которого создаётся образ (снапшот). Если указан — образ создаётся из диска, upload_url не нужен" + ), + upload_url: z + .string() + .url() + .optional() + .describe( + "НЕ ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ссылка для загрузки образа (qcow2/iso). Используется для импорта стороннего образа. Не указывать вместе с disk_id" + ), +}; + +const handler = async (params: { + os: string; + location: string; + name?: string; + description?: string; + disk_id?: number; + upload_url?: string; +}) => { + try { + if (params.disk_id !== undefined && params.upload_url) { + return createToolResponse( + "❌ Нельзя указывать одновременно disk_id и upload_url. Выбери один способ: снапшот диска (disk_id) или импорт по ссылке (upload_url)." + ); + } + + const image = await createImageAction({ + os: params.os, + location: params.location, + name: params.name, + description: params.description, + disk_id: params.disk_id, + upload_url: params.upload_url, + }); + + return createToolResponse( + `✅ Образ создан: ID ${image.id}, имя "${image.name || "(без имени)"}", статус ${image.status} (progress ${image.progress}%). Процесс асинхронный — перепроверь статус через get_image.` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось создать образ. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при создании образа"); + } +}; + +export const createImageTool = { + name: ToolNames.CREATE_IMAGE, + title: "Создание образа", + description: + "Создаёт образ: (а) снапшот существующего диска сервера (disk_id), (б) импорт qcow2/iso по upload_url, либо (в) пустой слот для последующей загрузки (без disk_id и upload_url — тогда заливай файл через HTTP). Процесс асинхронный, отслеживать через get_image.", + inputSchema, + handler, +}; diff --git a/src/tools/create-k8s-cluster.tool.ts b/src/tools/create-k8s-cluster.tool.ts new file mode 100644 index 0000000..4c39525 --- /dev/null +++ b/src/tools/create-k8s-cluster.tool.ts @@ -0,0 +1,167 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { createK8sClusterAction } from "../actions/create-k8s-cluster.action"; +import { + CreateK8sClusterRequestDto, + K8sWorkerGroupIn, +} from "../types/dto/create-k8s-cluster-request.dto"; + +const networkDriverEnum = z.enum([ + "kuberouter", + "calico", + "flannel", + "cilium", +]); +const availabilityZoneEnum = z.enum(["spb-3", "msk-1", "ams-1", "fra-1"]); + +const configurationSchema = z + .object({ + configurator_id: z.number().int(), + disk: z.number().int(), + cpu: z.number().int(), + ram: z.number().int(), + }) + .describe( + "Параметры конфигурации мастер-ноды (нельзя передавать вместе с preset_id)" + ); + +const workerGroupSchema = z + .object({ + name: z.string(), + node_count: z.number().int().min(1).max(100), + preset_id: z.number().int().optional(), + configuration: z + .object({ + configurator_id: z.number().int(), + disk: z.number().int(), + cpu: z.number().int(), + ram: z.number().int(), + gpu: z.number().int().optional(), + }) + .optional(), + labels: z + .array(z.object({ key: z.string(), value: z.string() })) + .optional(), + is_autoscaling: z.boolean().optional(), + "min-size": z.number().int().min(2).optional(), + "max-size": z.number().int().min(2).optional(), + is_autohealing: z.boolean().optional(), + }) + .describe("Описание одной worker-группы"); + +const inputSchema = { + name: z.string().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - название кластера"), + k8s_version: z + .string() + .describe( + "ОБЯЗАТЕЛЬНОЕ ПОЛЕ - версия Kubernetes (получить через list_k8s_versions)" + ), + network_driver: networkDriverEnum.describe( + "ОБЯЗАТЕЛЬНОЕ ПОЛЕ - сетевой драйвер: kuberouter, calico, flannel, cilium" + ), + description: z.string().optional().describe("Описание кластера"), + availability_zone: availabilityZoneEnum + .optional() + .describe("Зона доступности: spb-3, msk-1, ams-1, fra-1"), + is_ingress: z.boolean().optional().describe("Включить Ingress-контроллер"), + is_k8s_dashboard: z + .boolean() + .optional() + .describe("Включить Kubernetes Dashboard"), + preset_id: z + .number() + .int() + .optional() + .describe( + "ID тарифа мастер-ноды (взаимоисключающе с configuration)" + ), + configuration: configurationSchema.optional(), + master_nodes_count: z + .number() + .int() + .optional() + .describe("Количество мастер-нод"), + worker_groups: z + .array(workerGroupSchema) + .optional() + .describe("Группы воркер-нод"), + network_id: z.string().optional().describe("ID приватной сети (VPC)"), + project_id: z.number().int().optional().describe("ID проекта"), +}; + +const handler = async (params: { + name: string; + k8s_version: string; + network_driver: "kuberouter" | "calico" | "flannel" | "cilium"; + description?: string; + availability_zone?: "spb-3" | "msk-1" | "ams-1" | "fra-1"; + is_ingress?: boolean; + is_k8s_dashboard?: boolean; + preset_id?: number; + configuration?: { + configurator_id: number; + disk: number; + cpu: number; + ram: number; + }; + master_nodes_count?: number; + worker_groups?: K8sWorkerGroupIn[]; + network_id?: string; + project_id?: number; +}) => { + try { + if (params.preset_id && params.configuration) { + return createToolResponse( + "❌ Нельзя одновременно указывать preset_id и configuration для мастер-ноды. Выбери одно." + ); + } + + const data: CreateK8sClusterRequestDto = { + name: params.name, + k8s_version: params.k8s_version, + network_driver: params.network_driver, + description: params.description, + availability_zone: params.availability_zone, + is_ingress: params.is_ingress, + is_k8s_dashboard: params.is_k8s_dashboard, + preset_id: params.preset_id, + configuration: params.configuration, + master_nodes_count: params.master_nodes_count, + worker_groups: params.worker_groups, + network_id: params.network_id, + project_id: params.project_id, + }; + + const cluster = await createK8sClusterAction(data); + + return createToolResponse(`✅ Kubernetes-кластер создан! + +📋 Детали: +• ID: ${cluster.id} +• Название: ${cluster.name} +• Статус: ${cluster.status} +• Версия: ${cluster.k8s_version} +• Сетевой драйвер: ${cluster.network_driver} +• Зона: ${cluster.availability_zone ?? "—"} +• Ingress: ${cluster.ingress ? "вкл" : "выкл"} +• Preset мастер-ноды: ${cluster.preset_id} +• Создан: ${new Date(cluster.created_at).toLocaleString("ru-RU")}`); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка создания кластера. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при создании кластера"); + } +}; + +export const createK8sClusterTool = { + name: ToolNames.CREATE_K8S_CLUSTER, + title: "Создание Kubernetes-кластера", + description: + "Создаёт новый Kubernetes-кластер. Обязательные параметры: name, k8s_version, network_driver. Для мастер-ноды укажи либо preset_id, либо configuration (взаимоисключающе). Опционально задай worker_groups, OIDC, зону, ingress.", + inputSchema, + handler, +}; diff --git a/src/tools/create-k8s-node-group.tool.ts b/src/tools/create-k8s-node-group.tool.ts new file mode 100644 index 0000000..184cf0a --- /dev/null +++ b/src/tools/create-k8s-node-group.tool.ts @@ -0,0 +1,115 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { createK8sNodeGroupAction } from "../actions/create-k8s-node-group.action"; + +const configurationSchema = z.object({ + configurator_id: z.number().int(), + disk: z.number().int(), + cpu: z.number().int(), + ram: z.number().int(), + gpu: z.number().int().optional(), +}); + +const inputSchema = { + cluster_id: z.number().int().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID кластера"), + name: z.string().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - название группы"), + node_count: z + .number() + .int() + .min(1) + .max(100) + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - количество нод (1–100)"), + preset_id: z + .number() + .int() + .optional() + .describe("ID тарифа воркер-ноды (взаимоисключающе с configuration)"), + configuration: configurationSchema + .optional() + .describe("Кастомная конфигурация воркер-ноды"), + labels: z + .array(z.object({ key: z.string(), value: z.string() })) + .optional() + .describe("Лейблы для группы"), + is_autoscaling: z.boolean().optional().describe("Автомасштабирование"), + "min-size": z + .number() + .int() + .min(2) + .optional() + .describe("Минимум нод (для автомасштабирования)"), + "max-size": z + .number() + .int() + .min(2) + .optional() + .describe("Максимум нод (для автомасштабирования)"), + is_autohealing: z.boolean().optional().describe("Автовосстановление нод"), +}; + +const handler = async (params: { + cluster_id: number; + name: string; + node_count: number; + preset_id?: number; + configuration?: { + configurator_id: number; + disk: number; + cpu: number; + ram: number; + gpu?: number; + }; + labels?: Array<{ key: string; value: string }>; + is_autoscaling?: boolean; + "min-size"?: number; + "max-size"?: number; + is_autohealing?: boolean; +}) => { + try { + if (params.preset_id && params.configuration) { + return createToolResponse( + "❌ Нельзя одновременно указывать preset_id и configuration. Выбери одно." + ); + } + if (!params.preset_id && !params.configuration) { + return createToolResponse( + "❌ Нужно указать либо preset_id, либо configuration для воркер-ноды." + ); + } + + const group = await createK8sNodeGroupAction(params.cluster_id, { + name: params.name, + node_count: params.node_count, + preset_id: params.preset_id, + configuration: params.configuration, + labels: params.labels, + is_autoscaling: params.is_autoscaling, + "min-size": params["min-size"], + "max-size": params["max-size"], + is_autohealing: params.is_autohealing, + }); + + return createToolResponse( + `✅ Группа нод создана: ID ${group.id}, ${group.name}, preset ${group.preset_id}, нод: ${group.node_count}.` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка создания группы нод. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при создании группы нод" + ); + } +}; + +export const createK8sNodeGroupTool = { + name: ToolNames.CREATE_K8S_NODE_GROUP, + title: "Создание группы нод", + description: + "Создаёт новую группу воркер-нод в кластере. Обязательные: name, node_count. Для тарифа — либо preset_id, либо configuration (взаимоисключающе).", + inputSchema, + handler, +}; diff --git a/src/tools/create-mailbox-v1.tool.ts b/src/tools/create-mailbox-v1.tool.ts new file mode 100644 index 0000000..259f469 --- /dev/null +++ b/src/tools/create-mailbox-v1.tool.ts @@ -0,0 +1,53 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { createMailboxV1Action } from "../actions/create-mailbox-v1.action"; + +const inputSchema = { + domain: z.string().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - имя домена"), + mailbox: z + .string() + .describe( + "ОБЯЗАТЕЛЬНОЕ ПОЛЕ - имя ящика (часть до @). Полный адрес будет mailbox@domain" + ), + password: z + .string() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - пароль ящика"), + comment: z.string().optional().describe("Комментарий к ящику (опц.)"), +}; + +const handler = async (params: { + domain: string; + mailbox: string; + password: string; + comment?: string; +}) => { + try { + const { domain, ...rest } = params; + const m = await createMailboxV1Action(domain, rest); + const fullAddress = + m.mailbox && m.fqdn ? `${m.mailbox}@${m.fqdn}` : `${params.mailbox}@${domain}`; + + return createToolResponse(`✅ Почтовый ящик создан (API v1)! + +📋 Детали: +• Адрес: ${fullAddress} +• Комментарий: ${m.comment || "—"}`); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка создания почтового ящика (v1). Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при создании ящика (v1)"); + } +}; + +export const createMailboxV1Tool = { + name: ToolNames.CREATE_MAILBOX_V1, + title: "Создание почтового ящика (API v1)", + description: + "Создаёт почтовый ящик через API v1. Предпочитай create_mailbox (v2) — этот нужен только для совместимости.", + inputSchema, + handler, +}; diff --git a/src/tools/create-mailbox.tool.ts b/src/tools/create-mailbox.tool.ts new file mode 100644 index 0000000..2eb5a9f --- /dev/null +++ b/src/tools/create-mailbox.tool.ts @@ -0,0 +1,79 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { createMailboxAction } from "../actions/create-mailbox.action"; + +const inputSchema = { + domain: z + .string() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - имя домена"), + mailbox: z + .string() + .describe( + "ОБЯЗАТЕЛЬНОЕ ПОЛЕ - имя ящика (часть до @). Полный адрес будет mailbox@domain" + ), + password: z + .string() + .min(8) + .max(30) + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - пароль ящика, 8-30 символов"), + comment: z.string().optional().describe("Комментарий к ящику (опц.)"), + owner_full_name: z.string().optional().describe("ФИО владельца (опц.)"), + filter_status: z + .boolean() + .optional() + .describe("Включить спам-фильтр (опц.)"), + filter_action: z + .enum(["directory", "label"]) + .optional() + .describe( + "Действие при попадании в спам: directory — в папку Спам, label — пометить. Игнорировать если filter_status=false" + ), +}; + +const handler = async (params: { + domain: string; + mailbox: string; + password: string; + comment?: string; + owner_full_name?: string; + filter_status?: boolean; + filter_action?: "directory" | "label"; +}) => { + try { + if (params.filter_status === false && params.filter_action !== undefined) { + return createToolResponse( + "❌ Нельзя передавать filter_action, если filter_status=false" + ); + } + + const { domain, ...rest } = params; + const m = await createMailboxAction(domain, rest); + const fullAddress = + m.mailbox && m.fqdn ? `${m.mailbox}@${m.fqdn}` : `${params.mailbox}@${domain}`; + + return createToolResponse(`✅ Почтовый ящик создан! + +📋 Детали: +• Адрес: ${fullAddress} +• ФИО владельца: ${m.owner_full_name || "—"} +• Комментарий: ${m.comment || "—"} +• Спам-фильтр: ${m.filter_status ? "вкл" : "выкл"}${m.filter_status ? `, действие: ${m.filter_action}` : ""}`); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка создания почтового ящика. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при создании ящика"); + } +}; + +export const createMailboxTool = { + name: ToolNames.CREATE_MAILBOX, + title: "Создание почтового ящика", + description: + "Создаёт новый почтовый ящик на указанном домене (API v2). Поддерживает задание ФИО владельца и начальных настроек спам-фильтра.", + inputSchema, + handler, +}; diff --git a/src/tools/create-network-drive.tool.ts b/src/tools/create-network-drive.tool.ts new file mode 100644 index 0000000..f229b7b --- /dev/null +++ b/src/tools/create-network-drive.tool.ts @@ -0,0 +1,69 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { createNetworkDriveAction } from "../actions/create-network-drive.action"; + +const inputSchema = { + name: z.string().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - Название сетевого диска"), + size: z + .number() + .int() + .positive() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - Размер сетевого диска в ГБ"), + preset_id: z + .number() + .int() + .describe( + "ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID тарифа сетевого диска (получить список через list_network_drive_presets)" + ), + comment: z.string().optional().describe("Комментарий к диску (опц.)"), +}; + +const handler = async (params: { + name: string; + size: number; + preset_id: number; + comment?: string; +}) => { + try { + const drive = await createNetworkDriveAction({ + name: params.name, + size: params.size, + preset_id: params.preset_id, + ...(params.comment !== undefined ? { comment: params.comment } : {}), + }); + + return createToolResponse(`✅ Сетевой диск успешно создан! + +📋 Детали: +• ID: ${drive.id} +• Название: ${drive.name} +• Статус: ${drive.status} +• Тип: ${drive.type} +• Размер: ${drive.size} ГБ +• Зона доступности: ${drive.availability_zone} +• Локация: ${drive.location} +• Preset ID: ${drive.preset_id} +• Комментарий: ${drive.comment ?? "—"} + +🎉 Диск готов к подключению (используй mount_network_drive).`); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка создания сетевого диска. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при создании сетевого диска" + ); + } +}; + +export const createNetworkDriveTool = { + name: ToolNames.CREATE_NETWORK_DRIVE, + title: "Создание сетевого диска", + description: + "Создаёт новый сетевой диск указанного размера с выбранным тарифом (preset_id). Перед созданием стоит получить список доступных тарифов через list_network_drive_presets.", + inputSchema, + handler, +}; diff --git a/src/tools/create-project.tool.ts b/src/tools/create-project.tool.ts new file mode 100644 index 0000000..a4f67a7 --- /dev/null +++ b/src/tools/create-project.tool.ts @@ -0,0 +1,60 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { createProjectAction } from "../actions/create-project.action"; + +const inputSchema = { + name: z + .string() + .max(255) + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - имя проекта (до 255 символов)"), + description: z + .string() + .max(255) + .optional() + .describe("Описание проекта (до 255 символов, опц.)"), + avatar_id: z + .string() + .max(255) + .optional() + .describe("ID аватара (опц.)"), +}; + +const handler = async (params: { + name: string; + description?: string; + avatar_id?: string; +}) => { + try { + const project = await createProjectAction({ + name: params.name, + description: params.description, + avatar_id: params.avatar_id, + }); + + return createToolResponse( + `✅ Проект создан!\n\n` + + `📋 Детали:\n` + + `• ID: ${project.id}\n` + + `• Имя: ${project.name}\n` + + `• Описание: ${project.description || "—"}\n` + + `• По умолчанию: ${project.is_default ? "да" : "нет"}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось создать проект. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при создании проекта"); + } +}; + +export const createProjectTool = { + name: ToolNames.CREATE_PROJECT, + title: "Создание проекта", + description: + "Создаёт новый проект для группировки ресурсов (серверов, БД, хранилищ и т.д.).", + inputSchema, + handler, +}; diff --git a/src/tools/create-server-disk-backup.tool.ts b/src/tools/create-server-disk-backup.tool.ts new file mode 100644 index 0000000..ff10c34 --- /dev/null +++ b/src/tools/create-server-disk-backup.tool.ts @@ -0,0 +1,48 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { createServerDiskBackupAction } from "../actions/create-server-disk-backup.action"; + +const inputSchema = { + server_id: z.number().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID сервера"), + disk_id: z.number().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID диска"), + comment: z + .string() + .optional() + .describe( + "НЕ ОБЯЗАТЕЛЬНОЕ ПОЛЕ - комментарий к бэкапу (например, 'before-migration-v2')" + ), +}; + +const handler = async (params: { + server_id: number; + disk_id: number; + comment?: string; +}) => { + try { + const backup = await createServerDiskBackupAction( + params.server_id, + params.disk_id, + params.comment + ); + return createToolResponse( + `✅ Бэкап создан: ID ${backup.id}, имя "${backup.name}", статус: ${backup.status}. Процесс снятия бэкапа идёт асинхронно — повторно проверь статус через list_server_disk_backups.` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось создать бэкап. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при создании бэкапа"); + } +}; + +export const createServerDiskBackupTool = { + name: ToolNames.CREATE_SERVER_DISK_BACKUP, + title: "Создание бэкапа диска", + description: + "Создаёт ручной бэкап диска VPS. Процесс асинхронный: tool возвращается сразу, статус бэкапа переходит create → done в течение нескольких минут. Используй перед рискованными операциями (миграция, обновление ОС).", + inputSchema, + handler, +}; diff --git a/src/tools/create-server.tool.ts b/src/tools/create-server.tool.ts new file mode 100644 index 0000000..f47cb54 --- /dev/null +++ b/src/tools/create-server.tool.ts @@ -0,0 +1,204 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { createServerAction } from "../actions/create-server.action"; +import { CreateServerRequestDto } from "../types/dto/create-server-request.dto"; + +const inputSchema = { + name: z + .string() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - имя сервера (до 255 символов)"), + preset_id: z + .number() + .optional() + .describe( + "Режим 1: ID готового тарифа. Нельзя использовать вместе с configurator_id." + ), + configurator_id: z + .number() + .optional() + .describe( + "Режим 2: ID конфигуратора (для кастомной конфигурации). Нельзя использовать вместе с preset_id. Требует cpu, ram, disk." + ), + cpu: z + .number() + .optional() + .describe("Для configurator-режима: количество ядер CPU (обязательно)"), + ram: z + .number() + .optional() + .describe("Для configurator-режима: RAM в МБ (обязательно)"), + disk: z + .number() + .optional() + .describe("Для configurator-режима: размер диска в МБ (обязательно)"), + gpu: z + .number() + .optional() + .describe("Для configurator-режима: количество GPU (опц.)"), + os_id: z + .number() + .optional() + .describe( + "ID операционной системы. Нельзя использовать вместе с image_id." + ), + image_id: z + .string() + .optional() + .describe( + "UUID образа (snapshot). Нельзя использовать вместе с os_id." + ), + software_id: z + .number() + .optional() + .describe("ID ПО из маркетплейса (опц.)"), + bandwidth: z + .number() + .optional() + .describe( + "Пропускная способность в Мбит/с: от 100 до 1000, шаг 100 (опц.)" + ), + avatar_id: z.string().optional().describe("ID аватара сервера (опц.)"), + comment: z + .string() + .optional() + .describe("Комментарий к серверу (до 255 символов)"), + ssh_keys_ids: z + .array(z.number()) + .optional() + .describe("Массив ID SSH-ключей"), + is_ddos_guard: z + .boolean() + .optional() + .describe("Включить DDoS-защиту (L3/L4)"), + availability_zone: z + .string() + .optional() + .describe("Зона доступности (например: spb-3, msk-1)"), + project_id: z.number().optional().describe("ID проекта (опц.)"), + hostname: z.string().optional().describe("Сетевое имя сервера (опц.)"), + cloud_init: z + .string() + .optional() + .describe("Cloud-init скрипт (опц.)"), +}; + +const handler = async (params: { + name: string; + preset_id?: number; + configurator_id?: number; + cpu?: number; + ram?: number; + disk?: number; + gpu?: number; + os_id?: number; + image_id?: string; + software_id?: number; + bandwidth?: number; + avatar_id?: string; + comment?: string; + ssh_keys_ids?: number[]; + is_ddos_guard?: boolean; + availability_zone?: string; + project_id?: number; + hostname?: string; + cloud_init?: string; +}) => { + if (params.preset_id && params.configurator_id) { + return createToolResponse( + "❌ Нельзя передавать одновременно preset_id и configurator_id. Выбери один режим." + ); + } + if (!params.preset_id && !params.configurator_id) { + return createToolResponse( + "❌ Нужен либо preset_id (готовый тариф), либо configurator_id (кастомная конфигурация)." + ); + } + if (params.os_id && params.image_id) { + return createToolResponse( + "❌ Нельзя передавать одновременно os_id и image_id. Выбери одно." + ); + } + if (!params.os_id && !params.image_id) { + return createToolResponse( + "❌ Нужен либо os_id (ОС из каталога), либо image_id (UUID образа/snapshot)." + ); + } + if (params.configurator_id) { + if ( + params.cpu === undefined || + params.ram === undefined || + params.disk === undefined + ) { + return createToolResponse( + "❌ В режиме configurator_id обязательны поля cpu, ram, disk." + ); + } + } + + try { + const body: CreateServerRequestDto = { + name: params.name, + }; + + if (params.preset_id) { + body.preset_id = params.preset_id; + } else { + body.configuration = { + configurator_id: params.configurator_id!, + cpu: params.cpu!, + ram: params.ram!, + disk: params.disk!, + ...(params.gpu !== undefined && { gpu: params.gpu }), + }; + } + + if (params.os_id !== undefined) body.os_id = params.os_id; + if (params.image_id !== undefined) body.image_id = params.image_id; + if (params.software_id !== undefined) + body.software_id = params.software_id; + if (params.bandwidth !== undefined) body.bandwidth = params.bandwidth; + if (params.avatar_id !== undefined) body.avatar_id = params.avatar_id; + if (params.comment !== undefined) body.comment = params.comment; + if (params.ssh_keys_ids !== undefined) + body.ssh_keys_ids = params.ssh_keys_ids; + if (params.is_ddos_guard !== undefined) + body.is_ddos_guard = params.is_ddos_guard; + if (params.availability_zone !== undefined) + body.availability_zone = params.availability_zone; + if (params.project_id !== undefined) body.project_id = params.project_id; + if (params.hostname !== undefined) body.hostname = params.hostname; + if (params.cloud_init !== undefined) body.cloud_init = params.cloud_init; + + const server = await createServerAction(body); + + return createToolResponse( + `✅ Сервер создан.\n\n` + + `📋 Детали:\n` + + `• ID: ${server.id}\n` + + `• Имя: ${server.name}\n` + + `• Статус: ${server.status}\n` + + `• CPU: ${server.cpu}, RAM: ${server.ram} MB\n` + + `• Локация: ${server.location}\n` + + `• ОС: ${server.os?.name ?? "—"}\n` + + `• Preset: ${server.preset_id ?? "custom"}\n\n` + + `ℹ️ Создание занимает несколько минут. Проверь статус через get_server.` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось создать сервер. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при создании сервера"); + } +}; + +export const createServerTool = { + name: ToolNames.CREATE_SERVER, + title: "Создание сервера", + description: + "Создаёт новый облачный сервер. Выбор режима: preset_id XOR configurator_id (+cpu/ram/disk/[gpu]). Выбор ОС: os_id XOR image_id. Поддерживает ssh_keys_ids, is_ddos_guard, bandwidth, availability_zone, project_id, hostname, cloud_init.", + inputSchema, + handler, +}; diff --git a/src/tools/create-ssh-key.tool.ts b/src/tools/create-ssh-key.tool.ts new file mode 100644 index 0000000..2d19cb8 --- /dev/null +++ b/src/tools/create-ssh-key.tool.ts @@ -0,0 +1,58 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { createSshKeyAction } from "../actions/create-ssh-key.action"; + +const inputSchema = { + name: z.string().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - Название SSH-ключа"), + body: z + .string() + .describe( + "ОБЯЗАТЕЛЬНОЕ ПОЛЕ - Тело публичного SSH-ключа (например: 'ssh-rsa AAAA... user@host')" + ), + is_default: z + .boolean() + .describe( + "ОБЯЗАТЕЛЬНОЕ ПОЛЕ - Выбирать ли этот ключ по умолчанию при создании новых серверов" + ), +}; + +const handler = async (params: { + name: string; + body: string; + is_default: boolean; +}) => { + try { + const key = await createSshKeyAction( + params.name, + params.body, + params.is_default + ); + + return createToolResponse(`✅ SSH-ключ успешно создан! + +📋 Детали созданного ключа: +• ID: ${key.id} +• Название: ${key.name} +• По умолчанию: ${key.is_default ? "✅ Да" : "❌ Нет"} +• Создан: ${new Date(key.created_at).toLocaleString("ru-RU")} + +🎉 SSH-ключ готов к использованию!`); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка создания SSH-ключа. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при создании SSH-ключа"); + } +}; + +export const createSshKeyTool = { + name: ToolNames.CREATE_SSH_KEY, + title: "Создание SSH-ключа", + description: + "Создаёт новый SSH-ключ в аккаунте. Требуются имя, тело публичного ключа и флаг is_default (будет ли ключ выбираться по умолчанию при создании сервера).", + inputSchema, + handler, +}; diff --git a/src/tools/delete-ai-agent.tool.ts b/src/tools/delete-ai-agent.tool.ts new file mode 100644 index 0000000..1edcd4a --- /dev/null +++ b/src/tools/delete-ai-agent.tool.ts @@ -0,0 +1,31 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { deleteAiAgentAction } from "../actions/delete-ai-agent.action"; + +const inputSchema = { + agent_id: z.number().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID агента"), +}; + +const handler = async (params: { agent_id: number }) => { + try { + await deleteAiAgentAction(params.agent_id); + return createToolResponse(`✅ AI-агент ${params.agent_id} удалён.`); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось удалить агента ${params.agent_id}. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при удалении агента"); + } +}; + +export const deleteAiAgentTool = { + name: ToolNames.DELETE_AI_AGENT, + title: "Удаление AI-агента", + description: + "Удаляет AI-агента по ID. ⚠️ Операция необратима — подтверждай с пользователем.", + inputSchema, + handler, +}; diff --git a/src/tools/delete-api-key.tool.ts b/src/tools/delete-api-key.tool.ts new file mode 100644 index 0000000..56e6d9a --- /dev/null +++ b/src/tools/delete-api-key.tool.ts @@ -0,0 +1,30 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { deleteApiKeyAction } from "../actions/delete-api-key.action"; + +const inputSchema = { + token_id: z.string().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID API-токена"), +}; + +const handler = async (params: { token_id: string }) => { + try { + await deleteApiKeyAction(params.token_id); + return createToolResponse(`✅ API-токен ${params.token_id} удалён.`); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка при удалении API-токена. Причина: ${error.message}` + ); + } + return createToolResponse(`❌ Неизвестная ошибка при удалении API-токена`); + } +}; + +export const deleteApiKeyTool = { + name: ToolNames.DELETE_API_KEY, + title: "Удаление API-токена", + description: "Удаляет API-токен по его ID", + inputSchema, + handler, +}; diff --git a/src/tools/delete-balancer-rule.tool.ts b/src/tools/delete-balancer-rule.tool.ts new file mode 100644 index 0000000..12c0461 --- /dev/null +++ b/src/tools/delete-balancer-rule.tool.ts @@ -0,0 +1,42 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { deleteBalancerRuleAction } from "../actions/delete-balancer-rule.action"; + +const inputSchema = { + balancer_id: z + .number() + .int() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID балансировщика"), + rule_id: z + .number() + .int() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID правила для удаления"), +}; + +const handler = async (params: { balancer_id: number; rule_id: number }) => { + try { + await deleteBalancerRuleAction(params.balancer_id, params.rule_id); + return createToolResponse( + `✅ Правило ${params.rule_id} удалено у балансировщика ${params.balancer_id}.` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось удалить правило ${params.rule_id}. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при удалении правила балансировщика" + ); + } +}; + +export const deleteBalancerRuleTool = { + name: ToolNames.DELETE_BALANCER_RULE, + title: "Удаление правила балансировщика", + description: + "Удаляет правило маршрутизации у балансировщика. Действие необратимо.", + inputSchema, + handler, +}; diff --git a/src/tools/delete-balancer.tool.ts b/src/tools/delete-balancer.tool.ts new file mode 100644 index 0000000..b23c8fe --- /dev/null +++ b/src/tools/delete-balancer.tool.ts @@ -0,0 +1,67 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { deleteBalancerAction } from "../actions/delete-balancer.action"; + +const inputSchema = { + balancer_id: z + .number() + .int() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID балансировщика"), + hash: z + .string() + .optional() + .describe("Hash подтверждения (для аккаунтов с 2FA)"), + code: z + .string() + .optional() + .describe("Код 2FA из приложения-аутентификатора"), +}; + +const handler = async (params: { + balancer_id: number; + hash?: string; + code?: string; +}) => { + try { + const result = await deleteBalancerAction( + params.balancer_id, + params.hash, + params.code + ); + + if (result && result.hash) { + return createToolResponse( + `⚠️ Для удаления балансировщика ${params.balancer_id} требуется подтверждение 2FA.\n\nПередай hash и code в повторный вызов:\n• hash: ${result.hash}\n• code: <код из приложения>` + ); + } + + if (result && result.is_moved_in_quarantine) { + return createToolResponse( + `✅ Балансировщик ${params.balancer_id} перемещён в карантин (можно восстановить в ЛК).` + ); + } + + return createToolResponse( + `✅ Балансировщик ${params.balancer_id} удалён.` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось удалить балансировщик ${params.balancer_id}. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при удалении балансировщика" + ); + } +}; + +export const deleteBalancerTool = { + name: ToolNames.DELETE_BALANCER, + title: "Удаление балансировщика", + description: + "Удаляет балансировщик. Действие необратимо. Для аккаунтов с 2FA — первый вызов вернёт hash, повторный вызов с hash и code завершит удаление.", + inputSchema, + handler, +}; diff --git a/src/tools/delete-bucket-subdomains.tool.ts b/src/tools/delete-bucket-subdomains.tool.ts new file mode 100644 index 0000000..6391c0d --- /dev/null +++ b/src/tools/delete-bucket-subdomains.tool.ts @@ -0,0 +1,50 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { deleteBucketSubdomainsAction } from "../actions/delete-bucket-subdomains.action"; + +const inputSchema = { + bucket_id: z.number().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID S3-хранилища"), + subdomains: z + .array(z.string()) + .min(1) + .describe( + "ОБЯЗАТЕЛЬНОЕ ПОЛЕ - массив поддоменов для удаления, например ['test.example.com']" + ), +}; + +const handler = async (params: { + bucket_id: number; + subdomains: string[]; +}) => { + try { + const result = await deleteBucketSubdomainsAction( + params.bucket_id, + params.subdomains + ); + + const lines = result.map((s) => `• ${s.subdomain} — ${s.status}`); + + return createToolResponse( + `✅ Результат удаления поддоменов из хранилища ${params.bucket_id}:\n\n${lines.join("\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка удаления поддоменов из хранилища ${params.bucket_id}. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при удалении поддоменов" + ); + } +}; + +export const deleteBucketSubdomainsTool = { + name: ToolNames.DELETE_BUCKET_SUBDOMAINS, + title: "Удаление поддоменов S3-хранилища", + description: + "Удаляет один или несколько поддоменов из S3-хранилища. Возвращает статус удаления по каждому поддомену.", + inputSchema, + handler, +}; diff --git a/src/tools/delete-bucket.tool.ts b/src/tools/delete-bucket.tool.ts new file mode 100644 index 0000000..e546da5 --- /dev/null +++ b/src/tools/delete-bucket.tool.ts @@ -0,0 +1,68 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { deleteBucketAction } from "../actions/delete-bucket.action"; + +const inputSchema = { + bucket_id: z + .number() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID S3-хранилища для удаления"), + hash: z + .string() + .optional() + .describe( + "Hash подтверждения удаления (для аккаунтов с 2FA, получается из первого запроса удаления, опц.)" + ), + code: z + .string() + .optional() + .describe( + "Код 2FA для подтверждения удаления (только если включена 2FA, опц.)" + ), +}; + +const handler = async (params: { + bucket_id: number; + hash?: string; + code?: string; +}) => { + try { + const result = await deleteBucketAction( + params.bucket_id, + params.hash, + params.code + ); + + if (result.hash && !params.code) { + return createToolResponse( + `⚠️ Для подтверждения удаления хранилища ${params.bucket_id} требуется 2FA-код.\n\nПолучен hash: ${result.hash}\n\nПовтори вызов с параметрами hash и code.` + ); + } + + const movedMsg = result.is_moved_in_quarantine + ? "перемещено в карантин" + : "удалено немедленно"; + + return createToolResponse( + `✅ S3-хранилище ${params.bucket_id} ${movedMsg}.` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось удалить S3-хранилище ${params.bucket_id}. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при удалении S3-хранилища" + ); + } +}; + +export const deleteBucketTool = { + name: ToolNames.DELETE_BUCKET, + title: "Удаление S3-хранилища", + description: + "Удаляет S3-хранилище. Действие необратимо. Для аккаунтов с 2FA: первый вызов возвращает hash, второй вызов нужен с hash и code. Все данные в хранилище будут потеряны.", + inputSchema, + handler, +}; diff --git a/src/tools/delete-container-registry.tool.ts b/src/tools/delete-container-registry.tool.ts new file mode 100644 index 0000000..6f6fa6d --- /dev/null +++ b/src/tools/delete-container-registry.tool.ts @@ -0,0 +1,35 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { deleteContainerRegistryAction } from "../actions/delete-container-registry.action"; + +const inputSchema = { + registry_id: z + .number() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID реестра для удаления"), +}; + +const handler = async (params: { registry_id: number }) => { + try { + await deleteContainerRegistryAction(params.registry_id); + return createToolResponse( + `✅ Реестр контейнеров ${params.registry_id} удалён.` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось удалить реестр ${params.registry_id}. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при удалении реестра"); + } +}; + +export const deleteContainerRegistryTool = { + name: ToolNames.DELETE_CONTAINER_REGISTRY, + title: "Удаление реестра контейнеров", + description: + "Удаляет реестр контейнеров безвозвратно. ⚠️ Все образы в реестре будут потеряны. Перед удалением убедись, что реестр не используется.", + inputSchema, + handler, +}; diff --git a/src/tools/delete-database-admin.tool.ts b/src/tools/delete-database-admin.tool.ts new file mode 100644 index 0000000..0fb919d --- /dev/null +++ b/src/tools/delete-database-admin.tool.ts @@ -0,0 +1,45 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { deleteDatabaseAdminAction } from "../actions/delete-database-admin.action"; + +const inputSchema = { + db_cluster_id: z + .number() + .int() + .positive() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID кластера базы данных"), + admin_id: z + .number() + .int() + .positive() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID пользователя для удаления"), +}; + +const handler = async (params: { + db_cluster_id: number; + admin_id: number; +}) => { + try { + await deleteDatabaseAdminAction(params.db_cluster_id, params.admin_id); + return createToolResponse( + `✅ Пользователь ${params.admin_id} удалён из кластера ${params.db_cluster_id}.` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось удалить пользователя ${params.admin_id}. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при удалении пользователя"); + } +}; + +export const deleteDatabaseAdminTool = { + name: ToolNames.DELETE_DATABASE_ADMIN, + title: "Удаление пользователя кластера", + description: + "Удаляет пользователя кластера базы данных (`DELETE /api/v1/databases/{db_cluster_id}/admins/{admin_id}`). Действие необратимо.", + inputSchema, + handler, +}; diff --git a/src/tools/delete-database-cluster.tool.ts b/src/tools/delete-database-cluster.tool.ts new file mode 100644 index 0000000..199041d --- /dev/null +++ b/src/tools/delete-database-cluster.tool.ts @@ -0,0 +1,62 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { deleteDatabaseClusterAction } from "../actions/delete-database-cluster.action"; + +const inputSchema = { + db_cluster_id: z + .number() + .int() + .positive() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID кластера для удаления"), + hash: z + .string() + .optional() + .describe( + "НЕ ОБЯЗАТЕЛЬНОЕ ПОЛЕ - хеш для 2FA (возвращается после первого запроса для аккаунтов с 2FA)" + ), + code: z + .string() + .optional() + .describe("НЕ ОБЯЗАТЕЛЬНОЕ ПОЛЕ - код авторизации для 2FA"), +}; + +const handler = async (params: { + db_cluster_id: number; + hash?: string; + code?: string; +}) => { + try { + const result = await deleteDatabaseClusterAction( + params.db_cluster_id, + params.hash, + params.code + ); + + if (result?.hash && !params.code) { + return createToolResponse( + `⚠️ Требуется 2FA. Повторите запрос с hash="${result.hash}" и code из приложения-аутентификатора.` + ); + } + + return createToolResponse( + `✅ Кластер ${params.db_cluster_id} удалён (или перемещён в карантин).` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось удалить кластер ${params.db_cluster_id}. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при удалении кластера"); + } +}; + +export const deleteDatabaseClusterTool = { + name: ToolNames.DELETE_DATABASE_CLUSTER, + title: "Удаление кластера базы данных", + description: + "Удаляет кластер баз данных (`DELETE /api/v1/databases/{db_cluster_id}`). Для аккаунтов с 2FA в ответе вернётся hash — повторите запрос с ним и с code из аутентификатора.", + inputSchema, + handler, +}; diff --git a/src/tools/delete-dedicated-server.tool.ts b/src/tools/delete-dedicated-server.tool.ts new file mode 100644 index 0000000..758fe43 --- /dev/null +++ b/src/tools/delete-dedicated-server.tool.ts @@ -0,0 +1,37 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { deleteDedicatedServerAction } from "../actions/delete-dedicated-server.action"; + +const inputSchema = { + dedicated_id: z + .number() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID выделенного сервера для удаления"), +}; + +const handler = async (params: { dedicated_id: number }) => { + try { + await deleteDedicatedServerAction(params.dedicated_id); + return createToolResponse( + `✅ Выделенный сервер ${params.dedicated_id} удалён.` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось удалить выделенный сервер ${params.dedicated_id}. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при удалении выделенного сервера" + ); + } +}; + +export const deleteDedicatedServerTool = { + name: ToolNames.DELETE_DEDICATED_SERVER, + title: "Удаление выделенного сервера", + description: + "Удаляет выделенный (dedicated) сервер. ⚠️ Все данные на сервере будут потеряны безвозвратно. Подтверди операцию с пользователем перед вызовом.", + inputSchema, + handler, +}; diff --git a/src/tools/delete-dns-record.tool.ts b/src/tools/delete-dns-record.tool.ts new file mode 100644 index 0000000..281f342 --- /dev/null +++ b/src/tools/delete-dns-record.tool.ts @@ -0,0 +1,36 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { deleteDnsRecordAction } from "../actions/delete-dns-record.action"; + +const inputSchema = { + fqdn: z.string().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - полное имя домена"), + record_id: z + .number() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID DNS-записи для удаления"), +}; + +const handler = async (params: { fqdn: string; record_id: number }) => { + try { + await deleteDnsRecordAction(params.fqdn, params.record_id); + return createToolResponse( + `✅ DNS-запись ${params.record_id} удалена для домена ${params.fqdn}.` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка удаления DNS-записи ${params.record_id} для "${params.fqdn}". Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при удалении DNS-записи"); + } +}; + +export const deleteDnsRecordTool = { + name: ToolNames.DELETE_DNS_RECORD, + title: "Удаление DNS-записи", + description: + "Удаляет DNS-запись по ID для указанного домена. Использует API v2.", + inputSchema, + handler, +}; diff --git a/src/tools/delete-domain.tool.ts b/src/tools/delete-domain.tool.ts new file mode 100644 index 0000000..4ced6b7 --- /dev/null +++ b/src/tools/delete-domain.tool.ts @@ -0,0 +1,33 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { deleteDomainAction } from "../actions/delete-domain.action"; + +const inputSchema = { + fqdn: z + .string() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - полное имя домена для удаления"), +}; + +const handler = async (params: { fqdn: string }) => { + try { + await deleteDomainAction(params.fqdn); + return createToolResponse(`✅ Домен ${params.fqdn} удалён с аккаунта.`); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка удаления домена "${params.fqdn}". Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при удалении домена"); + } +}; + +export const deleteDomainTool = { + name: ToolNames.DELETE_DOMAIN, + title: "Удаление домена", + description: + "Удаляет домен с аккаунта по FQDN. Операция необратима — отвязывает домен от аккаунта Timeweb Cloud.", + inputSchema, + handler, +}; diff --git a/src/tools/delete-firewall-group.tool.ts b/src/tools/delete-firewall-group.tool.ts new file mode 100644 index 0000000..6782458 --- /dev/null +++ b/src/tools/delete-firewall-group.tool.ts @@ -0,0 +1,39 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { deleteFirewallGroupAction } from "../actions/delete-firewall-group.action"; + +const inputSchema = { + group_id: z + .string() + .describe( + "ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID группы правил firewall для удаления" + ), +}; + +const handler = async (params: { group_id: string }) => { + try { + await deleteFirewallGroupAction(params.group_id); + return createToolResponse( + `✅ Группа правил firewall ${params.group_id} удалена.` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось удалить группу firewall ${params.group_id}. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при удалении группы firewall" + ); + } +}; + +export const deleteFirewallGroupTool = { + name: ToolNames.DELETE_FIREWALL_GROUP, + title: "Удаление группы правил firewall", + description: + "Удаляет группу правил firewall. Действие необратимо. Перед удалением рекомендуется отлинковать все связанные ресурсы через unlink_firewall_resource.", + inputSchema, + handler, +}; diff --git a/src/tools/delete-firewall-rule.tool.ts b/src/tools/delete-firewall-rule.tool.ts new file mode 100644 index 0000000..c8c5aa2 --- /dev/null +++ b/src/tools/delete-firewall-rule.tool.ts @@ -0,0 +1,40 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { deleteFirewallRuleAction } from "../actions/delete-firewall-rule.action"; + +const inputSchema = { + group_id: z + .string() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID группы правил firewall"), + rule_id: z + .string() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID правила для удаления"), +}; + +const handler = async (params: { group_id: string; rule_id: string }) => { + try { + await deleteFirewallRuleAction(params.group_id, params.rule_id); + return createToolResponse( + `✅ Правило firewall ${params.rule_id} удалено из группы ${params.group_id}.` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось удалить правило ${params.rule_id}. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при удалении правила firewall" + ); + } +}; + +export const deleteFirewallRuleTool = { + name: ToolNames.DELETE_FIREWALL_RULE, + title: "Удаление правила firewall", + description: + "Удаляет правило из группы firewall. Действие необратимо.", + inputSchema, + handler, +}; diff --git a/src/tools/delete-floating-ip.tool.ts b/src/tools/delete-floating-ip.tool.ts new file mode 100644 index 0000000..bce51e6 --- /dev/null +++ b/src/tools/delete-floating-ip.tool.ts @@ -0,0 +1,36 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { deleteFloatingIpAction } from "../actions/delete-floating-ip.action"; + +const inputSchema = { + floating_ip_id: z + .string() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID плавающего IP"), +}; + +const handler = async (params: { floating_ip_id: string }) => { + try { + await deleteFloatingIpAction(params.floating_ip_id); + return createToolResponse( + `✅ Плавающий IP ${params.floating_ip_id} удалён.` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка при удалении плавающего IP. Причина: ${error.message}` + ); + } + return createToolResponse( + `❌ Неизвестная ошибка при удалении плавающего IP` + ); + } +}; + +export const deleteFloatingIpTool = { + name: ToolNames.DELETE_FLOATING_IP, + title: "Удаление плавающего IP", + description: "Удаляет плавающий IP по его ID", + inputSchema, + handler, +}; diff --git a/src/tools/delete-image-download.tool.ts b/src/tools/delete-image-download.tool.ts new file mode 100644 index 0000000..b9daa06 --- /dev/null +++ b/src/tools/delete-image-download.tool.ts @@ -0,0 +1,39 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { deleteImageDownloadAction } from "../actions/delete-image-download.action"; + +const inputSchema = { + image_id: z.string().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID образа"), + image_url_id: z + .string() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID ссылки на скачивание"), +}; + +const handler = async (params: { + image_id: string; + image_url_id: string; +}) => { + try { + await deleteImageDownloadAction(params.image_id, params.image_url_id); + return createToolResponse( + `✅ Ссылка на скачивание ${params.image_url_id} (образ ${params.image_id}) удалена.` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось удалить ссылку ${params.image_url_id}. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при удалении ссылки"); + } +}; + +export const deleteImageDownloadTool = { + name: ToolNames.DELETE_IMAGE_DOWNLOAD, + title: "Удаление ссылки на скачивание образа", + description: + "Удаляет ссылку на скачивание образа. Используй для отмены процесса копирования образа во внешнее хранилище.", + inputSchema, + handler, +}; diff --git a/src/tools/delete-image.tool.ts b/src/tools/delete-image.tool.ts new file mode 100644 index 0000000..ce27821 --- /dev/null +++ b/src/tools/delete-image.tool.ts @@ -0,0 +1,33 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { deleteImageAction } from "../actions/delete-image.action"; + +const inputSchema = { + image_id: z + .string() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID образа для удаления"), +}; + +const handler = async (params: { image_id: string }) => { + try { + await deleteImageAction(params.image_id); + return createToolResponse(`✅ Образ ${params.image_id} удалён.`); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось удалить образ ${params.image_id}. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при удалении образа"); + } +}; + +export const deleteImageTool = { + name: ToolNames.DELETE_IMAGE, + title: "Удаление образа", + description: + "⚠️ НЕОБРАТИМО: Удаляет образ по его ID. После удаления восстановить нельзя. Серверы, уже созданные из образа, продолжают работать — удаление влияет только на возможность создания новых серверов из этого образа.", + inputSchema, + handler, +}; diff --git a/src/tools/delete-k8s-cluster-node.tool.ts b/src/tools/delete-k8s-cluster-node.tool.ts new file mode 100644 index 0000000..3db010d --- /dev/null +++ b/src/tools/delete-k8s-cluster-node.tool.ts @@ -0,0 +1,37 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { deleteK8sClusterNodeAction } from "../actions/delete-k8s-cluster-node.action"; + +const inputSchema = { + cluster_id: z.number().int().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID кластера"), + node_id: z + .number() + .int() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID ноды для удаления"), +}; + +const handler = async (params: { cluster_id: number; node_id: number }) => { + try { + await deleteK8sClusterNodeAction(params.cluster_id, params.node_id); + return createToolResponse( + `✅ Нода ${params.node_id} удалена из кластера ${params.cluster_id}.` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка удаления ноды. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при удалении ноды"); + } +}; + +export const deleteK8sClusterNodeTool = { + name: ToolNames.DELETE_K8S_CLUSTER_NODE, + title: "Удаление ноды кластера", + description: + "Удаляет конкретную ноду из кластера. Действие необратимо.", + inputSchema, + handler, +}; diff --git a/src/tools/delete-k8s-cluster.tool.ts b/src/tools/delete-k8s-cluster.tool.ts new file mode 100644 index 0000000..79447a6 --- /dev/null +++ b/src/tools/delete-k8s-cluster.tool.ts @@ -0,0 +1,67 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { deleteK8sClusterAction } from "../actions/delete-k8s-cluster.action"; + +const inputSchema = { + cluster_id: z + .number() + .int() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID кластера для удаления"), + hash: z + .string() + .optional() + .describe( + "Хэш, полученный при первом запросе удаления (для аккаунтов с 2FA)" + ), + code: z + .string() + .optional() + .describe("Код подтверждения из приложения 2FA"), +}; + +const handler = async (params: { + cluster_id: number; + hash?: string; + code?: string; +}) => { + try { + const result = await deleteK8sClusterAction( + params.cluster_id, + params.hash, + params.code + ); + + if (result.hash && !result.is_moved_in_quarantine) { + return createToolResponse( + `⚠️ Требуется подтверждение 2FA. Повтори вызов с hash="${result.hash}" и code=<код из приложения 2FA>.` + ); + } + + if (result.is_moved_in_quarantine) { + return createToolResponse( + `✅ Кластер ${params.cluster_id} перемещён в карантин.` + ); + } + + return createToolResponse( + `✅ Кластер ${params.cluster_id} удалён.` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка удаления кластера ${params.cluster_id}. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при удалении кластера"); + } +}; + +export const deleteK8sClusterTool = { + name: ToolNames.DELETE_K8S_CLUSTER, + title: "Удаление Kubernetes-кластера", + description: + "Удаляет Kubernetes-кластер. Действие необратимо. Для аккаунтов с 2FA: первый вызов возвращает hash, затем повторный вызов с hash и code подтверждает удаление.", + inputSchema, + handler, +}; diff --git a/src/tools/delete-k8s-node-group.tool.ts b/src/tools/delete-k8s-node-group.tool.ts new file mode 100644 index 0000000..738eab9 --- /dev/null +++ b/src/tools/delete-k8s-node-group.tool.ts @@ -0,0 +1,38 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { deleteK8sNodeGroupAction } from "../actions/delete-k8s-node-group.action"; + +const inputSchema = { + cluster_id: z.number().int().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID кластера"), + group_id: z + .number() + .int() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID группы нод для удаления"), +}; + +const handler = async (params: { cluster_id: number; group_id: number }) => { + try { + await deleteK8sNodeGroupAction(params.cluster_id, params.group_id); + return createToolResponse( + `✅ Группа нод ${params.group_id} удалена из кластера ${params.cluster_id}.` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка удаления группы нод. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при удалении группы нод" + ); + } +}; + +export const deleteK8sNodeGroupTool = { + name: ToolNames.DELETE_K8S_NODE_GROUP, + title: "Удаление группы нод", + description: "Удаляет группу нод из кластера. Все ноды группы будут удалены.", + inputSchema, + handler, +}; diff --git a/src/tools/delete-mailbox.tool.ts b/src/tools/delete-mailbox.tool.ts new file mode 100644 index 0000000..31ba728 --- /dev/null +++ b/src/tools/delete-mailbox.tool.ts @@ -0,0 +1,36 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { deleteMailboxAction } from "../actions/delete-mailbox.action"; + +const inputSchema = { + domain: z.string().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - имя домена"), + mailbox: z + .string() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - имя ящика для удаления"), +}; + +const handler = async (params: { domain: string; mailbox: string }) => { + try { + await deleteMailboxAction(params.domain, params.mailbox); + return createToolResponse( + `✅ Почтовый ящик ${params.mailbox}@${params.domain} удалён.` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка удаления ящика. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при удалении ящика"); + } +}; + +export const deleteMailboxTool = { + name: ToolNames.DELETE_MAILBOX, + title: "Удаление почтового ящика", + description: + "Безвозвратно удаляет почтовый ящик. Операция необратима — вся почта будет потеряна.", + inputSchema, + handler, +}; diff --git a/src/tools/delete-network-drive.tool.ts b/src/tools/delete-network-drive.tool.ts new file mode 100644 index 0000000..e7d20d9 --- /dev/null +++ b/src/tools/delete-network-drive.tool.ts @@ -0,0 +1,37 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { deleteNetworkDriveAction } from "../actions/delete-network-drive.action"; + +const inputSchema = { + network_drive_id: z + .string() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID сетевого диска (UUID) для удаления"), +}; + +const handler = async (params: { network_drive_id: string }) => { + try { + await deleteNetworkDriveAction(params.network_drive_id); + return createToolResponse( + `✅ Сетевой диск ${params.network_drive_id} удалён. Данные на диске восстановить нельзя.` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось удалить сетевой диск ${params.network_drive_id}. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при удалении сетевого диска" + ); + } +}; + +export const deleteNetworkDriveTool = { + name: ToolNames.DELETE_NETWORK_DRIVE, + title: "Удаление сетевого диска", + description: + "Удаляет сетевой диск по ID. Действие необратимо, данные будут потеряны. Перед удалением диск должен быть отключён от всех сервисов (unmount_network_drive).", + inputSchema, + handler, +}; diff --git a/src/tools/delete-project.tool.ts b/src/tools/delete-project.tool.ts new file mode 100644 index 0000000..073c2ac --- /dev/null +++ b/src/tools/delete-project.tool.ts @@ -0,0 +1,33 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { deleteProjectAction } from "../actions/delete-project.action"; + +const inputSchema = { + project_id: z + .number() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID удаляемого проекта"), +}; + +const handler = async (params: { project_id: number }) => { + try { + await deleteProjectAction(params.project_id); + return createToolResponse(`✅ Проект ${params.project_id} удалён.`); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось удалить проект ${params.project_id}. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при удалении проекта"); + } +}; + +export const deleteProjectTool = { + name: ToolNames.DELETE_PROJECT, + title: "Удаление проекта", + description: + "Удаляет проект. Проект по умолчанию удалить нельзя. Ресурсы останутся на аккаунте — проверь и перенеси их заранее через transfer_project_resource.", + inputSchema, + handler, +}; diff --git a/src/tools/delete-server-disk-backup.tool.ts b/src/tools/delete-server-disk-backup.tool.ts new file mode 100644 index 0000000..3c7e6bf --- /dev/null +++ b/src/tools/delete-server-disk-backup.tool.ts @@ -0,0 +1,45 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { deleteServerDiskBackupAction } from "../actions/delete-server-disk-backup.action"; + +const inputSchema = { + server_id: z.number().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID сервера"), + disk_id: z.number().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID диска"), + backup_id: z + .number() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID бэкапа для удаления"), +}; + +const handler = async (params: { + server_id: number; + disk_id: number; + backup_id: number; +}) => { + try { + await deleteServerDiskBackupAction( + params.server_id, + params.disk_id, + params.backup_id + ); + return createToolResponse( + `✅ Бэкап ${params.backup_id} удалён с диска ${params.disk_id} сервера ${params.server_id}.` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось удалить бэкап ${params.backup_id}. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при удалении бэкапа"); + } +}; + +export const deleteServerDiskBackupTool = { + name: ToolNames.DELETE_SERVER_DISK_BACKUP, + title: "Удаление бэкапа диска", + description: + "Удаляет бэкап диска сервера. Действие необратимо. Перед удалением стоит убедиться через list_server_disk_backups что это не последний актуальный бэкап.", + inputSchema, + handler, +}; diff --git a/src/tools/delete-server-ip.tool.ts b/src/tools/delete-server-ip.tool.ts new file mode 100644 index 0000000..bb4d0da --- /dev/null +++ b/src/tools/delete-server-ip.tool.ts @@ -0,0 +1,36 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { deleteServerIpAction } from "../actions/delete-server-ip.action"; + +const inputSchema = { + server_id: z.number().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID сервера"), + ip: z + .string() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - IP-адрес (IPv4 или IPv6), который удалить"), +}; + +const handler = async (params: { server_id: number; ip: string }) => { + try { + await deleteServerIpAction(params.server_id, params.ip); + return createToolResponse( + `✅ IP-адрес ${params.ip} удалён с сервера ${params.server_id}.` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось удалить IP ${params.ip} с сервера ${params.server_id}. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при удалении IP"); + } +}; + +export const deleteServerIpTool = { + name: ToolNames.DELETE_SERVER_IP, + title: "Удаление IP-адреса сервера", + description: + "Удаляет конкретный IP-адрес (IPv4 или IPv6) с сервера. Основной IP удалить нельзя.", + inputSchema, + handler, +}; diff --git a/src/tools/delete-server.tool.ts b/src/tools/delete-server.tool.ts new file mode 100644 index 0000000..5f0f239 --- /dev/null +++ b/src/tools/delete-server.tool.ts @@ -0,0 +1,63 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { deleteServerAction } from "../actions/delete-server.action"; + +const inputSchema = { + server_id: z + .number() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID сервера для удаления"), + hash: z + .string() + .optional() + .describe( + "Хеш (для аккаунтов с 2FA, выдаётся после первого DELETE-запроса)" + ), + code: z + .string() + .optional() + .describe("Код подтверждения 2FA (передаётся вместе с hash)"), +}; + +const handler = async (params: { + server_id: number; + hash?: string; + code?: string; +}) => { + try { + const result = await deleteServerAction(params.server_id, { + hash: params.hash, + code: params.code, + }); + + if (result?.hash) { + return createToolResponse( + `⚠️ Требуется подтверждение через 2FA.\n\n` + + `Хеш: ${result.hash}\n` + + `Повтори запрос delete_server с server_id, hash и code из email/приложения 2FA.` + ); + } + + const quarantined = result?.is_moved_in_quarantine; + return createToolResponse( + `✅ Сервер ${params.server_id} ${quarantined ? "перемещён в карантин" : "удалён"}.` + + (quarantined ? "\nЕго можно будет восстановить в течение периода карантина." : "") + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось удалить сервер ${params.server_id}. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при удалении сервера"); + } +}; + +export const deleteServerTool = { + name: ToolNames.DELETE_SERVER, + title: "Удаление сервера", + description: + "Удаляет сервер. Для аккаунтов с 2FA первый вызов возвращает hash — повторный вызов с hash и code завершит удаление. Удалённый сервер может быть перемещён в карантин.", + inputSchema, + handler, +}; diff --git a/src/tools/delete-ssh-key.tool.ts b/src/tools/delete-ssh-key.tool.ts new file mode 100644 index 0000000..ab12734 --- /dev/null +++ b/src/tools/delete-ssh-key.tool.ts @@ -0,0 +1,35 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { deleteSshKeyAction } from "../actions/delete-ssh-key.action"; + +const inputSchema = { + ssh_key_id: z + .number() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID SSH-ключа для удаления"), +}; + +const handler = async (params: { ssh_key_id: number }) => { + try { + await deleteSshKeyAction(params.ssh_key_id); + return createToolResponse( + `✅ SSH-ключ ${params.ssh_key_id} удалён из аккаунта.` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось удалить SSH-ключ ${params.ssh_key_id}. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при удалении SSH-ключа"); + } +}; + +export const deleteSshKeyTool = { + name: ToolNames.DELETE_SSH_KEY, + title: "Удаление SSH-ключа", + description: + "Удаляет SSH-ключ из аккаунта по ID. Действие необратимо. Перед удалением проверь через list_ssh_keys, что ключ не используется на критичных серверах (поле used_by).", + inputSchema, + handler, +}; diff --git a/src/tools/delete-subdomain.tool.ts b/src/tools/delete-subdomain.tool.ts new file mode 100644 index 0000000..2fbe85c --- /dev/null +++ b/src/tools/delete-subdomain.tool.ts @@ -0,0 +1,38 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { deleteSubdomainAction } from "../actions/delete-subdomain.action"; + +const inputSchema = { + fqdn: z + .string() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - полное имя основного домена"), + subdomain_fqdn: z + .string() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - полное имя удаляемого поддомена"), +}; + +const handler = async (params: { fqdn: string; subdomain_fqdn: string }) => { + try { + await deleteSubdomainAction(params.fqdn, params.subdomain_fqdn); + return createToolResponse( + `✅ Поддомен ${params.subdomain_fqdn} удалён для домена ${params.fqdn}.` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка удаления поддомена "${params.subdomain_fqdn}". Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при удалении поддомена"); + } +}; + +export const deleteSubdomainTool = { + name: ToolNames.DELETE_SUBDOMAIN, + title: "Удаление поддомена", + description: + "Удаляет поддомен по его FQDN из указанного основного домена.", + inputSchema, + handler, +}; diff --git a/src/tools/delete-vpc.tool.ts b/src/tools/delete-vpc.tool.ts new file mode 100644 index 0000000..b1321ca --- /dev/null +++ b/src/tools/delete-vpc.tool.ts @@ -0,0 +1,30 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { deleteVpcAction } from "../actions/delete-vpc.action"; + +const inputSchema = { + vpc_id: z.string().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID VPC"), +}; + +const handler = async (params: { vpc_id: string }) => { + try { + await deleteVpcAction(params.vpc_id); + return createToolResponse(`✅ VPC ${params.vpc_id} удалена.`); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка при удалении VPC. Причина: ${error.message}` + ); + } + return createToolResponse(`❌ Неизвестная ошибка при удалении VPC`); + } +}; + +export const deleteVpcTool = { + name: ToolNames.DELETE_VPC, + title: "Удаление VPC", + description: "Удаляет виртуальную приватную сеть (VPC) по её ID", + inputSchema, + handler, +}; diff --git a/src/tools/edit-api-key.tool.ts b/src/tools/edit-api-key.tool.ts new file mode 100644 index 0000000..2175495 --- /dev/null +++ b/src/tools/edit-api-key.tool.ts @@ -0,0 +1,62 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { editApiKeyAction } from "../actions/edit-api-key.action"; +import { EditApiKeyRequestDto } from "../types/dto/edit-api-key-request.dto"; + +const inputSchema = { + token_id: z + .string() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID API-токена (UUID)"), + name: z.string().optional().describe("Новое имя токена (опц.)"), + is_able_to_delete: z + .boolean() + .optional() + .describe( + "Разрешить/запретить удалять сервисы этим токеном без подтверждения (опц.)" + ), +}; + +const handler = async (params: { + token_id: string; + name?: string; + is_able_to_delete?: boolean; +}) => { + try { + if (params.name === undefined && params.is_able_to_delete === undefined) { + return createToolResponse( + `❌ Нужно указать хотя бы одно поле для изменения: name или is_able_to_delete` + ); + } + + const data: EditApiKeyRequestDto = {}; + if (params.name !== undefined) data.name = params.name; + if (params.is_able_to_delete !== undefined) + data.is_able_to_delete = params.is_able_to_delete; + + const apiKey = await editApiKeyAction(params.token_id, data); + + return createToolResponse(`✅ API-токен ${apiKey.id} обновлён + +• Имя: ${apiKey.name} +• Удаление сервисов: ${apiKey.is_able_to_delete ? "✅ разрешено" : "❌ запрещено"}`); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка при обновлении API-токена. Причина: ${error.message}` + ); + } + return createToolResponse( + `❌ Неизвестная ошибка при обновлении API-токена` + ); + } +}; + +export const editApiKeyTool = { + name: ToolNames.EDIT_API_KEY, + title: "Изменение API-токена", + description: + "Изменяет имя и/или флаг is_able_to_delete API-токена по его ID", + inputSchema, + handler, +}; diff --git a/src/tools/edit-k8s-cluster.tool.ts b/src/tools/edit-k8s-cluster.tool.ts new file mode 100644 index 0000000..bc5fe5c --- /dev/null +++ b/src/tools/edit-k8s-cluster.tool.ts @@ -0,0 +1,70 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { editK8sClusterAction } from "../actions/edit-k8s-cluster.action"; + +const oidcSchema = z.object({ + name: z.string(), + issuer_url: z.string(), + client_id: z.string(), + username_claim: z.string().optional(), + groups_claim: z.string().optional(), +}); + +const inputSchema = { + cluster_id: z.number().int().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID кластера"), + name: z.string().optional().describe("Новое имя кластера"), + description: z.string().optional().describe("Новое описание"), + oidc_provider: oidcSchema + .optional() + .describe( + "OIDC-провайдер: name, issuer_url, client_id (+ опц. username_claim, groups_claim)" + ), +}; + +const handler = async (params: { + cluster_id: number; + name?: string; + description?: string; + oidc_provider?: { + name: string; + issuer_url: string; + client_id: string; + username_claim?: string; + groups_claim?: string; + }; +}) => { + try { + if (!params.name && !params.description && !params.oidc_provider) { + return createToolResponse( + "❌ Ничего не указано для изменения. Передай хотя бы одно: name, description или oidc_provider." + ); + } + + const cluster = await editK8sClusterAction(params.cluster_id, { + name: params.name, + description: params.description, + oidc_provider: params.oidc_provider, + }); + + return createToolResponse( + `✅ Кластер ${cluster.id} обновлён. Название: ${cluster.name}, описание: ${cluster.description || "—"}.` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка обновления кластера. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при обновлении кластера"); + } +}; + +export const editK8sClusterTool = { + name: ToolNames.EDIT_K8S_CLUSTER, + title: "Редактирование Kubernetes-кластера", + description: + "Редактирует имя, описание или OIDC-провайдера кластера. Другие параметры (версия, ноды) изменяются отдельными инструментами.", + inputSchema, + handler, +}; diff --git a/src/tools/get-account-finances.tool.ts b/src/tools/get-account-finances.tool.ts new file mode 100644 index 0000000..f98404b --- /dev/null +++ b/src/tools/get-account-finances.tool.ts @@ -0,0 +1,38 @@ +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { getAccountFinancesAction } from "../actions/get-account-finances.action"; + +const inputSchema = {}; + +const handler = async () => { + try { + const f = await getAccountFinancesAction(); + const hoursLeft = f.hours_left == null ? "—" : `${f.hours_left} ч`; + return createToolResponse( + `💰 Финансы аккаунта (${f.currency}):\n\n` + + `Баланс: ${f.balance}\n` + + `Абонентская плата: ${f.monthly_fee}/мес (${f.hourly_fee}/час)\n` + + `Стоимость услуг: ${f.monthly_cost}/мес (${f.hourly_cost}/час)\n` + + `Всего оплачено за всё время: ${f.total_paid}\n` + + `Часов работы оплачено: ${hoursLeft}\n` + + `Скидка: ${f.discount_percent}% (до ${f.discount_end_date_at ?? "—"})\n` + + `Автоплатёж: ${f.autopay_card_info ?? "не подключен"}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось получить финансы аккаунта. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при получении финансов"); + } +}; + +export const getAccountFinancesTool = { + name: ToolNames.GET_ACCOUNT_FINANCES, + title: "Финансы аккаунта", + description: + "Возвращает баланс, абонентскую плату, стоимость услуг, скидку и данные автоплатежа. Используй для ответа на вопросы 'сколько денег осталось', 'сколько тратим в месяц', 'когда кончатся деньги' (hours_left).", + inputSchema, + handler, +}; diff --git a/src/tools/get-account-services-cost.tool.ts b/src/tools/get-account-services-cost.tool.ts new file mode 100644 index 0000000..b560dfc --- /dev/null +++ b/src/tools/get-account-services-cost.tool.ts @@ -0,0 +1,60 @@ +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { getAccountServicesCostAction } from "../actions/get-account-services-cost.action"; + +const inputSchema = {}; + +const handler = async () => { + try { + const services = await getAccountServicesCostAction(); + + if (services.length === 0) { + return createToolResponse("Сервисов с расходами на аккаунте не найдено."); + } + + const grouped: Record = {}; + for (const s of services) { + const key = s.type || "unknown"; + if (!grouped[key]) grouped[key] = { count: 0, total: 0 }; + grouped[key].count += 1; + grouped[key].total += s.total_cost ?? s.cost ?? 0; + } + + const groupedLines = Object.entries(grouped) + .sort((a, b) => b[1].total - a[1].total) + .map(([type, g]) => `• ${type}: ${g.count} шт, суммарно ${g.total.toFixed(2)}`); + + const top = services + .slice() + .sort((a, b) => (b.total_cost ?? 0) - (a.total_cost ?? 0)) + .slice(0, 10) + .map((s) => { + const cfg = s.configuration + ? ` (CPU: ${s.configuration.cpu ?? "—"}, RAM: ${s.configuration.ram ?? "—"} MB)` + : ""; + return ` • ${s.type}#${s.service_id ?? "?"}: ${s.total_cost ?? s.cost}${cfg}`; + }); + + return createToolResponse( + `💸 Стоимость сервисов (${services.length} сервисов):\n\n` + + `По типам:\n${groupedLines.join("\n")}\n\n` + + `Топ-10 самых дорогих:\n${top.join("\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось получить стоимость сервисов. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка"); + } +}; + +export const getAccountServicesCostTool = { + name: ToolNames.GET_ACCOUNT_SERVICES_COST, + title: "Стоимость сервисов аккаунта", + description: + "Возвращает детализацию расходов по всем сервисам (VPS, БД, S3, DNS и пр.). Полезно для ответа 'куда уходят деньги' и поиска самых дорогих ресурсов. Для общего баланса используй get_account_finances.", + inputSchema, + handler, +}; diff --git a/src/tools/get-account-status.tool.ts b/src/tools/get-account-status.tool.ts new file mode 100644 index 0000000..5278b3b --- /dev/null +++ b/src/tools/get-account-status.tool.ts @@ -0,0 +1,37 @@ +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { getAccountStatusAction } from "../actions/get-account-status.action"; + +const inputSchema = {}; + +const handler = async () => { + try { + const s = await getAccountStatusAction(); + return createToolResponse( + `📋 Статус аккаунта:\n\n` + + `Заблокирован: ${s.is_blocked ? "да" : "нет"}\n` + + `Перманентно заблокирован: ${s.is_permanent_blocked ? "да" : "нет"}\n` + + `Получать письма о счетах: ${s.is_send_bill_letters ? "да" : "нет"}\n` + + `Последняя смена пароля: ${s.last_password_changed_at ?? "—"}` + + (s.bonus_balance !== undefined + ? `\nБонусный баланс: ${s.bonus_balance}` + : "") + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось получить статус аккаунта. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при получении статуса"); + } +}; + +export const getAccountStatusTool = { + name: ToolNames.GET_ACCOUNT_STATUS, + title: "Статус аккаунта", + description: + "Возвращает статус блокировки аккаунта и настройки уведомлений. Используй для диагностики 'почему API не отвечает' (возможна блокировка при недостатке средств).", + inputSchema, + handler, +}; diff --git a/src/tools/get-ai-agent-statistic.tool.ts b/src/tools/get-ai-agent-statistic.tool.ts new file mode 100644 index 0000000..a4d7aaf --- /dev/null +++ b/src/tools/get-ai-agent-statistic.tool.ts @@ -0,0 +1,78 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { getAiAgentStatisticAction } from "../actions/get-ai-agent-statistic.action"; + +const inputSchema = { + agent_id: z.number().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID агента"), + start_time: z + .string() + .optional() + .describe("Начало диапазона (ISO 8601, например 2024-10-01T00:00:00.000Z)"), + end_time: z + .string() + .optional() + .describe("Конец диапазона (ISO 8601, например 2024-10-16T23:59:59.999Z)"), + interval: z + .number() + .optional() + .describe("Интервал агрегации в минутах (по умолчанию 60)"), +}; + +const handler = async (params: { + agent_id: number; + start_time?: string; + end_time?: string; + interval?: number; +}) => { + try { + const stats = await getAiAgentStatisticAction(params.agent_id, { + startTime: params.start_time, + endTime: params.end_time, + interval: params.interval, + }); + + if (stats.length === 0) { + return createToolResponse( + `По агенту ${params.agent_id} нет статистики в указанном диапазоне.` + ); + } + + const totalIn = stats.reduce((s, p) => s + (p.ingoing_tokens ?? 0), 0); + const totalOut = stats.reduce((s, p) => s + (p.outgoing_tokens ?? 0), 0); + + const lines = stats + .slice(0, 20) + .map( + (s) => + `• ${new Date(s.time).toLocaleString("ru-RU")} — вход: ${s.ingoing_tokens}, выход: ${s.outgoing_tokens}` + ); + + const more = + stats.length > 20 ? `\n…и ещё ${stats.length - 20} точек` : ""; + + return createToolResponse(`📊 Статистика агента ${params.agent_id} (${stats.length} точек): + +Итого: вход ${totalIn}, выход ${totalOut} токенов + +${lines.join("\n")}${more}`); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось получить статистику агента ${params.agent_id}. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при получении статистики агента" + ); + } +}; + +export const getAiAgentStatisticTool = { + name: ToolNames.GET_AI_AGENT_STATISTIC, + title: "Статистика использования токенов AI-агента", + description: + "Возвращает статистику использования токенов агента по временным интервалам. Параметры start_time/end_time в ISO 8601, interval в минутах (60 по умолчанию).", + inputSchema, + handler, +}; diff --git a/src/tools/get-ai-agent.tool.ts b/src/tools/get-ai-agent.tool.ts new file mode 100644 index 0000000..5b512cd --- /dev/null +++ b/src/tools/get-ai-agent.tool.ts @@ -0,0 +1,56 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { getAiAgentAction } from "../actions/get-ai-agent.action"; + +const inputSchema = { + agent_id: z.number().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID AI-агента"), +}; + +const handler = async (params: { agent_id: number }) => { + try { + const a = await getAiAgentAction(params.agent_id); + + const linesBlock = [ + `• ID: ${a.id}`, + `• Название: ${a.name}`, + a.description ? `• Описание: ${a.description}` : null, + `• Статус: ${a.status}`, + `• Тип доступа: ${a.access_type}`, + `• Модель ID: ${a.model_id}`, + a.token_package_id ? `• Пакет токенов: ${a.token_package_id}` : null, + a.total_tokens !== undefined + ? `• Токены: использовано ${a.used_tokens ?? 0} из ${a.total_tokens} (осталось ${a.remaining_tokens ?? 0})` + : null, + a.settings?.system_prompt + ? `• System prompt: ${a.settings.system_prompt.slice(0, 200)}${a.settings.system_prompt.length > 200 ? "…" : ""}` + : null, + a.subscription_renewal_date + ? `• Обновление подписки: ${new Date(a.subscription_renewal_date).toLocaleString("ru-RU")}` + : null, + a.created_at + ? `• Создан: ${new Date(a.created_at).toLocaleString("ru-RU")}` + : null, + ] + .filter(Boolean) + .join("\n"); + + return createToolResponse(`📋 AI-агент ${a.id}:\n\n${linesBlock}`); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось получить агента ${params.agent_id}. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при получении агента"); + } +}; + +export const getAiAgentTool = { + name: ToolNames.GET_AI_AGENT, + title: "Получение AI-агента", + description: + "Возвращает детальную информацию об AI-агенте по ID: название, статус, доступ, модель, пакет токенов, system prompt, остаток токенов.", + inputSchema, + handler, +}; diff --git a/src/tools/get-balancer.tool.ts b/src/tools/get-balancer.tool.ts new file mode 100644 index 0000000..4223b03 --- /dev/null +++ b/src/tools/get-balancer.tool.ts @@ -0,0 +1,51 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { getBalancerAction } from "../actions/get-balancer.action"; + +const inputSchema = { + balancer_id: z + .number() + .int() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID балансировщика"), +}; + +const handler = async (params: { balancer_id: number }) => { + try { + const b = await getBalancerAction(params.balancer_id); + + return createToolResponse(`📋 Балансировщик ${b.id} — ${b.name} + +• Статус: ${b.status} +• Протокол/Порт: ${b.proto}:${b.port} +• Алгоритм: ${b.algo} +• IP: ${b.ip ?? "—"} (локальный: ${b.local_ip ?? "—"}) +• Локация: ${b.location}, зона: ${b.availability_zone} +• Путь health-check: ${b.path} +• SSL: ${b.is_ssl ? "да" : "нет"}, Sticky: ${b.is_sticky ? "да" : "нет"}, Keepalive: ${b.is_keepalive ? "да" : "нет"}, Proxy: ${b.is_use_proxy ? "да" : "нет"} +• Таймауты: inter=${b.inter}, timeout=${b.timeout}, connect=${b.connect_timeout}, client=${b.client_timeout}, server=${b.server_timeout}, http=${b.httprequest_timeout} +• Пороги: fall=${b.fall}, rise=${b.rise}, maxconn=${b.maxconn} +• Preset: ${b.preset_id}, Project: ${b.project_id} +• Правил: ${b.rules?.length ?? 0} +• Привязанные IP (${b.ips?.length ?? 0}): ${b.ips?.join(", ") || "—"} +• Создан: ${new Date(b.created_at).toLocaleString("ru-RU")}`); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения балансировщика ${params.balancer_id}. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при получении балансировщика" + ); + } +}; + +export const getBalancerTool = { + name: ToolNames.GET_BALANCER, + title: "Получение балансировщика", + description: + "Возвращает детальную информацию о балансировщике по ID: статус, протокол, порт, алгоритм, таймауты, сертификаты, правила, IP-адреса.", + inputSchema, + handler, +}; diff --git a/src/tools/get-bucket-presets.tool.ts b/src/tools/get-bucket-presets.tool.ts new file mode 100644 index 0000000..6fe53df --- /dev/null +++ b/src/tools/get-bucket-presets.tool.ts @@ -0,0 +1,42 @@ +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { getBucketPresetsAction } from "../actions/get-bucket-presets.action"; + +const inputSchema = {}; + +const handler = async () => { + try { + const presets = await getBucketPresetsAction(); + + if (presets.length === 0) { + return createToolResponse("Тарифы S3-хранилищ не найдены."); + } + + const lines = presets.map( + (p) => + `• ID ${p.id} — ${p.description_short} (${p.storage_class})\n диск: ${p.disk} ГБ, цена: ${p.price} руб., локация: ${p.location}\n ${p.description}` + ); + + return createToolResponse( + `Тарифы S3-хранилищ (${presets.length}):\n\n${lines.join("\n\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения тарифов S3-хранилищ. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при получении тарифов S3-хранилищ" + ); + } +}; + +export const getBucketPresetsTool = { + name: ToolNames.GET_BUCKET_PRESETS, + title: "Тарифы S3-хранилищ", + description: + "Возвращает список доступных тарифов для S3-хранилищ с id, размером диска, ценой, классом (cold/hot), локацией. Используй перед create_bucket, чтобы получить preset_id.", + inputSchema, + handler, +}; diff --git a/src/tools/get-bucket-transfer-status.tool.ts b/src/tools/get-bucket-transfer-status.tool.ts new file mode 100644 index 0000000..ad8edfd --- /dev/null +++ b/src/tools/get-bucket-transfer-status.tool.ts @@ -0,0 +1,43 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { getBucketTransferStatusAction } from "../actions/get-bucket-transfer-status.action"; + +const inputSchema = { + bucket_id: z.number().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID S3-хранилища"), +}; + +const handler = async (params: { bucket_id: number }) => { + try { + const s = await getBucketTransferStatusAction(params.bucket_id); + + const errorsBlock = + s.errors.length > 0 + ? `\n\n⚠️ Ошибки (${s.errors.length}):\n${s.errors.map((e) => ` • попытка ${e.try}: ${e.value}`).join("\n")}` + : ""; + + return createToolResponse(`📋 Статус переноса S3-хранилища ${params.bucket_id}: +• Общий статус: ${s.status} +• Попыток: ${s.tries} +• Всего объектов: ${s.total_count} (размер: ${s.total_size} байт) +• Перенесено: ${s.uploaded_count} (размер: ${s.uploaded_size} байт)${errorsBlock}`); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения статуса переноса хранилища ${params.bucket_id}. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при получении статуса переноса хранилища" + ); + } +}; + +export const getBucketTransferStatusTool = { + name: ToolNames.GET_BUCKET_TRANSFER_STATUS, + title: "Статус переноса S3-хранилища", + description: + "Возвращает статус переноса хранилища от стороннего S3-провайдера в Timeweb Cloud: started/suspended/failed, количество и размер объектов, перенесено, попытки, ошибки. Используй после transfer_bucket.", + inputSchema, + handler, +}; diff --git a/src/tools/get-bucket.tool.ts b/src/tools/get-bucket.tool.ts new file mode 100644 index 0000000..e3fbc4f --- /dev/null +++ b/src/tools/get-bucket.tool.ts @@ -0,0 +1,57 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { getBucketAction } from "../actions/get-bucket.action"; + +const inputSchema = { + bucket_id: z.number().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID S3-хранилища"), +}; + +const handler = async (params: { bucket_id: number }) => { + try { + const b = await getBucketAction(params.bucket_id); + + const sizeGb = b.disk_stats.is_unlimited + ? "безлимитно" + : `${(b.disk_stats.size / 1024 / 1024).toFixed(2)} ГБ`; + const usedGb = `${(b.disk_stats.used / 1024 / 1024).toFixed(2)} ГБ`; + + return createToolResponse(`📋 S3-хранилище: +• ID: ${b.id} +• Название: ${b.name} +• Описание: ${b.description || "—"} +• Тип: ${b.type} +• Статус: ${b.status} +• Класс хранилища: ${b.storage_class} +• Локация: ${b.location} +• Hostname: ${b.hostname} +• Access key: ${b.access_key} +• Secret key: ${b.secret_key} +• Объектов: ${b.object_amount} +• Диск: ${usedGb} / ${sizeGb} +• Preset ID: ${b.preset_id ?? "—"} +• Configurator ID: ${b.configurator_id ?? "—"} +• Project ID: ${b.project_id} +• Авто-апгрейд: ${b.is_allow_auto_upgrade ? "вкл." : "выкл."} +• В карантине с: ${b.moved_in_quarantine_at ? new Date(b.moved_in_quarantine_at).toLocaleString("ru-RU") : "—"} +• Website config: ${b.website_config?.enabled ? "включён" : "выключен"}`); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения S3-хранилища ${params.bucket_id}. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при получении S3-хранилища" + ); + } +}; + +export const getBucketTool = { + name: ToolNames.GET_BUCKET, + title: "Получение S3-хранилища", + description: + "Возвращает детальную информацию об одном S3-хранилище по его ID: название, тип, статус, класс, локация, hostname, ключи доступа, использование диска, настройки веб-сайта.", + inputSchema, + handler, +}; diff --git a/src/tools/get-container-registry.tool.ts b/src/tools/get-container-registry.tool.ts new file mode 100644 index 0000000..6726e0e --- /dev/null +++ b/src/tools/get-container-registry.tool.ts @@ -0,0 +1,44 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { getContainerRegistryAction } from "../actions/get-container-registry.action"; + +const inputSchema = { + registry_id: z + .number() + .describe( + "ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID реестра (получить через list_container_registries)" + ), +}; + +const handler = async (params: { registry_id: number }) => { + try { + const r = await getContainerRegistryAction(params.registry_id); + return createToolResponse( + `Реестр контейнеров ${r.id} — ${r.name}\n\n` + + `Описание: ${r.description || "—"}\n` + + `Preset ID: ${r.preset_id}\n` + + `Configurator ID: ${r.configurator_id}\n` + + `Project ID: ${r.project_id}\n` + + `Диск: ${r.disk_stats.used}/${r.disk_stats.size} ГБ (использовано/всего)\n` + + `Создан: ${new Date(r.created_at).toLocaleString("ru-RU")}\n` + + `Обновлён: ${new Date(r.updated_at).toLocaleString("ru-RU")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения реестра ${params.registry_id}. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при получении реестра"); + } +}; + +export const getContainerRegistryTool = { + name: ToolNames.GET_CONTAINER_REGISTRY, + title: "Получение информации о реестре контейнеров", + description: + "Возвращает детальную информацию о конкретном реестре контейнеров по ID: имя, описание, тариф, использование диска, дата создания и обновления.", + inputSchema, + handler, +}; diff --git a/src/tools/get-database-admin.tool.ts b/src/tools/get-database-admin.tool.ts new file mode 100644 index 0000000..b9a69a2 --- /dev/null +++ b/src/tools/get-database-admin.tool.ts @@ -0,0 +1,60 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { getDatabaseAdminAction } from "../actions/get-database-admin.action"; + +const inputSchema = { + db_cluster_id: z + .number() + .int() + .positive() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID кластера базы данных"), + admin_id: z + .number() + .int() + .positive() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID пользователя базы данных"), +}; + +const handler = async (params: { + db_cluster_id: number; + admin_id: number; +}) => { + try { + const a = await getDatabaseAdminAction( + params.db_cluster_id, + params.admin_id + ); + + return createToolResponse(`👤 Пользователь базы данных + +• ID: ${a.id} +• Login: ${a.login} +• Хост: ${a.host ?? "—"} +• Описание: ${a.description || "—"} +• Инстансы и привилегии: +${(a.instances ?? []) + .map( + (i) => + ` — instance ${i.instance_id}: ${i.privileges.join(", ") || "—"}` + ) + .join("\n") || " —"} +• Создан: ${new Date(a.created_at).toLocaleString("ru-RU")}`); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения пользователя ${params.admin_id}. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при получении пользователя"); + } +}; + +export const getDatabaseAdminTool = { + name: ToolNames.GET_DATABASE_ADMIN, + title: "Получение пользователя кластера", + description: + "Возвращает информацию о пользователе кластера базы данных (`GET /api/v1/databases/{db_cluster_id}/admins/{admin_id}`).", + inputSchema, + handler, +}; diff --git a/src/tools/get-database-cluster.tool.ts b/src/tools/get-database-cluster.tool.ts new file mode 100644 index 0000000..fde5312 --- /dev/null +++ b/src/tools/get-database-cluster.tool.ts @@ -0,0 +1,57 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { getDatabaseClusterAction } from "../actions/get-database-cluster.action"; + +const inputSchema = { + db_cluster_id: z + .number() + .int() + .positive() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID кластера базы данных"), +}; + +const handler = async (params: { db_cluster_id: number }) => { + try { + const c = await getDatabaseClusterAction(params.db_cluster_id); + + if (!c) { + return createToolResponse( + `❌ Кластер ${params.db_cluster_id} не найден` + ); + } + + return createToolResponse(`📋 Кластер базы данных + +• ID: ${c.id} +• Название: ${c.name} +• Тип: ${c.type} +• Статус: ${c.status} +• Локация: ${c.location ?? "—"} +• Пресет: ${c.preset_id} +• Порт: ${c.port ?? "—"} +• Hash type: ${c.hash_type ?? "—"} +• Зона доступности: ${c.availability_zone ?? "—"} +• Публичный доступ: ${c.is_enabled_public_network ? "✅" : "❌"} +• Создан: ${new Date(c.created_at).toLocaleString("ru-RU")} + +Полный JSON: +${JSON.stringify(c, null, 2)}`); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения кластера ${params.db_cluster_id}. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при получении кластера"); + } +}; + +export const getDatabaseClusterTool = { + name: ToolNames.GET_DATABASE_CLUSTER, + title: "Получение кластера базы данных", + description: + "Возвращает детальную информацию о конкретном кластере баз данных по его ID (`GET /api/v1/databases/{db_cluster_id}`).", + inputSchema, + handler, +}; diff --git a/src/tools/get-database-instance.tool.ts b/src/tools/get-database-instance.tool.ts new file mode 100644 index 0000000..7b4b074 --- /dev/null +++ b/src/tools/get-database-instance.tool.ts @@ -0,0 +1,51 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { getDatabaseInstanceAction } from "../actions/get-database-instance.action"; + +const inputSchema = { + db_cluster_id: z + .number() + .int() + .positive() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID кластера базы данных"), + instance_id: z + .number() + .int() + .positive() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID инстанса базы данных"), +}; + +const handler = async (params: { + db_cluster_id: number; + instance_id: number; +}) => { + try { + const i = await getDatabaseInstanceAction( + params.db_cluster_id, + params.instance_id + ); + return createToolResponse(`📋 Инстанс базы данных + +• ID: ${i.id} +• Название: ${i.name} +• Описание: ${i.description || "—"} +• Создан: ${new Date(i.created_at).toLocaleString("ru-RU")}`); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения инстанса ${params.instance_id}. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при получении инстанса"); + } +}; + +export const getDatabaseInstanceTool = { + name: ToolNames.GET_DATABASE_INSTANCE, + title: "Получение инстанса кластера", + description: + "Возвращает информацию об инстансе базы данных в кластере (`GET /api/v1/databases/{db_cluster_id}/instances/{instance_id}`).", + inputSchema, + handler, +}; diff --git a/src/tools/get-dedicated-server.tool.ts b/src/tools/get-dedicated-server.tool.ts new file mode 100644 index 0000000..78b5c6d --- /dev/null +++ b/src/tools/get-dedicated-server.tool.ts @@ -0,0 +1,59 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { getDedicatedServerAction } from "../actions/get-dedicated-server.action"; + +const inputSchema = { + dedicated_id: z + .number() + .describe( + "ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID выделенного сервера (получить через list_dedicated_servers)" + ), +}; + +const handler = async (params: { dedicated_id: number }) => { + try { + const s = await getDedicatedServerAction(params.dedicated_id); + return createToolResponse( + `Выделенный сервер ${s.id} — ${s.name}\n\n` + + `Статус: ${s.status}\n` + + `Локация: ${s.location}\n` + + `CPU: ${s.cpu_description}\n` + + `RAM: ${s.ram_description}\n` + + `HDD: ${s.hdd_description}\n` + + `IPv4: ${s.ip ?? "—"}\n` + + `IPv6: ${s.ipv6 ?? "—"}\n` + + `IPMI IP: ${s.ipmi_ip ?? "—"}\n` + + `IPMI login: ${s.ipmi_login ?? "—"}\n` + + `VNC pass: ${s.vnc_pass ?? "—"}\n` + + `Preset ID: ${s.preset_id}\n` + + `Plan ID: ${s.plan_id ?? "—"}\n` + + `OS ID: ${s.os_id ?? "—"}, CP ID: ${s.cp_id ?? "—"}\n` + + `Bandwidth ID: ${s.bandwidth_id ?? "—"}, Network drive ID: ${s.network_drive_id ?? "—"}\n` + + `Additional IP addr ID: ${s.additional_ip_addr_id ?? "—"}\n` + + `Project ID: ${s.project_id ?? "—"}\n` + + `Цена: ${s.price} руб\n` + + `Autoinstall ready: ${s.autoinstall_ready ?? "—"}, pre-installed: ${s.is_pre_installed ?? "—"}\n` + + `Комментарий: ${s.comment || "—"}\n` + + `Создан: ${new Date(s.created_at).toLocaleString("ru-RU")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения выделенного сервера ${params.dedicated_id}. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при получении выделенного сервера" + ); + } +}; + +export const getDedicatedServerTool = { + name: ToolNames.GET_DEDICATED_SERVER, + title: "Получение выделенного сервера", + description: + "Возвращает детальную информацию по конкретному выделенному (dedicated) серверу: статус, CPU/RAM/HDD, IP-адреса, IPMI-доступ, VNC-пароль, параметры тарифа, цена, комментарий. Используй, когда нужны подробности по одному серверу (например, IPMI-учётка для подключения).", + inputSchema, + handler, +}; diff --git a/src/tools/get-domain-name-servers.tool.ts b/src/tools/get-domain-name-servers.tool.ts new file mode 100644 index 0000000..0e454dd --- /dev/null +++ b/src/tools/get-domain-name-servers.tool.ts @@ -0,0 +1,51 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { getDomainNameServersAction } from "../actions/get-domain-name-servers.action"; + +const inputSchema = { + fqdn: z.string().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - полное имя домена"), +}; + +const handler = async (params: { fqdn: string }) => { + try { + const groups = await getDomainNameServersAction(params.fqdn); + if (groups.length === 0) { + return createToolResponse( + `У домена ${params.fqdn} нет настроенных name-серверов.` + ); + } + const blocks = groups.map((g) => { + const items = g.items + .map( + (i) => + ` • ${i.host}${i.ips.length ? ` (${i.ips.join(", ")})` : ""}` + ) + .join("\n"); + return `• Делегирование разрешено: ${g.is_delegation_allowed ? "да" : "нет"} +• Статус задачи: ${g.task_status} +${items}`; + }); + return createToolResponse( + `Name-серверы домена ${params.fqdn}:\n\n${blocks.join("\n\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения name-серверов "${params.fqdn}". Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при получении name-серверов" + ); + } +}; + +export const getDomainNameServersTool = { + name: ToolNames.GET_DOMAIN_NAME_SERVERS, + title: "Name-серверы домена", + description: + "Возвращает список name-серверов домена (host + IP-адреса), статус делегирования и задачи обновления NS.", + inputSchema, + handler, +}; diff --git a/src/tools/get-domain-request.tool.ts b/src/tools/get-domain-request.tool.ts new file mode 100644 index 0000000..9dabd5f --- /dev/null +++ b/src/tools/get-domain-request.tool.ts @@ -0,0 +1,41 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { getDomainRequestAction } from "../actions/domain-requests.action"; + +const inputSchema = { + request_id: z.number().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID заявки"), +}; + +const handler = async (params: { request_id: number }) => { + try { + const r = await getDomainRequestAction(params.request_id); + return createToolResponse(`📋 Заявка ID ${r.id}: +• FQDN: ${r.fqdn} +• Тип: ${r.type ?? "—"} +• Статус: ${r.status ?? "—"} +• Источник оплаты: ${r.money_source ?? "—"} +• Период: ${r.period ?? "—"} +• Дата создания: ${r.date ?? "—"} +• Автопродление: ${r.is_autoprolong_enabled ? "да" : "нет"} +• Whois privacy: ${r.is_whois_privacy_enabled ? "да" : "нет"} +• Сообщение: ${r.message ?? "—"} +• Auth code: ${r.auth_code ?? "—"}`); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения заявки ${params.request_id}. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при получении заявки"); + } +}; + +export const getDomainRequestTool = { + name: ToolNames.GET_DOMAIN_REQUEST, + title: "Получение заявки на домен", + description: + "Возвращает детали заявки на регистрацию/продление/трансфер по её ID.", + inputSchema, + handler, +}; diff --git a/src/tools/get-domain.tool.ts b/src/tools/get-domain.tool.ts new file mode 100644 index 0000000..eda4007 --- /dev/null +++ b/src/tools/get-domain.tool.ts @@ -0,0 +1,45 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { getDomainAction } from "../actions/get-domain.action"; + +const inputSchema = { + fqdn: z + .string() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - полное имя домена (например: example.com)"), +}; + +const handler = async (params: { fqdn: string }) => { + try { + const d = await getDomainAction(params.fqdn); + return createToolResponse(`📋 Домен ${d.fqdn}: +• ID: ${d.id} +• Статус: ${d.domain_status} +• Дата окончания: ${d.expiration} +• Дней осталось: ${d.days_left ?? "—"} +• Автопродление: ${d.is_autoprolong_enabled ? "да" : "нет"} +• Premium: ${d.is_premium ? "да" : "нет"} +• Можно продлить сейчас: ${d.is_prolong_allowed ? "да" : "нет"} +• Технический: ${d.is_technical ? "да" : "нет"} +• Whois privacy: ${d.is_whois_privacy_enabled ? "включена" : "выключена"} +• Регистратор: ${d.registrar ?? "—"} +• Провайдер: ${d.provider ?? "—"} +• Поддоменов: ${d.subdomains?.length ?? 0}`); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения домена "${params.fqdn}". Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при получении домена"); + } +}; + +export const getDomainTool = { + name: ToolNames.GET_DOMAIN, + title: "Получение информации о домене", + description: + "Возвращает подробную информацию о домене по его FQDN: статус, дата окончания, автопродление, whois privacy, поддомены.", + inputSchema, + handler, +}; diff --git a/src/tools/get-firewall-group.tool.ts b/src/tools/get-firewall-group.tool.ts new file mode 100644 index 0000000..e6cc45b --- /dev/null +++ b/src/tools/get-firewall-group.tool.ts @@ -0,0 +1,44 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { getFirewallGroupAction } from "../actions/get-firewall-group.action"; + +const inputSchema = { + group_id: z + .string() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID группы правил firewall"), +}; + +const handler = async (params: { group_id: string }) => { + try { + const g = await getFirewallGroupAction(params.group_id); + + return createToolResponse(`🛡️ Группа правил firewall: + +📋 Детали: +• ID: ${g.id} +• Имя: ${g.name} +• Описание: ${g.description || "—"} +• Политика: ${g.policy} +• Создана: ${new Date(g.created_at).toLocaleString("ru-RU")} +• Обновлена: ${new Date(g.updated_at).toLocaleString("ru-RU")}`); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения группы firewall ${params.group_id}. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при получении группы firewall" + ); + } +}; + +export const getFirewallGroupTool = { + name: ToolNames.GET_FIREWALL_GROUP, + title: "Информация о группе правил firewall", + description: + "Возвращает детали конкретной группы правил firewall по её ID: имя, описание, политика (ACCEPT/DROP), даты создания и обновления.", + inputSchema, + handler, +}; diff --git a/src/tools/get-firewall-rule.tool.ts b/src/tools/get-firewall-rule.tool.ts new file mode 100644 index 0000000..0a0f128 --- /dev/null +++ b/src/tools/get-firewall-rule.tool.ts @@ -0,0 +1,48 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { getFirewallRuleAction } from "../actions/get-firewall-rule.action"; + +const inputSchema = { + group_id: z + .string() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID группы правил firewall"), + rule_id: z + .string() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID правила"), +}; + +const handler = async (params: { group_id: string; rule_id: string }) => { + try { + const r = await getFirewallRuleAction(params.group_id, params.rule_id); + + return createToolResponse(`🛡️ Правило firewall: + +📋 Детали: +• ID: ${r.id} +• Группа: ${r.group_id} +• Направление: ${r.direction} +• Протокол: ${r.protocol} +• Порт: ${r.port || "—"} +• CIDR: ${r.cidr || "—"} +• Описание: ${r.description || "—"}`); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения правила ${params.rule_id}. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при получении правила firewall" + ); + } +}; + +export const getFirewallRuleTool = { + name: ToolNames.GET_FIREWALL_RULE, + title: "Информация о правиле firewall", + description: + "Возвращает детали конкретного правила firewall: направление, протокол, порт, CIDR, описание, ID группы.", + inputSchema, + handler, +}; diff --git a/src/tools/get-floating-ip.tool.ts b/src/tools/get-floating-ip.tool.ts new file mode 100644 index 0000000..619f397 --- /dev/null +++ b/src/tools/get-floating-ip.tool.ts @@ -0,0 +1,44 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { getFloatingIpAction } from "../actions/get-floating-ip.action"; + +const inputSchema = { + floating_ip_id: z + .string() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID плавающего IP (UUID)"), +}; + +const handler = async (params: { floating_ip_id: string }) => { + try { + const ip = await getFloatingIpAction(params.floating_ip_id); + + const bound = ip.resource_type + ? `${ip.resource_type}${ip.resource_id !== null && ip.resource_id !== undefined ? ` (ID ${ip.resource_id})` : ""}` + : "не привязан"; + + return createToolResponse(`📋 Плавающий IP ${ip.id} + +• IP адрес: ${ip.ip ?? "не назначен"} +• Зона доступности: ${ip.availability_zone} +• DDoS Guard: ${ip.is_ddos_guard ? "✅ включён" : "❌ выключен"} +• Привязан к: ${bound} +• Комментарий: ${ip.comment ?? "—"} +• PTR: ${ip.ptr ?? "—"}`); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка при получении плавающего IP. Причина: ${error.message}` + ); + } + return createToolResponse(`❌ Неизвестная ошибка при получении плавающего IP`); + } +}; + +export const getFloatingIpTool = { + name: ToolNames.GET_FLOATING_IP, + title: "Получение плавающего IP", + description: "Возвращает детальную информацию о плавающем IP по его ID", + inputSchema, + handler, +}; diff --git a/src/tools/get-image-download.tool.ts b/src/tools/get-image-download.tool.ts new file mode 100644 index 0000000..5ab7736 --- /dev/null +++ b/src/tools/get-image-download.tool.ts @@ -0,0 +1,50 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { getImageDownloadAction } from "../actions/get-image-download.action"; + +const inputSchema = { + image_id: z.string().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID образа"), + image_url_id: z + .string() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID ссылки на скачивание"), +}; + +const handler = async (params: { + image_id: string; + image_url_id: string; +}) => { + try { + const d = await getImageDownloadAction( + params.image_id, + params.image_url_id + ); + + const lines = [ + `📋 Ссылка на скачивание ${d.id}:`, + ` образ: ${d.image}`, + ` тип: ${d.type}`, + ` статус: ${d.status} (progress ${d.progress}%)`, + ` url: ${d.url ?? "—"}`, + ` создана: ${d.created_at}`, + ]; + + return createToolResponse(lines.join("\n")); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось получить ссылку ${params.image_url_id}. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при получении ссылки"); + } +}; + +export const getImageDownloadTool = { + name: ToolNames.GET_IMAGE_DOWNLOAD, + title: "Информация о ссылке на скачивание образа", + description: + "Возвращает детальную информацию о конкретной ссылке на скачивание образа: тип, статус, прогресс, сам URL (если статус finished).", + inputSchema, + handler, +}; diff --git a/src/tools/get-image.tool.ts b/src/tools/get-image.tool.ts new file mode 100644 index 0000000..05a6755 --- /dev/null +++ b/src/tools/get-image.tool.ts @@ -0,0 +1,44 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { getImageAction } from "../actions/get-image.action"; + +const inputSchema = { + image_id: z.string().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID образа"), +}; + +const handler = async (params: { image_id: string }) => { + try { + const i = await getImageAction(params.image_id); + + const lines = [ + `📋 Образ ${i.id}:`, + ` имя: ${i.name || "(без имени)"}`, + ` описание: ${i.description || "—"}`, + ` статус: ${i.status} (progress ${i.progress}%)`, + ` ОС: ${i.os}, тип: ${i.type}, локация: ${i.location}`, + ` размер физический: ${i.size} MB, виртуальный: ${i.virtual_size} MB`, + ` disk_id: ${i.disk_id ?? "—"}, custom: ${i.is_custom}`, + ` создан: ${i.created_at}`, + ` удалён: ${i.deleted_at ?? "—"}`, + ]; + + return createToolResponse(lines.join("\n")); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось получить образ ${params.image_id}. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при получении образа"); + } +}; + +export const getImageTool = { + name: ToolNames.GET_IMAGE, + title: "Информация об образе", + description: + "Возвращает детальную информацию об образе по его ID: статус, прогресс создания, размеры, ОС, локацию, disk_id, флаг custom.", + inputSchema, + handler, +}; diff --git a/src/tools/get-k8s-cluster-resources.tool.ts b/src/tools/get-k8s-cluster-resources.tool.ts new file mode 100644 index 0000000..a37a926 --- /dev/null +++ b/src/tools/get-k8s-cluster-resources.tool.ts @@ -0,0 +1,39 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { getK8sClusterResourcesAction } from "../actions/get-k8s-cluster-resources.action"; + +const inputSchema = { + cluster_id: z.number().int().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID кластера"), +}; + +const handler = async (params: { cluster_id: number }) => { + try { + const r = await getK8sClusterResourcesAction(params.cluster_id); + const fmt = (x: { requested: number; allocatable: number; capacity: number; used: number }) => + `requested=${x.requested}, allocatable=${x.allocatable}, capacity=${x.capacity}, used=${x.used}`; + + return createToolResponse(`📊 Ресурсы кластера ${params.cluster_id}: + +• Нод: ${r.nodes} +• CPU (ядра): ${fmt(r.cores)} +• Memory: ${fmt(r.memory)} +• Pods: ${fmt(r.pods)}`); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения ресурсов кластера. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при получении ресурсов"); + } +}; + +export const getK8sClusterResourcesTool = { + name: ToolNames.GET_K8S_CLUSTER_RESOURCES, + title: "Ресурсы Kubernetes-кластера", + description: + "Возвращает агрегированные показатели ресурсов кластера: количество нод, CPU, memory, pods (requested/allocatable/capacity/used).", + inputSchema, + handler, +}; diff --git a/src/tools/get-k8s-cluster.tool.ts b/src/tools/get-k8s-cluster.tool.ts new file mode 100644 index 0000000..483516d --- /dev/null +++ b/src/tools/get-k8s-cluster.tool.ts @@ -0,0 +1,46 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { getK8sClusterAction } from "../actions/get-k8s-cluster.action"; + +const inputSchema = { + cluster_id: z + .number() + .int() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID кластера"), +}; + +const handler = async (params: { cluster_id: number }) => { + try { + const c = await getK8sClusterAction(params.cluster_id); + return createToolResponse(`📋 Kubernetes-кластер ID ${c.id} + +• Название: ${c.name} +• Описание: ${c.description || "—"} +• Статус: ${c.status} +• Версия: ${c.k8s_version} +• Сетевой драйвер: ${c.network_driver} +• Зона: ${c.availability_zone ?? "—"} +• Ingress: ${c.ingress ? "вкл" : "выкл"} +• Preset мастер-ноды: ${c.preset_id} +• CPU: ${c.cpu ?? 0}, RAM: ${c.ram ?? 0} МБ, Disk: ${c.disk ?? 0} МБ +• Проект: ${c.project_id ?? "—"} +• Создан: ${new Date(c.created_at).toLocaleString("ru-RU")}`); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения кластера ${params.cluster_id}. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при получении кластера"); + } +}; + +export const getK8sClusterTool = { + name: ToolNames.GET_K8S_CLUSTER, + title: "Информация о Kubernetes-кластере", + description: + "Возвращает детальную информацию о Kubernetes-кластере по его ID: имя, статус, версия, драйвер, ресурсы, зона, ingress.", + inputSchema, + handler, +}; diff --git a/src/tools/get-k8s-kubeconfig.tool.ts b/src/tools/get-k8s-kubeconfig.tool.ts new file mode 100644 index 0000000..1f9172b --- /dev/null +++ b/src/tools/get-k8s-kubeconfig.tool.ts @@ -0,0 +1,35 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { getK8sKubeconfigAction } from "../actions/get-k8s-kubeconfig.action"; + +const inputSchema = { + cluster_id: z.number().int().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID кластера"), +}; + +const handler = async (params: { cluster_id: number }) => { + try { + const config = await getK8sKubeconfigAction(params.cluster_id); + return createToolResponse( + `✅ Kubeconfig кластера ${params.cluster_id}:\n\n${config}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения kubeconfig. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при получении kubeconfig" + ); + } +}; + +export const getK8sKubeconfigTool = { + name: ToolNames.GET_K8S_KUBECONFIG, + title: "Kubeconfig кластера", + description: + "Возвращает содержимое файла kubeconfig для подключения kubectl к кластеру. Содержит секреты — не публиковать.", + inputSchema, + handler, +}; diff --git a/src/tools/get-k8s-node-group.tool.ts b/src/tools/get-k8s-node-group.tool.ts new file mode 100644 index 0000000..984c5c0 --- /dev/null +++ b/src/tools/get-k8s-node-group.tool.ts @@ -0,0 +1,37 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { getK8sNodeGroupAction } from "../actions/get-k8s-node-group.action"; + +const inputSchema = { + cluster_id: z.number().int().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID кластера"), + group_id: z.number().int().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID группы нод"), +}; + +const handler = async (params: { cluster_id: number; group_id: number }) => { + try { + const g = await getK8sNodeGroupAction(params.cluster_id, params.group_id); + return createToolResponse(`📋 Группа нод ID ${g.id} +• Название: ${g.name} +• Preset (мастер): ${g.preset_id} +• Количество нод: ${g.node_count} +• Создана: ${new Date(g.created_at).toLocaleString("ru-RU")}`); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения группы нод. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при получении группы нод" + ); + } +}; + +export const getK8sNodeGroupTool = { + name: ToolNames.GET_K8S_NODE_GROUP, + title: "Информация о группе нод", + description: "Возвращает детальную информацию о группе нод кластера по её ID.", + inputSchema, + handler, +}; diff --git a/src/tools/get-mail-domain-info.tool.ts b/src/tools/get-mail-domain-info.tool.ts new file mode 100644 index 0000000..016c177 --- /dev/null +++ b/src/tools/get-mail-domain-info.tool.ts @@ -0,0 +1,37 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { getMailDomainInfoAction } from "../actions/get-mail-domain-info.action"; + +const inputSchema = { + domain: z.string().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - имя домена"), +}; + +const handler = async (params: { domain: string }) => { + try { + const info = await getMailDomainInfoAction(params.domain); + + return createToolResponse(`📋 Почтовая информация о домене ${params.domain}: + +• Сборный адрес для ошибочных писем: ${info.email || "—"} +• Использованное место: ${info.used} МБ`); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения информации о домене. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при получении информации о домене" + ); + } +}; + +export const getMailDomainInfoTool = { + name: ToolNames.GET_MAIL_DOMAIN_INFO, + title: "Почтовая информация о домене", + description: + "Возвращает почтовую информацию домена: адрес-сборщик для писем на несуществующие ящики и объём используемого места.", + inputSchema, + handler, +}; diff --git a/src/tools/get-mailbox-v1.tool.ts b/src/tools/get-mailbox-v1.tool.ts new file mode 100644 index 0000000..8fe1d93 --- /dev/null +++ b/src/tools/get-mailbox-v1.tool.ts @@ -0,0 +1,49 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { getMailboxV1Action } from "../actions/get-mailbox-v1.action"; + +const inputSchema = { + domain: z + .string() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - имя домена (например: example.com)"), + mailbox: z + .string() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - имя ящика (часть до @)"), +}; + +const handler = async (params: { domain: string; mailbox: string }) => { + try { + const m = await getMailboxV1Action(params.domain, params.mailbox); + + const fullAddress = + m.mailbox && m.fqdn ? `${m.mailbox}@${m.fqdn}` : params.mailbox; + + return createToolResponse(`📋 Почтовый ящик ${fullAddress} (API v1): + +• Комментарий: ${m.comment || "—"} +• Спам-фильтр: ${m.spam_filter?.is_enabled ? "вкл" : "выкл"}, действие: ${m.spam_filter?.action ?? "—"}${m.spam_filter?.forward_to ? `, пересылка на: ${m.spam_filter.forward_to}` : ""} +• Пересылка входящих: ${m.forwarding_incoming?.is_enabled ? "вкл" : "выкл"} → ${m.forwarding_incoming?.incoming_list?.join(", ") || "—"} +• Пересылка исходящих: ${m.forwarding_outgoing?.is_enabled ? "вкл" : "выкл"} → ${m.forwarding_outgoing?.outgoing_to || "—"} +• Автоответчик: ${m.auto_reply?.is_enabled ? "вкл" : "выкл"}${m.auto_reply?.subject ? `, тема: "${m.auto_reply.subject}"` : ""} +• Webmail: ${m.webmail ? "да" : "нет"}`); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения ящика (v1). Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при получении ящика (v1)" + ); + } +}; + +export const getMailboxV1Tool = { + name: ToolNames.GET_MAILBOX_V1, + title: "Получение почтового ящика (API v1)", + description: + "Возвращает данные одного почтового ящика в формате API v1 со структурированными блоками auto_reply/spam_filter/forwarding_*.", + inputSchema, + handler, +}; diff --git a/src/tools/get-mailbox.tool.ts b/src/tools/get-mailbox.tool.ts new file mode 100644 index 0000000..2d8f915 --- /dev/null +++ b/src/tools/get-mailbox.tool.ts @@ -0,0 +1,50 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { getMailboxAction } from "../actions/get-mailbox.action"; + +const inputSchema = { + domain: z + .string() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - имя домена (например: example.com)"), + mailbox: z + .string() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - имя ящика (часть до @)"), +}; + +const handler = async (params: { domain: string; mailbox: string }) => { + try { + const m = await getMailboxAction(params.domain, params.mailbox); + + const fullAddress = + m.mailbox && m.fqdn ? `${m.mailbox}@${m.fqdn}` : params.mailbox; + + return createToolResponse(`📋 Почтовый ящик ${fullAddress}: + +• Домен (IDN): ${m.idn_name} +• ФИО владельца: ${m.owner_full_name || "—"} +• Комментарий: ${m.comment || "—"} +• Спам-фильтр: ${m.filter_status ? "вкл" : "выкл"}, действие: ${m.filter_action} +• Белый список: ${m.white_list.length ? m.white_list.join(", ") : "—"} +• Пересылка входящих: ${m.forward_status ? "вкл" : "выкл"} → ${m.forward_list.length ? m.forward_list.join(", ") : "—"} +• Пересылка исходящих: ${m.outgoing_control ? "вкл" : "выкл"} → ${m.outgoing_email || "—"} +• Автоответчик: ${m.autoreply_status ? "вкл" : "выкл"}${m.autoreply_subject ? `, тема: "${m.autoreply_subject}"` : ""} +• Webmail: ${m.webmail ? "да" : "нет"}, Dovecot: ${m.dovecot ? "да" : "нет"}`); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения ящика. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при получении ящика"); + } +}; + +export const getMailboxTool = { + name: ToolNames.GET_MAILBOX, + title: "Получение почтового ящика", + description: + "Возвращает подробные данные одного почтового ящика (API v2): владелец, спам-фильтр, пересылки, автоответчик, webmail.", + inputSchema, + handler, +}; diff --git a/src/tools/get-network-drive.tool.ts b/src/tools/get-network-drive.tool.ts new file mode 100644 index 0000000..7c8698b --- /dev/null +++ b/src/tools/get-network-drive.tool.ts @@ -0,0 +1,53 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { getNetworkDriveAction } from "../actions/get-network-drive.action"; + +const inputSchema = { + network_drive_id: z + .string() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID сетевого диска (UUID)"), +}; + +const handler = async (params: { network_drive_id: string }) => { + try { + const drive = await getNetworkDriveAction(params.network_drive_id); + + const services = + drive.service_list && drive.service_list.length > 0 + ? drive.service_list + .map((s) => `${s.resource_type}#${s.resource_id}`) + .join(", ") + : "не подключён"; + + return createToolResponse(`📋 Сетевой диск ${drive.id}: + +• Название: ${drive.name} +• Статус: ${drive.status} +• Тип: ${drive.type} +• Размер: ${drive.size} ГБ +• Зона доступности: ${drive.availability_zone} +• Локация: ${drive.location} +• Preset ID: ${drive.preset_id} +• Подключения: ${services} +• Комментарий: ${drive.comment ?? "—"}`); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения сетевого диска ${params.network_drive_id}. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при получении сетевого диска" + ); + } +}; + +export const getNetworkDriveTool = { + name: ToolNames.GET_NETWORK_DRIVE, + title: "Получение сетевого диска", + description: + "Возвращает детальную информацию о конкретном сетевом диске по его ID: имя, статус, тип, размер, зона, локация, preset, подключённые сервисы.", + inputSchema, + handler, +}; diff --git a/src/tools/get-project.tool.ts b/src/tools/get-project.tool.ts new file mode 100644 index 0000000..19ea37c --- /dev/null +++ b/src/tools/get-project.tool.ts @@ -0,0 +1,38 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { getProjectAction } from "../actions/get-project.action"; + +const inputSchema = { + project_id: z.number().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID проекта"), +}; + +const handler = async (params: { project_id: number }) => { + try { + const p = await getProjectAction(params.project_id); + + return createToolResponse( + `📋 Проект ID ${p.id}:\n` + + `• Имя: ${p.name}\n` + + `• Описание: ${p.description || "—"}\n` + + `• По умолчанию: ${p.is_default ? "да" : "нет"}\n` + + `• Аватар: ${p.avatar_id || "—"}\n` + + `• Аккаунт: ${p.account_id}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось получить проект ${params.project_id}. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при получении проекта"); + } +}; + +export const getProjectTool = { + name: ToolNames.GET_PROJECT, + title: "Получение проекта", + description: "Возвращает детальную информацию о проекте по его ID.", + inputSchema, + handler, +}; diff --git a/src/tools/get-server-logs.tool.ts b/src/tools/get-server-logs.tool.ts new file mode 100644 index 0000000..101e9ba --- /dev/null +++ b/src/tools/get-server-logs.tool.ts @@ -0,0 +1,59 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { getServerLogsAction } from "../actions/get-server-logs.action"; + +const inputSchema = { + server_id: z + .number() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID сервера"), + order: z + .enum(["asc", "desc"]) + .default("desc") + .describe( + "НЕ ОБЯЗАТЕЛЬНОЕ ПОЛЕ - порядок сортировки по дате (по умолчанию: desc — сначала новые)" + ), +}; + +const handler = async (params: { + server_id: number; + order?: "asc" | "desc"; +}) => { + try { + const logs = await getServerLogsAction( + params.server_id, + params.order ?? "desc" + ); + + if (logs.length === 0) { + return createToolResponse( + `На сервере ${params.server_id} нет событий в логах.` + ); + } + + const lines = logs + .slice(0, 50) + .map((l) => `• ${l.logged_at} — ${l.event}`); + + const suffix = logs.length > 50 ? `\n\n... и ещё ${logs.length - 50}` : ""; + return createToolResponse( + `Логи сервера ${params.server_id} (${logs.length} событий):\n\n${lines.join("\n")}${suffix}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось получить логи сервера ${params.server_id}. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при получении логов"); + } +}; + +export const getServerLogsTool = { + name: ToolNames.GET_SERVER_LOGS, + title: "Логи событий сервера", + description: + "Возвращает лог жизненного цикла сервера: install, reboot, shutdown, reinstall и пр. Полезно для диагностики (почему сервер сейчас в off, когда последний reinstall). Это НЕ application logs и НЕ syslog — только события уровня гипервизора.", + inputSchema, + handler, +}; diff --git a/src/tools/get-server.tool.ts b/src/tools/get-server.tool.ts new file mode 100644 index 0000000..b0cf001 --- /dev/null +++ b/src/tools/get-server.tool.ts @@ -0,0 +1,46 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { getServerAction } from "../actions/get-server.action"; + +const inputSchema = { + server_id: z + .number() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID сервера (получить через list_servers)"), +}; + +const handler = async (params: { server_id: number }) => { + try { + const server = await getServerAction(params.server_id); + return createToolResponse( + `Сервер ${server.id} — ${server.name}\n\n` + + `Статус: ${server.status}\n` + + `Локация: ${server.location}\n` + + `CPU: ${server.cpu} ядер (${server.cpu_frequency})\n` + + `RAM: ${server.ram} MB\n` + + `ОС: ${server.os?.name ?? "—"} ${server.os?.version ?? ""}\n` + + `IPv4: ${server.main_ipv4 ?? "—"}\n` + + `IPv6: ${server.main_ipv6 ?? "—"}\n` + + `Preset ID: ${server.preset_id ?? "—"}, Configurator ID: ${server.configurator_id ?? "—"}\n` + + `Boot mode: ${server.boot_mode}\n` + + `Создан: ${server.created_at}\n` + + `Комментарий: ${server.comment || "—"}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения сервера ${params.server_id}. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при получении сервера"); + } +}; + +export const getServerTool = { + name: ToolNames.GET_SERVER, + title: "Получение сервера", + description: + "Возвращает детальную информацию по конкретному VPS-серверу: статус, конфигурация CPU/RAM, ОС, IP-адреса, preset/configurator ID. Использовать когда нужны подробности по одному серверу (количество ядер для расчёта нагрузки, текущий статус перед операцией).", + inputSchema, + handler, +}; diff --git a/src/tools/get-ssh-key.tool.ts b/src/tools/get-ssh-key.tool.ts new file mode 100644 index 0000000..e3dee65 --- /dev/null +++ b/src/tools/get-ssh-key.tool.ts @@ -0,0 +1,43 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { getSshKeyAction } from "../actions/get-ssh-key.action"; + +const inputSchema = { + ssh_key_id: z.number().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID SSH-ключа"), +}; + +const handler = async (params: { ssh_key_id: number }) => { + try { + const key = await getSshKeyAction(params.ssh_key_id); + + const usedBy = + key.used_by && key.used_by.length > 0 + ? key.used_by.map((s) => `${s.name} (ID ${s.id})`).join(", ") + : "—"; + + return createToolResponse(`📋 SSH-ключ ID ${key.id}: + +• Название: ${key.name} +• По умолчанию: ${key.is_default ? "✅ Да" : "❌ Нет"} +• Создан: ${new Date(key.created_at).toLocaleString("ru-RU")} +• Используется на серверах: ${usedBy} +• Тело ключа: ${key.body}`); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения SSH-ключа ${params.ssh_key_id}. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при получении SSH-ключа"); + } +}; + +export const getSshKeyTool = { + name: ToolNames.GET_SSH_KEY, + title: "Получение SSH-ключа", + description: + "Возвращает детальную информацию об SSH-ключе по его ID: имя, тело ключа, дата создания, is_default и список серверов, где он используется.", + inputSchema, + handler, +}; diff --git a/src/tools/get-tld.tool.ts b/src/tools/get-tld.tool.ts new file mode 100644 index 0000000..74caf95 --- /dev/null +++ b/src/tools/get-tld.tool.ts @@ -0,0 +1,51 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { getTldAction } from "../actions/tlds.action"; + +const inputSchema = { + tld_id: z.number().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID доменной зоны"), +}; + +const handler = async (params: { tld_id: number }) => { + try { + const t = await getTldAction(params.tld_id); + const periods = + t.allowed_buy_periods && t.allowed_buy_periods.length > 0 + ? t.allowed_buy_periods + .map((p) => ` - ${p.period}: ${p.price} руб.`) + .join("\n") + : " —"; + return createToolResponse(`📋 Доменная зона .${t.name} (ID ${t.id}): +• Цена регистрации: ${t.price ?? "—"} руб. +• Цена продления: ${t.prolong_price ?? "—"} руб. +• Регистратор: ${t.registrar ?? "—"} +• Льготный период: ${t.grace_period ?? "—"} дней +• Досрочное продление: ${t.early_renew_period ?? "—"} дней +• Опубликована: ${t.is_published ? "да" : "нет"} +• Зарегистрирована: ${t.is_registered ? "да" : "нет"} +• Whois privacy управление: ${t.is_whois_privacy_enabled ? "да" : "нет"} +• Whois privacy по умолчанию: ${t.is_whois_privacy_default_enabled ? "да" : "нет"} + +Доступные периоды: +${periods}`); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения доменной зоны ${params.tld_id}. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при получении доменной зоны" + ); + } +}; + +export const getTldTool = { + name: ToolNames.GET_TLD, + title: "Получение доменной зоны по ID", + description: + "Возвращает подробную информацию о доменной зоне (TLD) по её ID: цены, регистратор, льготные периоды, whois privacy.", + inputSchema, + handler, +}; diff --git a/src/tools/get-vpc.tool.ts b/src/tools/get-vpc.tool.ts new file mode 100644 index 0000000..20bbc82 --- /dev/null +++ b/src/tools/get-vpc.tool.ts @@ -0,0 +1,41 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { getVpcAction } from "../actions/get-vpc.action"; + +const inputSchema = { + vpc_id: z.string().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID VPC"), +}; + +const handler = async (params: { vpc_id: string }) => { + try { + const vpc = await getVpcAction(params.vpc_id); + + return createToolResponse(`📋 VPC ${vpc.id} + +• Название: ${vpc.name} +• Описание: ${vpc.description ?? "—"} +• Подсеть IPv4: ${vpc.subnet_v4} +• Локация: ${vpc.location} +• Зона доступности: ${vpc.availability_zone} +• Тип: ${vpc.type} +• Публичный IP: ${vpc.public_ip ?? "—"} +• Занятые адреса: ${vpc.busy_address.length > 0 ? vpc.busy_address.join(", ") : "—"} +• Создана: ${new Date(vpc.created_at).toLocaleString("ru-RU")}`); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка при получении VPC. Причина: ${error.message}` + ); + } + return createToolResponse(`❌ Неизвестная ошибка при получении VPC`); + } +}; + +export const getVpcTool = { + name: ToolNames.GET_VPC, + title: "Получение VPC", + description: "Возвращает детальную информацию о виртуальной приватной сети (VPC) по её ID", + inputSchema, + handler, +}; diff --git a/src/tools/hard-reboot-server.tool.ts b/src/tools/hard-reboot-server.tool.ts new file mode 100644 index 0000000..213f9f7 --- /dev/null +++ b/src/tools/hard-reboot-server.tool.ts @@ -0,0 +1,35 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { hardRebootServerAction } from "../actions/hard-reboot-server.action"; + +const inputSchema = { + server_id: z + .number() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID сервера для принудительной перезагрузки"), +}; + +const handler = async (params: { server_id: number }) => { + try { + await hardRebootServerAction(params.server_id); + return createToolResponse( + `✅ Команда принудительной перезагрузки отправлена для сервера ${params.server_id}.` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось принудительно перезагрузить сервер ${params.server_id}. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка"); + } +}; + +export const hardRebootServerTool = { + name: ToolNames.HARD_REBOOT_SERVER, + title: "Принудительная перезагрузка сервера", + description: + "Принудительно перезагружает сервер (reset power). Использовать когда мягкий reboot_server не помогает (зависшая ОС). Данные в RAM потеряются.", + inputSchema, + handler, +}; diff --git a/src/tools/hard-shutdown-server.tool.ts b/src/tools/hard-shutdown-server.tool.ts new file mode 100644 index 0000000..3e83698 --- /dev/null +++ b/src/tools/hard-shutdown-server.tool.ts @@ -0,0 +1,35 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { hardShutdownServerAction } from "../actions/hard-shutdown-server.action"; + +const inputSchema = { + server_id: z + .number() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID сервера для принудительного выключения"), +}; + +const handler = async (params: { server_id: number }) => { + try { + await hardShutdownServerAction(params.server_id); + return createToolResponse( + `✅ Команда принудительного выключения отправлена для сервера ${params.server_id}. Эквивалент выдёргивания кабеля питания — ОС не успеет корректно завершиться.` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось принудительно выключить сервер ${params.server_id}. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка"); + } +}; + +export const hardShutdownServerTool = { + name: ToolNames.HARD_SHUTDOWN_SERVER, + title: "Принудительное выключение сервера", + description: + "Принудительно выключает сервер (reset power). Использовать только если мягкий shutdown_server завис или не реагирует — данные в RAM и незавершённые write-ы будут потеряны.", + inputSchema, + handler, +}; diff --git a/src/tools/increase-k8s-node-group-nodes.tool.ts b/src/tools/increase-k8s-node-group-nodes.tool.ts new file mode 100644 index 0000000..9e4f038 --- /dev/null +++ b/src/tools/increase-k8s-node-group-nodes.tool.ts @@ -0,0 +1,52 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { increaseK8sNodeGroupNodesAction } from "../actions/increase-k8s-node-group-nodes.action"; + +const inputSchema = { + cluster_id: z.number().int().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID кластера"), + group_id: z.number().int().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID группы нод"), + count: z + .number() + .int() + .min(1) + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - количество добавляемых нод"), + labels: z + .array(z.object({ key: z.string(), value: z.string() })) + .optional() + .describe("Лейблы для добавляемых нод"), +}; + +const handler = async (params: { + cluster_id: number; + group_id: number; + count: number; + labels?: Array<{ key: string; value: string }>; +}) => { + try { + const nodes = await increaseK8sNodeGroupNodesAction( + params.cluster_id, + params.group_id, + { count: params.count, labels: params.labels } + ); + return createToolResponse( + `✅ В группу ${params.group_id} кластера ${params.cluster_id} добавлено ${params.count} нод. Всего в ответе: ${nodes.length}.` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка увеличения количества нод. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при увеличении нод"); + } +}; + +export const increaseK8sNodeGroupNodesTool = { + name: ToolNames.INCREASE_K8S_NODE_GROUP_NODES, + title: "Увеличение количества нод в группе", + description: + "Добавляет указанное количество воркер-нод в группу. Опционально назначает лейблы новым нодам.", + inputSchema, + handler, +}; diff --git a/src/tools/index.ts b/src/tools/index.ts index 4490036..6e25aab 100644 --- a/src/tools/index.ts +++ b/src/tools/index.ts @@ -6,7 +6,240 @@ export { getVcsProviderRepositoriesTool } from "./get-vcs-provider-repositories. export { getVcsProviderByRepositoryUrlTool } from "./get-vcs-provider-by-repository-url.tool"; export { getDeploySettingsTool } from "./get-deploy-settings.tool"; export { createFloatingIpTool } from "./create-floating-ip.tool"; +export { listFloatingIpsTool } from "./list-floating-ips.tool"; +export { getFloatingIpTool } from "./get-floating-ip.tool"; +export { updateFloatingIpTool } from "./update-floating-ip.tool"; +export { deleteFloatingIpTool } from "./delete-floating-ip.tool"; +export { bindFloatingIpTool } from "./bind-floating-ip.tool"; +export { unbindFloatingIpTool } from "./unbind-floating-ip.tool"; export { createVpcTool } from "./create-vpc.tool"; export { getVpcsTool } from "./get-vpcs.tool"; +export { getVpcTool } from "./get-vpc.tool"; +export { updateVpcTool } from "./update-vpc.tool"; +export { deleteVpcTool } from "./delete-vpc.tool"; +export { listVpcServicesTool } from "./list-vpc-services.tool"; +export { listVpcPortsTool } from "./list-vpc-ports.tool"; +export { listApiKeysTool } from "./list-api-keys.tool"; +export { createApiKeyTool } from "./create-api-key.tool"; +export { editApiKeyTool } from "./edit-api-key.tool"; +export { refreshApiKeyTool } from "./refresh-api-key.tool"; +export { deleteApiKeyTool } from "./delete-api-key.tool"; export { createDatabaseTool } from "./create-database.tool"; export { getDatabasePresetsTool } from "./get-database-presets.tool"; +export { listServersTool } from "./list-servers.tool"; +export { getServerTool } from "./get-server.tool"; +export { startServerTool } from "./start-server.tool"; +export { shutdownServerTool } from "./shutdown-server.tool"; +export { hardShutdownServerTool } from "./hard-shutdown-server.tool"; +export { rebootServerTool } from "./reboot-server.tool"; +export { hardRebootServerTool } from "./hard-reboot-server.tool"; +export { cloneServerTool } from "./clone-server.tool"; +export { resizeServerTool } from "./resize-server.tool"; +export { getServerLogsTool } from "./get-server-logs.tool"; +export { listServerDisksTool } from "./list-server-disks.tool"; +export { listServerDiskBackupsTool } from "./list-server-disk-backups.tool"; +export { createServerDiskBackupTool } from "./create-server-disk-backup.tool"; +export { deleteServerDiskBackupTool } from "./delete-server-disk-backup.tool"; +export { getAccountFinancesTool } from "./get-account-finances.tool"; +export { getAccountStatusTool } from "./get-account-status.tool"; +export { getAccountServicesCostTool } from "./get-account-services-cost.tool"; +export { listServerPresetsTool } from "./list-server-presets.tool"; +export { listServerOsTool } from "./list-server-os.tool"; +export { listServerConfiguratorsTool } from "./list-server-configurators.tool"; +export { listServerSoftwareTool } from "./list-server-software.tool"; +export { listLocationsTool } from "./list-locations.tool"; +export { listSshKeysTool } from "./list-ssh-keys.tool"; +export { createSshKeyTool } from "./create-ssh-key.tool"; +export { getSshKeyTool } from "./get-ssh-key.tool"; +export { updateSshKeyTool } from "./update-ssh-key.tool"; +export { deleteSshKeyTool } from "./delete-ssh-key.tool"; +export { addSshKeysToServerTool } from "./add-ssh-keys-to-server.tool"; +export { removeSshKeyFromServerTool } from "./remove-ssh-key-from-server.tool"; +export { listBucketsTool } from "./list-buckets.tool"; +export { createBucketTool } from "./create-bucket.tool"; +export { getBucketTool } from "./get-bucket.tool"; +export { updateBucketTool } from "./update-bucket.tool"; +export { deleteBucketTool } from "./delete-bucket.tool"; +export { getBucketPresetsTool } from "./get-bucket-presets.tool"; +export { listBucketUsersTool } from "./list-bucket-users.tool"; +export { updateBucketUserTool } from "./update-bucket-user.tool"; +export { getBucketTransferStatusTool } from "./get-bucket-transfer-status.tool"; +export { transferBucketTool } from "./transfer-bucket.tool"; +export { listBucketSubdomainsTool } from "./list-bucket-subdomains.tool"; +export { addBucketSubdomainsTool } from "./add-bucket-subdomains.tool"; +export { deleteBucketSubdomainsTool } from "./delete-bucket-subdomains.tool"; +export { addBucketSubdomainCertificateTool } from "./add-bucket-subdomain-certificate.tool"; +export { listDomainsTool } from "./list-domains.tool"; +export { getDomainTool } from "./get-domain.tool"; +export { updateDomainTool } from "./update-domain.tool"; +export { deleteDomainTool } from "./delete-domain.tool"; +export { addDomainTool } from "./add-domain.tool"; +export { checkDomainTool } from "./check-domain.tool"; +export { listDnsRecordsTool } from "./list-dns-records.tool"; +export { listDefaultDnsRecordsTool } from "./list-default-dns-records.tool"; +export { createDnsRecordTool } from "./create-dns-record.tool"; +export { updateDnsRecordTool } from "./update-dns-record.tool"; +export { deleteDnsRecordTool } from "./delete-dns-record.tool"; +export { addSubdomainTool } from "./add-subdomain.tool"; +export { deleteSubdomainTool } from "./delete-subdomain.tool"; +export { getDomainNameServersTool } from "./get-domain-name-servers.tool"; +export { updateDomainNameServersTool } from "./update-domain-name-servers.tool"; +export { listDomainRequestsTool } from "./list-domain-requests.tool"; +export { getDomainRequestTool } from "./get-domain-request.tool"; +export { createDomainRequestTool } from "./create-domain-request.tool"; +export { updateDomainRequestTool } from "./update-domain-request.tool"; +export { listTldsTool } from "./list-tlds.tool"; +export { getTldTool } from "./get-tld.tool"; +export { listImagesTool } from "./list-images.tool"; +export { createImageTool } from "./create-image.tool"; +export { getImageTool } from "./get-image.tool"; +export { updateImageTool } from "./update-image.tool"; +export { deleteImageTool } from "./delete-image.tool"; +export { listImageDownloadsTool } from "./list-image-downloads.tool"; +export { createImageDownloadTool } from "./create-image-download.tool"; +export { getImageDownloadTool } from "./get-image-download.tool"; +export { deleteImageDownloadTool } from "./delete-image-download.tool"; +export { listFirewallGroupsTool } from "./list-firewall-groups.tool"; +export { getFirewallGroupTool } from "./get-firewall-group.tool"; +export { createFirewallGroupTool } from "./create-firewall-group.tool"; +export { updateFirewallGroupTool } from "./update-firewall-group.tool"; +export { deleteFirewallGroupTool } from "./delete-firewall-group.tool"; +export { listFirewallGroupResourcesTool } from "./list-firewall-group-resources.tool"; +export { linkFirewallResourceTool } from "./link-firewall-resource.tool"; +export { unlinkFirewallResourceTool } from "./unlink-firewall-resource.tool"; +export { listFirewallRulesTool } from "./list-firewall-rules.tool"; +export { getFirewallRuleTool } from "./get-firewall-rule.tool"; +export { createFirewallRuleTool } from "./create-firewall-rule.tool"; +export { updateFirewallRuleTool } from "./update-firewall-rule.tool"; +export { deleteFirewallRuleTool } from "./delete-firewall-rule.tool"; +export { listFirewallGroupsByResourceTool } from "./list-firewall-groups-by-resource.tool"; +export { listNetworkDrivesTool } from "./list-network-drives.tool"; +export { getNetworkDriveTool } from "./get-network-drive.tool"; +export { createNetworkDriveTool } from "./create-network-drive.tool"; +export { updateNetworkDriveTool } from "./update-network-drive.tool"; +export { deleteNetworkDriveTool } from "./delete-network-drive.tool"; +export { mountNetworkDriveTool } from "./mount-network-drive.tool"; +export { unmountNetworkDriveTool } from "./unmount-network-drive.tool"; +export { listNetworkDriveAvailableResourcesTool } from "./list-network-drive-available-resources.tool"; +export { listNetworkDrivePresetsTool } from "./list-network-drive-presets.tool"; +export { listProjectsTool } from "./list-projects.tool"; +export { getProjectTool } from "./get-project.tool"; +export { createProjectTool } from "./create-project.tool"; +export { updateProjectTool } from "./update-project.tool"; +export { deleteProjectTool } from "./delete-project.tool"; +export { listProjectResourcesTool } from "./list-project-resources.tool"; +export { listProjectBalancersTool } from "./list-project-balancers.tool"; +export { addBalancerToProjectTool } from "./add-balancer-to-project.tool"; +export { listProjectBucketsTool } from "./list-project-buckets.tool"; +export { addBucketToProjectTool } from "./add-bucket-to-project.tool"; +export { listProjectClustersTool } from "./list-project-clusters.tool"; +export { addClusterToProjectTool } from "./add-cluster-to-project.tool"; +export { listProjectServersTool } from "./list-project-servers.tool"; +export { addServerToProjectTool } from "./add-server-to-project.tool"; +export { listProjectDatabasesTool } from "./list-project-databases.tool"; +export { addDatabaseToProjectTool } from "./add-database-to-project.tool"; +export { listProjectDedicatedTool } from "./list-project-dedicated.tool"; +export { addDedicatedToProjectTool } from "./add-dedicated-to-project.tool"; +export { listAllProjectBalancersTool } from "./list-all-project-balancers.tool"; +export { listAllProjectServersTool } from "./list-all-project-servers.tool"; +export { listAllProjectBucketsTool } from "./list-all-project-buckets.tool"; +export { listAllProjectClustersTool } from "./list-all-project-clusters.tool"; +export { listAllProjectDatabasesTool } from "./list-all-project-databases.tool"; +export { listAllProjectDedicatedTool } from "./list-all-project-dedicated.tool"; +export { transferProjectResourceTool } from "./transfer-project-resource.tool"; +export { listK8sClustersTool } from "./list-k8s-clusters.tool"; +export { createK8sClusterTool } from "./create-k8s-cluster.tool"; +export { getK8sClusterTool } from "./get-k8s-cluster.tool"; +export { deleteK8sClusterTool } from "./delete-k8s-cluster.tool"; +export { editK8sClusterTool } from "./edit-k8s-cluster.tool"; +export { getK8sClusterResourcesTool } from "./get-k8s-cluster-resources.tool"; +export { getK8sKubeconfigTool } from "./get-k8s-kubeconfig.tool"; +export { updateK8sClusterVersionTool } from "./update-k8s-cluster-version.tool"; +export { listK8sNodeGroupsTool } from "./list-k8s-node-groups.tool"; +export { createK8sNodeGroupTool } from "./create-k8s-node-group.tool"; +export { getK8sNodeGroupTool } from "./get-k8s-node-group.tool"; +export { deleteK8sNodeGroupTool } from "./delete-k8s-node-group.tool"; +export { listK8sNodeGroupNodesTool } from "./list-k8s-node-group-nodes.tool"; +export { increaseK8sNodeGroupNodesTool } from "./increase-k8s-node-group-nodes.tool"; +export { reduceK8sNodeGroupNodesTool } from "./reduce-k8s-node-group-nodes.tool"; +export { listK8sClusterNodesTool } from "./list-k8s-cluster-nodes.tool"; +export { deleteK8sClusterNodeTool } from "./delete-k8s-cluster-node.tool"; +export { listK8sVersionsTool } from "./list-k8s-versions.tool"; +export { listK8sNetworkDriversTool } from "./list-k8s-network-drivers.tool"; +export { listK8sPresetsTool } from "./list-k8s-presets.tool"; +export { listK8sAddonConfigsTool } from "./list-k8s-addon-configs.tool"; +export { listK8sAddonsTool } from "./list-k8s-addons.tool"; +export { installK8sAddonTool } from "./install-k8s-addon.tool"; +export { updateK8sAddonTool } from "./update-k8s-addon.tool"; +export { uninstallK8sAddonTool } from "./uninstall-k8s-addon.tool"; +export { listBalancersTool } from "./list-balancers.tool"; +export { getBalancerTool } from "./get-balancer.tool"; +export { createBalancerTool } from "./create-balancer.tool"; +export { updateBalancerTool } from "./update-balancer.tool"; +export { deleteBalancerTool } from "./delete-balancer.tool"; +export { listBalancerIpsTool } from "./list-balancer-ips.tool"; +export { addBalancerIpsTool } from "./add-balancer-ips.tool"; +export { removeBalancerIpsTool } from "./remove-balancer-ips.tool"; +export { listBalancerRulesTool } from "./list-balancer-rules.tool"; +export { createBalancerRuleTool } from "./create-balancer-rule.tool"; +export { updateBalancerRuleTool } from "./update-balancer-rule.tool"; +export { deleteBalancerRuleTool } from "./delete-balancer-rule.tool"; +export { listBalancerPresetsTool } from "./list-balancer-presets.tool"; +export { listContainerRegistriesTool } from "./list-container-registries.tool"; +export { getContainerRegistryTool } from "./get-container-registry.tool"; +export { createContainerRegistryTool } from "./create-container-registry.tool"; +export { updateContainerRegistryTool } from "./update-container-registry.tool"; +export { deleteContainerRegistryTool } from "./delete-container-registry.tool"; +export { listContainerRegistryPresetsTool } from "./list-container-registry-presets.tool"; +export { listContainerRegistryRepositoriesTool } from "./list-container-registry-repositories.tool"; +export { listDedicatedServersTool } from "./list-dedicated-servers.tool"; +export { getDedicatedServerTool } from "./get-dedicated-server.tool"; +export { createDedicatedServerTool } from "./create-dedicated-server.tool"; +export { updateDedicatedServerTool } from "./update-dedicated-server.tool"; +export { deleteDedicatedServerTool } from "./delete-dedicated-server.tool"; +export { listDedicatedServerPresetsTool } from "./list-dedicated-server-presets.tool"; +export { listDedicatedServerAdditionalServicesTool } from "./list-dedicated-server-additional-services.tool"; +export { listMailboxesTool } from "./list-mailboxes.tool"; +export { listMailboxesV1Tool } from "./list-mailboxes-v1.tool"; +export { listMailboxesByDomainTool } from "./list-mailboxes-by-domain.tool"; +export { getMailboxTool } from "./get-mailbox.tool"; +export { getMailboxV1Tool } from "./get-mailbox-v1.tool"; +export { createMailboxTool } from "./create-mailbox.tool"; +export { createMailboxV1Tool } from "./create-mailbox-v1.tool"; +export { batchCreateMailboxesTool } from "./batch-create-mailboxes.tool"; +export { batchCreateMailboxesV1Tool } from "./batch-create-mailboxes-v1.tool"; +export { updateMailboxTool } from "./update-mailbox.tool"; +export { updateMailboxV1Tool } from "./update-mailbox-v1.tool"; +export { deleteMailboxTool } from "./delete-mailbox.tool"; +export { getMailDomainInfoTool } from "./get-mail-domain-info.tool"; +export { updateMailDomainInfoTool } from "./update-mail-domain-info.tool"; +export { addServerIpTool } from "./add-server-ip.tool"; +export { createAiAgentTool } from "./create-ai-agent.tool"; +export { createDatabaseAdminTool } from "./create-database-admin.tool"; +export { createDatabaseInstanceTool } from "./create-database-instance.tool"; +export { createServerTool } from "./create-server.tool"; +export { deleteAiAgentTool } from "./delete-ai-agent.tool"; +export { deleteDatabaseAdminTool } from "./delete-database-admin.tool"; +export { deleteDatabaseClusterTool } from "./delete-database-cluster.tool"; +export { deleteServerIpTool } from "./delete-server-ip.tool"; +export { deleteServerTool } from "./delete-server.tool"; +export { getAiAgentStatisticTool } from "./get-ai-agent-statistic.tool"; +export { getAiAgentTool } from "./get-ai-agent.tool"; +export { getDatabaseAdminTool } from "./get-database-admin.tool"; +export { getDatabaseClusterTool } from "./get-database-cluster.tool"; +export { getDatabaseInstanceTool } from "./get-database-instance.tool"; +export { listAiAgentsTool } from "./list-ai-agents.tool"; +export { listDatabaseAdminsTool } from "./list-database-admins.tool"; +export { listDatabaseClustersTool } from "./list-database-clusters.tool"; +export { listDatabaseInstancesTool } from "./list-database-instances.tool"; +export { listServerIpsTool } from "./list-server-ips.tool"; +export { resetServerPasswordTool } from "./reset-server-password.tool"; +export { setServerBootModeTool } from "./set-server-boot-mode.tool"; +export { setServerNatModeTool } from "./set-server-nat-mode.tool"; +export { unmountServerImageTool } from "./unmount-server-image.tool"; +export { updateAiAgentTool } from "./update-ai-agent.tool"; +export { updateDatabaseAdminTool } from "./update-database-admin.tool"; +export { updateDatabaseClusterTool } from "./update-database-cluster.tool"; +export { updateDatabaseInstanceTool } from "./update-database-instance.tool"; +export { updateServerIpTool } from "./update-server-ip.tool"; +export { updateServerTool } from "./update-server.tool"; diff --git a/src/tools/install-k8s-addon.tool.ts b/src/tools/install-k8s-addon.tool.ts new file mode 100644 index 0000000..ac91540 --- /dev/null +++ b/src/tools/install-k8s-addon.tool.ts @@ -0,0 +1,58 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { installK8sAddonAction } from "../actions/install-k8s-addon.action"; + +const inputSchema = { + cluster_id: z.number().int().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID кластера"), + type: z + .string() + .describe( + "ОБЯЗАТЕЛЬНОЕ ПОЛЕ - тип дополнения (например, ingress, dbaas-operator)" + ), + config_type: z + .enum(["basic", "custom"]) + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - тип конфигурации: basic или custom"), + yaml_config: z + .string() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - YAML-конфигурация дополнения"), + version: z + .string() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - версия дополнения (например, 4.12.1)"), +}; + +const handler = async (params: { + cluster_id: number; + type: string; + config_type: "basic" | "custom"; + yaml_config: string; + version: string; +}) => { + try { + await installK8sAddonAction(params.cluster_id, { + type: params.type, + config_type: params.config_type, + yaml_config: params.yaml_config, + version: params.version, + }); + return createToolResponse( + `✅ Дополнение ${params.type} v${params.version} установлено в кластер ${params.cluster_id}.` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка установки дополнения. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при установке дополнения"); + } +}; + +export const installK8sAddonTool = { + name: ToolNames.INSTALL_K8S_ADDON, + title: "Установка дополнения в кластер", + description: + "Устанавливает дополнение (addon) в кластер. Нужны тип, версия, config_type (basic/custom) и YAML-конфигурация. Каталог доступных дополнений — list_k8s_addon_configs.", + inputSchema, + handler, +}; diff --git a/src/tools/link-firewall-resource.tool.ts b/src/tools/link-firewall-resource.tool.ts new file mode 100644 index 0000000..9f99311 --- /dev/null +++ b/src/tools/link-firewall-resource.tool.ts @@ -0,0 +1,54 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { linkFirewallResourceAction } from "../actions/link-firewall-resource.action"; +import { FirewallResourceType } from "../types/firewall-resource.type"; + +const inputSchema = { + group_id: z + .string() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID группы правил firewall"), + resource_id: z + .string() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID ресурса (например, ID сервера)"), + resource_type: z + .enum(["server"]) + .optional() + .describe("Тип ресурса. По умолчанию: server"), +}; + +const handler = async (params: { + group_id: string; + resource_id: string; + resource_type?: FirewallResourceType; +}) => { + try { + const r = await linkFirewallResourceAction( + params.group_id, + params.resource_id, + params.resource_type + ); + + return createToolResponse( + `✅ Ресурс ${r.type} #${r.id} привязан к группе firewall ${params.group_id}.` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось привязать ресурс ${params.resource_id} к группе ${params.group_id}. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при привязке ресурса к группе firewall" + ); + } +}; + +export const linkFirewallResourceTool = { + name: ToolNames.LINK_FIREWALL_RESOURCE, + title: "Привязка ресурса к группе firewall", + description: + "Привязывает ресурс (сейчас только сервер) к группе правил firewall. После привязки правила группы начинают действовать на ресурс.", + inputSchema, + handler, +}; diff --git a/src/tools/list-ai-agents.tool.ts b/src/tools/list-ai-agents.tool.ts new file mode 100644 index 0000000..85ea258 --- /dev/null +++ b/src/tools/list-ai-agents.tool.ts @@ -0,0 +1,43 @@ +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listAiAgentsAction } from "../actions/list-ai-agents.action"; + +const inputSchema = {}; + +const handler = async () => { + try { + const agents = await listAiAgentsAction(); + + if (agents.length === 0) { + return createToolResponse("AI-агентов на аккаунте нет."); + } + + const lines = agents.map((a) => { + const tokens = + a.total_tokens !== undefined + ? `токены: ${a.used_tokens ?? 0}/${a.total_tokens}` + : ""; + return `• ID ${a.id} — ${a.name}\n статус: ${a.status}, доступ: ${a.access_type}, модель #${a.model_id}${tokens ? `, ${tokens}` : ""}`; + }); + + return createToolResponse( + `AI-агенты (${agents.length}):\n\n${lines.join("\n\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения списка AI-агентов. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при получении агентов"); + } +}; + +export const listAiAgentsTool = { + name: ToolNames.LIST_AI_AGENTS, + title: "Список AI-агентов", + description: + "Возвращает список всех AI-агентов аккаунта: ID, название, статус, тип доступа, ID модели, использование токенов. Используй перед операциями над агентом для получения ID.", + inputSchema, + handler, +}; diff --git a/src/tools/list-all-project-balancers.tool.ts b/src/tools/list-all-project-balancers.tool.ts new file mode 100644 index 0000000..c12d374 --- /dev/null +++ b/src/tools/list-all-project-balancers.tool.ts @@ -0,0 +1,39 @@ +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listAllProjectBalancersAction } from "../actions/list-all-project-balancers.action"; + +const inputSchema = {}; + +const handler = async () => { + try { + const items = await listAllProjectBalancersAction(); + if (items.length === 0) { + return createToolResponse("На аккаунте нет балансировщиков."); + } + const lines = items.map( + (b: any) => + `• ID ${b.id} — ${b.name ?? "без имени"}, проект: ${b.project_id ?? "—"}, статус: ${b.status ?? "—"}` + ); + return createToolResponse( + `Все балансировщики аккаунта (${items.length}):\n${lines.join("\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось получить балансировщики. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при получении балансировщиков" + ); + } +}; + +export const listAllProjectBalancersTool = { + name: ToolNames.LIST_ALL_PROJECT_BALANCERS, + title: "Все балансировщики аккаунта (по проектам)", + description: + "Список всех балансировщиков на аккаунте с привязкой к проекту (project_id). Удобно искать в каком проекте висит ресурс.", + inputSchema, + handler, +}; diff --git a/src/tools/list-all-project-buckets.tool.ts b/src/tools/list-all-project-buckets.tool.ts new file mode 100644 index 0000000..fc74235 --- /dev/null +++ b/src/tools/list-all-project-buckets.tool.ts @@ -0,0 +1,37 @@ +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listAllProjectBucketsAction } from "../actions/list-all-project-buckets.action"; + +const inputSchema = {}; + +const handler = async () => { + try { + const items = await listAllProjectBucketsAction(); + if (items.length === 0) { + return createToolResponse("На аккаунте нет хранилищ."); + } + const lines = items.map( + (b: any) => + `• ID ${b.id} — ${b.name ?? "без имени"}, проект: ${b.project_id ?? "—"}, тип: ${b.type ?? "—"}` + ); + return createToolResponse( + `Все хранилища аккаунта (${items.length}):\n${lines.join("\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось получить хранилища. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при получении хранилищ"); + } +}; + +export const listAllProjectBucketsTool = { + name: ToolNames.LIST_ALL_PROJECT_BUCKETS, + title: "Все хранилища аккаунта (по проектам)", + description: + "Список всех S3-хранилищ аккаунта с привязкой к проекту (project_id).", + inputSchema, + handler, +}; diff --git a/src/tools/list-all-project-clusters.tool.ts b/src/tools/list-all-project-clusters.tool.ts new file mode 100644 index 0000000..3b33d2f --- /dev/null +++ b/src/tools/list-all-project-clusters.tool.ts @@ -0,0 +1,37 @@ +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listAllProjectClustersAction } from "../actions/list-all-project-clusters.action"; + +const inputSchema = {}; + +const handler = async () => { + try { + const items = await listAllProjectClustersAction(); + if (items.length === 0) { + return createToolResponse("На аккаунте нет кластеров."); + } + const lines = items.map( + (c: any) => + `• ID ${c.id} — ${c.name ?? "без имени"}, проект: ${c.project_id ?? "—"}, статус: ${c.status ?? "—"}` + ); + return createToolResponse( + `Все кластеры k8s аккаунта (${items.length}):\n${lines.join("\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось получить кластеры. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при получении кластеров"); + } +}; + +export const listAllProjectClustersTool = { + name: ToolNames.LIST_ALL_PROJECT_CLUSTERS, + title: "Все кластеры k8s аккаунта (по проектам)", + description: + "Список всех Kubernetes-кластеров аккаунта с привязкой к проекту.", + inputSchema, + handler, +}; diff --git a/src/tools/list-all-project-databases.tool.ts b/src/tools/list-all-project-databases.tool.ts new file mode 100644 index 0000000..2a5a495 --- /dev/null +++ b/src/tools/list-all-project-databases.tool.ts @@ -0,0 +1,37 @@ +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listAllProjectDatabasesAction } from "../actions/list-all-project-databases.action"; + +const inputSchema = {}; + +const handler = async () => { + try { + const items = await listAllProjectDatabasesAction(); + if (items.length === 0) { + return createToolResponse("На аккаунте нет баз данных."); + } + const lines = items.map( + (d: any) => + `• ID ${d.id} — ${d.name ?? "без имени"}, проект: ${d.project_id ?? "—"}, тип: ${d.type ?? "—"}, статус: ${d.status ?? "—"}` + ); + return createToolResponse( + `Все БД аккаунта (${items.length}):\n${lines.join("\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось получить БД. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при получении БД"); + } +}; + +export const listAllProjectDatabasesTool = { + name: ToolNames.LIST_ALL_PROJECT_DATABASES, + title: "Все БД аккаунта (по проектам)", + description: + "Список всех managed-БД аккаунта с привязкой к проекту (project_id).", + inputSchema, + handler, +}; diff --git a/src/tools/list-all-project-dedicated.tool.ts b/src/tools/list-all-project-dedicated.tool.ts new file mode 100644 index 0000000..53b0672 --- /dev/null +++ b/src/tools/list-all-project-dedicated.tool.ts @@ -0,0 +1,39 @@ +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listAllProjectDedicatedAction } from "../actions/list-all-project-dedicated.action"; + +const inputSchema = {}; + +const handler = async () => { + try { + const items = await listAllProjectDedicatedAction(); + if (items.length === 0) { + return createToolResponse("На аккаунте нет выделенных серверов."); + } + const lines = items.map( + (d: any) => + `• ID ${d.id} — ${d.name ?? "без имени"}, проект: ${d.project_id ?? "—"}, CPU: ${d.cpu_description ?? "—"}` + ); + return createToolResponse( + `Все выделенные серверы аккаунта (${items.length}):\n${lines.join("\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось получить выделенные серверы. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при получении выделенных серверов" + ); + } +}; + +export const listAllProjectDedicatedTool = { + name: ToolNames.LIST_ALL_PROJECT_DEDICATED, + title: "Все выделенные серверы аккаунта (по проектам)", + description: + "Список всех dedicated-серверов аккаунта с привязкой к проекту.", + inputSchema, + handler, +}; diff --git a/src/tools/list-all-project-servers.tool.ts b/src/tools/list-all-project-servers.tool.ts new file mode 100644 index 0000000..0df5cde --- /dev/null +++ b/src/tools/list-all-project-servers.tool.ts @@ -0,0 +1,37 @@ +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listAllProjectServersAction } from "../actions/list-all-project-servers.action"; + +const inputSchema = {}; + +const handler = async () => { + try { + const items = await listAllProjectServersAction(); + if (items.length === 0) { + return createToolResponse("На аккаунте нет серверов."); + } + const lines = items.map( + (s: any) => + `• ID ${s.id} — ${s.name ?? "без имени"}, проект: ${s.project_id ?? "—"}, статус: ${s.status ?? "—"}` + ); + return createToolResponse( + `Все серверы аккаунта (${items.length}):\n${lines.join("\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось получить серверы. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при получении серверов"); + } +}; + +export const listAllProjectServersTool = { + name: ToolNames.LIST_ALL_PROJECT_SERVERS, + title: "Все серверы аккаунта (по проектам)", + description: + "Список всех VPS аккаунта с привязкой к проекту (project_id). В отличие от list_servers — содержит поле project_id для каждого сервера.", + inputSchema, + handler, +}; diff --git a/src/tools/list-api-keys.tool.ts b/src/tools/list-api-keys.tool.ts new file mode 100644 index 0000000..786f4f9 --- /dev/null +++ b/src/tools/list-api-keys.tool.ts @@ -0,0 +1,47 @@ +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listApiKeysAction } from "../actions/list-api-keys.action"; + +const inputSchema = {}; + +const handler = async () => { + try { + const keys = await listApiKeysAction(); + + if (!keys || keys.length === 0) { + return createToolResponse( + `💡 API-токены не найдены. Создайте первый с помощью tool ${ToolNames.CREATE_API_KEY}` + ); + } + + const lines = keys.map((k) => { + const created = new Date(k.created_at).toLocaleString("ru-RU"); + const expires = k.expired_at + ? new Date(k.expired_at).toLocaleString("ru-RU") + : "без срока"; + return `• ${k.id} — ${k.name} | создан: ${created} | истекает: ${expires} | удаление сервисов: ${k.is_able_to_delete ? "✅" : "❌"}`; + }); + + return createToolResponse( + `📋 API-токены (всего: ${keys.length}):\n${lines.join("\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка при получении списка API-токенов. Причина: ${error.message}` + ); + } + return createToolResponse( + `❌ Неизвестная ошибка при получении списка API-токенов` + ); + } +}; + +export const listApiKeysTool = { + name: ToolNames.LIST_API_KEYS, + title: "Список API-токенов", + description: + "Возвращает список всех выпущенных API-токенов аккаунта с их ID, именами и сроком жизни", + inputSchema, + handler, +}; diff --git a/src/tools/list-balancer-ips.tool.ts b/src/tools/list-balancer-ips.tool.ts new file mode 100644 index 0000000..24e6892 --- /dev/null +++ b/src/tools/list-balancer-ips.tool.ts @@ -0,0 +1,46 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listBalancerIpsAction } from "../actions/list-balancer-ips.action"; + +const inputSchema = { + balancer_id: z + .number() + .int() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID балансировщика"), +}; + +const handler = async (params: { balancer_id: number }) => { + try { + const ips = await listBalancerIpsAction(params.balancer_id); + + if (ips.length === 0) { + return createToolResponse( + `Балансировщик ${params.balancer_id}: привязанных backend-IP нет.` + ); + } + + const lines = ips.map((ip) => `• ${ip}`); + return createToolResponse( + `IP-адреса балансировщика ${params.balancer_id} (${ips.length}):\n${lines.join("\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения IP балансировщика ${params.balancer_id}. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при получении IP балансировщика" + ); + } +}; + +export const listBalancerIpsTool = { + name: ToolNames.LIST_BALANCER_IPS, + title: "IP-адреса балансировщика", + description: + "Получает список backend IP-адресов, привязанных к балансировщику (на эти IP распределяется трафик).", + inputSchema, + handler, +}; diff --git a/src/tools/list-balancer-presets.tool.ts b/src/tools/list-balancer-presets.tool.ts new file mode 100644 index 0000000..20849a3 --- /dev/null +++ b/src/tools/list-balancer-presets.tool.ts @@ -0,0 +1,42 @@ +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listBalancerPresetsAction } from "../actions/list-balancer-presets.action"; + +const inputSchema = {}; + +const handler = async () => { + try { + const presets = await listBalancerPresetsAction(); + + if (presets.length === 0) { + return createToolResponse("Тарифы для балансировщиков не найдены."); + } + + const lines = presets.map( + (p) => + `• ID ${p.id} — ${p.description_short}\n ${p.description}\n Пропускная способность: ${p.bandwidth}, реплик: ${p.replica_count}, RPS: ${p.request_per_second}, локация: ${p.location}\n Цена: ${p.price}` + ); + + return createToolResponse( + `Тарифы для балансировщиков (${presets.length}):\n\n${lines.join("\n\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения тарифов балансировщиков. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при получении тарифов балансировщиков" + ); + } +}; + +export const listBalancerPresetsTool = { + name: ToolNames.LIST_BALANCER_PRESETS, + title: "Тарифы балансировщиков", + description: + "Возвращает список доступных тарифов (preset) для балансировщиков. Используй перед create_balancer, чтобы выбрать preset_id.", + inputSchema, + handler, +}; diff --git a/src/tools/list-balancer-rules.tool.ts b/src/tools/list-balancer-rules.tool.ts new file mode 100644 index 0000000..31c3266 --- /dev/null +++ b/src/tools/list-balancer-rules.tool.ts @@ -0,0 +1,50 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listBalancerRulesAction } from "../actions/list-balancer-rules.action"; + +const inputSchema = { + balancer_id: z + .number() + .int() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID балансировщика"), +}; + +const handler = async (params: { balancer_id: number }) => { + try { + const rules = await listBalancerRulesAction(params.balancer_id); + + if (rules.length === 0) { + return createToolResponse( + `У балансировщика ${params.balancer_id} нет правил.` + ); + } + + const lines = rules.map( + (r) => + `• ID ${r.id}: ${r.balancer_proto}:${r.balancer_port} → ${r.server_proto}:${r.server_port}` + ); + + return createToolResponse( + `Правила балансировщика ${params.balancer_id} (${rules.length}):\n${lines.join("\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения правил балансировщика ${params.balancer_id}. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при получении правил балансировщика" + ); + } +}; + +export const listBalancerRulesTool = { + name: ToolNames.LIST_BALANCER_RULES, + title: "Правила балансировщика", + description: + "Возвращает список правил балансировщика — соответствий между портом балансировщика и портом backend-сервера.", + inputSchema, + handler, +}; diff --git a/src/tools/list-balancers.tool.ts b/src/tools/list-balancers.tool.ts new file mode 100644 index 0000000..46f3cf2 --- /dev/null +++ b/src/tools/list-balancers.tool.ts @@ -0,0 +1,56 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listBalancersAction } from "../actions/list-balancers.action"; + +const inputSchema = { + limit: z + .number() + .int() + .positive() + .optional() + .describe("Лимит (опц.) — количество элементов на страницу"), + offset: z + .number() + .int() + .nonnegative() + .optional() + .describe("Смещение (опц.) — с какого элемента начать"), +}; + +const handler = async (params: { limit?: number; offset?: number }) => { + try { + const balancers = await listBalancersAction(params.limit, params.offset); + + if (balancers.length === 0) { + return createToolResponse("На аккаунте нет балансировщиков."); + } + + const lines = balancers.map( + (b) => + `• ID ${b.id} — ${b.name}\n статус: ${b.status}, протокол: ${b.proto}, порт: ${b.port}, алгоритм: ${b.algo}\n IP: ${b.ip ?? "—"}, локация: ${b.location}, зона: ${b.availability_zone}\n правил: ${b.rules?.length ?? 0}, привязанных IP: ${b.ips?.length ?? 0}` + ); + + return createToolResponse( + `Балансировщики (${balancers.length}):\n\n${lines.join("\n\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения списка балансировщиков. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при получении балансировщиков" + ); + } +}; + +export const listBalancersTool = { + name: ToolNames.LIST_BALANCERS, + title: "Список балансировщиков", + description: + "Возвращает все балансировщики нагрузки аккаунта с ключевыми параметрами: ID, имя, статус, протокол, порт, алгоритм, IP, локация. Используй перед любыми операциями над балансировщиком, чтобы получить его ID.", + inputSchema, + handler, +}; diff --git a/src/tools/list-bucket-subdomains.tool.ts b/src/tools/list-bucket-subdomains.tool.ts new file mode 100644 index 0000000..2151ca8 --- /dev/null +++ b/src/tools/list-bucket-subdomains.tool.ts @@ -0,0 +1,47 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listBucketSubdomainsAction } from "../actions/list-bucket-subdomains.action"; + +const inputSchema = { + bucket_id: z.number().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID S3-хранилища"), +}; + +const handler = async (params: { bucket_id: number }) => { + try { + const subdomains = await listBucketSubdomainsAction(params.bucket_id); + + if (subdomains.length === 0) { + return createToolResponse( + `У хранилища ${params.bucket_id} нет поддоменов.` + ); + } + + const lines = subdomains.map( + (s) => + `• ID ${s.id} — ${s.subdomain}\n SSL статус: ${s.status}, попыток: ${s.tries}\n Сертификат выдан: ${s.cert_released ? new Date(s.cert_released).toLocaleString("ru-RU") : "—"}` + ); + + return createToolResponse( + `Поддомены хранилища ${params.bucket_id} (${subdomains.length}):\n\n${lines.join("\n\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения поддоменов хранилища ${params.bucket_id}. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при получении поддоменов хранилища" + ); + } +}; + +export const listBucketSubdomainsTool = { + name: ToolNames.LIST_BUCKET_SUBDOMAINS, + title: "Список поддоменов S3-хранилища", + description: + "Возвращает все поддомены, привязанные к S3-хранилищу: id, subdomain, статус SSL (ssl_released, ssl_not_requested, ssl_re_release_error), когда выдан сертификат, количество попыток перевыпуска.", + inputSchema, + handler, +}; diff --git a/src/tools/list-bucket-users.tool.ts b/src/tools/list-bucket-users.tool.ts new file mode 100644 index 0000000..d0e56fe --- /dev/null +++ b/src/tools/list-bucket-users.tool.ts @@ -0,0 +1,41 @@ +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listBucketUsersAction } from "../actions/list-bucket-users.action"; + +const inputSchema = {}; + +const handler = async () => { + try { + const users = await listBucketUsersAction(); + + if (users.length === 0) { + return createToolResponse("Пользователей S3-хранилищ нет."); + } + + const lines = users.map( + (u) => `• ID ${u.id} — access_key: ${u.access_key}` + ); + + return createToolResponse( + `Пользователи S3-хранилищ (${users.length}):\n\n${lines.join("\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения пользователей S3-хранилищ. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при получении пользователей S3-хранилищ" + ); + } +}; + +export const listBucketUsersTool = { + name: ToolNames.LIST_BUCKET_USERS, + title: "Список пользователей S3-хранилищ", + description: + "Возвращает всех пользователей-администраторов S3-хранилищ аккаунта: id и access_key. secret_key может быть в ответе, но на практике его безопаснее обновлять через update_bucket_user.", + inputSchema, + handler, +}; diff --git a/src/tools/list-buckets.tool.ts b/src/tools/list-buckets.tool.ts new file mode 100644 index 0000000..9a1c837 --- /dev/null +++ b/src/tools/list-buckets.tool.ts @@ -0,0 +1,45 @@ +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listBucketsAction } from "../actions/list-buckets.action"; + +const inputSchema = {}; + +const handler = async () => { + try { + const buckets = await listBucketsAction(); + + if (buckets.length === 0) { + return createToolResponse("На аккаунте нет S3-хранилищ."); + } + + const lines = buckets.map((b) => { + const sizeGb = b.disk_stats.is_unlimited + ? "безлимитно" + : `${(b.disk_stats.size / 1024 / 1024).toFixed(2)} ГБ`; + const usedGb = `${(b.disk_stats.used / 1024 / 1024).toFixed(2)} ГБ`; + return `• ID ${b.id} — ${b.name}\n тип: ${b.type}, статус: ${b.status}, класс: ${b.storage_class}\n локация: ${b.location}, hostname: ${b.hostname}\n объектов: ${b.object_amount}, использовано: ${usedGb} / ${sizeGb}`; + }); + + return createToolResponse( + `S3-хранилища (${buckets.length}):\n\n${lines.join("\n\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения списка S3-хранилищ. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при получении S3-хранилищ" + ); + } +}; + +export const listBucketsTool = { + name: ToolNames.LIST_BUCKETS, + title: "Список S3-хранилищ", + description: + "Возвращает все S3-хранилища аккаунта с id, name, type (private/public), статусом, классом (cold/hot), локацией, hostname, использованием диска. Используй перед любой операцией над хранилищем, чтобы получить его ID.", + inputSchema, + handler, +}; diff --git a/src/tools/list-container-registries.tool.ts b/src/tools/list-container-registries.tool.ts new file mode 100644 index 0000000..c3db096 --- /dev/null +++ b/src/tools/list-container-registries.tool.ts @@ -0,0 +1,42 @@ +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listContainerRegistriesAction } from "../actions/list-container-registries.action"; + +const inputSchema = {}; + +const handler = async () => { + try { + const registries = await listContainerRegistriesAction(); + + if (registries.length === 0) { + return createToolResponse("На аккаунте нет реестров контейнеров."); + } + + const lines = registries.map( + (r) => + `• ID ${r.id} — ${r.name}\n описание: ${r.description || "—"}, preset: ${r.preset_id}, проект: ${r.project_id}\n диск: ${r.disk_stats.used}/${r.disk_stats.size} ГБ, создан: ${new Date(r.created_at).toLocaleString("ru-RU")}` + ); + + return createToolResponse( + `Реестры контейнеров (${registries.length}):\n\n${lines.join("\n\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения списка реестров контейнеров. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при получении реестров контейнеров" + ); + } +}; + +export const listContainerRegistriesTool = { + name: ToolNames.LIST_CONTAINER_REGISTRIES, + title: "Список реестров контейнеров", + description: + "Возвращает список всех реестров контейнеров (Container Registry) аккаунта: ID, имя, описание, тариф, использование диска, дата создания. Используй перед операциями над реестром, чтобы получить его ID.", + inputSchema, + handler, +}; diff --git a/src/tools/list-container-registry-presets.tool.ts b/src/tools/list-container-registry-presets.tool.ts new file mode 100644 index 0000000..22f2de5 --- /dev/null +++ b/src/tools/list-container-registry-presets.tool.ts @@ -0,0 +1,42 @@ +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listContainerRegistryPresetsAction } from "../actions/list-container-registry-presets.action"; + +const inputSchema = {}; + +const handler = async () => { + try { + const presets = await listContainerRegistryPresetsAction(); + + if (presets.length === 0) { + return createToolResponse("Тарифы реестров контейнеров не найдены."); + } + + const lines = presets.map( + (p) => + `• ID ${p.id} — ${p.description_short}\n диск: ${p.disk} ГБ, цена: ${p.price} руб, локация: ${p.location ?? "—"}\n описание: ${p.description}` + ); + + return createToolResponse( + `Тарифы реестров контейнеров (${presets.length}):\n\n${lines.join("\n\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения тарифов реестров. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при получении тарифов реестров" + ); + } +}; + +export const listContainerRegistryPresetsTool = { + name: ToolNames.LIST_CONTAINER_REGISTRY_PRESETS, + title: "Список тарифов реестров контейнеров", + description: + "Возвращает список доступных тарифов для реестров контейнеров (Container Registry): ID, описание, размер диска, цена, локация. Используй перед create_container_registry, чтобы выбрать preset_id.", + inputSchema, + handler, +}; diff --git a/src/tools/list-container-registry-repositories.tool.ts b/src/tools/list-container-registry-repositories.tool.ts new file mode 100644 index 0000000..60fdf67 --- /dev/null +++ b/src/tools/list-container-registry-repositories.tool.ts @@ -0,0 +1,53 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listContainerRegistryRepositoriesAction } from "../actions/list-container-registry-repositories.action"; + +const inputSchema = { + registry_id: z + .number() + .describe( + "ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID реестра (получить через list_container_registries)" + ), +}; + +const handler = async (params: { registry_id: number }) => { + try { + const repos = await listContainerRegistryRepositoriesAction( + params.registry_id + ); + + if (repos.length === 0) { + return createToolResponse( + `В реестре ${params.registry_id} нет репозиториев.` + ); + } + + const lines = repos.map( + (r) => + `• ${r.name}\n тег: ${r.tags.tag}, размер: ${r.tags.size} байт\n digest: ${r.tags.digest}` + ); + + return createToolResponse( + `Репозитории реестра ${params.registry_id} (${repos.length}):\n\n${lines.join("\n\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения репозиториев реестра ${params.registry_id}. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при получении репозиториев" + ); + } +}; + +export const listContainerRegistryRepositoriesTool = { + name: ToolNames.LIST_CONTAINER_REGISTRY_REPOSITORIES, + title: "Список репозиториев реестра контейнеров", + description: + "Возвращает список репозиториев (образов) внутри конкретного реестра контейнеров: имя репозитория, тег, digest, размер. Используй чтобы посмотреть, какие образы уже загружены в реестр.", + inputSchema, + handler, +}; diff --git a/src/tools/list-database-admins.tool.ts b/src/tools/list-database-admins.tool.ts new file mode 100644 index 0000000..6888df7 --- /dev/null +++ b/src/tools/list-database-admins.tool.ts @@ -0,0 +1,51 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listDatabaseAdminsAction } from "../actions/list-database-admins.action"; + +const inputSchema = { + db_cluster_id: z + .number() + .int() + .positive() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID кластера базы данных"), +}; + +const handler = async (params: { db_cluster_id: number }) => { + try { + const admins = await listDatabaseAdminsAction(params.db_cluster_id); + + if (admins.length === 0) { + return createToolResponse( + `В кластере ${params.db_cluster_id} нет пользователей базы данных.` + ); + } + + const lines = admins.map( + (a) => + `• ID ${a.id} — ${a.login}\n хост: ${a.host ?? "—"}, инстансов: ${a.instances?.length ?? 0}, описание: ${a.description || "—"}` + ); + + return createToolResponse( + `Пользователи кластера ${params.db_cluster_id} (${admins.length}):\n\n${lines.join("\n\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения пользователей кластера ${params.db_cluster_id}. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при получении пользователей кластера" + ); + } +}; + +export const listDatabaseAdminsTool = { + name: ToolNames.LIST_DATABASE_ADMINS, + title: "Список пользователей кластера базы данных", + description: + "Возвращает список пользователей (admins) кластера базы данных (`GET /api/v1/databases/{db_cluster_id}/admins`).", + inputSchema, + handler, +}; diff --git a/src/tools/list-database-clusters.tool.ts b/src/tools/list-database-clusters.tool.ts new file mode 100644 index 0000000..8c6c5f3 --- /dev/null +++ b/src/tools/list-database-clusters.tool.ts @@ -0,0 +1,59 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listDatabaseClustersAction } from "../actions/list-database-clusters.action"; + +const inputSchema = { + limit: z + .number() + .int() + .positive() + .optional() + .describe("НЕ ОБЯЗАТЕЛЬНОЕ ПОЛЕ - лимит записей в ответе"), + offset: z + .number() + .int() + .nonnegative() + .optional() + .describe("НЕ ОБЯЗАТЕЛЬНОЕ ПОЛЕ - смещение"), +}; + +const handler = async (params: { limit?: number; offset?: number }) => { + try { + const clusters = await listDatabaseClustersAction( + params.limit, + params.offset + ); + + if (clusters.length === 0) { + return createToolResponse("На аккаунте нет кластеров баз данных."); + } + + const lines = clusters.map( + (c) => + `• ID ${c.id} — ${c.name}\n тип: ${c.type}, статус: ${c.status}, локация: ${c.location ?? "—"}, preset: ${c.preset_id}, port: ${c.port ?? "—"}` + ); + + return createToolResponse( + `Кластеры баз данных (${clusters.length}):\n\n${lines.join("\n\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения списка кластеров. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при получении кластеров баз данных" + ); + } +}; + +export const listDatabaseClustersTool = { + name: ToolNames.LIST_DATABASE_CLUSTERS, + title: "Список кластеров баз данных", + description: + "Возвращает список кластеров баз данных аккаунта (`GET /api/v1/databases`). Используй перед операциями над кластером, чтобы получить его ID.", + inputSchema, + handler, +}; diff --git a/src/tools/list-database-instances.tool.ts b/src/tools/list-database-instances.tool.ts new file mode 100644 index 0000000..8943b87 --- /dev/null +++ b/src/tools/list-database-instances.tool.ts @@ -0,0 +1,51 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listDatabaseInstancesAction } from "../actions/list-database-instances.action"; + +const inputSchema = { + db_cluster_id: z + .number() + .int() + .positive() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID кластера базы данных"), +}; + +const handler = async (params: { db_cluster_id: number }) => { + try { + const instances = await listDatabaseInstancesAction(params.db_cluster_id); + + if (instances.length === 0) { + return createToolResponse( + `В кластере ${params.db_cluster_id} нет инстансов баз данных.` + ); + } + + const lines = instances.map( + (i) => + `• ID ${i.id} — ${i.name}\n описание: ${i.description || "—"}, создан: ${new Date(i.created_at).toLocaleString("ru-RU")}` + ); + + return createToolResponse( + `Инстансы баз данных в кластере ${params.db_cluster_id} (${instances.length}):\n\n${lines.join("\n\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения инстансов кластера ${params.db_cluster_id}. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при получении инстансов кластера" + ); + } +}; + +export const listDatabaseInstancesTool = { + name: ToolNames.LIST_DATABASE_INSTANCES, + title: "Список инстансов кластера", + description: + "Возвращает список инстансов (баз данных внутри кластера) (`GET /api/v1/databases/{db_cluster_id}/instances`).", + inputSchema, + handler, +}; diff --git a/src/tools/list-dedicated-server-additional-services.tool.ts b/src/tools/list-dedicated-server-additional-services.tool.ts new file mode 100644 index 0000000..b25c0f5 --- /dev/null +++ b/src/tools/list-dedicated-server-additional-services.tool.ts @@ -0,0 +1,53 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listDedicatedServerAdditionalServicesAction } from "../actions/list-dedicated-server-additional-services.action"; + +const inputSchema = { + preset_id: z + .number() + .describe( + "ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID тарифа выделенного сервера (получить через list_dedicated_server_presets)" + ), +}; + +const handler = async (params: { preset_id: number }) => { + try { + const services = await listDedicatedServerAdditionalServicesAction( + params.preset_id + ); + + if (services.length === 0) { + return createToolResponse( + `Для тарифа ${params.preset_id} нет дополнительных услуг.` + ); + } + + const lines = services.map( + (s) => + `• ID ${s.id} — ${s.short_description}\n имя: ${s.name}, цена: ${s.price} руб, период: ${s.period}\n описание: ${s.description}` + ); + + return createToolResponse( + `Дополнительные услуги для тарифа ${params.preset_id} (${services.length}):\n\n${lines.join("\n\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения дополнительных услуг для тарифа ${params.preset_id}. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при получении дополнительных услуг" + ); + } +}; + +export const listDedicatedServerAdditionalServicesTool = { + name: ToolNames.LIST_DEDICATED_SERVER_ADDITIONAL_SERVICES, + title: "Дополнительные услуги выделенного сервера", + description: + "Возвращает список дополнительных услуг для конкретного тарифа выделенного сервера (plan_id): ID, имя, цена, период, описание. Используй, чтобы узнать plan_id для передачи в create_dedicated_server.", + inputSchema, + handler, +}; diff --git a/src/tools/list-dedicated-server-presets.tool.ts b/src/tools/list-dedicated-server-presets.tool.ts new file mode 100644 index 0000000..38ef322 --- /dev/null +++ b/src/tools/list-dedicated-server-presets.tool.ts @@ -0,0 +1,57 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listDedicatedServerPresetsAction } from "../actions/list-dedicated-server-presets.action"; +import { DedicatedServerLocation } from "../types/dedicated-server.type"; + +const locations = ["ru-1", "ru-2", "kz-1", "pl-1"] as const; + +const inputSchema = { + location: z + .enum(locations) + .optional() + .describe( + "Фильтр по локации: ru-1, ru-2, kz-1, pl-1. Если не указан — возвращаются все тарифы." + ), +}; + +const handler = async (params: { location?: DedicatedServerLocation }) => { + try { + const presets = await listDedicatedServerPresetsAction(params.location); + + if (presets.length === 0) { + return createToolResponse( + params.location + ? `Тарифы выделенных серверов для локации ${params.location} не найдены.` + : "Тарифы выделенных серверов не найдены." + ); + } + + const lines = presets.map( + (p) => + `• ID ${p.id} — ${p.description}\n CPU: ${p.cpu?.description_short ?? "—"}${p.cpu?.count ? ` (${p.cpu.count} ядер)` : ""}\n IPMI: ${p.is_ipmi_enabled ? "да" : "нет"}, pre-installed: ${p.is_pre_installed ? "да" : "нет"}` + ); + + return createToolResponse( + `Тарифы выделенных серверов${params.location ? ` (${params.location})` : ""} — всего ${presets.length}:\n\n${lines.join("\n\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения тарифов выделенных серверов. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при получении тарифов выделенных серверов" + ); + } +}; + +export const listDedicatedServerPresetsTool = { + name: ToolNames.LIST_DEDICATED_SERVER_PRESETS, + title: "Список тарифов выделенных серверов", + description: + "Возвращает список доступных тарифов (presets) для выделенных серверов: ID, описание, CPU, IPMI-поддержка, pre-installed. Опциональный фильтр по локации (ru-1/ru-2/kz-1/pl-1). Используй перед create_dedicated_server, чтобы выбрать preset_id.", + inputSchema, + handler, +}; diff --git a/src/tools/list-dedicated-servers.tool.ts b/src/tools/list-dedicated-servers.tool.ts new file mode 100644 index 0000000..1d7f320 --- /dev/null +++ b/src/tools/list-dedicated-servers.tool.ts @@ -0,0 +1,42 @@ +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listDedicatedServersAction } from "../actions/list-dedicated-servers.action"; + +const inputSchema = {}; + +const handler = async () => { + try { + const servers = await listDedicatedServersAction(); + + if (servers.length === 0) { + return createToolResponse("На аккаунте нет выделенных серверов."); + } + + const lines = servers.map( + (s) => + `• ID ${s.id} — ${s.name}\n статус: ${s.status}, локация: ${s.location}, preset: ${s.preset_id}\n CPU: ${s.cpu_description}, RAM: ${s.ram_description}, HDD: ${s.hdd_description}\n IPv4: ${s.ip ?? "—"}, IPv6: ${s.ipv6 ?? "—"}, цена: ${s.price} руб` + ); + + return createToolResponse( + `Выделенные серверы (${servers.length}):\n\n${lines.join("\n\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения списка выделенных серверов. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при получении выделенных серверов" + ); + } +}; + +export const listDedicatedServersTool = { + name: ToolNames.LIST_DEDICATED_SERVERS, + title: "Список выделенных серверов", + description: + "Возвращает список всех выделенных (dedicated) серверов аккаунта: ID, имя, статус (installing/installed/on/off), локация, CPU/RAM/HDD описания, IPv4/IPv6, цена. Используй перед операциями над выделенным сервером, чтобы получить его ID.", + inputSchema, + handler, +}; diff --git a/src/tools/list-default-dns-records.tool.ts b/src/tools/list-default-dns-records.tool.ts new file mode 100644 index 0000000..1caa8bf --- /dev/null +++ b/src/tools/list-default-dns-records.tool.ts @@ -0,0 +1,44 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listDefaultDnsRecordsAction } from "../actions/list-default-dns-records.action"; + +const inputSchema = { + fqdn: z.string().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - полное имя домена"), +}; + +const handler = async (params: { fqdn: string }) => { + try { + const records = await listDefaultDnsRecordsAction(params.fqdn); + if (records.length === 0) { + return createToolResponse( + `У домена ${params.fqdn} нет DNS-записей по умолчанию.` + ); + } + const lines = records.map( + (r) => + `• ${r.type}: ${r.data.value ?? "—"} (TTL: ${r.ttl ?? "default"}${r.data.subdomain ? `, поддомен: ${r.data.subdomain}` : ""})` + ); + return createToolResponse( + `DNS-записи по умолчанию для ${params.fqdn} (${records.length}):\n\n${lines.join("\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения DNS-записей по умолчанию для "${params.fqdn}". Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при получении DNS-записей по умолчанию" + ); + } +}; + +export const listDefaultDnsRecordsTool = { + name: ToolNames.LIST_DEFAULT_DNS_RECORDS, + title: "DNS-записи домена по умолчанию", + description: + "Возвращает список DNS-записей по умолчанию для домена или поддомена (системные записи Timeweb).", + inputSchema, + handler, +}; diff --git a/src/tools/list-dns-records.tool.ts b/src/tools/list-dns-records.tool.ts new file mode 100644 index 0000000..e61979b --- /dev/null +++ b/src/tools/list-dns-records.tool.ts @@ -0,0 +1,46 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listDnsRecordsAction } from "../actions/list-dns-records.action"; + +const inputSchema = { + fqdn: z.string().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - полное имя домена"), +}; + +const handler = async (params: { fqdn: string }) => { + try { + const records = await listDnsRecordsAction(params.fqdn); + if (records.length === 0) { + return createToolResponse( + `У домена ${params.fqdn} нет пользовательских DNS-записей.` + ); + } + const lines = records.map((r) => { + const parts: string[] = []; + if (r.data.subdomain) parts.push(`поддомен: ${r.data.subdomain}`); + if (r.data.priority !== undefined) + parts.push(`priority: ${r.data.priority}`); + const extra = parts.length ? `, ${parts.join(", ")}` : ""; + return `• ID ${r.id ?? "—"} — ${r.type}: ${r.data.value ?? "—"} (TTL: ${r.ttl ?? "default"}${extra})`; + }); + return createToolResponse( + `DNS-записи домена ${params.fqdn} (${records.length}):\n\n${lines.join("\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения DNS-записей домена "${params.fqdn}". Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при получении DNS-записей"); + } +}; + +export const listDnsRecordsTool = { + name: ToolNames.LIST_DNS_RECORDS, + title: "Список DNS-записей домена", + description: + "Возвращает все пользовательские DNS-записи домена: ID, тип (A/AAAA/CNAME/MX/TXT/SRV), значение, TTL, поддомен, priority.", + inputSchema, + handler, +}; diff --git a/src/tools/list-domain-requests.tool.ts b/src/tools/list-domain-requests.tool.ts new file mode 100644 index 0000000..6e89180 --- /dev/null +++ b/src/tools/list-domain-requests.tool.ts @@ -0,0 +1,36 @@ +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listDomainRequestsAction } from "../actions/domain-requests.action"; + +const inputSchema = {}; + +const handler = async () => { + try { + const requests = await listDomainRequestsAction(); + if (requests.length === 0) { + return createToolResponse("Заявок на регистрацию/продление/трансфер нет."); + } + const lines = requests.map((r) => { + return `• ID ${r.id} — ${r.fqdn}\n тип: ${r.type ?? "—"}, статус: ${r.status ?? "—"}, источник оплаты: ${r.money_source ?? "—"}, дата: ${r.date ?? "—"}`; + }); + return createToolResponse( + `Заявки на домены (${requests.length}):\n\n${lines.join("\n\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения списка заявок. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при получении заявок"); + } +}; + +export const listDomainRequestsTool = { + name: ToolNames.LIST_DOMAIN_REQUESTS, + title: "Список заявок на регистрацию/продление/трансфер доменов", + description: + "Возвращает все заявки пользователя на операции с доменами: регистрация, продление, трансфер. Включает ID, FQDN, тип, статус, источник оплаты.", + inputSchema, + handler, +}; diff --git a/src/tools/list-domains.tool.ts b/src/tools/list-domains.tool.ts new file mode 100644 index 0000000..8393d87 --- /dev/null +++ b/src/tools/list-domains.tool.ts @@ -0,0 +1,40 @@ +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listDomainsAction } from "../actions/list-domains.action"; + +const inputSchema = {}; + +const handler = async () => { + try { + const domains = await listDomainsAction(); + + if (domains.length === 0) { + return createToolResponse("На аккаунте нет доменов."); + } + + const lines = domains.map((d) => { + const autoprolong = d.is_autoprolong_enabled ? "да" : "нет"; + return `• ID ${d.id} — ${d.fqdn}\n статус: ${d.domain_status}, истекает: ${d.expiration}, дней осталось: ${d.days_left ?? "—"}\n автопродление: ${autoprolong}, premium: ${d.is_premium ? "да" : "нет"}`; + }); + + return createToolResponse( + `Домены (${domains.length}):\n\n${lines.join("\n\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения списка доменов. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при получении доменов"); + } +}; + +export const listDomainsTool = { + name: ToolNames.LIST_DOMAINS, + title: "Список доменов", + description: + "Возвращает список всех доменов аккаунта с ключевыми параметрами: ID, FQDN, статус, дата окончания регистрации, автопродление. Используй перед любой операцией над доменом.", + inputSchema, + handler, +}; diff --git a/src/tools/list-firewall-group-resources.tool.ts b/src/tools/list-firewall-group-resources.tool.ts new file mode 100644 index 0000000..fdba842 --- /dev/null +++ b/src/tools/list-firewall-group-resources.tool.ts @@ -0,0 +1,48 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listFirewallGroupResourcesAction } from "../actions/list-firewall-group-resources.action"; + +const inputSchema = { + group_id: z + .string() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID группы правил firewall"), +}; + +const handler = async (params: { group_id: string }) => { + try { + const resources = await listFirewallGroupResourcesAction(params.group_id); + + if (resources.length === 0) { + return createToolResponse( + `К группе firewall ${params.group_id} не привязано ни одного ресурса.` + ); + } + + const lines = resources.map( + (r) => `• ${r.type} #${r.id}` + ); + + return createToolResponse( + `🔗 Ресурсы, привязанные к группе ${params.group_id} (${resources.length}):\n${lines.join("\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения ресурсов группы firewall ${params.group_id}. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при получении ресурсов группы firewall" + ); + } +}; + +export const listFirewallGroupResourcesTool = { + name: ToolNames.LIST_FIREWALL_GROUP_RESOURCES, + title: "Список ресурсов группы firewall", + description: + "Возвращает список ресурсов (сейчас только серверы), привязанных к указанной группе правил firewall.", + inputSchema, + handler, +}; diff --git a/src/tools/list-firewall-groups-by-resource.tool.ts b/src/tools/list-firewall-groups-by-resource.tool.ts new file mode 100644 index 0000000..e615995 --- /dev/null +++ b/src/tools/list-firewall-groups-by-resource.tool.ts @@ -0,0 +1,59 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listFirewallGroupsByResourceAction } from "../actions/list-firewall-groups-by-resource.action"; +import { FirewallResourceType } from "../types/firewall-resource.type"; + +const inputSchema = { + resource_type: z + .enum(["server"]) + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - тип ресурса. Сейчас поддерживается: server"), + resource_id: z + .string() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID ресурса (например, ID сервера)"), +}; + +const handler = async (params: { + resource_type: FirewallResourceType; + resource_id: string; +}) => { + try { + const groups = await listFirewallGroupsByResourceAction( + params.resource_type, + params.resource_id + ); + + if (groups.length === 0) { + return createToolResponse( + `К ресурсу ${params.resource_type} #${params.resource_id} не привязано ни одной группы firewall.` + ); + } + + const lines = groups.map( + (g) => + `• ID ${g.id} — ${g.name}\n политика: ${g.policy}, описание: ${g.description || "—"}` + ); + + return createToolResponse( + `🛡️ Группы firewall, привязанные к ${params.resource_type} #${params.resource_id} (${groups.length}):\n\n${lines.join("\n\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения групп firewall для ресурса ${params.resource_id}. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при получении групп firewall для ресурса" + ); + } +}; + +export const listFirewallGroupsByResourceTool = { + name: ToolNames.LIST_FIREWALL_GROUPS_BY_RESOURCE, + title: "Группы firewall для ресурса", + description: + "Возвращает список групп правил firewall, привязанных к конкретному ресурсу (например, серверу). Используй, чтобы узнать какие группы защищают сервер.", + inputSchema, + handler, +}; diff --git a/src/tools/list-firewall-groups.tool.ts b/src/tools/list-firewall-groups.tool.ts new file mode 100644 index 0000000..0cadf5f --- /dev/null +++ b/src/tools/list-firewall-groups.tool.ts @@ -0,0 +1,42 @@ +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listFirewallGroupsAction } from "../actions/list-firewall-groups.action"; + +const inputSchema = {}; + +const handler = async () => { + try { + const groups = await listFirewallGroupsAction(); + + if (groups.length === 0) { + return createToolResponse("Групп правил firewall нет."); + } + + const lines = groups.map( + (g) => + `• ID ${g.id} — ${g.name}\n политика: ${g.policy}, описание: ${g.description || "—"}\n создана: ${new Date(g.created_at).toLocaleString("ru-RU")}, обновлена: ${new Date(g.updated_at).toLocaleString("ru-RU")}` + ); + + return createToolResponse( + `🛡️ Группы правил firewall (${groups.length}):\n\n${lines.join("\n\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения списка групп firewall. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при получении групп firewall" + ); + } +}; + +export const listFirewallGroupsTool = { + name: ToolNames.LIST_FIREWALL_GROUPS, + title: "Список групп правил firewall", + description: + "Возвращает все группы правил firewall аккаунта: ID, имя, описание, политика (ACCEPT/DROP), даты создания и обновления. Используй перед любой операцией над группой, чтобы получить её ID.", + inputSchema, + handler, +}; diff --git a/src/tools/list-firewall-rules.tool.ts b/src/tools/list-firewall-rules.tool.ts new file mode 100644 index 0000000..54dfe56 --- /dev/null +++ b/src/tools/list-firewall-rules.tool.ts @@ -0,0 +1,49 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listFirewallRulesAction } from "../actions/list-firewall-rules.action"; + +const inputSchema = { + group_id: z + .string() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID группы правил firewall"), +}; + +const handler = async (params: { group_id: string }) => { + try { + const rules = await listFirewallRulesAction(params.group_id); + + if (rules.length === 0) { + return createToolResponse( + `В группе firewall ${params.group_id} нет правил.` + ); + } + + const lines = rules.map( + (r) => + `• ID ${r.id} — ${r.direction.toUpperCase()} ${r.protocol.toUpperCase()}${r.port ? ` port ${r.port}` : ""}${r.cidr ? ` cidr ${r.cidr}` : ""}\n описание: ${r.description || "—"}` + ); + + return createToolResponse( + `🛡️ Правила в группе ${params.group_id} (${rules.length}):\n\n${lines.join("\n\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения правил группы firewall ${params.group_id}. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при получении правил firewall" + ); + } +}; + +export const listFirewallRulesTool = { + name: ToolNames.LIST_FIREWALL_RULES, + title: "Список правил firewall в группе", + description: + "Возвращает список правил firewall в указанной группе: ID, направление (ingress/egress), протокол (tcp/udp/icmp), порт, CIDR, описание.", + inputSchema, + handler, +}; diff --git a/src/tools/list-floating-ips.tool.ts b/src/tools/list-floating-ips.tool.ts new file mode 100644 index 0000000..5f8f818 --- /dev/null +++ b/src/tools/list-floating-ips.tool.ts @@ -0,0 +1,46 @@ +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listFloatingIpsAction } from "../actions/list-floating-ips.action"; + +const inputSchema = {}; + +const handler = async () => { + try { + const response = await listFloatingIpsAction(); + const ips = response.ips; + + if (!ips || ips.length === 0) { + return createToolResponse( + `💡 Плавающие IP не найдены. Создайте первый с помощью tool ${ToolNames.CREATE_FLOATING_IP}` + ); + } + + const lines = ips.map((ip) => { + const bound = ip.resource_type + ? `${ip.resource_type}${ip.resource_id !== null && ip.resource_id !== undefined ? ` #${ip.resource_id}` : ""}` + : "не привязан"; + return `• ID ${ip.id} — ${ip.ip ?? "без адреса"} | зона: ${ip.availability_zone} | DDoS: ${ip.is_ddos_guard ? "✅" : "❌"} | привязка: ${bound}${ip.comment ? ` | комментарий: ${ip.comment}` : ""}`; + }); + + return createToolResponse( + `📋 Плавающие IP (всего: ${response.meta?.total ?? ips.length}):\n${lines.join("\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка при получении списка плавающих IP. Причина: ${error.message}` + ); + } + return createToolResponse( + `❌ Неизвестная ошибка при получении списка плавающих IP` + ); + } +}; + +export const listFloatingIpsTool = { + name: ToolNames.LIST_FLOATING_IPS, + title: "Список плавающих IP", + description: "Возвращает список всех плавающих IP пользователя с их ID, адресами, зонами и привязкой к сервисам", + inputSchema, + handler, +}; diff --git a/src/tools/list-image-downloads.tool.ts b/src/tools/list-image-downloads.tool.ts new file mode 100644 index 0000000..fdfe0fd --- /dev/null +++ b/src/tools/list-image-downloads.tool.ts @@ -0,0 +1,69 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listImageDownloadsAction } from "../actions/list-image-downloads.action"; + +const inputSchema = { + image_id: z.string().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID образа"), + limit: z + .number() + .int() + .optional() + .describe( + "НЕ ОБЯЗАТЕЛЬНОЕ ПОЛЕ - лимит количества ссылок (по умолчанию 100)" + ), + offset: z + .number() + .int() + .optional() + .describe( + "НЕ ОБЯЗАТЕЛЬНОЕ ПОЛЕ - смещение для пагинации (по умолчанию 0)" + ), +}; + +const handler = async (params: { + image_id: string; + limit?: number; + offset?: number; +}) => { + try { + const downloads = await listImageDownloadsAction( + params.image_id, + params.limit, + params.offset + ); + + if (downloads.length === 0) { + return createToolResponse( + `У образа ${params.image_id} нет ссылок на скачивание.` + ); + } + + const lines = downloads.map( + (d) => + `• ID ${d.id} — тип: ${d.type}, статус: ${d.status} (progress ${d.progress}%)\n создана: ${d.created_at}\n url: ${d.url ?? "—"}` + ); + + return createToolResponse( + `Ссылки на скачивание образа ${params.image_id} (${downloads.length}):\n\n${lines.join("\n\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось получить ссылки на скачивание. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при получении ссылок на скачивание" + ); + } +}; + +export const listImageDownloadsTool = { + name: ToolNames.LIST_IMAGE_DOWNLOADS, + title: "Список ссылок на скачивание образа", + description: + "Возвращает список всех ссылок на скачивание конкретного образа. Используется при миграции образа во внешние хранилища (Timeweb, Google Drive, Яндекс.Диск).", + inputSchema, + handler, +}; diff --git a/src/tools/list-images.tool.ts b/src/tools/list-images.tool.ts new file mode 100644 index 0000000..7c652bb --- /dev/null +++ b/src/tools/list-images.tool.ts @@ -0,0 +1,56 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listImagesAction } from "../actions/list-images.action"; + +const inputSchema = { + limit: z + .number() + .int() + .optional() + .describe( + "НЕ ОБЯЗАТЕЛЬНОЕ ПОЛЕ - лимит количества возвращаемых образов (по умолчанию 100)" + ), + offset: z + .number() + .int() + .optional() + .describe( + "НЕ ОБЯЗАТЕЛЬНОЕ ПОЛЕ - смещение для пагинации (по умолчанию 0)" + ), +}; + +const handler = async (params: { limit?: number; offset?: number }) => { + try { + const images = await listImagesAction(params.limit, params.offset); + + if (images.length === 0) { + return createToolResponse("На аккаунте нет образов."); + } + + const lines = images.map( + (i) => + `• ID ${i.id} — ${i.name || "(без имени)"}\n статус: ${i.status} (progress ${i.progress}%), ОС: ${i.os}, локация: ${i.location}, тип: ${i.type}\n размер: ${i.size} MB (виртуальный: ${i.virtual_size} MB), disk_id: ${i.disk_id ?? "—"}, custom: ${i.is_custom}` + ); + + return createToolResponse( + `Образы (${images.length}):\n\n${lines.join("\n\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось получить список образов. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при получении образов"); + } +}; + +export const listImagesTool = { + name: ToolNames.LIST_IMAGES, + title: "Список образов", + description: + "Возвращает список всех образов (custom images, snapshots) аккаунта с id, name, статусом, ОС, локацией, размером. Образы — это снимки дисков/загруженные qcow2 или iso, которые можно использовать для создания серверов.", + inputSchema, + handler, +}; diff --git a/src/tools/list-k8s-addon-configs.tool.ts b/src/tools/list-k8s-addon-configs.tool.ts new file mode 100644 index 0000000..7a6c3b1 --- /dev/null +++ b/src/tools/list-k8s-addon-configs.tool.ts @@ -0,0 +1,44 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listK8sAddonConfigsAction } from "../actions/list-k8s-addon-configs.action"; + +const inputSchema = { + cluster_id: z.number().int().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID кластера"), +}; + +const handler = async (params: { cluster_id: number }) => { + try { + const addons = await listK8sAddonConfigsAction(params.cluster_id); + if (addons.length === 0) { + return createToolResponse("Нет доступных конфигураций дополнений."); + } + + const lines = addons.map( + (a) => + `• ID ${a.id} — ${a.type} v${a.version}${a.dependencies.length ? `, зависимости: ${a.dependencies.join(", ")}` : ""}` + ); + + return createToolResponse( + `Каталог дополнений для кластера ${params.cluster_id} (${addons.length}):\n${lines.join("\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения каталога дополнений. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при получении каталога дополнений" + ); + } +}; + +export const listK8sAddonConfigsTool = { + name: ToolNames.LIST_K8S_ADDON_CONFIGS, + title: "Каталог дополнений кластера", + description: + "Возвращает доступные для установки в кластер дополнения (аддоны): тип, версию, зависимости и базовый YAML-шаблон.", + inputSchema, + handler, +}; diff --git a/src/tools/list-k8s-addons.tool.ts b/src/tools/list-k8s-addons.tool.ts new file mode 100644 index 0000000..c817fe8 --- /dev/null +++ b/src/tools/list-k8s-addons.tool.ts @@ -0,0 +1,46 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listK8sAddonsAction } from "../actions/list-k8s-addons.action"; + +const inputSchema = { + cluster_id: z.number().int().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID кластера"), +}; + +const handler = async (params: { cluster_id: number }) => { + try { + const addons = await listK8sAddonsAction(params.cluster_id); + if (addons.length === 0) { + return createToolResponse( + `В кластере ${params.cluster_id} нет установленных дополнений.` + ); + } + + const lines = addons.map( + (a) => + `• ID ${a.id} — ${a.type} v${a.version}, статус: ${a.status}, config_type: ${a.config_type}, установлено: ${new Date(a.created_at).toLocaleString("ru-RU")}` + ); + + return createToolResponse( + `Установленные дополнения кластера ${params.cluster_id} (${addons.length}):\n${lines.join("\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения установленных дополнений. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при получении установленных дополнений" + ); + } +}; + +export const listK8sAddonsTool = { + name: ToolNames.LIST_K8S_ADDONS, + title: "Установленные дополнения кластера", + description: + "Возвращает список установленных в кластере дополнений (addons) с их ID, типом, версией и статусом.", + inputSchema, + handler, +}; diff --git a/src/tools/list-k8s-cluster-nodes.tool.ts b/src/tools/list-k8s-cluster-nodes.tool.ts new file mode 100644 index 0000000..dd2a968 --- /dev/null +++ b/src/tools/list-k8s-cluster-nodes.tool.ts @@ -0,0 +1,44 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listK8sClusterNodesAction } from "../actions/list-k8s-cluster-nodes.action"; + +const inputSchema = { + cluster_id: z.number().int().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID кластера"), +}; + +const handler = async (params: { cluster_id: number }) => { + try { + const nodes = await listK8sClusterNodesAction(params.cluster_id); + if (nodes.length === 0) { + return createToolResponse( + `В кластере ${params.cluster_id} нет нод.` + ); + } + const lines = nodes.map( + (n) => + `• ID ${n.id} — тип: ${n.type}, группа: ${n.group_id}, статус: ${n.status}, IP: ${n.node_ip}, CPU: ${n.cpu}, RAM: ${n.ram}, Disk: ${n.disk}` + ); + return createToolResponse( + `Все ноды кластера ${params.cluster_id} (${nodes.length}):\n${lines.join("\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения списка нод. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при получении списка нод" + ); + } +}; + +export const listK8sClusterNodesTool = { + name: ToolNames.LIST_K8S_CLUSTER_NODES, + title: "Список всех нод кластера", + description: + "Возвращает список всех нод (мастер и воркер) в кластере с их ID, типом, группой, статусом и характеристиками.", + inputSchema, + handler, +}; diff --git a/src/tools/list-k8s-clusters.tool.ts b/src/tools/list-k8s-clusters.tool.ts new file mode 100644 index 0000000..3acdc74 --- /dev/null +++ b/src/tools/list-k8s-clusters.tool.ts @@ -0,0 +1,56 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listK8sClustersAction } from "../actions/list-k8s-clusters.action"; + +const inputSchema = { + limit: z + .number() + .int() + .min(1) + .optional() + .describe("Максимальное количество возвращаемых кластеров"), + offset: z + .number() + .int() + .min(0) + .optional() + .describe("Смещение относительно начала списка"), +}; + +const handler = async (params: { limit?: number; offset?: number }) => { + try { + const clusters = await listK8sClustersAction(params.limit, params.offset); + + if (clusters.length === 0) { + return createToolResponse("Kubernetes-кластеров на аккаунте нет."); + } + + const lines = clusters.map( + (c) => + `• ID ${c.id} — ${c.name}\n статус: ${c.status}, версия: ${c.k8s_version}, драйвер: ${c.network_driver}\n зона: ${c.availability_zone ?? "—"}, ingress: ${c.ingress ? "вкл" : "выкл"}, preset_id (мастер): ${c.preset_id}\n CPU: ${c.cpu ?? 0}, RAM: ${c.ram ?? 0} МБ, Disk: ${c.disk ?? 0} МБ` + ); + + return createToolResponse( + `Kubernetes-кластеры (${clusters.length}):\n\n${lines.join("\n\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения списка кластеров. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при получении кластеров" + ); + } +}; + +export const listK8sClustersTool = { + name: ToolNames.LIST_K8S_CLUSTERS, + title: "Список Kubernetes-кластеров", + description: + "Возвращает список всех Kubernetes-кластеров аккаунта с ID, именем, статусом, версией k8s, сетевым драйвером, зоной доступности и агрегированными CPU/RAM/Disk. Используй перед операциями над кластером, чтобы получить его ID.", + inputSchema, + handler, +}; diff --git a/src/tools/list-k8s-network-drivers.tool.ts b/src/tools/list-k8s-network-drivers.tool.ts new file mode 100644 index 0000000..2ed2dc5 --- /dev/null +++ b/src/tools/list-k8s-network-drivers.tool.ts @@ -0,0 +1,35 @@ +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listK8sNetworkDriversAction } from "../actions/list-k8s-network-drivers.action"; + +const inputSchema = {}; + +const handler = async () => { + try { + const drivers = await listK8sNetworkDriversAction(); + if (drivers.length === 0) { + return createToolResponse("Нет доступных сетевых драйверов."); + } + return createToolResponse( + `Сетевые драйверы Kubernetes (${drivers.length}):\n${drivers.map((d) => `• ${d}`).join("\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения сетевых драйверов. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при получении сетевых драйверов" + ); + } +}; + +export const listK8sNetworkDriversTool = { + name: ToolNames.LIST_K8S_NETWORK_DRIVERS, + title: "Список сетевых драйверов Kubernetes", + description: + "Возвращает список доступных сетевых драйверов для создания кластера (kuberouter, calico, flannel, cilium).", + inputSchema, + handler, +}; diff --git a/src/tools/list-k8s-node-group-nodes.tool.ts b/src/tools/list-k8s-node-group-nodes.tool.ts new file mode 100644 index 0000000..2938fe8 --- /dev/null +++ b/src/tools/list-k8s-node-group-nodes.tool.ts @@ -0,0 +1,55 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listK8sNodeGroupNodesAction } from "../actions/list-k8s-node-group-nodes.action"; + +const inputSchema = { + cluster_id: z.number().int().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID кластера"), + group_id: z.number().int().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID группы нод"), + limit: z.number().int().min(1).optional().describe("Лимит нод"), + offset: z.number().int().min(0).optional().describe("Смещение"), +}; + +const handler = async (params: { + cluster_id: number; + group_id: number; + limit?: number; + offset?: number; +}) => { + try { + const nodes = await listK8sNodeGroupNodesAction( + params.cluster_id, + params.group_id, + params.limit, + params.offset + ); + if (nodes.length === 0) { + return createToolResponse( + `В группе ${params.group_id} кластера ${params.cluster_id} нет нод.` + ); + } + const lines = nodes.map( + (n) => + `• ID ${n.id} — тип: ${n.type}, статус: ${n.status}, IP: ${n.node_ip}, CPU: ${n.cpu}, RAM: ${n.ram}, Disk: ${n.disk}` + ); + return createToolResponse( + `Ноды группы ${params.group_id} (${nodes.length}):\n${lines.join("\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения нод группы. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при получении нод группы"); + } +}; + +export const listK8sNodeGroupNodesTool = { + name: ToolNames.LIST_K8S_NODE_GROUP_NODES, + title: "Список нод группы", + description: + "Возвращает список нод, принадлежащих конкретной группе кластера. Поддерживает пагинацию через limit/offset.", + inputSchema, + handler, +}; diff --git a/src/tools/list-k8s-node-groups.tool.ts b/src/tools/list-k8s-node-groups.tool.ts new file mode 100644 index 0000000..2264188 --- /dev/null +++ b/src/tools/list-k8s-node-groups.tool.ts @@ -0,0 +1,46 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listK8sNodeGroupsAction } from "../actions/list-k8s-node-groups.action"; + +const inputSchema = { + cluster_id: z.number().int().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID кластера"), +}; + +const handler = async (params: { cluster_id: number }) => { + try { + const groups = await listK8sNodeGroupsAction(params.cluster_id); + if (groups.length === 0) { + return createToolResponse( + `В кластере ${params.cluster_id} нет групп нод.` + ); + } + + const lines = groups.map( + (g) => + `• ID ${g.id} — ${g.name}, preset_id: ${g.preset_id}, нод: ${g.node_count}, создана: ${new Date(g.created_at).toLocaleString("ru-RU")}` + ); + + return createToolResponse( + `Группы нод кластера ${params.cluster_id} (${groups.length}):\n${lines.join("\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения групп нод. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при получении групп нод" + ); + } +}; + +export const listK8sNodeGroupsTool = { + name: ToolNames.LIST_K8S_NODE_GROUPS, + title: "Список групп нод кластера", + description: + "Возвращает список всех групп нод (node groups) в кластере с ID, именем, preset_id и количеством нод.", + inputSchema, + handler, +}; diff --git a/src/tools/list-k8s-presets.tool.ts b/src/tools/list-k8s-presets.tool.ts new file mode 100644 index 0000000..4132610 --- /dev/null +++ b/src/tools/list-k8s-presets.tool.ts @@ -0,0 +1,39 @@ +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listK8sPresetsAction } from "../actions/list-k8s-presets.action"; + +const inputSchema = {}; + +const handler = async () => { + try { + const presets = await listK8sPresetsAction(); + if (presets.length === 0) { + return createToolResponse("Нет доступных тарифов Kubernetes."); + } + + const lines = presets.map((p) => { + const limitStr = p.type === "master" && p.limit ? `, лимит воркеров: ${p.limit}` : ""; + return `• ID ${p.id} (${p.type}) — ${p.description_short}\n CPU: ${p.cpu}, RAM: ${p.ram}, Disk: ${p.disk}, Network: ${p.network}, Цена: ${p.price}${limitStr}`; + }); + + return createToolResponse( + `Тарифы Kubernetes (${presets.length}):\n\n${lines.join("\n\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения тарифов. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при получении тарифов"); + } +}; + +export const listK8sPresetsTool = { + name: ToolNames.LIST_K8S_PRESETS, + title: "Список тарифов Kubernetes", + description: + "Возвращает тарифы для мастер- и воркер-нод: ID, тип (master/worker), CPU, RAM, Disk, Network, цену. Используй перед созданием кластера или группы нод.", + inputSchema, + handler, +}; diff --git a/src/tools/list-k8s-versions.tool.ts b/src/tools/list-k8s-versions.tool.ts new file mode 100644 index 0000000..4f591ee --- /dev/null +++ b/src/tools/list-k8s-versions.tool.ts @@ -0,0 +1,33 @@ +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listK8sVersionsAction } from "../actions/list-k8s-versions.action"; + +const inputSchema = {}; + +const handler = async () => { + try { + const versions = await listK8sVersionsAction(); + if (versions.length === 0) { + return createToolResponse("Нет доступных версий Kubernetes."); + } + return createToolResponse( + `Доступные версии Kubernetes (${versions.length}):\n${versions.map((v) => `• ${v}`).join("\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения версий. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при получении версий"); + } +}; + +export const listK8sVersionsTool = { + name: ToolNames.LIST_K8S_VERSIONS, + title: "Список доступных версий Kubernetes", + description: + "Возвращает все доступные для создания/обновления версии Kubernetes. Используй перед create_k8s_cluster или update_k8s_cluster_version.", + inputSchema, + handler, +}; diff --git a/src/tools/list-locations.tool.ts b/src/tools/list-locations.tool.ts new file mode 100644 index 0000000..0a2dcf4 --- /dev/null +++ b/src/tools/list-locations.tool.ts @@ -0,0 +1,40 @@ +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listLocationsAction } from "../actions/list-locations.action"; + +const inputSchema = {}; + +const handler = async () => { + try { + const locations = await listLocationsAction(); + + if (locations.length === 0) { + return createToolResponse("Локации не найдены."); + } + + const lines = locations.map( + (l) => + `• ${l.location} (${l.location_code}) — зоны: ${l.availability_zones.join(", ") || "—"}` + ); + + return createToolResponse( + `🌍 Локации (${locations.length}):\n\n${lines.join("\n")}\n\n💡 Используйте значение location при создании VPS (фильтр по локации для тарифов/конфигураторов) и availability_zone для выбора зоны.` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения локаций. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при получении локаций"); + } +}; + +export const listLocationsTool = { + name: ToolNames.LIST_LOCATIONS, + title: "Список локаций", + description: + "Возвращает список доступных локаций и зон доступности: код локации, ISO-код, список availability_zones. Нужен для выбора location/availability_zone при создании VPS.", + inputSchema, + handler, +}; diff --git a/src/tools/list-mailboxes-by-domain.tool.ts b/src/tools/list-mailboxes-by-domain.tool.ts new file mode 100644 index 0000000..f5a11e4 --- /dev/null +++ b/src/tools/list-mailboxes-by-domain.tool.ts @@ -0,0 +1,49 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listMailboxesByDomainAction } from "../actions/list-mailboxes-by-domain.action"; + +const inputSchema = { + domain: z + .string() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - имя домена (например: example.com)"), +}; + +const handler = async (params: { domain: string }) => { + try { + const mailboxes = await listMailboxesByDomainAction(params.domain); + + if (mailboxes.length === 0) { + return createToolResponse( + `На домене ${params.domain} почтовых ящиков нет.` + ); + } + + const lines = mailboxes.map((m) => { + const full = m.mailbox && m.fqdn ? `${m.mailbox}@${m.fqdn}` : (m.mailbox ?? "—"); + return `• ${full}${m.comment ? ` — ${m.comment}` : ""}`; + }); + + return createToolResponse( + `Почтовые ящики домена ${params.domain} (${mailboxes.length}):\n\n${lines.join("\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения ящиков домена. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при получении ящиков домена" + ); + } +}; + +export const listMailboxesByDomainTool = { + name: ToolNames.LIST_MAILBOXES_BY_DOMAIN, + title: "Список почтовых ящиков домена", + description: + "Возвращает список почтовых ящиков указанного домена (API v1). Используй, когда нужны только ящики конкретного домена.", + inputSchema, + handler, +}; diff --git a/src/tools/list-mailboxes-v1.tool.ts b/src/tools/list-mailboxes-v1.tool.ts new file mode 100644 index 0000000..236fc56 --- /dev/null +++ b/src/tools/list-mailboxes-v1.tool.ts @@ -0,0 +1,44 @@ +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listMailboxesV1Action } from "../actions/list-mailboxes-v1.action"; + +const inputSchema = {}; + +const handler = async () => { + try { + const mailboxes = await listMailboxesV1Action(); + + if (mailboxes.length === 0) { + return createToolResponse("На аккаунте нет почтовых ящиков."); + } + + const lines = mailboxes.map((m) => { + const full = m.mailbox && m.fqdn ? `${m.mailbox}@${m.fqdn}` : (m.fqdn ?? "—"); + const spam = m.spam_filter?.is_enabled ? "вкл" : "выкл"; + const fwd = m.forwarding_incoming?.is_enabled ? "вкл" : "выкл"; + return `• ${full}\n спам-фильтр: ${spam}, пересылка входящих: ${fwd}${m.comment ? `\n комментарий: ${m.comment}` : ""}`; + }); + + return createToolResponse( + `Почтовые ящики (API v1, ${mailboxes.length}):\n\n${lines.join("\n\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения списка почтовых ящиков (v1). Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при получении списка почтовых ящиков (v1)" + ); + } +}; + +export const listMailboxesV1Tool = { + name: ToolNames.LIST_MAILBOXES_V1, + title: "Список почтовых ящиков аккаунта (API v1)", + description: + "Возвращает все почтовые ящики аккаунта в формате API v1 (с полной детализацией auto_reply/spam_filter/forwarding). Предпочитай list_mailboxes (v2), этот нужен только если требуются v1-поля.", + inputSchema, + handler, +}; diff --git a/src/tools/list-mailboxes.tool.ts b/src/tools/list-mailboxes.tool.ts new file mode 100644 index 0000000..a67558d --- /dev/null +++ b/src/tools/list-mailboxes.tool.ts @@ -0,0 +1,42 @@ +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listMailboxesAction } from "../actions/list-mailboxes.action"; + +const inputSchema = {}; + +const handler = async () => { + try { + const mailboxes = await listMailboxesAction(); + + if (mailboxes.length === 0) { + return createToolResponse("На аккаунте нет почтовых ящиков."); + } + + const lines = mailboxes.map((m) => { + const full = m.mailbox && m.fqdn ? `${m.mailbox}@${m.fqdn}` : (m.fqdn ?? "—"); + return `• ${full}\n спам-фильтр: ${m.filter_status ? "вкл" : "выкл"}, webmail: ${m.webmail ? "да" : "нет"}, пересылка: ${m.forward_status ? "вкл" : "выкл"}${m.comment ? `\n комментарий: ${m.comment}` : ""}`; + }); + + return createToolResponse( + `Почтовые ящики (${mailboxes.length}):\n\n${lines.join("\n\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения списка почтовых ящиков. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при получении списка почтовых ящиков" + ); + } +}; + +export const listMailboxesTool = { + name: ToolNames.LIST_MAILBOXES, + title: "Список всех почтовых ящиков аккаунта", + description: + "Возвращает все почтовые ящики аккаунта (API v2). Для каждого ящика: адрес, статусы спам-фильтра, webmail, пересылки, комментарий.", + inputSchema, + handler, +}; diff --git a/src/tools/list-network-drive-available-resources.tool.ts b/src/tools/list-network-drive-available-resources.tool.ts new file mode 100644 index 0000000..8e3a951 --- /dev/null +++ b/src/tools/list-network-drive-available-resources.tool.ts @@ -0,0 +1,44 @@ +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listNetworkDriveAvailableResourcesAction } from "../actions/list-network-drive-available-resources.action"; + +const inputSchema = {}; + +const handler = async () => { + try { + const resources = await listNetworkDriveAvailableResourcesAction(); + + if (resources.length === 0) { + return createToolResponse( + "💡 Нет сервисов, доступных для подключения сетевого диска." + ); + } + + const lines = resources.map( + (r) => + `• ${r.resource_type}#${r.resource_id} — зона: ${r.availability_zone}, IP: ${r.ip ?? "—"}` + ); + + return createToolResponse( + `📋 Сервисы, доступные для подключения сетевого диска (${resources.length}):\n\n${lines.join("\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения списка доступных сервисов. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при получении доступных сервисов" + ); + } +}; + +export const listNetworkDriveAvailableResourcesTool = { + name: ToolNames.LIST_NETWORK_DRIVE_AVAILABLE_RESOURCES, + title: "Список сервисов для подключения сетевого диска", + description: + "Возвращает список сервисов (серверов), к которым можно подключить сетевой диск. Используй перед mount_network_drive, чтобы узнать допустимые resource_id.", + inputSchema, + handler, +}; diff --git a/src/tools/list-network-drive-presets.tool.ts b/src/tools/list-network-drive-presets.tool.ts new file mode 100644 index 0000000..362a6ae --- /dev/null +++ b/src/tools/list-network-drive-presets.tool.ts @@ -0,0 +1,44 @@ +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listNetworkDrivePresetsAction } from "../actions/list-network-drive-presets.action"; + +const inputSchema = {}; + +const handler = async () => { + try { + const presets = await listNetworkDrivePresetsAction(); + + if (presets.length === 0) { + return createToolResponse( + "💡 Нет доступных тарифов для сетевого диска." + ); + } + + const lines = presets.map( + (p) => + `• ID ${p.id} — тип ${p.type}, цена: ${p.cost_per_gb}/ГБ, размер: ${p.min}–${p.max} ГБ (шаг ${p.step})\n IOPS чтение: ${p.read?.min ?? "—"}–${p.read?.max ?? "—"}, запись: ${p.write?.min ?? "—"}–${p.write?.max ?? "—"}` + ); + + return createToolResponse( + `📋 Тарифы сетевых дисков (${presets.length}):\n\n${lines.join("\n\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения списка тарифов сетевых дисков. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при получении тарифов сетевых дисков" + ); + } +}; + +export const listNetworkDrivePresetsTool = { + name: ToolNames.LIST_NETWORK_DRIVE_PRESETS, + title: "Список тарифов сетевых дисков", + description: + "Возвращает список доступных тарифов (preset) для сетевых дисков с ценой за ГБ, допустимым диапазоном размеров и IOPS. Используй перед create_network_drive для выбора preset_id.", + inputSchema, + handler, +}; diff --git a/src/tools/list-network-drives.tool.ts b/src/tools/list-network-drives.tool.ts new file mode 100644 index 0000000..5f838f4 --- /dev/null +++ b/src/tools/list-network-drives.tool.ts @@ -0,0 +1,47 @@ +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listNetworkDrivesAction } from "../actions/list-network-drives.action"; + +const inputSchema = {}; + +const handler = async () => { + try { + const drives = await listNetworkDrivesAction(); + + if (drives.length === 0) { + return createToolResponse("Сетевых дисков на аккаунте нет."); + } + + const lines = drives.map((d) => { + const services = + d.service_list && d.service_list.length > 0 + ? d.service_list + .map((s) => `${s.resource_type}#${s.resource_id}`) + .join(", ") + : "не подключён"; + return `• ID ${d.id} — ${d.name}\n статус: ${d.status}, тип: ${d.type}, размер: ${d.size} ГБ, зона: ${d.availability_zone}, локация: ${d.location}, preset_id: ${d.preset_id}\n подключения: ${services}\n комментарий: ${d.comment ?? "—"}`; + }); + + return createToolResponse( + `Сетевые диски (${drives.length}):\n\n${lines.join("\n\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения списка сетевых дисков. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при получении сетевых дисков" + ); + } +}; + +export const listNetworkDrivesTool = { + name: ToolNames.LIST_NETWORK_DRIVES, + title: "Список сетевых дисков", + description: + "Возвращает список всех сетевых дисков аккаунта с ключевыми параметрами: ID, имя, статус, тип (nvme/hdd), размер, зона доступности, локация, preset_id, подключённые сервисы. Используй перед любой операцией над диском, чтобы получить его ID.", + inputSchema, + handler, +}; diff --git a/src/tools/list-project-balancers.tool.ts b/src/tools/list-project-balancers.tool.ts new file mode 100644 index 0000000..794fb2a --- /dev/null +++ b/src/tools/list-project-balancers.tool.ts @@ -0,0 +1,43 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listProjectBalancersAction } from "../actions/list-project-balancers.action"; + +const inputSchema = { + project_id: z.number().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID проекта"), +}; + +const handler = async (params: { project_id: number }) => { + try { + const items = await listProjectBalancersAction(params.project_id); + if (items.length === 0) { + return createToolResponse( + `Балансировщиков в проекте ${params.project_id} нет.` + ); + } + const lines = items.map( + (b: any) => + `• ID ${b.id} — ${b.name ?? "без имени"}, статус: ${b.status ?? "—"}` + ); + return createToolResponse( + `Балансировщики проекта ${params.project_id} (${items.length}):\n${lines.join("\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось получить балансировщики. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при получении балансировщиков" + ); + } +}; + +export const listProjectBalancersTool = { + name: ToolNames.LIST_PROJECT_BALANCERS, + title: "Балансировщики проекта", + description: "Список балансировщиков в указанном проекте.", + inputSchema, + handler, +}; diff --git a/src/tools/list-project-buckets.tool.ts b/src/tools/list-project-buckets.tool.ts new file mode 100644 index 0000000..3df180c --- /dev/null +++ b/src/tools/list-project-buckets.tool.ts @@ -0,0 +1,41 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listProjectBucketsAction } from "../actions/list-project-buckets.action"; + +const inputSchema = { + project_id: z.number().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID проекта"), +}; + +const handler = async (params: { project_id: number }) => { + try { + const items = await listProjectBucketsAction(params.project_id); + if (items.length === 0) { + return createToolResponse( + `Хранилищ в проекте ${params.project_id} нет.` + ); + } + const lines = items.map( + (b: any) => + `• ID ${b.id} — ${b.name ?? "без имени"}, тип: ${b.type ?? "—"}, статус: ${b.status ?? "—"}` + ); + return createToolResponse( + `Хранилища (S3) проекта ${params.project_id} (${items.length}):\n${lines.join("\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось получить хранилища. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при получении хранилищ"); + } +}; + +export const listProjectBucketsTool = { + name: ToolNames.LIST_PROJECT_BUCKETS, + title: "Хранилища проекта", + description: "Список S3-хранилищ в указанном проекте.", + inputSchema, + handler, +}; diff --git a/src/tools/list-project-clusters.tool.ts b/src/tools/list-project-clusters.tool.ts new file mode 100644 index 0000000..5d95b13 --- /dev/null +++ b/src/tools/list-project-clusters.tool.ts @@ -0,0 +1,41 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listProjectClustersAction } from "../actions/list-project-clusters.action"; + +const inputSchema = { + project_id: z.number().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID проекта"), +}; + +const handler = async (params: { project_id: number }) => { + try { + const items = await listProjectClustersAction(params.project_id); + if (items.length === 0) { + return createToolResponse( + `Кластеров k8s в проекте ${params.project_id} нет.` + ); + } + const lines = items.map( + (c: any) => + `• ID ${c.id} — ${c.name ?? "без имени"}, статус: ${c.status ?? "—"}` + ); + return createToolResponse( + `Kubernetes-кластеры проекта ${params.project_id} (${items.length}):\n${lines.join("\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось получить кластеры. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при получении кластеров"); + } +}; + +export const listProjectClustersTool = { + name: ToolNames.LIST_PROJECT_CLUSTERS, + title: "Kubernetes-кластеры проекта", + description: "Список k8s-кластеров в указанном проекте.", + inputSchema, + handler, +}; diff --git a/src/tools/list-project-databases.tool.ts b/src/tools/list-project-databases.tool.ts new file mode 100644 index 0000000..6d7148b --- /dev/null +++ b/src/tools/list-project-databases.tool.ts @@ -0,0 +1,41 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listProjectDatabasesAction } from "../actions/list-project-databases.action"; + +const inputSchema = { + project_id: z.number().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID проекта"), +}; + +const handler = async (params: { project_id: number }) => { + try { + const items = await listProjectDatabasesAction(params.project_id); + if (items.length === 0) { + return createToolResponse( + `Баз данных в проекте ${params.project_id} нет.` + ); + } + const lines = items.map( + (d: any) => + `• ID ${d.id} — ${d.name ?? "без имени"}, тип: ${d.type ?? "—"}, статус: ${d.status ?? "—"}` + ); + return createToolResponse( + `Базы данных проекта ${params.project_id} (${items.length}):\n${lines.join("\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось получить БД проекта. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при получении БД"); + } +}; + +export const listProjectDatabasesTool = { + name: ToolNames.LIST_PROJECT_DATABASES, + title: "Базы данных проекта", + description: "Список managed-БД в указанном проекте.", + inputSchema, + handler, +}; diff --git a/src/tools/list-project-dedicated.tool.ts b/src/tools/list-project-dedicated.tool.ts new file mode 100644 index 0000000..1527b51 --- /dev/null +++ b/src/tools/list-project-dedicated.tool.ts @@ -0,0 +1,43 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listProjectDedicatedAction } from "../actions/list-project-dedicated.action"; + +const inputSchema = { + project_id: z.number().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID проекта"), +}; + +const handler = async (params: { project_id: number }) => { + try { + const items = await listProjectDedicatedAction(params.project_id); + if (items.length === 0) { + return createToolResponse( + `Выделенных серверов в проекте ${params.project_id} нет.` + ); + } + const lines = items.map( + (d: any) => + `• ID ${d.id} — ${d.name ?? "без имени"}, CPU: ${d.cpu_description ?? "—"}, RAM: ${d.ram_description ?? "—"}` + ); + return createToolResponse( + `Выделенные серверы проекта ${params.project_id} (${items.length}):\n${lines.join("\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось получить выделенные серверы. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при получении выделенных серверов" + ); + } +}; + +export const listProjectDedicatedTool = { + name: ToolNames.LIST_PROJECT_DEDICATED, + title: "Выделенные серверы проекта", + description: "Список dedicated-серверов в указанном проекте.", + inputSchema, + handler, +}; diff --git a/src/tools/list-project-resources.tool.ts b/src/tools/list-project-resources.tool.ts new file mode 100644 index 0000000..3164736 --- /dev/null +++ b/src/tools/list-project-resources.tool.ts @@ -0,0 +1,55 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listProjectResourcesAction } from "../actions/list-project-resources.action"; + +const inputSchema = { + project_id: z.number().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID проекта"), +}; + +const handler = async (params: { project_id: number }) => { + try { + const res = await listProjectResourcesAction(params.project_id); + + const servers = res.servers?.length ?? 0; + const balancers = res.balancers?.length ?? 0; + const buckets = res.buckets?.length ?? 0; + const clusters = res.clusters?.length ?? 0; + const databases = res.databases?.length ?? 0; + const dedicated = res.dedicated_servers?.length ?? 0; + const total = + servers + balancers + buckets + clusters + databases + dedicated; + + if (total === 0) { + return createToolResponse( + `В проекте ${params.project_id} нет ресурсов.` + ); + } + + return createToolResponse( + `📋 Ресурсы проекта ${params.project_id} (всего ${total}):\n` + + `• Серверы: ${servers}\n` + + `• Балансировщики: ${balancers}\n` + + `• Хранилища: ${buckets}\n` + + `• Кластеры k8s: ${clusters}\n` + + `• Базы данных: ${databases}\n` + + `• Выделенные серверы: ${dedicated}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось получить ресурсы проекта ${params.project_id}. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при получении ресурсов"); + } +}; + +export const listProjectResourcesTool = { + name: ToolNames.LIST_PROJECT_RESOURCES, + title: "Все ресурсы проекта", + description: + "Возвращает сводку по всем ресурсам проекта: серверы, балансировщики, хранилища, кластеры, БД, выделенные серверы.", + inputSchema, + handler, +}; diff --git a/src/tools/list-project-servers.tool.ts b/src/tools/list-project-servers.tool.ts new file mode 100644 index 0000000..1ef18d4 --- /dev/null +++ b/src/tools/list-project-servers.tool.ts @@ -0,0 +1,41 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listProjectServersAction } from "../actions/list-project-servers.action"; + +const inputSchema = { + project_id: z.number().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID проекта"), +}; + +const handler = async (params: { project_id: number }) => { + try { + const items = await listProjectServersAction(params.project_id); + if (items.length === 0) { + return createToolResponse( + `Серверов в проекте ${params.project_id} нет.` + ); + } + const lines = items.map( + (s: any) => + `• ID ${s.id} — ${s.name ?? "без имени"}, статус: ${s.status ?? "—"}, локация: ${s.location ?? "—"}` + ); + return createToolResponse( + `Серверы проекта ${params.project_id} (${items.length}):\n${lines.join("\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось получить серверы проекта. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при получении серверов"); + } +}; + +export const listProjectServersTool = { + name: ToolNames.LIST_PROJECT_SERVERS, + title: "Серверы проекта", + description: "Список VPS-серверов в указанном проекте.", + inputSchema, + handler, +}; diff --git a/src/tools/list-projects.tool.ts b/src/tools/list-projects.tool.ts new file mode 100644 index 0000000..cc847a7 --- /dev/null +++ b/src/tools/list-projects.tool.ts @@ -0,0 +1,40 @@ +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listProjectsAction } from "../actions/list-projects.action"; + +const inputSchema = {}; + +const handler = async () => { + try { + const projects = await listProjectsAction(); + + if (projects.length === 0) { + return createToolResponse("Проектов нет."); + } + + const lines = projects.map( + (p) => + `• ID ${p.id} — ${p.name}${p.is_default ? " (по умолчанию)" : ""}\n описание: ${p.description || "—"}` + ); + + return createToolResponse( + `Проекты (${projects.length}):\n\n${lines.join("\n\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения списка проектов. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при получении проектов"); + } +}; + +export const listProjectsTool = { + name: ToolNames.LIST_PROJECTS, + title: "Список проектов", + description: + "Возвращает список всех проектов аккаунта с id, именем, описанием и флагом по умолчанию. Используй перед работой с ресурсами проекта, чтобы получить project_id.", + inputSchema, + handler, +}; diff --git a/src/tools/list-server-configurators.tool.ts b/src/tools/list-server-configurators.tool.ts new file mode 100644 index 0000000..d902a29 --- /dev/null +++ b/src/tools/list-server-configurators.tool.ts @@ -0,0 +1,53 @@ +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listServerConfiguratorsAction } from "../actions/list-server-configurators.action"; + +const inputSchema = {}; + +const handler = async () => { + try { + const configurators = await listServerConfiguratorsAction(); + + if (configurators.length === 0) { + return createToolResponse("Конфигураторы серверов не найдены."); + } + + const lines = configurators.map((c) => { + const r = c.requirements; + const gpu = + r.gpu_min != null || r.gpu_max != null + ? `\n 🎮 GPU: ${r.gpu_min ?? "—"}…${r.gpu_max ?? "—"} (шаг ${r.gpu_step ?? "—"})` + : ""; + return ( + `• ID ${c.id} — 📍 ${c.location} | диск: ${c.disk_type} | CPU: ${c.cpu_frequency}GHz | локальная сеть: ${c.is_allowed_local_network ? "да" : "нет"}\n` + + ` 🖥️ CPU: ${r.cpu_min}…${r.cpu_max} (шаг ${r.cpu_step})\n` + + ` 💾 RAM (MB): ${r.ram_min}…${r.ram_max} (шаг ${r.ram_step})\n` + + ` 💿 Диск (MB): ${r.disk_min}…${r.disk_max} (шаг ${r.disk_step})\n` + + ` 🌐 Канал (Мбит/с): ${r.network_bandwidth_min}…${r.network_bandwidth_max} (шаг ${r.network_bandwidth_step})` + + gpu + ); + }); + + return createToolResponse( + `⚙️ Конфигураторы VPS (${configurators.length}):\n\n${lines.join("\n\n")}\n\n💡 Используйте ID в поле configurator.configurator_id при создании/изменении VPS с произвольной конфигурацией.` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения конфигураторов. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при получении конфигураторов" + ); + } +}; + +export const listServerConfiguratorsTool = { + name: ToolNames.LIST_SERVER_CONFIGURATORS, + title: "Список конфигураторов VPS", + description: + "Возвращает конфигураторы серверов с диапазонами CPU/RAM/Disk/Bandwidth/GPU и шагами изменения. Используй, если нужно создать VPS с произвольной конфигурацией (не тарифом).", + inputSchema, + handler, +}; diff --git a/src/tools/list-server-disk-backups.tool.ts b/src/tools/list-server-disk-backups.tool.ts new file mode 100644 index 0000000..0857c41 --- /dev/null +++ b/src/tools/list-server-disk-backups.tool.ts @@ -0,0 +1,53 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listServerDiskBackupsAction } from "../actions/list-server-disk-backups.action"; + +const inputSchema = { + server_id: z.number().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID сервера"), + disk_id: z + .number() + .describe( + "ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID диска (получить через GET /api/v1/servers/{id}/disks)" + ), +}; + +const handler = async (params: { server_id: number; disk_id: number }) => { + try { + const backups = await listServerDiskBackupsAction( + params.server_id, + params.disk_id + ); + + if (backups.length === 0) { + return createToolResponse( + `На диске ${params.disk_id} сервера ${params.server_id} нет бэкапов.` + ); + } + + const lines = backups.map( + (b) => + `• ID ${b.id} — ${b.name} (${b.type})\n статус: ${b.status} (progress ${b.progress}%), размер: ${b.size} MB, создан: ${b.created_at}\n комментарий: ${b.comment ?? "—"}` + ); + + return createToolResponse( + `Бэкапы диска ${params.disk_id} сервера ${params.server_id} (${backups.length}):\n\n${lines.join("\n\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось получить бэкапы. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при получении бэкапов"); + } +}; + +export const listServerDiskBackupsTool = { + name: ToolNames.LIST_SERVER_DISK_BACKUPS, + title: "Список бэкапов диска сервера", + description: + "Возвращает список бэкапов (manual + auto) конкретного диска VPS-сервера. Бэкапы в Timeweb Cloud — это снапшоты на уровне диска, а не всего сервера. Для получения disk_id сначала запроси список дисков сервера через API.", + inputSchema, + handler, +}; diff --git a/src/tools/list-server-disks.tool.ts b/src/tools/list-server-disks.tool.ts new file mode 100644 index 0000000..f6ed23f --- /dev/null +++ b/src/tools/list-server-disks.tool.ts @@ -0,0 +1,43 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listServerDisksAction } from "../actions/list-server-disks.action"; + +const inputSchema = { + server_id: z.number().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID сервера"), +}; + +const handler = async (params: { server_id: number }) => { + try { + const disks = await listServerDisksAction(params.server_id); + + if (disks.length === 0) { + return createToolResponse(`На сервере ${params.server_id} нет дисков.`); + } + + const lines = disks.map( + (d) => + `• ID ${d.id} — ${d.system_name} (${d.type})\n размер: ${d.size} MB, использовано: ${d.used} MB\n статус: ${d.status}, примонтирован: ${d.is_mounted ? "да" : "нет"}, системный: ${d.is_system ? "да" : "нет"}` + ); + + return createToolResponse( + `Диски сервера ${params.server_id} (${disks.length}):\n\n${lines.join("\n\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось получить диски сервера ${params.server_id}. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при получении дисков"); + } +}; + +export const listServerDisksTool = { + name: ToolNames.LIST_SERVER_DISKS, + title: "Список дисков сервера", + description: + "Возвращает список дисков сервера с ID, размером, загрузкой и статусом. Используй перед операциями с бэкапами — disk_id нужен для list_server_disk_backups и create_server_disk_backup.", + inputSchema, + handler, +}; diff --git a/src/tools/list-server-ips.tool.ts b/src/tools/list-server-ips.tool.ts new file mode 100644 index 0000000..b5246e4 --- /dev/null +++ b/src/tools/list-server-ips.tool.ts @@ -0,0 +1,42 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listServerIpsAction } from "../actions/list-server-ips.action"; + +const inputSchema = { + server_id: z.number().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID сервера"), +}; + +const handler = async (params: { server_id: number }) => { + try { + const ips = await listServerIpsAction(params.server_id); + if (ips.length === 0) { + return createToolResponse( + `У сервера ${params.server_id} нет IP-адресов.` + ); + } + const lines = ips.map( + (ip) => + `• ${ip.type.toUpperCase()} ${ip.ip}${ip.is_main ? " (main)" : ""} — PTR: ${ip.ptr || "—"}` + ); + return createToolResponse( + `IP-адреса сервера ${params.server_id} (${ips.length}):\n${lines.join("\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось получить список IP сервера ${params.server_id}. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при получении IP"); + } +}; + +export const listServerIpsTool = { + name: ToolNames.LIST_SERVER_IPS, + title: "Список IP-адресов сервера", + description: + "Возвращает все IPv4 и IPv6 адреса, назначенные серверу, включая PTR-записи и признак основного IP.", + inputSchema, + handler, +}; diff --git a/src/tools/list-server-os.tool.ts b/src/tools/list-server-os.tool.ts new file mode 100644 index 0000000..fdbdda3 --- /dev/null +++ b/src/tools/list-server-os.tool.ts @@ -0,0 +1,47 @@ +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listServerOsAction } from "../actions/list-server-os.action"; + +const inputSchema = {}; + +const handler = async () => { + try { + const oses = await listServerOsAction(); + + if (oses.length === 0) { + return createToolResponse("Доступных ОС не найдено."); + } + + const lines = oses.map((o) => { + const req = o.requirements + ? ` 📐 Мин. требования: CPU ${o.requirements.cpu_min ?? "—"}, RAM ${o.requirements.ram_min ?? "—"}, Диск ${o.requirements.disk_min ?? "—"}, Канал ${o.requirements.bandwidth_min ?? "—"}` + : ""; + const codename = o.version_codename ? ` (${o.version_codename})` : ""; + const family = o.family ? ` | ${o.family}` : ""; + return ( + `• ID ${o.id} — ${o.name} ${o.version}${codename}${family}` + + (req ? `\n${req}` : "") + ); + }); + + return createToolResponse( + `💿 Операционные системы (${oses.length}):\n\n${lines.join("\n")}\n\n💡 Используйте ID при создании VPS в поле os_id.` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения списка ОС. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при получении списка ОС"); + } +}; + +export const listServerOsTool = { + name: ToolNames.LIST_SERVER_OS, + title: "Список ОС для VPS", + description: + "Возвращает список операционных систем, доступных для установки на VPS-сервер: ID, семейство, имя, версия, codename, минимальные требования. Используй перед созданием VPS, чтобы выбрать os_id.", + inputSchema, + handler, +}; diff --git a/src/tools/list-server-presets.tool.ts b/src/tools/list-server-presets.tool.ts new file mode 100644 index 0000000..7d2b906 --- /dev/null +++ b/src/tools/list-server-presets.tool.ts @@ -0,0 +1,47 @@ +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listServerPresetsAction } from "../actions/list-server-presets.action"; + +const inputSchema = {}; + +const handler = async () => { + try { + const presets = await listServerPresetsAction(); + + if (presets.length === 0) { + return createToolResponse("Тарифы серверов не найдены."); + } + + const lines = presets.map((p) => { + const ramGb = (p.ram / 1024).toFixed(1); + const diskGb = (p.disk / 1024).toFixed(1); + const tags = p.tags && p.tags.length ? ` [${p.tags.join(", ")}]` : ""; + return ( + `• ID ${p.id} — ${p.description_short}${tags}\n` + + ` 💰 ${p.price}₽/мес | 📍 ${p.location}\n` + + ` 🖥️ CPU: ${p.cpu} × ${p.cpu_frequency}GHz | 💾 RAM: ${ramGb} GB | 💿 Диск: ${diskGb} GB (${p.disk_type})\n` + + ` 🌐 Канал: ${p.bandwidth} Мбит/с | Локальная сеть: ${p.is_allowed_local_network ? "да" : "нет"}` + ); + }); + + return createToolResponse( + `📋 Тарифы VPS-серверов (${presets.length}):\n\n${lines.join("\n\n")}\n\n💡 Используйте ID тарифа при создании сервера в поле preset_id.` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения тарифов серверов. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при получении тарифов"); + } +}; + +export const listServerPresetsTool = { + name: ToolNames.LIST_SERVER_PRESETS, + title: "Список тарифов VPS-серверов", + description: + "Возвращает все доступные тарифы (пресеты) для VPS-серверов: ID, цена, локация, CPU, RAM, диск, тип диска, пропускная способность. Используй перед созданием VPS, чтобы выбрать preset_id. Это справочник VPS-тарифов (НЕ пресеты для приложений — для них есть get_allowed_presets).", + inputSchema, + handler, +}; diff --git a/src/tools/list-server-software.tool.ts b/src/tools/list-server-software.tool.ts new file mode 100644 index 0000000..f199d7c --- /dev/null +++ b/src/tools/list-server-software.tool.ts @@ -0,0 +1,47 @@ +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listServerSoftwareAction } from "../actions/list-server-software.action"; + +const inputSchema = {}; + +const handler = async () => { + try { + const software = await listServerSoftwareAction(); + + if (software.length === 0) { + return createToolResponse("ПО из маркетплейса не найдено."); + } + + const lines = software.map((s) => { + const osIds = + s.os_ids && s.os_ids.length ? s.os_ids.join(", ") : "—"; + const req = s.requirements + ? ` | 📐 мин. CPU ${s.requirements.cpu_min ?? "—"}, RAM ${s.requirements.ram_min ?? "—"}, Диск ${s.requirements.disk_min ?? "—"}` + : ""; + const desc = s.description ? `\n ${s.description}` : ""; + return `• ID ${s.id} — ${s.name} | установок: ${s.installations ?? 0} | os_ids: [${osIds}]${req}${desc}`; + }); + + return createToolResponse( + `🧩 ПО из маркетплейса (${software.length}):\n\n${lines.join("\n")}\n\n💡 Используйте ID в поле software_id при создании VPS (ОС должна быть из os_ids).` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения ПО из маркетплейса. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при получении списка ПО" + ); + } +}; + +export const listServerSoftwareTool = { + name: ToolNames.LIST_SERVER_SOFTWARE, + title: "Список ПО из маркетплейса", + description: + "Возвращает список ПО из маркетплейса, доступного для установки на VPS при создании: ID, название, совместимые os_ids, требования. Используй, чтобы выбрать software_id.", + inputSchema, + handler, +}; diff --git a/src/tools/list-servers.tool.ts b/src/tools/list-servers.tool.ts new file mode 100644 index 0000000..3b3f671 --- /dev/null +++ b/src/tools/list-servers.tool.ts @@ -0,0 +1,40 @@ +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listServersAction } from "../actions/list-servers.action"; + +const inputSchema = {}; + +const handler = async () => { + try { + const servers = await listServersAction(); + + if (servers.length === 0) { + return createToolResponse("На аккаунте нет серверов."); + } + + const lines = servers.map( + (s) => + `• ID ${s.id} — ${s.name}\n статус: ${s.status}, локация: ${s.location}, CPU: ${s.cpu}, RAM: ${s.ram} MB\n IPv4: ${s.main_ipv4 ?? "—"}, ОС: ${s.os?.name ?? "—"} ${s.os?.version ?? ""}` + ); + + return createToolResponse( + `Серверы (${servers.length}):\n\n${lines.join("\n\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения списка серверов. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при получении серверов"); + } +}; + +export const listServersTool = { + name: ToolNames.LIST_SERVERS, + title: "Список серверов", + description: + "Возвращает список всех VPS-серверов аккаунта с ключевыми параметрами: ID, имя, статус, локация, количество CPU, размер RAM, основной IPv4, ОС. Используй перед любой операцией над сервером, чтобы получить его ID.", + inputSchema, + handler, +}; diff --git a/src/tools/list-ssh-keys.tool.ts b/src/tools/list-ssh-keys.tool.ts new file mode 100644 index 0000000..6430f92 --- /dev/null +++ b/src/tools/list-ssh-keys.tool.ts @@ -0,0 +1,46 @@ +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listSshKeysAction } from "../actions/list-ssh-keys.action"; + +const inputSchema = {}; + +const handler = async () => { + try { + const keys = await listSshKeysAction(); + + if (keys.length === 0) { + return createToolResponse("На аккаунте нет SSH-ключей."); + } + + const lines = keys.map((k) => { + const usedBy = + k.used_by && k.used_by.length > 0 + ? k.used_by.map((s) => `${s.name} (ID ${s.id})`).join(", ") + : "—"; + const isDefault = k.is_default ? " (по умолчанию)" : ""; + return `• ID ${k.id} — ${k.name}${isDefault}\n создан: ${new Date(k.created_at).toLocaleString("ru-RU")}\n используется на серверах: ${usedBy}`; + }); + + return createToolResponse( + `SSH-ключи (${keys.length}):\n\n${lines.join("\n\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения списка SSH-ключей. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при получении списка SSH-ключей" + ); + } +}; + +export const listSshKeysTool = { + name: ToolNames.LIST_SSH_KEYS, + title: "Список SSH-ключей", + description: + "Возвращает список всех SSH-ключей аккаунта: ID, имя, дата создания, флаг is_default и список серверов, на которых ключ используется. Используй перед операциями с SSH-ключами чтобы получить их ID.", + inputSchema, + handler, +}; diff --git a/src/tools/list-tlds.tool.ts b/src/tools/list-tlds.tool.ts new file mode 100644 index 0000000..1ab13ab --- /dev/null +++ b/src/tools/list-tlds.tool.ts @@ -0,0 +1,39 @@ +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listTldsAction } from "../actions/tlds.action"; + +const inputSchema = {}; + +const handler = async () => { + try { + const tlds = await listTldsAction(); + if (tlds.length === 0) { + return createToolResponse("Доменные зоны не найдены."); + } + const lines = tlds.map( + (t) => + `• ID ${t.id} — .${t.name} — регистрация: ${t.price ?? "—"} руб., продление: ${t.prolong_price ?? "—"} руб.${t.registrar ? ` (регистратор: ${t.registrar})` : ""}` + ); + return createToolResponse( + `Доменные зоны (${tlds.length}):\n\n${lines.join("\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка получения списка доменных зон. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при получении доменных зон" + ); + } +}; + +export const listTldsTool = { + name: ToolNames.LIST_TLDS, + title: "Список доменных зон (TLD)", + description: + "Возвращает список всех доступных доменных зон с ценами регистрации и продления. Используй перед созданием заявки на регистрацию.", + inputSchema, + handler, +}; diff --git a/src/tools/list-vpc-ports.tool.ts b/src/tools/list-vpc-ports.tool.ts new file mode 100644 index 0000000..5117b09 --- /dev/null +++ b/src/tools/list-vpc-ports.tool.ts @@ -0,0 +1,42 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listVpcPortsAction } from "../actions/list-vpc-ports.action"; + +const inputSchema = { + vpc_id: z.string().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID VPC"), +}; + +const handler = async (params: { vpc_id: string }) => { + try { + const ports = await listVpcPortsAction(params.vpc_id); + + if (!ports || ports.length === 0) { + return createToolResponse(`💡 В VPC ${params.vpc_id} нет портов.`); + } + + const lines = ports.map( + (p) => + `• ${p.id} | IPv4: ${p.ipv4} | MAC: ${p.mac} | NAT: ${p.nat_mode} | сервис: ${p.service.type} "${p.service.name}" (ID ${p.service.id})` + ); + + return createToolResponse( + `📋 Порты VPC ${params.vpc_id} (всего: ${ports.length}):\n${lines.join("\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка при получении портов VPC. Причина: ${error.message}` + ); + } + return createToolResponse(`❌ Неизвестная ошибка при получении портов VPC`); + } +}; + +export const listVpcPortsTool = { + name: ToolNames.LIST_VPC_PORTS, + title: "Список портов VPC", + description: "Возвращает список портов VPC с MAC-адресами, IPv4 и сервисами", + inputSchema, + handler, +}; diff --git a/src/tools/list-vpc-services.tool.ts b/src/tools/list-vpc-services.tool.ts new file mode 100644 index 0000000..266f5a5 --- /dev/null +++ b/src/tools/list-vpc-services.tool.ts @@ -0,0 +1,45 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { listVpcServicesAction } from "../actions/list-vpc-services.action"; + +const inputSchema = { + vpc_id: z.string().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID VPC"), +}; + +const handler = async (params: { vpc_id: string }) => { + try { + const services = await listVpcServicesAction(params.vpc_id); + + if (!services || services.length === 0) { + return createToolResponse(`💡 В VPC ${params.vpc_id} нет сервисов.`); + } + + const lines = services.map( + (s) => + `• ID ${s.id} — ${s.name} | тип: ${s.type} | локальный IP: ${s.local_ip ?? "—"} | публичный IP: ${s.public_ip ?? "—"}` + ); + + return createToolResponse( + `📋 Сервисы в VPC ${params.vpc_id} (всего: ${services.length}):\n${lines.join("\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка при получении сервисов VPC. Причина: ${error.message}` + ); + } + return createToolResponse( + `❌ Неизвестная ошибка при получении сервисов VPC` + ); + } +}; + +export const listVpcServicesTool = { + name: ToolNames.LIST_VPC_SERVICES, + title: "Сервисы в VPC", + description: + "Возвращает список сервисов (server / balancer / dbaas), привязанных к VPC", + inputSchema, + handler, +}; diff --git a/src/tools/mount-network-drive.tool.ts b/src/tools/mount-network-drive.tool.ts new file mode 100644 index 0000000..6a2b78e --- /dev/null +++ b/src/tools/mount-network-drive.tool.ts @@ -0,0 +1,55 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { mountNetworkDriveAction } from "../actions/mount-network-drive.action"; + +const inputSchema = { + network_drive_id: z + .string() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID сетевого диска (UUID)"), + resource_type: z + .enum(["server"]) + .describe( + "ОБЯЗАТЕЛЬНОЕ ПОЛЕ - Тип ресурса, к которому подключаем диск (сейчас поддерживается только server)" + ), + resource_id: z + .number() + .int() + .describe( + "ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID ресурса (например, ID сервера) — узнать через list_network_drive_available_resources" + ), +}; + +const handler = async (params: { + network_drive_id: string; + resource_type: "server"; + resource_id: number; +}) => { + try { + await mountNetworkDriveAction(params.network_drive_id, { + resource_type: params.resource_type, + resource_id: params.resource_id, + }); + return createToolResponse( + `✅ Сетевой диск ${params.network_drive_id} подключён к ${params.resource_type}#${params.resource_id}.` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось подключить сетевой диск ${params.network_drive_id}. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при подключении сетевого диска" + ); + } +}; + +export const mountNetworkDriveTool = { + name: ToolNames.MOUNT_NETWORK_DRIVE, + title: "Подключение сетевого диска к сервису", + description: + "Подключает сетевой диск к сервису (серверу). Сервис и диск должны быть в одной зоне доступности. Доступные для подключения сервисы можно получить через list_network_drive_available_resources.", + inputSchema, + handler, +}; diff --git a/src/tools/reboot-server.tool.ts b/src/tools/reboot-server.tool.ts new file mode 100644 index 0000000..21102e0 --- /dev/null +++ b/src/tools/reboot-server.tool.ts @@ -0,0 +1,35 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { rebootServerAction } from "../actions/reboot-server.action"; + +const inputSchema = { + server_id: z + .number() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID сервера для перезагрузки"), +}; + +const handler = async (params: { server_id: number }) => { + try { + await rebootServerAction(params.server_id); + return createToolResponse( + `✅ Команда мягкой перезагрузки (ACPI reboot) отправлена для сервера ${params.server_id}. Статус перейдёт в rebooting → on.` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось перезагрузить сервер ${params.server_id}. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при перезагрузке"); + } +}; + +export const rebootServerTool = { + name: ToolNames.REBOOT_SERVER, + title: "Перезагрузка сервера", + description: + "Мягко перезагружает сервер через ACPI reboot. ОС корректно завершает процессы перед рестартом. Используй для применения обновлений ядра или сброса подвисшего состояния.", + inputSchema, + handler, +}; diff --git a/src/tools/reduce-k8s-node-group-nodes.tool.ts b/src/tools/reduce-k8s-node-group-nodes.tool.ts new file mode 100644 index 0000000..327f29c --- /dev/null +++ b/src/tools/reduce-k8s-node-group-nodes.tool.ts @@ -0,0 +1,47 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { reduceK8sNodeGroupNodesAction } from "../actions/reduce-k8s-node-group-nodes.action"; + +const inputSchema = { + cluster_id: z.number().int().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID кластера"), + group_id: z.number().int().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID группы нод"), + count: z + .number() + .int() + .min(1) + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - количество удаляемых нод"), +}; + +const handler = async (params: { + cluster_id: number; + group_id: number; + count: number; +}) => { + try { + await reduceK8sNodeGroupNodesAction( + params.cluster_id, + params.group_id, + params.count + ); + return createToolResponse( + `✅ Из группы ${params.group_id} кластера ${params.cluster_id} удалено ${params.count} нод.` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка уменьшения количества нод. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при уменьшении нод"); + } +}; + +export const reduceK8sNodeGroupNodesTool = { + name: ToolNames.REDUCE_K8S_NODE_GROUP_NODES, + title: "Уменьшение количества нод в группе", + description: + "Удаляет указанное количество воркер-нод из группы. Действие необратимо — удалённые ноды нельзя восстановить.", + inputSchema, + handler, +}; diff --git a/src/tools/refresh-api-key.tool.ts b/src/tools/refresh-api-key.tool.ts new file mode 100644 index 0000000..ec5a7a4 --- /dev/null +++ b/src/tools/refresh-api-key.tool.ts @@ -0,0 +1,59 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { refreshApiKeyAction } from "../actions/refresh-api-key.action"; +import { RefreshApiKeyRequestDto } from "../types/dto/refresh-api-key-request.dto"; + +const inputSchema = { + token_id: z + .string() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID API-токена, который нужно перевыпустить"), + expire: z + .string() + .optional() + .describe( + "Новое время истечения токена в ISO8601 (например 2026-12-31T23:59:59Z). Если не указано — без срока" + ), +}; + +const handler = async (params: { token_id: string; expire?: string }) => { + try { + const data: RefreshApiKeyRequestDto = {}; + if (params.expire !== undefined) data.expire = params.expire; + + const apiKey = await refreshApiKeyAction(params.token_id, data); + + const expires = apiKey.expired_at + ? new Date(apiKey.expired_at).toLocaleString("ru-RU") + : "без срока"; + + return createToolResponse(`✅ API-токен перевыпущен + +⚠️ ВНИМАНИЕ: новое значение токена показывается только один раз. Сохраните его: + +Token: ${apiKey.token} + +📋 Детали: +• ID: ${apiKey.id} +• Имя: ${apiKey.name} +• Истекает: ${expires}`); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка при перевыпуске API-токена. Причина: ${error.message}` + ); + } + return createToolResponse( + `❌ Неизвестная ошибка при перевыпуске API-токена` + ); + } +}; + +export const refreshApiKeyTool = { + name: ToolNames.REFRESH_API_KEY, + title: "Перевыпуск API-токена", + description: + "Перевыпускает существующий API-токен. Возвращает новое значение токена (один раз)", + inputSchema, + handler, +}; diff --git a/src/tools/remove-balancer-ips.tool.ts b/src/tools/remove-balancer-ips.tool.ts new file mode 100644 index 0000000..e2070bb --- /dev/null +++ b/src/tools/remove-balancer-ips.tool.ts @@ -0,0 +1,45 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { removeBalancerIpsAction } from "../actions/remove-balancer-ips.action"; + +const inputSchema = { + balancer_id: z + .number() + .int() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID балансировщика"), + ips: z + .array(z.string()) + .min(1) + .describe( + "ОБЯЗАТЕЛЬНОЕ ПОЛЕ - массив backend IP-адресов для удаления" + ), +}; + +const handler = async (params: { balancer_id: number; ips: string[] }) => { + try { + await removeBalancerIpsAction(params.balancer_id, params.ips); + + return createToolResponse( + `✅ Удалено IP у балансировщика ${params.balancer_id} (${params.ips.length}):\n${params.ips.map((i) => `• ${i}`).join("\n")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка удаления IP у балансировщика ${params.balancer_id}. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при удалении IP у балансировщика" + ); + } +}; + +export const removeBalancerIpsTool = { + name: ToolNames.REMOVE_BALANCER_IPS, + title: "Удаление IP у балансировщика", + description: + "Удаляет backend IP-адреса у балансировщика (снимает их из распределения трафика).", + inputSchema, + handler, +}; diff --git a/src/tools/remove-ssh-key-from-server.tool.ts b/src/tools/remove-ssh-key-from-server.tool.ts new file mode 100644 index 0000000..fddc805 --- /dev/null +++ b/src/tools/remove-ssh-key-from-server.tool.ts @@ -0,0 +1,39 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { removeSshKeyFromServerAction } from "../actions/remove-ssh-key-from-server.action"; + +const inputSchema = { + server_id: z.number().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID сервера"), + ssh_key_id: z + .number() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID SSH-ключа, который нужно снять с сервера"), +}; + +const handler = async (params: { server_id: number; ssh_key_id: number }) => { + try { + await removeSshKeyFromServerAction(params.server_id, params.ssh_key_id); + + return createToolResponse( + `✅ SSH-ключ ${params.ssh_key_id} снят с сервера ${params.server_id}.` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось снять SSH-ключ ${params.ssh_key_id} с сервера ${params.server_id}. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при снятии SSH-ключа с сервера" + ); + } +}; + +export const removeSshKeyFromServerTool = { + name: ToolNames.REMOVE_SSH_KEY_FROM_SERVER, + title: "Снятие SSH-ключа с сервера", + description: + "Удаляет конкретный SSH-ключ с сервера. Сам ключ в аккаунте остаётся — удаляется только привязка к серверу. Для полного удаления ключа используй delete_ssh_key.", + inputSchema, + handler, +}; diff --git a/src/tools/reset-server-password.tool.ts b/src/tools/reset-server-password.tool.ts new file mode 100644 index 0000000..5a9dad3 --- /dev/null +++ b/src/tools/reset-server-password.tool.ts @@ -0,0 +1,36 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { resetServerPasswordAction } from "../actions/reset-server-password.action"; + +const inputSchema = { + server_id: z + .number() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID сервера, у которого сбросить пароль"), +}; + +const handler = async (params: { server_id: number }) => { + try { + await resetServerPasswordAction(params.server_id); + return createToolResponse( + `✅ Запрос на сброс пароля сервера ${params.server_id} отправлен.\n` + + `Новый пароль root придёт на email, привязанный к аккаунту.` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось сбросить пароль сервера ${params.server_id}. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при сбросе пароля"); + } +}; + +export const resetServerPasswordTool = { + name: ToolNames.RESET_SERVER_PASSWORD, + title: "Сброс пароля root сервера", + description: + "Инициирует сброс root-пароля сервера. Новый пароль отправляется на email владельца аккаунта.", + inputSchema, + handler, +}; diff --git a/src/tools/resize-server.tool.ts b/src/tools/resize-server.tool.ts new file mode 100644 index 0000000..b56bf10 --- /dev/null +++ b/src/tools/resize-server.tool.ts @@ -0,0 +1,94 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { resizeServerAction } from "../actions/resize-server.action"; + +const inputSchema = { + server_id: z.number().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID сервера"), + preset_id: z + .number() + .optional() + .describe( + "Режим 1: ID готового тарифа. Нельзя использовать вместе с configurator_id." + ), + configurator_id: z + .number() + .optional() + .describe( + "Режим 2: ID конфигуратора (для кастомной конфигурации). Нельзя использовать вместе с preset_id." + ), + cpu: z + .number() + .optional() + .describe("Для configurator-режима: количество ядер CPU"), + ram: z + .number() + .optional() + .describe("Для configurator-режима: RAM в МБ"), + disk: z + .number() + .optional() + .describe("Для configurator-режима: размер диска в МБ"), + gpu: z + .number() + .optional() + .describe("Для configurator-режима: количество GPU"), +}; + +const handler = async (params: { + server_id: number; + preset_id?: number; + configurator_id?: number; + cpu?: number; + ram?: number; + disk?: number; + gpu?: number; +}) => { + if (params.preset_id && params.configurator_id) { + return createToolResponse( + "❌ Нельзя передавать одновременно preset_id и configurator_id. Выбери один режим." + ); + } + if (!params.preset_id && !params.configurator_id) { + return createToolResponse( + "❌ Нужен либо preset_id (готовый тариф), либо configurator_id (кастомная конфигурация)." + ); + } + + try { + const body = params.preset_id + ? { preset_id: params.preset_id } + : { + configurator: { + configurator_id: params.configurator_id!, + ...(params.cpu !== undefined && { cpu: params.cpu }), + ...(params.ram !== undefined && { ram: params.ram }), + ...(params.disk !== undefined && { disk: params.disk }), + ...(params.gpu !== undefined && { gpu: params.gpu }), + }, + }; + + const server = await resizeServerAction(params.server_id, body); + return createToolResponse( + `✅ Сервер ${server.id} переконфигурирован.\n` + + `Новая конфигурация: CPU ${server.cpu}, RAM ${server.ram} MB, preset ${server.preset_id ?? "custom"}.\n` + + `Статус: ${server.status} — процесс ресайза занимает несколько минут.` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось изменить конфигурацию сервера ${params.server_id}. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при ресайзе"); + } +}; + +export const resizeServerTool = { + name: ToolNames.RESIZE_SERVER, + title: "Изменение конфигурации сервера", + description: + "Меняет тариф (preset_id) или кастомную конфигурацию (configurator_id + cpu/ram/disk/gpu). Применяется к существующему серверу — потребуется downtime. Для получения списка presets используй get_allowed_presets.", + inputSchema, + handler, +}; diff --git a/src/tools/set-server-boot-mode.tool.ts b/src/tools/set-server-boot-mode.tool.ts new file mode 100644 index 0000000..7c57c9f --- /dev/null +++ b/src/tools/set-server-boot-mode.tool.ts @@ -0,0 +1,51 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { setServerBootModeAction } from "../actions/set-server-boot-mode.action"; +import { ServerBootMode } from "../api/servers"; + +const BOOT_MODES: ServerBootMode[] = ["default", "single", "recovery_disk"]; + +const inputSchema = { + server_id: z.number().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID сервера"), + boot_mode: z + .enum(["default", "single", "recovery_disk"]) + .describe( + "ОБЯЗАТЕЛЬНОЕ ПОЛЕ - тип загрузки: default (обычный), single (однопользовательский), recovery_disk (диск восстановления)" + ), +}; + +const handler = async (params: { + server_id: number; + boot_mode: ServerBootMode; +}) => { + if (!BOOT_MODES.includes(params.boot_mode)) { + return createToolResponse( + `❌ Неверный boot_mode: ${params.boot_mode}. Допустимые: ${BOOT_MODES.join(", ")}.` + ); + } + + try { + await setServerBootModeAction(params.server_id, params.boot_mode); + return createToolResponse( + `✅ Тип загрузки сервера ${params.server_id} установлен: ${params.boot_mode}.\n` + + `Сервер будет перезагружен для применения изменения.` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось изменить boot_mode сервера ${params.server_id}. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при смене boot-mode"); + } +}; + +export const setServerBootModeTool = { + name: ToolNames.SET_SERVER_BOOT_MODE, + title: "Установка типа загрузки ОС сервера", + description: + "Меняет boot_mode сервера: default (штатный), single (однопользовательский — для восстановления root), recovery_disk (загрузка с диска восстановления). Сервер перезагружается.", + inputSchema, + handler, +}; diff --git a/src/tools/set-server-nat-mode.tool.ts b/src/tools/set-server-nat-mode.tool.ts new file mode 100644 index 0000000..4dcd1a9 --- /dev/null +++ b/src/tools/set-server-nat-mode.tool.ts @@ -0,0 +1,50 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { setServerNatModeAction } from "../actions/set-server-nat-mode.action"; +import { ServerNatMode } from "../api/servers"; + +const NAT_MODES: ServerNatMode[] = ["dnat_and_snat", "snat", "no_nat"]; + +const inputSchema = { + server_id: z.number().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID сервера"), + nat_mode: z + .enum(["dnat_and_snat", "snat", "no_nat"]) + .describe( + "ОБЯЗАТЕЛЬНОЕ ПОЛЕ - правило маршрутизации: dnat_and_snat (входящий + исходящий), snat (только исходящий), no_nat (только локальная сеть)" + ), +}; + +const handler = async (params: { + server_id: number; + nat_mode: ServerNatMode; +}) => { + if (!NAT_MODES.includes(params.nat_mode)) { + return createToolResponse( + `❌ Неверный nat_mode: ${params.nat_mode}. Допустимые: ${NAT_MODES.join(", ")}.` + ); + } + + try { + await setServerNatModeAction(params.server_id, params.nat_mode); + return createToolResponse( + `✅ NAT-режим сервера ${params.server_id} установлен: ${params.nat_mode}.` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось изменить NAT-режим сервера ${params.server_id}. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при смене NAT-режима"); + } +}; + +export const setServerNatModeTool = { + name: ToolNames.SET_SERVER_NAT_MODE, + title: "Установка NAT-режима сервера в локальной сети", + description: + "Меняет правила маршрутизации трафика: dnat_and_snat (полный доступ), snat (только исходящий), no_nat (изоляция в локальной сети).", + inputSchema, + handler, +}; diff --git a/src/tools/shutdown-server.tool.ts b/src/tools/shutdown-server.tool.ts new file mode 100644 index 0000000..18d4f34 --- /dev/null +++ b/src/tools/shutdown-server.tool.ts @@ -0,0 +1,35 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { shutdownServerAction } from "../actions/shutdown-server.action"; + +const inputSchema = { + server_id: z + .number() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID сервера для выключения"), +}; + +const handler = async (params: { server_id: number }) => { + try { + await shutdownServerAction(params.server_id); + return createToolResponse( + `✅ Команда мягкого выключения (ACPI shutdown) отправлена для сервера ${params.server_id}. Статус перейдёт в turning_off → off.` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось выключить сервер ${params.server_id}. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при выключении сервера"); + } +}; + +export const shutdownServerTool = { + name: ToolNames.SHUTDOWN_SERVER, + title: "Выключение сервера", + description: + "Мягко выключает сервер через ACPI shutdown (аналог нажатия кнопки питания). ОС корректно завершает процессы. Для принудительного выключения используй hard-shutdown через /action API (не покрыто этим tool-ом).", + inputSchema, + handler, +}; diff --git a/src/tools/start-server.tool.ts b/src/tools/start-server.tool.ts new file mode 100644 index 0000000..da4482b --- /dev/null +++ b/src/tools/start-server.tool.ts @@ -0,0 +1,35 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { startServerAction } from "../actions/start-server.action"; + +const inputSchema = { + server_id: z + .number() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID сервера для запуска"), +}; + +const handler = async (params: { server_id: number }) => { + try { + await startServerAction(params.server_id); + return createToolResponse( + `✅ Команда запуска отправлена для сервера ${params.server_id}. Статус перейдёт в turning_on → on через несколько секунд.` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось запустить сервер ${params.server_id}. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при запуске сервера"); + } +}; + +export const startServerTool = { + name: ToolNames.START_SERVER, + title: "Запуск сервера", + description: + "Запускает выключенный VPS. Идемпотентен: на уже работающем сервере вернёт ошибку. Проверь статус через get_server перед вызовом.", + inputSchema, + handler, +}; diff --git a/src/tools/transfer-bucket.tool.ts b/src/tools/transfer-bucket.tool.ts new file mode 100644 index 0000000..c17f736 --- /dev/null +++ b/src/tools/transfer-bucket.tool.ts @@ -0,0 +1,80 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { transferBucketAction } from "../actions/transfer-bucket.action"; + +const inputSchema = { + access_key: z + .string() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - access_key от стороннего S3-хранилища"), + secret_key: z + .string() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - secret_key от стороннего S3-хранилища"), + location: z + .string() + .describe( + "ОБЯЗАТЕЛЬНОЕ ПОЛЕ - регион источника, например 'ru-1'" + ), + is_force_path_style: z + .boolean() + .describe( + "ОБЯЗАТЕЛЬНОЕ ПОЛЕ - принудительно использовать path-style URL для S3-объектов" + ), + endpoint: z + .string() + .describe( + "ОБЯЗАТЕЛЬНОЕ ПОЛЕ - URL источника (например 'https://s3.test.ru')" + ), + bucket_name: z + .string() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - имя хранилища источника"), + new_bucket_name: z + .string() + .describe( + "ОБЯЗАТЕЛЬНОЕ ПОЛЕ - имя хранилища-получателя в Timeweb Cloud" + ), +}; + +const handler = async (params: { + access_key: string; + secret_key: string; + location: string; + is_force_path_style: boolean; + endpoint: string; + bucket_name: string; + new_bucket_name: string; +}) => { + try { + await transferBucketAction({ + access_key: params.access_key, + secret_key: params.secret_key, + location: params.location, + is_force_path_style: params.is_force_path_style, + endpoint: params.endpoint, + bucket_name: params.bucket_name, + new_bucket_name: params.new_bucket_name, + }); + + return createToolResponse( + `✅ Запущен перенос хранилища '${params.bucket_name}' (${params.endpoint}) → '${params.new_bucket_name}' в Timeweb Cloud.\n\nИспользуй get_bucket_transfer_status чтобы отслеживать прогресс.` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка запуска переноса хранилища. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при запуске переноса хранилища" + ); + } +}; + +export const transferBucketTool = { + name: ToolNames.TRANSFER_BUCKET, + title: "Перенос S3-хранилища от стороннего провайдера", + description: + "Запускает перенос S3-хранилища от стороннего провайдера (указывается endpoint, access_key, secret_key, имя bucket) в Timeweb Cloud под именем new_bucket_name. Мониторь прогресс через get_bucket_transfer_status.", + inputSchema, + handler, +}; diff --git a/src/tools/transfer-project-resource.tool.ts b/src/tools/transfer-project-resource.tool.ts new file mode 100644 index 0000000..773fd5d --- /dev/null +++ b/src/tools/transfer-project-resource.tool.ts @@ -0,0 +1,69 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { ProjectResourceTypeEnum } from "../types/project-resource-type.enum"; +import { transferProjectResourceAction } from "../actions/transfer-project-resource.action"; + +const inputSchema = { + from_project_id: z + .number() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID проекта-источника"), + to_project_id: z + .number() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID проекта-приёмника"), + resource_id: z + .number() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID переносимого ресурса"), + resource_type: z + .nativeEnum(ProjectResourceTypeEnum) + .describe( + "ОБЯЗАТЕЛЬНОЕ ПОЛЕ - тип ресурса: server | balancer | database | kubernetes | storage | dedicated" + ), +}; + +const handler = async (params: { + from_project_id: number; + to_project_id: number; + resource_id: number; + resource_type: ProjectResourceTypeEnum; +}) => { + try { + const allowedTypes = Object.values(ProjectResourceTypeEnum); + if (!allowedTypes.includes(params.resource_type)) { + return createToolResponse( + `❌ Неверный resource_type: ${params.resource_type}. Доступны: ${allowedTypes.join(", ")}` + ); + } + + const r = await transferProjectResourceAction( + params.from_project_id, + params.to_project_id, + params.resource_id, + params.resource_type + ); + + return createToolResponse( + `✅ Ресурс перенесён.\n` + + `• Тип: ${r.type}\n` + + `• resource_id: ${r.resource_id}\n` + + `• Новый проект: ${r.project?.id ?? params.to_project_id} (${r.project?.name ?? "—"})\n` + + `• ID связи: ${r.id}, создан: ${new Date(r.created_at).toLocaleString("ru-RU")}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось перенести ресурс ${params.resource_id} (${params.resource_type}). Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при переносе ресурса"); + } +}; + +export const transferProjectResourceTool = { + name: ToolNames.TRANSFER_PROJECT_RESOURCE, + title: "Перенос ресурса в другой проект", + description: + "Переносит сервер/БД/балансировщик/хранилище/кластер/dedicated из одного проекта в другой. resource_type обязателен.", + inputSchema, + handler, +}; diff --git a/src/tools/unbind-floating-ip.tool.ts b/src/tools/unbind-floating-ip.tool.ts new file mode 100644 index 0000000..c1acefd --- /dev/null +++ b/src/tools/unbind-floating-ip.tool.ts @@ -0,0 +1,36 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { unbindFloatingIpAction } from "../actions/unbind-floating-ip.action"; + +const inputSchema = { + floating_ip_id: z + .string() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID плавающего IP"), +}; + +const handler = async (params: { floating_ip_id: string }) => { + try { + await unbindFloatingIpAction(params.floating_ip_id); + return createToolResponse( + `✅ Плавающий IP ${params.floating_ip_id} отвязан от сервиса.` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка при отвязке плавающего IP. Причина: ${error.message}` + ); + } + return createToolResponse( + `❌ Неизвестная ошибка при отвязке плавающего IP` + ); + } +}; + +export const unbindFloatingIpTool = { + name: ToolNames.UNBIND_FLOATING_IP, + title: "Отвязка плавающего IP от сервиса", + description: "Отвязывает плавающий IP от текущего сервиса", + inputSchema, + handler, +}; diff --git a/src/tools/uninstall-k8s-addon.tool.ts b/src/tools/uninstall-k8s-addon.tool.ts new file mode 100644 index 0000000..4d4b5ef --- /dev/null +++ b/src/tools/uninstall-k8s-addon.tool.ts @@ -0,0 +1,39 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { uninstallK8sAddonAction } from "../actions/uninstall-k8s-addon.action"; + +const inputSchema = { + cluster_id: z.number().int().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID кластера"), + addon_id: z + .number() + .int() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID дополнения для удаления"), +}; + +const handler = async (params: { cluster_id: number; addon_id: number }) => { + try { + await uninstallK8sAddonAction(params.cluster_id, params.addon_id); + return createToolResponse( + `✅ Дополнение ${params.addon_id} удалено из кластера ${params.cluster_id}.` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка удаления дополнения. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при удалении дополнения" + ); + } +}; + +export const uninstallK8sAddonTool = { + name: ToolNames.UNINSTALL_K8S_ADDON, + title: "Удаление дополнения из кластера", + description: + "Удаляет установленное ранее дополнение из кластера. Действие необратимо.", + inputSchema, + handler, +}; diff --git a/src/tools/unlink-firewall-resource.tool.ts b/src/tools/unlink-firewall-resource.tool.ts new file mode 100644 index 0000000..b8bb06c --- /dev/null +++ b/src/tools/unlink-firewall-resource.tool.ts @@ -0,0 +1,54 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { unlinkFirewallResourceAction } from "../actions/unlink-firewall-resource.action"; +import { FirewallResourceType } from "../types/firewall-resource.type"; + +const inputSchema = { + group_id: z + .string() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID группы правил firewall"), + resource_id: z + .string() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID ресурса (например, ID сервера)"), + resource_type: z + .enum(["server"]) + .optional() + .describe("Тип ресурса. По умолчанию: server"), +}; + +const handler = async (params: { + group_id: string; + resource_id: string; + resource_type?: FirewallResourceType; +}) => { + try { + await unlinkFirewallResourceAction( + params.group_id, + params.resource_id, + params.resource_type + ); + + return createToolResponse( + `✅ Ресурс ${params.resource_id} отвязан от группы firewall ${params.group_id}.` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось отвязать ресурс ${params.resource_id} от группы ${params.group_id}. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при отвязке ресурса от группы firewall" + ); + } +}; + +export const unlinkFirewallResourceTool = { + name: ToolNames.UNLINK_FIREWALL_RESOURCE, + title: "Отвязка ресурса от группы firewall", + description: + "Отвязывает ресурс от группы правил firewall. После отвязки правила группы перестают действовать на этот ресурс.", + inputSchema, + handler, +}; diff --git a/src/tools/unmount-network-drive.tool.ts b/src/tools/unmount-network-drive.tool.ts new file mode 100644 index 0000000..d7450cc --- /dev/null +++ b/src/tools/unmount-network-drive.tool.ts @@ -0,0 +1,37 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { unmountNetworkDriveAction } from "../actions/unmount-network-drive.action"; + +const inputSchema = { + network_drive_id: z + .string() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID сетевого диска (UUID)"), +}; + +const handler = async (params: { network_drive_id: string }) => { + try { + await unmountNetworkDriveAction(params.network_drive_id); + return createToolResponse( + `✅ Сетевой диск ${params.network_drive_id} отключён от сервиса.` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось отключить сетевой диск ${params.network_drive_id}. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при отключении сетевого диска" + ); + } +}; + +export const unmountNetworkDriveTool = { + name: ToolNames.UNMOUNT_NETWORK_DRIVE, + title: "Отключение сетевого диска от сервиса", + description: + "Отключает сетевой диск от сервиса (сервера), к которому он был подключён. Перед удалением диска его нужно отключить.", + inputSchema, + handler, +}; diff --git a/src/tools/unmount-server-image.tool.ts b/src/tools/unmount-server-image.tool.ts new file mode 100644 index 0000000..e344f8b --- /dev/null +++ b/src/tools/unmount-server-image.tool.ts @@ -0,0 +1,35 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { unmountServerImageAction } from "../actions/unmount-server-image.action"; + +const inputSchema = { + server_id: z.number().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID сервера"), +}; + +const handler = async (params: { server_id: number }) => { + try { + await unmountServerImageAction(params.server_id); + return createToolResponse( + `✅ ISO-образ сервера ${params.server_id} отмонтирован. Сервер перезагружается для продолжения штатной работы.` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось отмонтировать ISO сервера ${params.server_id}. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при отмонтировании ISO" + ); + } +}; + +export const unmountServerImageTool = { + name: ToolNames.UNMOUNT_SERVER_IMAGE, + title: "Отмонтирование ISO-образа сервера", + description: + "Отмонтирует примонтированный ISO-образ и перезагружает сервер в штатном режиме.", + inputSchema, + handler, +}; diff --git a/src/tools/update-ai-agent.tool.ts b/src/tools/update-ai-agent.tool.ts new file mode 100644 index 0000000..1c099bf --- /dev/null +++ b/src/tools/update-ai-agent.tool.ts @@ -0,0 +1,105 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { updateAiAgentAction } from "../actions/update-ai-agent.action"; +import { UpdateAiAgentRequestDto } from "../types/dto/update-ai-agent-request.dto"; + +const inputSchema = { + agent_id: z.number().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID агента"), + name: z.string().optional().describe("Новое название"), + description: z.string().optional().describe("Новое описание"), + access_type: z + .enum(["public", "private"]) + .optional() + .describe("Новый тип доступа"), + status: z.enum(["active", "suspended"]).optional().describe("Новый статус"), + token_package_id: z.number().optional().describe("Новый пакет токенов"), + system_prompt: z.string().optional().describe("Новый system prompt"), + refine_query: z.boolean().optional().describe("Уточнять запрос"), + temperature: z.number().optional().describe("temperature"), + top_p: z.number().optional().describe("top_p"), + max_tokens: z.number().optional().describe("Максимум токенов"), + frequency_penalty: z.number().optional().describe("frequency_penalty"), + presence_penalty: z.number().optional().describe("presence_penalty"), + project_id: z.number().optional().describe("ID проекта"), +}; + +const handler = async (params: { + agent_id: number; + name?: string; + description?: string; + access_type?: "public" | "private"; + status?: "active" | "suspended"; + token_package_id?: number; + system_prompt?: string; + refine_query?: boolean; + temperature?: number; + top_p?: number; + max_tokens?: number; + frequency_penalty?: number; + presence_penalty?: number; + project_id?: number; +}) => { + try { + const body: UpdateAiAgentRequestDto = {}; + if (params.name !== undefined) body.name = params.name; + if (params.description !== undefined) body.description = params.description; + if (params.access_type !== undefined) body.access_type = params.access_type; + if (params.status !== undefined) body.status = params.status; + if (params.token_package_id !== undefined) + body.token_package_id = params.token_package_id; + if (params.project_id !== undefined) body.project_id = params.project_id; + + const modelSettings: Record = {}; + if (params.temperature !== undefined) + modelSettings.temperature = params.temperature; + if (params.top_p !== undefined) modelSettings.top_p = params.top_p; + if (params.max_tokens !== undefined) + modelSettings.max_tokens = params.max_tokens; + if (params.frequency_penalty !== undefined) + modelSettings.frequency_penalty = params.frequency_penalty; + if (params.presence_penalty !== undefined) + modelSettings.presence_penalty = params.presence_penalty; + + const hasSettings = + params.system_prompt !== undefined || + params.refine_query !== undefined || + Object.keys(modelSettings).length > 0; + + if (hasSettings) { + body.settings = { + ...(params.system_prompt !== undefined && { + system_prompt: params.system_prompt, + }), + ...(params.refine_query !== undefined && { + refine_query: params.refine_query, + }), + ...(Object.keys(modelSettings).length > 0 && { + model: modelSettings as any, + }), + } as any; + } + + const agent = await updateAiAgentAction(params.agent_id, body); + return createToolResponse(`✅ AI-агент ${agent.id} обновлён. +• Название: ${agent.name} +• Статус: ${agent.status} +• Тип доступа: ${agent.access_type}`); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось обновить агента ${params.agent_id}. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при обновлении агента"); + } +}; + +export const updateAiAgentTool = { + name: ToolNames.UPDATE_AI_AGENT, + title: "Обновление AI-агента", + description: + "Обновляет параметры AI-агента: имя, описание, статус, access_type, пакет токенов, system prompt и настройки модели. Передавай только поля, которые нужно изменить.", + inputSchema, + handler, +}; diff --git a/src/tools/update-balancer-rule.tool.ts b/src/tools/update-balancer-rule.tool.ts new file mode 100644 index 0000000..ed8247c --- /dev/null +++ b/src/tools/update-balancer-rule.tool.ts @@ -0,0 +1,76 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { updateBalancerRuleAction } from "../actions/update-balancer-rule.action"; + +const BalancerProtoEnum = z.enum(["http", "http2", "https", "tcp"]); + +const inputSchema = { + balancer_id: z + .number() + .int() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID балансировщика"), + rule_id: z + .number() + .int() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID правила"), + balancer_proto: BalancerProtoEnum.describe( + "ОБЯЗАТЕЛЬНОЕ ПОЛЕ - протокол балансировщика" + ), + balancer_port: z + .number() + .int() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - порт балансировщика"), + server_proto: BalancerProtoEnum.describe( + "ОБЯЗАТЕЛЬНОЕ ПОЛЕ - протокол backend-сервера" + ), + server_port: z + .number() + .int() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - порт backend-сервера"), +}; + +const handler = async (params: { + balancer_id: number; + rule_id: number; + balancer_proto: "http" | "http2" | "https" | "tcp"; + balancer_port: number; + server_proto: "http" | "http2" | "https" | "tcp"; + server_port: number; +}) => { + try { + const rule = await updateBalancerRuleAction( + params.balancer_id, + params.rule_id, + { + balancer_proto: params.balancer_proto, + balancer_port: params.balancer_port, + server_proto: params.server_proto, + server_port: params.server_port, + } + ); + + return createToolResponse(`✅ Правило ${rule.id} обновлено (балансировщик ${params.balancer_id}). + +• Вход: ${rule.balancer_proto}:${rule.balancer_port} +• На backend: ${rule.server_proto}:${rule.server_port}`); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка обновления правила ${params.rule_id} балансировщика ${params.balancer_id}. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при обновлении правила балансировщика" + ); + } +}; + +export const updateBalancerRuleTool = { + name: ToolNames.UPDATE_BALANCER_RULE, + title: "Обновление правила балансировщика", + description: + "Обновляет правило маршрутизации балансировщика. Все поля (кроме id) обязательны — API ожидает полное описание правила.", + inputSchema, + handler, +}; diff --git a/src/tools/update-balancer.tool.ts b/src/tools/update-balancer.tool.ts new file mode 100644 index 0000000..f803845 --- /dev/null +++ b/src/tools/update-balancer.tool.ts @@ -0,0 +1,154 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { updateBalancerAction } from "../actions/update-balancer.action"; +import { UpdateBalancerRequestDto } from "../types/dto/update-balancer-request.dto"; + +const BalancerProtoEnum = z.enum(["http", "http2", "https", "tcp"]); +const BalancerAlgoEnum = z.enum(["roundrobin", "leastconn"]); + +const inputSchema = { + balancer_id: z + .number() + .int() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID балансировщика"), + name: z.string().optional().describe("Новое имя (опц.)"), + algo: BalancerAlgoEnum.optional().describe("Алгоритм (опц.)"), + is_sticky: z.boolean().optional().describe("Сохранять сессию (опц.)"), + is_use_proxy: z.boolean().optional().describe("Использовать прокси (опц.)"), + is_ssl: z.boolean().optional().describe("Перенаправление на SSL (опц.)"), + is_keepalive: z.boolean().optional().describe("Keepalive (опц.)"), + proto: BalancerProtoEnum.optional().describe("Протокол (опц.)"), + port: z.number().optional().describe("Порт (опц.)"), + path: z.string().optional().describe("Путь (опц.)"), + inter: z.number().optional().describe("Интервал проверки (опц.)"), + timeout: z.number().optional().describe("Таймаут ответа (опц.)"), + fall: z.number().optional().describe("Порог ошибок (опц.)"), + rise: z.number().optional().describe("Порог успешных (опц.)"), + maxconn: z.number().optional().describe("Макс. соединений (опц.)"), + connect_timeout: z + .number() + .optional() + .describe("Таймаут подключения (опц.)"), + client_timeout: z.number().optional().describe("Таймаут клиента (опц.)"), + server_timeout: z.number().optional().describe("Таймаут сервера (опц.)"), + httprequest_timeout: z + .number() + .optional() + .describe("Таймаут HTTP-запроса (опц.)"), + comment: z.string().optional().describe("Комментарий (опц.)"), + certificate_type: z + .enum(["lets_encrypt", "custom"]) + .optional() + .describe("Тип SSL-сертификата (опц.)"), + certificate_fqdn: z.string().optional().describe("FQDN (опц.)"), + certificate_cert_data: z + .string() + .optional() + .describe("PEM-данные сертификата (опц.)"), + certificate_key_data: z + .string() + .optional() + .describe("PEM-данные приватного ключа (опц.)"), +}; + +const handler = async (params: { + balancer_id: number; + name?: string; + algo?: "roundrobin" | "leastconn"; + is_sticky?: boolean; + is_use_proxy?: boolean; + is_ssl?: boolean; + is_keepalive?: boolean; + proto?: "http" | "http2" | "https" | "tcp"; + port?: number; + path?: string; + inter?: number; + timeout?: number; + fall?: number; + rise?: number; + maxconn?: number; + connect_timeout?: number; + client_timeout?: number; + server_timeout?: number; + httprequest_timeout?: number; + comment?: string; + certificate_type?: "lets_encrypt" | "custom"; + certificate_fqdn?: string; + certificate_cert_data?: string; + certificate_key_data?: string; +}) => { + try { + const payload: UpdateBalancerRequestDto = {}; + const copyIfSet = (k: K) => { + const v = (params as any)[k]; + if (typeof v !== "undefined") (payload as any)[k] = v; + }; + + ( + [ + "name", + "algo", + "is_sticky", + "is_use_proxy", + "is_ssl", + "is_keepalive", + "proto", + "port", + "path", + "inter", + "timeout", + "fall", + "rise", + "maxconn", + "connect_timeout", + "client_timeout", + "server_timeout", + "httprequest_timeout", + "comment", + ] as const + ).forEach(copyIfSet); + + if (params.certificate_type) { + payload.certificates = { + type: params.certificate_type, + fqdn: params.certificate_fqdn, + cert_data: params.certificate_cert_data, + key_data: params.certificate_key_data, + }; + } + + if (Object.keys(payload).length === 0) { + return createToolResponse( + "⚠️ Не указано ни одно поле для обновления балансировщика." + ); + } + + const b = await updateBalancerAction(params.balancer_id, payload); + + return createToolResponse(`✅ Балансировщик ${b.id} обновлён. + +• Имя: ${b.name} +• Статус: ${b.status} +• Протокол/Порт: ${b.proto}:${b.port} +• Алгоритм: ${b.algo}`); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка обновления балансировщика ${params.balancer_id}. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при обновлении балансировщика" + ); + } +}; + +export const updateBalancerTool = { + name: ToolNames.UPDATE_BALANCER, + title: "Обновление балансировщика", + description: + "Обновляет параметры существующего балансировщика. Все поля кроме balancer_id — опциональные; передавай только то, что меняется.", + inputSchema, + handler, +}; diff --git a/src/tools/update-bucket-user.tool.ts b/src/tools/update-bucket-user.tool.ts new file mode 100644 index 0000000..c2a174d --- /dev/null +++ b/src/tools/update-bucket-user.tool.ts @@ -0,0 +1,51 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { updateBucketUserAction } from "../actions/update-bucket-user.action"; + +const inputSchema = { + user_id: z + .number() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID пользователя S3-хранилища"), + secret_key: z + .string() + .min(1) + .max(255) + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - новый secret_key (1-255 символов)"), +}; + +const handler = async (params: { user_id: number; secret_key: string }) => { + try { + const user = await updateBucketUserAction( + params.user_id, + params.secret_key + ); + + return createToolResponse(`✅ Пароль пользователя ${user.id} обновлён. + +📋 Параметры: +• ID: ${user.id} +• Access key: ${user.access_key} +• Secret key: ${user.secret_key} + +⚠️ Обнови конфигурацию всех клиентов, подключающихся к хранилищу.`); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка обновления пароля пользователя ${params.user_id}. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при обновлении пароля пользователя" + ); + } +}; + +export const updateBucketUserTool = { + name: ToolNames.UPDATE_BUCKET_USER, + title: "Изменение пароля пользователя S3-хранилища", + description: + "Меняет secret_key пользователя-администратора S3-хранилища. После смены пароля нужно обновить конфигурацию всех клиентов, подключающихся к хранилищу.", + inputSchema, + handler, +}; diff --git a/src/tools/update-bucket.tool.ts b/src/tools/update-bucket.tool.ts new file mode 100644 index 0000000..056dbaf --- /dev/null +++ b/src/tools/update-bucket.tool.ts @@ -0,0 +1,100 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { updateBucketAction } from "../actions/update-bucket.action"; + +const inputSchema = { + bucket_id: z.number().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID S3-хранилища"), + preset_id: z + .number() + .optional() + .describe("Новый ID тарифа. Нельзя вместе с configurator (опц.)"), + configurator_id: z + .number() + .optional() + .describe("ID конфигуратора хранилища. Нельзя вместе с preset_id (опц.)"), + configurator_disk_mb: z + .number() + .optional() + .describe("Новый размер диска в МБ для конфигуратора (опц.)"), + bucket_type: z + .enum(["private", "public"]) + .optional() + .describe("Новый тип хранилища: private/public (опц.)"), + description: z + .string() + .min(1) + .max(255) + .optional() + .describe("Новый комментарий (1-255 символов, опц.)"), +}; + +const handler = async (params: { + bucket_id: number; + preset_id?: number; + configurator_id?: number; + configurator_disk_mb?: number; + bucket_type?: "private" | "public"; + description?: string; +}) => { + try { + const hasPreset = params.preset_id !== undefined; + const hasConfigurator = + params.configurator_id !== undefined || + params.configurator_disk_mb !== undefined; + + if (hasPreset && hasConfigurator) { + return createToolResponse( + "❌ Нельзя передавать одновременно preset_id и конфигуратор." + ); + } + + const body: any = {}; + if (hasPreset) body.preset_id = params.preset_id; + if (hasConfigurator) { + body.configurator = {}; + if (params.configurator_id !== undefined) + body.configurator.id = params.configurator_id; + if (params.configurator_disk_mb !== undefined) + body.configurator.disk = params.configurator_disk_mb; + } + if (params.bucket_type) body.bucket_type = params.bucket_type; + if (params.description) body.description = params.description; + + if (Object.keys(body).length === 0) { + return createToolResponse( + "❌ Передай хотя бы один параметр для изменения (preset_id, configurator, bucket_type, description)." + ); + } + + const bucket = await updateBucketAction(params.bucket_id, body); + + return createToolResponse(`✅ S3-хранилище ${bucket.id} обновлено. + +📋 Актуальные параметры: +• Название: ${bucket.name} +• Тип: ${bucket.type} +• Класс хранилища: ${bucket.storage_class} +• Preset ID: ${bucket.preset_id ?? "—"} +• Configurator ID: ${bucket.configurator_id ?? "—"} +• Описание: ${bucket.description || "—"}`); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка обновления S3-хранилища ${params.bucket_id}. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при обновлении S3-хранилища" + ); + } +}; + +export const updateBucketTool = { + name: ToolNames.UPDATE_BUCKET, + title: "Изменение S3-хранилища", + description: + "Изменяет параметры S3-хранилища: preset_id ИЛИ configurator (disk, configurator_id), bucket_type (private/public), описание. Нельзя передавать одновременно preset_id и configurator.", + inputSchema, + handler, +}; diff --git a/src/tools/update-container-registry.tool.ts b/src/tools/update-container-registry.tool.ts new file mode 100644 index 0000000..cbb59c8 --- /dev/null +++ b/src/tools/update-container-registry.tool.ts @@ -0,0 +1,91 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { updateContainerRegistryAction } from "../actions/update-container-registry.action"; + +const inputSchema = { + registry_id: z + .number() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID реестра для обновления"), + description: z.string().optional().describe("Новое описание реестра"), + preset_id: z + .number() + .optional() + .describe("Новый ID тарифа. Нельзя вместе с configurator_id."), + configurator_id: z + .number() + .optional() + .describe( + "ID конфигуратора для кастомной конфигурации. Нельзя вместе с preset_id." + ), + disk: z + .number() + .optional() + .describe( + "Для configurator-режима: размер диска в ГБ. ОБЯЗАТЕЛЬНО если передан configurator_id." + ), +}; + +const handler = async (params: { + registry_id: number; + description?: string; + preset_id?: number; + configurator_id?: number; + disk?: number; +}) => { + if (params.preset_id && params.configurator_id) { + return createToolResponse( + "❌ Нельзя передавать одновременно preset_id и configurator_id. Выбери один режим." + ); + } + if (params.configurator_id && !params.disk) { + return createToolResponse( + "❌ При использовании configurator_id обязательно укажи disk (размер диска в ГБ)." + ); + } + if ( + params.description === undefined && + !params.preset_id && + !params.configurator_id + ) { + return createToolResponse( + "❌ Нужно передать хотя бы одно поле для обновления: description, preset_id или configurator_id." + ); + } + + try { + const body: any = {}; + if (params.description !== undefined) body.description = params.description; + if (params.preset_id) body.preset_id = params.preset_id; + if (params.configurator_id) + body.configuration = { + id: params.configurator_id, + disk: params.disk!, + }; + + const r = await updateContainerRegistryAction(params.registry_id, body); + return createToolResponse( + `✅ Реестр ${r.id} обновлён.\n` + + `Имя: ${r.name}\n` + + `Описание: ${r.description || "—"}\n` + + `Preset ID: ${r.preset_id}, Configurator ID: ${r.configurator_id}\n` + + `Диск: ${r.disk_stats.used}/${r.disk_stats.size} ГБ` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось обновить реестр ${params.registry_id}. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при обновлении реестра"); + } +}; + +export const updateContainerRegistryTool = { + name: ToolNames.UPDATE_CONTAINER_REGISTRY, + title: "Обновление реестра контейнеров", + description: + "Изменяет параметры реестра контейнеров: описание, тариф (preset_id) или кастомную конфигурацию (configurator_id + disk). Имя реестра изменить нельзя.", + inputSchema, + handler, +}; diff --git a/src/tools/update-database-admin.tool.ts b/src/tools/update-database-admin.tool.ts new file mode 100644 index 0000000..7980d58 --- /dev/null +++ b/src/tools/update-database-admin.tool.ts @@ -0,0 +1,104 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { updateDatabaseAdminAction } from "../actions/update-database-admin.action"; + +const PRIVILEGES = [ + "ALTER", + "CREATE_VIEW", + "CREATE", + "DELETE", + "DROP", + "EVENT", + "INDEX", + "INSERT", + "LOCK_TABLES", + "REFERENCES", + "SELECT", + "SHOW_VIEW", + "TRUNCATE", + "UPDATE", + "READ", + "WRITE", + "CONNECTION", + "FAST", + "readWrite", + "ALTER_ROUTINE", + "CREATE_ROUTINE", + "TRANSACTION", + "SLOW_LOG", + "TRIGGER", + "CREATE_TEMPORARY_TABLES", +] as const; + +const inputSchema = { + db_cluster_id: z + .number() + .int() + .positive() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID кластера базы данных"), + admin_id: z + .number() + .int() + .positive() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID пользователя"), + password: z + .string() + .min(8) + .optional() + .describe("НЕ ОБЯЗАТЕЛЬНОЕ ПОЛЕ - новый пароль (мин. 8 символов)"), + privileges: z + .array(z.enum(PRIVILEGES)) + .optional() + .describe("НЕ ОБЯЗАТЕЛЬНОЕ ПОЛЕ - новый список привилегий"), + description: z + .string() + .optional() + .describe("НЕ ОБЯЗАТЕЛЬНОЕ ПОЛЕ - описание"), + instance_id: z + .number() + .int() + .positive() + .optional() + .describe( + "НЕ ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID инстанса для применения привилегий (только MySQL)" + ), +}; + +const handler = async (params: { + db_cluster_id: number; + admin_id: number; + password?: string; + privileges?: string[]; + description?: string; + instance_id?: number; +}) => { + try { + const { db_cluster_id, admin_id, ...data } = params; + if (Object.keys(data).length === 0) { + return createToolResponse( + "❌ Передайте хотя бы одно поле для обновления: password, privileges, description или instance_id" + ); + } + const a = await updateDatabaseAdminAction(db_cluster_id, admin_id, data); + return createToolResponse( + `✅ Пользователь ${a.login} (ID ${a.id}) в кластере ${db_cluster_id} обновлён.` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось обновить пользователя ${params.admin_id}. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при обновлении пользователя"); + } +}; + +export const updateDatabaseAdminTool = { + name: ToolNames.UPDATE_DATABASE_ADMIN, + title: "Изменение пользователя кластера", + description: + "Изменяет параметры пользователя кластера: пароль, привилегии, описание (`PATCH /api/v1/databases/{db_cluster_id}/admins/{admin_id}`).", + inputSchema, + handler, +}; diff --git a/src/tools/update-database-cluster.tool.ts b/src/tools/update-database-cluster.tool.ts new file mode 100644 index 0000000..c50b753 --- /dev/null +++ b/src/tools/update-database-cluster.tool.ts @@ -0,0 +1,67 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { updateDatabaseClusterAction } from "../actions/update-database-cluster.action"; + +const inputSchema = { + db_cluster_id: z + .number() + .int() + .positive() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID кластера базы данных"), + name: z + .string() + .optional() + .describe("НЕ ОБЯЗАТЕЛЬНОЕ ПОЛЕ - новое название кластера"), + preset_id: z + .number() + .int() + .positive() + .optional() + .describe("НЕ ОБЯЗАТЕЛЬНОЕ ПОЛЕ - новый ID тарифа"), + description: z + .string() + .optional() + .describe("НЕ ОБЯЗАТЕЛЬНОЕ ПОЛЕ - описание кластера"), + is_enabled_public_network: z + .boolean() + .optional() + .describe("НЕ ОБЯЗАТЕЛЬНОЕ ПОЛЕ - включить/выключить публичный IP"), +}; + +const handler = async (params: { + db_cluster_id: number; + name?: string; + preset_id?: number; + description?: string; + is_enabled_public_network?: boolean; +}) => { + try { + const { db_cluster_id, ...data } = params; + if (Object.keys(data).length === 0) { + return createToolResponse( + "❌ Необходимо передать хотя бы одно поле для обновления: name, preset_id, description или is_enabled_public_network" + ); + } + const c = await updateDatabaseClusterAction(db_cluster_id, data); + return createToolResponse( + `✅ Кластер ${c.id} (${c.name}) обновлён. Статус: ${c.status}, пресет: ${c.preset_id}.` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось обновить кластер ${params.db_cluster_id}. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при обновлении кластера"); + } +}; + +export const updateDatabaseClusterTool = { + name: ToolNames.UPDATE_DATABASE_CLUSTER, + title: "Изменение кластера базы данных", + description: + "Изменяет параметры кластера базы данных: название, тариф, описание, публичную сеть (`PATCH /api/v1/databases/{db_cluster_id}`).", + inputSchema, + handler, +}; diff --git a/src/tools/update-database-instance.tool.ts b/src/tools/update-database-instance.tool.ts new file mode 100644 index 0000000..73b4dea --- /dev/null +++ b/src/tools/update-database-instance.tool.ts @@ -0,0 +1,62 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { updateDatabaseInstanceAction } from "../actions/update-database-instance.action"; + +const inputSchema = { + db_cluster_id: z + .number() + .int() + .positive() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID кластера базы данных"), + instance_id: z + .number() + .int() + .positive() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID инстанса"), + name: z.string().optional().describe("НЕ ОБЯЗАТЕЛЬНОЕ ПОЛЕ - новое название"), + description: z + .string() + .optional() + .describe("НЕ ОБЯЗАТЕЛЬНОЕ ПОЛЕ - новое описание"), +}; + +const handler = async (params: { + db_cluster_id: number; + instance_id: number; + name?: string; + description?: string; +}) => { + try { + const { db_cluster_id, instance_id, ...data } = params; + if (Object.keys(data).length === 0) { + return createToolResponse( + "❌ Передайте хотя бы одно поле для обновления: name или description" + ); + } + const i = await updateDatabaseInstanceAction( + db_cluster_id, + instance_id, + data + ); + return createToolResponse( + `✅ Инстанс ${i.id} (${i.name}) в кластере ${db_cluster_id} обновлён.` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось обновить инстанс ${params.instance_id}. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при обновлении инстанса"); + } +}; + +export const updateDatabaseInstanceTool = { + name: ToolNames.UPDATE_DATABASE_INSTANCE, + title: "Изменение инстанса кластера", + description: + "Изменяет параметры инстанса базы данных в кластере (`PATCH /api/v1/databases/{db_cluster_id}/instances/{instance_id}`).", + inputSchema, + handler, +}; diff --git a/src/tools/update-dedicated-server.tool.ts b/src/tools/update-dedicated-server.tool.ts new file mode 100644 index 0000000..fd4bfda --- /dev/null +++ b/src/tools/update-dedicated-server.tool.ts @@ -0,0 +1,64 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { updateDedicatedServerAction } from "../actions/update-dedicated-server.action"; + +const inputSchema = { + dedicated_id: z + .number() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID выделенного сервера"), + name: z + .string() + .max(255) + .optional() + .describe("Новое имя сервера (до 255 символов, уникальное)"), + comment: z + .string() + .max(255) + .optional() + .describe("Новый комментарий к серверу (до 255 символов)"), +}; + +const handler = async (params: { + dedicated_id: number; + name?: string; + comment?: string; +}) => { + if (params.name === undefined && params.comment === undefined) { + return createToolResponse( + "❌ Нужно передать хотя бы одно поле для обновления: name или comment." + ); + } + + try { + const body: { name?: string; comment?: string } = {}; + if (params.name !== undefined) body.name = params.name; + if (params.comment !== undefined) body.comment = params.comment; + + const s = await updateDedicatedServerAction(params.dedicated_id, body); + return createToolResponse( + `✅ Выделенный сервер ${s.id} обновлён.\n` + + `Имя: ${s.name}\n` + + `Комментарий: ${s.comment || "—"}\n` + + `Статус: ${s.status}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось обновить выделенный сервер ${params.dedicated_id}. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при обновлении выделенного сервера" + ); + } +}; + +export const updateDedicatedServerTool = { + name: ToolNames.UPDATE_DEDICATED_SERVER, + title: "Обновление выделенного сервера", + description: + "Изменяет параметры выделенного сервера: имя и/или комментарий. Оба поля опциональны, но хотя бы одно должно быть передано.", + inputSchema, + handler, +}; diff --git a/src/tools/update-dns-record.tool.ts b/src/tools/update-dns-record.tool.ts new file mode 100644 index 0000000..aee9a2d --- /dev/null +++ b/src/tools/update-dns-record.tool.ts @@ -0,0 +1,87 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { updateDnsRecordAction } from "../actions/update-dns-record.action"; +import { CreateDnsRecordV2RequestDto } from "../types/dto/create-dns-record-request.dto"; + +const DNS_TYPES = ["A", "AAAA", "TXT", "CNAME", "MX", "SRV"] as const; + +const inputSchema = { + fqdn: z.string().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - полное имя домена"), + record_id: z + .number() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID DNS-записи для обновления"), + type: z + .enum(DNS_TYPES) + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - тип DNS-записи"), + value: z.string().optional().describe("Новое значение DNS-записи"), + ttl: z.number().optional().describe("Новый TTL в секундах"), + priority: z.number().optional().describe("Приоритет (MX, SRV)"), + subdomain: z + .string() + .optional() + .describe("Имя поддомена (только префикс)"), + app_id: z.number().optional().describe("ID приложения App Platform"), + host: z.string().optional().describe("SRV: хост сервиса"), + port: z.number().optional().describe("SRV: порт"), + service: z.string().optional().describe("SRV: имя сервиса"), + protocol: z.string().optional().describe("SRV: протокол"), +}; + +const handler = async (params: { + fqdn: string; + record_id: number; + type: (typeof DNS_TYPES)[number]; + value?: string; + ttl?: number; + priority?: number; + subdomain?: string; + app_id?: number; + host?: string; + port?: number; + service?: string; + protocol?: string; +}) => { + try { + const body: CreateDnsRecordV2RequestDto = { type: params.type }; + if (params.value !== undefined) body.value = params.value; + if (params.ttl !== undefined) body.ttl = params.ttl; + if (params.priority !== undefined) body.priority = params.priority; + if (params.subdomain !== undefined) body.subdomain = params.subdomain; + if (params.app_id !== undefined) body.app_id = params.app_id; + if (params.host !== undefined) body.host = params.host; + if (params.port !== undefined) body.port = params.port; + if (params.service !== undefined) body.service = params.service; + if (params.protocol !== undefined) body.protocol = params.protocol; + + const record = await updateDnsRecordAction( + params.fqdn, + params.record_id, + body + ); + + return createToolResponse(`✅ DNS-запись обновлена! +• ID: ${record.id ?? params.record_id} +• Тип: ${record.type} +• Значение: ${record.data.value ?? "—"} +• TTL: ${record.ttl ?? "default"}`); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка обновления DNS-записи ${params.record_id} для "${params.fqdn}". Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при обновлении DNS-записи" + ); + } +}; + +export const updateDnsRecordTool = { + name: ToolNames.UPDATE_DNS_RECORD, + title: "Обновление DNS-записи", + description: + "Обновляет существующую DNS-запись по ID. Использует API v2. Нужно передать тип записи и новые поля.", + inputSchema, + handler, +}; diff --git a/src/tools/update-domain-name-servers.tool.ts b/src/tools/update-domain-name-servers.tool.ts new file mode 100644 index 0000000..cb5b9ea --- /dev/null +++ b/src/tools/update-domain-name-servers.tool.ts @@ -0,0 +1,59 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { updateDomainNameServersAction } from "../actions/update-domain-name-servers.action"; + +const nameServerSchema = z.object({ + host: z.string().describe("Хост name-сервера, например ns1.timeweb.ru"), + ips: z + .array(z.string()) + .optional() + .describe("Список IP-адресов name-сервера (опц.)"), +}); + +const inputSchema = { + fqdn: z.string().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - полное имя домена"), + name_servers: z + .array(nameServerSchema) + .describe( + "ОБЯЗАТЕЛЬНОЕ ПОЛЕ - новый список name-серверов (каждый с host и опционально ips)" + ), +}; + +const handler = async (params: { + fqdn: string; + name_servers: { host: string; ips?: string[] }[]; +}) => { + try { + if (params.name_servers.length === 0) { + return createToolResponse( + "❌ Список name_servers не может быть пустым." + ); + } + const groups = await updateDomainNameServersAction(params.fqdn, { + name_servers: params.name_servers, + }); + const count = groups.reduce((n, g) => n + g.items.length, 0); + return createToolResponse( + `✅ Name-серверы домена ${params.fqdn} обновлены (записей: ${count}).\nСтатус задачи: ${groups[0]?.task_status ?? "—"}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка обновления name-серверов "${params.fqdn}". Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при обновлении name-серверов" + ); + } +}; + +export const updateDomainNameServersTool = { + name: ToolNames.UPDATE_DOMAIN_NAME_SERVERS, + title: "Обновление name-серверов домена", + description: + "Заменяет список name-серверов у домена. Принимает массив объектов {host, ips?}.", + inputSchema, + handler, +}; diff --git a/src/tools/update-domain-request.tool.ts b/src/tools/update-domain-request.tool.ts new file mode 100644 index 0000000..6095bdc --- /dev/null +++ b/src/tools/update-domain-request.tool.ts @@ -0,0 +1,125 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { updateDomainRequestAction } from "../actions/domain-requests.action"; +import { UpdateDomainRequestBodyDto } from "../types/dto/create-domain-request-request.dto"; + +const PAYMENT_TYPES = [ + "receipt", + "card", + "mobile-card", + "wm", + "webmoney", + "yandex", + "ya", + "invoice", + "sofort", + "qiwi_wallet", + "wechat", +] as const; + +const inputSchema = { + request_id: z + .number() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID заявки для оплаты/обновления"), + money_source: z + .enum(["use", "invoice", "free", "bonus"]) + .describe( + "ОБЯЗАТЕЛЬНОЕ ПОЛЕ - способ оплаты: use (с баланса), invoice (платёжка), free (только для transfer), bonus" + ), + person_id: z.number().optional().describe("ID администратора домена"), + payment_type: z + .enum(PAYMENT_TYPES) + .optional() + .describe("Тип платёжной системы (ОБЯЗАТЕЛЕН для invoice)"), + payer_id: z + .number() + .optional() + .describe("ID плательщика (ОБЯЗАТЕЛЕН для invoice)"), + auth_code: z + .string() + .optional() + .describe("Код авторизации переноса (ОБЯЗАТЕЛЕН для free/transfer)"), + bonus_id: z + .number() + .optional() + .describe("ID бонуса (ОБЯЗАТЕЛЕН для bonus)"), +}; + +const handler = async (params: { + request_id: number; + money_source: "use" | "invoice" | "free" | "bonus"; + person_id?: number; + payment_type?: (typeof PAYMENT_TYPES)[number]; + payer_id?: number; + auth_code?: string; + bonus_id?: number; +}) => { + try { + let body: UpdateDomainRequestBodyDto; + + if (params.money_source === "use") { + body = { + money_source: "use", + ...(params.person_id !== undefined && { person_id: params.person_id }), + }; + } else if (params.money_source === "invoice") { + if (!params.payment_type || params.payer_id === undefined) { + return createToolResponse( + "❌ Для money_source=invoice нужны payment_type и payer_id." + ); + } + body = { + money_source: "invoice", + payment_type: params.payment_type, + payer_id: params.payer_id, + ...(params.person_id !== undefined && { person_id: params.person_id }), + }; + } else if (params.money_source === "free") { + if (!params.auth_code) { + return createToolResponse( + "❌ Для money_source=free нужен auth_code." + ); + } + body = { + money_source: "free", + auth_code: params.auth_code, + ...(params.person_id !== undefined && { person_id: params.person_id }), + }; + } else { + if (params.bonus_id === undefined) { + return createToolResponse( + "❌ Для money_source=bonus нужен bonus_id." + ); + } + body = { + money_source: "bonus", + bonus_id: params.bonus_id, + ...(params.person_id !== undefined && { person_id: params.person_id }), + }; + } + + const r = await updateDomainRequestAction(params.request_id, body); + return createToolResponse(`✅ Заявка ${r.id} обновлена! +• FQDN: ${r.fqdn} +• Статус: ${r.status ?? "—"} +• Источник оплаты: ${r.money_source ?? params.money_source} +• Сообщение: ${r.message ?? "—"}`); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка обновления заявки ${params.request_id}. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при обновлении заявки"); + } +}; + +export const updateDomainRequestTool = { + name: ToolNames.UPDATE_DOMAIN_REQUEST, + title: "Оплата/обновление заявки на домен", + description: + "Обновляет заявку на регистрацию/продление/трансфер, указывая источник оплаты: use (с баланса), invoice (платёжка), free (бесплатный трансфер), bonus.", + inputSchema, + handler, +}; diff --git a/src/tools/update-domain.tool.ts b/src/tools/update-domain.tool.ts new file mode 100644 index 0000000..85bb841 --- /dev/null +++ b/src/tools/update-domain.tool.ts @@ -0,0 +1,65 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { updateDomainAction } from "../actions/update-domain.action"; + +const inputSchema = { + fqdn: z.string().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - полное имя домена"), + is_autoprolong_enabled: z + .boolean() + .optional() + .describe("Включить/выключить автопродление домена"), + linked_ip: z + .string() + .nullable() + .optional() + .describe("Привязать IP-адрес к домену (null — отвязать)"), +}; + +const handler = async (params: { + fqdn: string; + is_autoprolong_enabled?: boolean; + linked_ip?: string | null; +}) => { + try { + if ( + params.is_autoprolong_enabled === undefined && + params.linked_ip === undefined + ) { + return createToolResponse( + "❌ Нужно указать хотя бы одно из полей: is_autoprolong_enabled или linked_ip." + ); + } + + const body: { is_autoprolong_enabled?: boolean; linked_ip?: string | null } = + {}; + if (params.is_autoprolong_enabled !== undefined) { + body.is_autoprolong_enabled = params.is_autoprolong_enabled; + } + if (params.linked_ip !== undefined) { + body.linked_ip = params.linked_ip; + } + + const d = await updateDomainAction(params.fqdn, body); + + return createToolResponse(`✅ Домен ${d.fqdn} обновлён! +• Автопродление: ${d.is_autoprolong_enabled ? "да" : "нет"} +• Статус: ${d.domain_status}`); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка обновления домена "${params.fqdn}". Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при обновлении домена"); + } +}; + +export const updateDomainTool = { + name: ToolNames.UPDATE_DOMAIN, + title: "Обновление параметров домена", + description: + "Включает/выключает автопродление домена и/или меняет привязанный IP-адрес. FQDN обязателен.", + inputSchema, + handler, +}; diff --git a/src/tools/update-firewall-group.tool.ts b/src/tools/update-firewall-group.tool.ts new file mode 100644 index 0000000..c2c04b8 --- /dev/null +++ b/src/tools/update-firewall-group.tool.ts @@ -0,0 +1,56 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { updateFirewallGroupAction } from "../actions/update-firewall-group.action"; + +const inputSchema = { + group_id: z + .string() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID группы правил firewall"), + name: z.string().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - новое имя группы"), + description: z + .string() + .optional() + .describe("Новое описание группы (опц.)"), +}; + +const handler = async (params: { + group_id: string; + name: string; + description?: string; +}) => { + try { + const g = await updateFirewallGroupAction( + params.group_id, + params.name, + params.description + ); + + return createToolResponse(`✅ Группа правил firewall обновлена! + +📋 Детали: +• ID: ${g.id} +• Имя: ${g.name} +• Описание: ${g.description || "—"} +• Политика: ${g.policy} +• Обновлена: ${new Date(g.updated_at).toLocaleString("ru-RU")}`); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка обновления группы firewall ${params.group_id}. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при обновлении группы firewall" + ); + } +}; + +export const updateFirewallGroupTool = { + name: ToolNames.UPDATE_FIREWALL_GROUP, + title: "Обновление группы правил firewall", + description: + "Обновляет имя и/или описание группы правил firewall. Политика группы через этот эндпоинт не меняется.", + inputSchema, + handler, +}; diff --git a/src/tools/update-firewall-rule.tool.ts b/src/tools/update-firewall-rule.tool.ts new file mode 100644 index 0000000..1b4c5aa --- /dev/null +++ b/src/tools/update-firewall-rule.tool.ts @@ -0,0 +1,90 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { updateFirewallRuleAction } from "../actions/update-firewall-rule.action"; +import { + FirewallRuleDirection, + FirewallRuleProtocol, +} from "../types/firewall-rule.type"; + +const inputSchema = { + group_id: z + .string() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID группы правил firewall"), + rule_id: z.string().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID правила"), + direction: z + .enum(["ingress", "egress"]) + .describe( + "ОБЯЗАТЕЛЬНОЕ ПОЛЕ - направление трафика: ingress или egress" + ), + protocol: z + .enum(["tcp", "udp", "icmp"]) + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - протокол: tcp, udp или icmp"), + port: z + .string() + .optional() + .describe("Порт или диапазон портов (только для tcp/udp)"), + cidr: z + .string() + .optional() + .describe("Сетевой адрес или подсеть (IPv4/IPv6, CIDR)"), + description: z + .string() + .optional() + .describe("Описание правила (опц.)"), +}; + +const handler = async (params: { + group_id: string; + rule_id: string; + direction: FirewallRuleDirection; + protocol: FirewallRuleProtocol; + port?: string; + cidr?: string; + description?: string; +}) => { + try { + if (params.protocol === "icmp" && params.port) { + return createToolResponse( + "❌ Для протокола icmp параметр port не указывается." + ); + } + + const r = await updateFirewallRuleAction(params.group_id, params.rule_id, { + direction: params.direction, + protocol: params.protocol, + port: params.port, + cidr: params.cidr, + description: params.description, + }); + + return createToolResponse(`✅ Правило firewall обновлено! + +📋 Детали: +• ID: ${r.id} +• Группа: ${r.group_id} +• Направление: ${r.direction} +• Протокол: ${r.protocol} +• Порт: ${r.port || "—"} +• CIDR: ${r.cidr || "—"} +• Описание: ${r.description || "—"}`); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка обновления правила ${params.rule_id}. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при обновлении правила firewall" + ); + } +}; + +export const updateFirewallRuleTool = { + name: ToolNames.UPDATE_FIREWALL_RULE, + title: "Обновление правила firewall", + description: + "Полностью обновляет правило firewall. Передаются direction, protocol (обязательно) и опциональные port, cidr, description — эти поля перезаписывают текущие значения правила.", + inputSchema, + handler, +}; diff --git a/src/tools/update-floating-ip.tool.ts b/src/tools/update-floating-ip.tool.ts new file mode 100644 index 0000000..ca0c864 --- /dev/null +++ b/src/tools/update-floating-ip.tool.ts @@ -0,0 +1,63 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { updateFloatingIpAction } from "../actions/update-floating-ip.action"; +import { UpdateFloatingIpRequestDto } from "../types/dto/update-floating-ip-request.dto"; + +const inputSchema = { + floating_ip_id: z + .string() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID плавающего IP"), + comment: z + .string() + .optional() + .describe("Комментарий к плавающему IP (опц.)"), + ptr: z + .string() + .optional() + .describe("PTR-запись (обратная DNS-запись) для плавающего IP (опц.)"), +}; + +const handler = async (params: { + floating_ip_id: string; + comment?: string; + ptr?: string; +}) => { + try { + if (params.comment === undefined && params.ptr === undefined) { + return createToolResponse( + `❌ Нужно указать хотя бы одно поле для изменения: comment или ptr` + ); + } + + const data: UpdateFloatingIpRequestDto = {}; + if (params.comment !== undefined) data.comment = params.comment; + if (params.ptr !== undefined) data.ptr = params.ptr; + + const ip = await updateFloatingIpAction(params.floating_ip_id, data); + + return createToolResponse(`✅ Плавающий IP ${ip.id} обновлён + +• IP адрес: ${ip.ip ?? "не назначен"} +• Комментарий: ${ip.comment ?? "—"} +• PTR: ${ip.ptr ?? "—"}`); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка при обновлении плавающего IP. Причина: ${error.message}` + ); + } + return createToolResponse( + `❌ Неизвестная ошибка при обновлении плавающего IP` + ); + } +}; + +export const updateFloatingIpTool = { + name: ToolNames.UPDATE_FLOATING_IP, + title: "Изменение плавающего IP", + description: + "Изменяет комментарий и/или PTR-запись плавающего IP по его ID", + inputSchema, + handler, +}; diff --git a/src/tools/update-image.tool.ts b/src/tools/update-image.tool.ts new file mode 100644 index 0000000..55f0330 --- /dev/null +++ b/src/tools/update-image.tool.ts @@ -0,0 +1,55 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { updateImageAction } from "../actions/update-image.action"; + +const inputSchema = { + image_id: z.string().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID образа"), + name: z + .string() + .optional() + .describe("НЕ ОБЯЗАТЕЛЬНОЕ ПОЛЕ - новое имя образа"), + description: z + .string() + .optional() + .describe("НЕ ОБЯЗАТЕЛЬНОЕ ПОЛЕ - новое описание образа"), +}; + +const handler = async (params: { + image_id: string; + name?: string; + description?: string; +}) => { + try { + if (params.name === undefined && params.description === undefined) { + return createToolResponse( + "❌ Нужно передать хотя бы одно из полей: name или description." + ); + } + + const image = await updateImageAction(params.image_id, { + name: params.name, + description: params.description, + }); + + return createToolResponse( + `✅ Образ ${image.id} обновлён. Имя: "${image.name || "(без имени)"}", описание: "${image.description || "—"}".` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось обновить образ ${params.image_id}. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при обновлении образа"); + } +}; + +export const updateImageTool = { + name: ToolNames.UPDATE_IMAGE, + title: "Обновление образа", + description: + "Обновляет имя и/или описание образа. Другие атрибуты (ОС, локация, disk_id) изменить нельзя.", + inputSchema, + handler, +}; diff --git a/src/tools/update-k8s-addon.tool.ts b/src/tools/update-k8s-addon.tool.ts new file mode 100644 index 0000000..8fe4098 --- /dev/null +++ b/src/tools/update-k8s-addon.tool.ts @@ -0,0 +1,62 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { updateK8sAddonAction } from "../actions/update-k8s-addon.action"; + +const inputSchema = { + cluster_id: z.number().int().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID кластера"), + addon_id: z.number().int().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID дополнения"), + type: z + .string() + .describe( + "ОБЯЗАТЕЛЬНОЕ ПОЛЕ - тип дополнения (должен совпадать с установленным)" + ), + config_type: z + .enum(["basic", "custom"]) + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - тип конфигурации: basic или custom"), + yaml_config: z + .string() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - новая YAML-конфигурация"), + version: z + .string() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - новая версия дополнения"), +}; + +const handler = async (params: { + cluster_id: number; + addon_id: number; + type: string; + config_type: "basic" | "custom"; + yaml_config: string; + version: string; +}) => { + try { + await updateK8sAddonAction(params.cluster_id, params.addon_id, { + type: params.type, + config_type: params.config_type, + yaml_config: params.yaml_config, + version: params.version, + }); + return createToolResponse( + `✅ Дополнение ${params.addon_id} (${params.type} v${params.version}) обновлено в кластере ${params.cluster_id}.` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка обновления дополнения. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при обновлении дополнения" + ); + } +}; + +export const updateK8sAddonTool = { + name: ToolNames.UPDATE_K8S_ADDON, + title: "Изменение конфигурации дополнения", + description: + "Изменяет конфигурацию или версию ранее установленного дополнения. Нужны type, config_type, yaml_config, version.", + inputSchema, + handler, +}; diff --git a/src/tools/update-k8s-cluster-version.tool.ts b/src/tools/update-k8s-cluster-version.tool.ts new file mode 100644 index 0000000..cf39dfe --- /dev/null +++ b/src/tools/update-k8s-cluster-version.tool.ts @@ -0,0 +1,42 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { updateK8sClusterVersionAction } from "../actions/update-k8s-cluster-version.action"; + +const inputSchema = { + cluster_id: z.number().int().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID кластера"), + k8s_version: z + .string() + .optional() + .describe( + "Новая версия Kubernetes (например, v1.33.4+k0s.0). Получить список через list_k8s_versions." + ), +}; + +const handler = async (params: { + cluster_id: number; + k8s_version?: string; +}) => { + try { + await updateK8sClusterVersionAction(params.cluster_id, params.k8s_version); + return createToolResponse( + `✅ Запрос на обновление версии кластера ${params.cluster_id} отправлен${params.k8s_version ? ` (целевая версия: ${params.k8s_version})` : ""}. Проверь статус через get_k8s_cluster.` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка обновления версии кластера. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при обновлении версии"); + } +}; + +export const updateK8sClusterVersionTool = { + name: ToolNames.UPDATE_K8S_CLUSTER_VERSION, + title: "Обновление версии Kubernetes-кластера", + description: + "Обновляет версию Kubernetes в кластере. Версию можно не передавать — тогда будет выбрана следующая доступная.", + inputSchema, + handler, +}; diff --git a/src/tools/update-mail-domain-info.tool.ts b/src/tools/update-mail-domain-info.tool.ts new file mode 100644 index 0000000..d31ed7f --- /dev/null +++ b/src/tools/update-mail-domain-info.tool.ts @@ -0,0 +1,41 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { updateMailDomainInfoAction } from "../actions/update-mail-domain-info.action"; + +const inputSchema = { + domain: z.string().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - имя домена"), + email: z + .string() + .email() + .describe( + "ОБЯЗАТЕЛЬНОЕ ПОЛЕ - адрес-сборщик почты, приходящей на несуществующие ящики домена" + ), +}; + +const handler = async (params: { domain: string; email: string }) => { + try { + const info = await updateMailDomainInfoAction(params.domain, params.email); + return createToolResponse( + `✅ Почтовая информация домена ${params.domain} обновлена. Сборщик: ${info.email}, использовано: ${info.used} МБ.` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка обновления почтовой информации. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при обновлении почтовой информации" + ); + } +}; + +export const updateMailDomainInfoTool = { + name: ToolNames.UPDATE_MAIL_DOMAIN_INFO, + title: "Изменение почтовой информации о домене", + description: + "Меняет адрес-сборщик для писем, приходящих на несуществующие ящики домена.", + inputSchema, + handler, +}; diff --git a/src/tools/update-mailbox-v1.tool.ts b/src/tools/update-mailbox-v1.tool.ts new file mode 100644 index 0000000..bd3f4e2 --- /dev/null +++ b/src/tools/update-mailbox-v1.tool.ts @@ -0,0 +1,78 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { updateMailboxV1Action } from "../actions/update-mailbox-v1.action"; + +const inputSchema = { + domain: z.string().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - имя домена"), + mailbox: z.string().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - имя ящика (часть до @)"), + password: z.string().optional().describe("Новый пароль (опц.)"), + comment: z.string().optional().describe("Новый комментарий (опц.)"), + auto_reply: z + .any() + .optional() + .describe("Автоответчик (v1): объект с is_enabled и message/subject"), + spam_filter: z + .any() + .optional() + .describe( + "Спам-фильтр (v1): объект с is_enabled/action/forward_to/white_list" + ), + forwarding_incoming: z + .any() + .optional() + .describe( + "Пересылка входящих (v1): is_enabled/incoming_list/is_delete_messages" + ), + forwarding_outgoing: z + .any() + .optional() + .describe("Пересылка исходящих (v1): is_enabled/outgoing_to"), +}; + +const handler = async (params: { + domain: string; + mailbox: string; + password?: string; + comment?: string; + auto_reply?: any; + spam_filter?: any; + forwarding_incoming?: any; + forwarding_outgoing?: any; +}) => { + try { + const { domain, mailbox, ...rest } = params; + const body = Object.fromEntries( + Object.entries(rest).filter(([, v]) => v !== undefined) + ); + if (Object.keys(body).length === 0) { + return createToolResponse( + "❌ Нужно передать хотя бы одно поле для обновления." + ); + } + + const updated = await updateMailboxV1Action(domain, mailbox, body); + + return createToolResponse( + `✅ Ящик ${mailbox}@${domain} обновлён (API v1). Комментарий: ${updated.comment || "—"}. Спам-фильтр: ${updated.spam_filter?.is_enabled ? "вкл" : "выкл"}. Автоответчик: ${updated.auto_reply?.is_enabled ? "вкл" : "выкл"}.` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка обновления ящика (v1). Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при обновлении ящика (v1)" + ); + } +}; + +export const updateMailboxV1Tool = { + name: ToolNames.UPDATE_MAILBOX_V1, + title: "Изменение почтового ящика (API v1)", + description: + "Обновляет почтовый ящик через API v1. Предпочитай update_mailbox (v2). Использует структурированные блоки auto_reply/spam_filter/forwarding_incoming/forwarding_outgoing.", + inputSchema, + handler, +}; diff --git a/src/tools/update-mailbox.tool.ts b/src/tools/update-mailbox.tool.ts new file mode 100644 index 0000000..8a591b0 --- /dev/null +++ b/src/tools/update-mailbox.tool.ts @@ -0,0 +1,95 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { updateMailboxAction } from "../actions/update-mailbox.action"; + +const inputSchema = { + domain: z.string().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - имя домена"), + mailbox: z.string().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - имя ящика (часть до @)"), + password: z + .string() + .min(8) + .max(30) + .optional() + .describe("Новый пароль (8-30 символов, опц.)"), + comment: z.string().optional().describe("Новый комментарий (опц.)"), + owner_full_name: z + .string() + .optional() + .describe("Новое ФИО владельца (опц.)"), + spam_protection_settings: z + .any() + .optional() + .describe( + "Спам-фильтр. Объект с is_enabled и (при вкл.) полями action/forward_to/white_list. Детали см. в OpenAPI schema spam-protection-is-enabled/-is-disabled" + ), + forward_settings: z + .any() + .optional() + .describe( + "Пересылка входящих. Объект с is_enabled и (при вкл.) incoming_list/is_delete_messages" + ), + autoreply_settings: z + .any() + .optional() + .describe( + "Автоответчик. Объект с is_enabled и (при вкл.) message/subject" + ), + outgoing_settings: z + .any() + .optional() + .describe("Пересылка исходящих. Объект с is_enabled и (при вкл.) outgoing_to"), +}; + +const handler = async (params: { + domain: string; + mailbox: string; + password?: string; + comment?: string; + owner_full_name?: string; + spam_protection_settings?: any; + forward_settings?: any; + autoreply_settings?: any; + outgoing_settings?: any; +}) => { + try { + const { domain, mailbox, ...rest } = params; + const body = Object.fromEntries( + Object.entries(rest).filter(([, v]) => v !== undefined) + ); + + if (Object.keys(body).length === 0) { + return createToolResponse( + "❌ Нужно передать хотя бы одно поле для обновления." + ); + } + + const updated = await updateMailboxAction(domain, mailbox, body); + + return createToolResponse(`✅ Ящик ${mailbox}@${domain} обновлён. + +📋 Актуальное состояние: +• Комментарий: ${updated.comment || "—"} +• ФИО владельца: ${updated.owner_full_name || "—"} +• Спам-фильтр: ${updated.filter_status ? "вкл" : "выкл"} +• Пересылка входящих: ${updated.forward_status ? "вкл" : "выкл"} +• Автоответчик: ${updated.autoreply_status ? "вкл" : "выкл"} +• Пересылка исходящих: ${updated.outgoing_control ? "вкл" : "выкл"}`); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка обновления ящика. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при обновлении ящика"); + } +}; + +export const updateMailboxTool = { + name: ToolNames.UPDATE_MAILBOX, + title: "Изменение почтового ящика", + description: + "Обновляет почтовый ящик (API v2): пароль, комментарий, ФИО, спам-фильтр, автоответчик, пересылки. Передавай только изменяемые поля. Сложные блоки (spam/forward/autoreply/outgoing) принимают объект с is_enabled и дополнительными полями при включении.", + inputSchema, + handler, +}; diff --git a/src/tools/update-network-drive.tool.ts b/src/tools/update-network-drive.tool.ts new file mode 100644 index 0000000..becd53a --- /dev/null +++ b/src/tools/update-network-drive.tool.ts @@ -0,0 +1,77 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { updateNetworkDriveAction } from "../actions/update-network-drive.action"; + +const inputSchema = { + network_drive_id: z + .string() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID сетевого диска (UUID)"), + name: z.string().optional().describe("Новое название диска (опц.)"), + comment: z.string().optional().describe("Новый комментарий (опц.)"), + size: z + .number() + .int() + .positive() + .optional() + .describe("Новый размер диска в ГБ (опц.)"), +}; + +const handler = async (params: { + network_drive_id: string; + name?: string; + comment?: string; + size?: number; +}) => { + try { + if ( + params.name === undefined && + params.comment === undefined && + params.size === undefined + ) { + return createToolResponse( + "❌ Нужно указать хотя бы одно из полей для изменения: name, comment, size" + ); + } + + const body: { + name?: string; + comment?: string; + size?: number; + } = {}; + if (params.name !== undefined) body.name = params.name; + if (params.comment !== undefined) body.comment = params.comment; + if (params.size !== undefined) body.size = params.size; + + const drive = await updateNetworkDriveAction( + params.network_drive_id, + body + ); + + return createToolResponse(`✅ Сетевой диск ${drive.id} обновлён. + +📋 Актуальные параметры: +• Название: ${drive.name} +• Размер: ${drive.size} ГБ +• Статус: ${drive.status} +• Комментарий: ${drive.comment ?? "—"}`); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка обновления сетевого диска ${params.network_drive_id}. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при обновлении сетевого диска" + ); + } +}; + +export const updateNetworkDriveTool = { + name: ToolNames.UPDATE_NETWORK_DRIVE, + title: "Изменение сетевого диска", + description: + "Изменяет параметры сетевого диска (name, comment, size). Размер можно только увеличивать. Нужно указать хотя бы одно из полей.", + inputSchema, + handler, +}; diff --git a/src/tools/update-project.tool.ts b/src/tools/update-project.tool.ts new file mode 100644 index 0000000..99352f1 --- /dev/null +++ b/src/tools/update-project.tool.ts @@ -0,0 +1,62 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { updateProjectAction } from "../actions/update-project.action"; + +const inputSchema = { + project_id: z.number().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID проекта"), + name: z.string().max(255).optional().describe("Новое имя (опц.)"), + description: z + .string() + .max(255) + .optional() + .describe("Новое описание (опц.)"), + avatar_id: z.string().max(255).optional().describe("Новый ID аватара (опц.)"), +}; + +const handler = async (params: { + project_id: number; + name?: string; + description?: string; + avatar_id?: string; +}) => { + try { + if ( + params.name === undefined && + params.description === undefined && + params.avatar_id === undefined + ) { + return createToolResponse( + "❌ Укажи хотя бы одно поле для обновления: name, description или avatar_id." + ); + } + + const project = await updateProjectAction(params.project_id, { + name: params.name, + description: params.description, + avatar_id: params.avatar_id, + }); + + return createToolResponse( + `✅ Проект ${project.id} обновлён.\n` + + `• Имя: ${project.name}\n` + + `• Описание: ${project.description || "—"}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось обновить проект ${params.project_id}. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при обновлении проекта"); + } +}; + +export const updateProjectTool = { + name: ToolNames.UPDATE_PROJECT, + title: "Изменение проекта", + description: + "Обновляет имя, описание или аватар существующего проекта. Минимум одно поле.", + inputSchema, + handler, +}; diff --git a/src/tools/update-server-ip.tool.ts b/src/tools/update-server-ip.tool.ts new file mode 100644 index 0000000..7450f51 --- /dev/null +++ b/src/tools/update-server-ip.tool.ts @@ -0,0 +1,47 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { updateServerIpAction } from "../actions/update-server-ip.action"; + +const inputSchema = { + server_id: z.number().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID сервера"), + ip: z + .string() + .describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - IP-адрес, у которого меняется PTR"), + ptr: z.string().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - новая PTR-запись"), +}; + +const handler = async (params: { + server_id: number; + ip: string; + ptr: string; +}) => { + try { + const ip = await updateServerIpAction( + params.server_id, + params.ip, + params.ptr + ); + return createToolResponse( + `✅ PTR-запись для ${params.ip} на сервере ${params.server_id} обновлена.\n` + + `• ${ip.type.toUpperCase()} ${ip.ip}\n` + + `• PTR: ${ip.ptr}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось обновить PTR для IP ${params.ip}. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при обновлении PTR"); + } +}; + +export const updateServerIpTool = { + name: ToolNames.UPDATE_SERVER_IP, + title: "Изменение PTR-записи IP-адреса", + description: + "Меняет PTR-запись (обратное DNS) для конкретного IP-адреса сервера.", + inputSchema, + handler, +}; diff --git a/src/tools/update-server.tool.ts b/src/tools/update-server.tool.ts new file mode 100644 index 0000000..e32a957 --- /dev/null +++ b/src/tools/update-server.tool.ts @@ -0,0 +1,62 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { updateServerAction } from "../actions/update-server.action"; +import { UpdateServerRequestDto } from "../types/dto/update-server-request.dto"; + +const inputSchema = { + server_id: z.number().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID сервера"), + name: z.string().optional().describe("Новое имя сервера (до 255 символов)"), + comment: z + .string() + .optional() + .describe("Новый комментарий (до 255 символов)"), + avatar_id: z.string().optional().describe("ID аватара сервера"), + cloud_init: z.string().optional().describe("Cloud-init скрипт"), +}; + +const handler = async (params: { + server_id: number; + name?: string; + comment?: string; + avatar_id?: string; + cloud_init?: string; +}) => { + const body: UpdateServerRequestDto = {}; + if (params.name !== undefined) body.name = params.name; + if (params.comment !== undefined) body.comment = params.comment; + if (params.avatar_id !== undefined) body.avatar_id = params.avatar_id; + if (params.cloud_init !== undefined) body.cloud_init = params.cloud_init; + + if (Object.keys(body).length === 0) { + return createToolResponse( + "❌ Нужно передать хотя бы одно поле: name, comment, avatar_id или cloud_init." + ); + } + + try { + const server = await updateServerAction(params.server_id, body); + return createToolResponse( + `✅ Сервер ${server.id} обновлён.\n` + + `• Имя: ${server.name}\n` + + `• Комментарий: ${server.comment ?? "—"}\n` + + `• Статус: ${server.status}` + ); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Не удалось обновить сервер ${params.server_id}. Причина: ${error.message}` + ); + } + return createToolResponse("❌ Неизвестная ошибка при обновлении сервера"); + } +}; + +export const updateServerTool = { + name: ToolNames.UPDATE_SERVER, + title: "Изменение метаданных сервера", + description: + "Обновляет имя, комментарий, avatar_id или cloud_init у сервера. Для ресайза (preset/configurator) используй resize_server.", + inputSchema, + handler, +}; diff --git a/src/tools/update-ssh-key.tool.ts b/src/tools/update-ssh-key.tool.ts new file mode 100644 index 0000000..124f8dc --- /dev/null +++ b/src/tools/update-ssh-key.tool.ts @@ -0,0 +1,67 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { updateSshKeyAction } from "../actions/update-ssh-key.action"; +import { UpdateSshKeyRequestDto } from "../types/dto/update-ssh-key-request.dto"; + +const inputSchema = { + ssh_key_id: z.number().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID SSH-ключа"), + name: z.string().optional().describe("Новое имя SSH-ключа (опц.)"), + body: z + .string() + .optional() + .describe("Новое тело публичного SSH-ключа (опц.)"), + is_default: z + .boolean() + .optional() + .describe( + "Сделать ключ дефолтным при создании новых серверов (true/false, опц.)" + ), +}; + +const handler = async (params: { + ssh_key_id: number; + name?: string; + body?: string; + is_default?: boolean; +}) => { + try { + const patch: UpdateSshKeyRequestDto = {}; + if (params.name !== undefined) patch.name = params.name; + if (params.body !== undefined) patch.body = params.body; + if (params.is_default !== undefined) patch.is_default = params.is_default; + + if (Object.keys(patch).length === 0) { + return createToolResponse( + "⚠️ Не передано ни одного поля для обновления (name, body, is_default)." + ); + } + + const key = await updateSshKeyAction(params.ssh_key_id, patch); + + return createToolResponse(`✅ SSH-ключ ${key.id} обновлён. + +📋 Текущее состояние: +• Название: ${key.name} +• По умолчанию: ${key.is_default ? "✅ Да" : "❌ Нет"} +• Создан: ${new Date(key.created_at).toLocaleString("ru-RU")}`); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка обновления SSH-ключа ${params.ssh_key_id}. Причина: ${error.message}` + ); + } + return createToolResponse( + "❌ Неизвестная ошибка при обновлении SSH-ключа" + ); + } +}; + +export const updateSshKeyTool = { + name: ToolNames.UPDATE_SSH_KEY, + title: "Изменение SSH-ключа", + description: + "Изменяет параметры SSH-ключа по ID. Можно обновить имя, тело ключа и/или флаг is_default. Передавай только те поля, которые нужно изменить.", + inputSchema, + handler, +}; diff --git a/src/tools/update-vpc.tool.ts b/src/tools/update-vpc.tool.ts new file mode 100644 index 0000000..d8dbf84 --- /dev/null +++ b/src/tools/update-vpc.tool.ts @@ -0,0 +1,51 @@ +import { z } from "zod"; +import { createToolResponse } from "../utils"; +import { ToolNames } from "../types/tool-names.enum"; +import { updateVpcAction } from "../actions/update-vpc.action"; +import { UpdateVpcRequestDto } from "../types/dto/update-vpc-request.dto"; + +const inputSchema = { + vpc_id: z.string().describe("ОБЯЗАТЕЛЬНОЕ ПОЛЕ - ID VPC"), + name: z.string().optional().describe("Новое имя VPC (опц.)"), + description: z.string().optional().describe("Новое описание VPC (опц.)"), +}; + +const handler = async (params: { + vpc_id: string; + name?: string; + description?: string; +}) => { + try { + if (params.name === undefined && params.description === undefined) { + return createToolResponse( + `❌ Нужно указать хотя бы одно поле для изменения: name или description` + ); + } + + const data: UpdateVpcRequestDto = {}; + if (params.name !== undefined) data.name = params.name; + if (params.description !== undefined) data.description = params.description; + + const vpc = await updateVpcAction(params.vpc_id, data); + + return createToolResponse(`✅ VPC ${vpc.id} обновлена + +• Название: ${vpc.name} +• Описание: ${vpc.description ?? "—"}`); + } catch (error) { + if (error instanceof Error) { + return createToolResponse( + `❌ Ошибка при обновлении VPC. Причина: ${error.message}` + ); + } + return createToolResponse(`❌ Неизвестная ошибка при обновлении VPC`); + } +}; + +export const updateVpcTool = { + name: ToolNames.UPDATE_VPC, + title: "Изменение VPC", + description: "Изменяет имя и/или описание VPC по её ID", + inputSchema, + handler, +}; diff --git a/src/types/ai-agent.type.ts b/src/types/ai-agent.type.ts new file mode 100644 index 0000000..f38b63c --- /dev/null +++ b/src/types/ai-agent.type.ts @@ -0,0 +1,44 @@ +export type AgentModelSettings = { + temperature?: number; + top_p?: number; + max_tokens?: number; + frequency_penalty?: number; + presence_penalty?: number; +}; + +export type AgentWidgetSettings = { + whitelist_domains: string[]; + name: string; + signature?: string; + welcome_message: string; + primary_color: string; + font: string; + icon_url?: string; + chat_position: "bottom_right" | "bottom_left" | "top_right" | "top_left"; +}; + +export type AgentSettings = { + model: AgentModelSettings; + system_prompt: string; + refine_query: boolean; + widget?: AgentWidgetSettings; +}; + +export type AiAgent = { + id: number; + name: string; + description?: string; + model_id: number; + provider_id?: number; + settings: AgentSettings; + status: "active" | "blocked" | "deleted" | "suspended"; + access_type: "public" | "private"; + total_tokens?: number; + used_tokens?: number; + remaining_tokens?: number; + token_package_id?: number; + subscription_renewal_date?: string; + project_id?: number; + created_at?: string; + [key: string]: any; +}; diff --git a/src/types/ai-model.type.ts b/src/types/ai-model.type.ts new file mode 100644 index 0000000..f7c3133 --- /dev/null +++ b/src/types/ai-model.type.ts @@ -0,0 +1,12 @@ +export type AiModel = { + id: number; + provider_id?: number; + name: string; + public_name?: string; + type: "llm" | "embedding"; + is_deprecated?: boolean; + is_reasoning?: boolean; + version?: string; + params_info?: any; + [key: string]: any; +}; diff --git a/src/types/api-key.type.ts b/src/types/api-key.type.ts new file mode 100644 index 0000000..a222c04 --- /dev/null +++ b/src/types/api-key.type.ts @@ -0,0 +1,15 @@ +export interface ApiKey { + id: string; + created_at: string; + name: string; + expired_at: string | null; + is_able_to_delete: boolean; +} + +export interface CreatedApiKey { + token: string; + id: string; + created_at: string; + name: string; + expired_at: string | null; +} diff --git a/src/types/auto-backup.type.ts b/src/types/auto-backup.type.ts new file mode 100644 index 0000000..650ed6f --- /dev/null +++ b/src/types/auto-backup.type.ts @@ -0,0 +1,7 @@ +export type AutoBackupSettings = { + is_enabled: boolean; + copy_count?: number; + creation_start_at?: string; + interval?: "day" | "week" | "month" | string; + day_of_week?: number; +}; diff --git a/src/types/balancer.type.ts b/src/types/balancer.type.ts new file mode 100644 index 0000000..0298b58 --- /dev/null +++ b/src/types/balancer.type.ts @@ -0,0 +1,75 @@ +export type BalancerProto = "http" | "http2" | "https" | "tcp"; +export type BalancerAlgo = "roundrobin" | "leastconn"; +export type BalancerStatus = "started" | "stoped" | "starting" | "no_paid"; + +export type BalancerRule = { + id: number; + balancer_proto: BalancerProto; + balancer_port: number; + server_proto: BalancerProto; + server_port: number; +}; + +export type BalancerNetwork = { + id?: string; + type: "public" | "local"; + nat_mode?: "dnat_and_snat" | "snat" | "no_nat"; + port_id?: string; + ips: + | { + type: "ipv4" | "ipv6"; + ip: string; + }[] + | null; +}; + +export type Balancer = { + id: number; + account_id?: string; + algo: BalancerAlgo; + created_at: string; + fall: number; + inter: number; + ip: string | null; + local_ip: string | null; + is_keepalive: boolean; + name: string; + path: string; + port: number; + proto: BalancerProto; + rise: number; + maxconn: number; + connect_timeout: number; + client_timeout: number; + server_timeout: number; + httprequest_timeout: number; + preset_id: number; + is_ssl: boolean; + status: BalancerStatus; + is_sticky: boolean; + timeout: number; + avatar_link: string | null; + is_use_proxy: boolean; + rules: BalancerRule[]; + ips: string[]; + location: string; + availability_zone: string; + project_id: number; + networks: BalancerNetwork[]; +}; + +export type BalancerPreset = { + id: number; + description: string; + description_short: string; + bandwidth: number; + replica_count: number; + request_per_second: string; + price: number; + location: string; +}; + +export type DeleteBalancerResult = { + hash?: string; + is_moved_in_quarantine?: boolean; +}; diff --git a/src/types/bucket-delete-response.type.ts b/src/types/bucket-delete-response.type.ts new file mode 100644 index 0000000..48f3550 --- /dev/null +++ b/src/types/bucket-delete-response.type.ts @@ -0,0 +1,4 @@ +export interface BucketDeleteResponse { + hash?: string; + is_moved_in_quarantine?: boolean; +} diff --git a/src/types/bucket-preset.type.ts b/src/types/bucket-preset.type.ts new file mode 100644 index 0000000..d17c876 --- /dev/null +++ b/src/types/bucket-preset.type.ts @@ -0,0 +1,12 @@ +export type BucketPresetStorageClass = "cold" | "hot"; + +export interface BucketPreset { + id: number; + description: string; + description_short: string; + disk: number; + price: number; + location: string; + tags: string[]; + storage_class: BucketPresetStorageClass; +} diff --git a/src/types/bucket-subdomain.type.ts b/src/types/bucket-subdomain.type.ts new file mode 100644 index 0000000..81f1051 --- /dev/null +++ b/src/types/bucket-subdomain.type.ts @@ -0,0 +1,23 @@ +export type BucketSubdomainStatus = + | "ssl_released" + | "ssl_not_requested" + | "ssl_re_release_error"; + +export interface BucketSubdomain { + id: number; + subdomain: string; + cert_released: string; + tries: number; + status: BucketSubdomainStatus; +} + +export type AddedBucketSubdomainStatus = + | "success" + | "empty_cname" + | "duplicate" + | "failed"; + +export interface AddedBucketSubdomain { + subdomain: string; + status: AddedBucketSubdomainStatus; +} diff --git a/src/types/bucket-transfer-status.type.ts b/src/types/bucket-transfer-status.type.ts new file mode 100644 index 0000000..aecd6dc --- /dev/null +++ b/src/types/bucket-transfer-status.type.ts @@ -0,0 +1,16 @@ +export type BucketTransferOverallStatus = "started" | "suspended" | "failed"; + +export interface BucketTransferError { + value: string; + try: number; +} + +export interface BucketTransferStatus { + status: BucketTransferOverallStatus; + tries: number; + total_count: number; + total_size: number; + uploaded_count: number; + uploaded_size: number; + errors: BucketTransferError[]; +} diff --git a/src/types/bucket-user.type.ts b/src/types/bucket-user.type.ts new file mode 100644 index 0000000..51eaa2c --- /dev/null +++ b/src/types/bucket-user.type.ts @@ -0,0 +1,5 @@ +export interface BucketUser { + id: number; + access_key: string; + secret_key: string; +} diff --git a/src/types/bucket.type.ts b/src/types/bucket.type.ts new file mode 100644 index 0000000..817f479 --- /dev/null +++ b/src/types/bucket.type.ts @@ -0,0 +1,41 @@ +export type BucketType = "private" | "public"; +export type BucketStatus = "no_paid" | "created" | "transfer"; +export type BucketStorageClass = "cold" | "hot"; + +export interface BucketDiskStats { + size: number; + used: number; + is_unlimited: boolean; +} + +export interface BucketWebsiteConfig { + enabled?: boolean; + index_page?: string; + error_pages?: Array<{ + code?: number; + document?: string; + }>; +} + +export interface Bucket { + id: number; + name: string; + description: string; + disk_stats: BucketDiskStats; + type: BucketType; + preset_id: number | null; + configurator_id: number | null; + avatar_link: string | null; + status: BucketStatus; + object_amount: number; + location: string; + hostname: string; + access_key: string; + secret_key: string; + moved_in_quarantine_at: string | null; + storage_class: BucketStorageClass; + project_id: number; + rate_id: number; + website_config: BucketWebsiteConfig | null; + is_allow_auto_upgrade: boolean; +} diff --git a/src/types/container-registry.type.ts b/src/types/container-registry.type.ts new file mode 100644 index 0000000..2fadd36 --- /dev/null +++ b/src/types/container-registry.type.ts @@ -0,0 +1,36 @@ +export type ContainerRegistryDiskStats = { + size: number; + used: number; +}; + +export type ContainerRegistry = { + id: number; + name: string; + description: string; + preset_id: number; + configurator_id: number; + project_id: number; + created_at: string; + updated_at: string; + disk_stats: ContainerRegistryDiskStats; +}; + +export type ContainerRegistryPreset = { + id: number; + description: string; + description_short: string; + disk: number; + price: number; + location?: string; +}; + +export type ContainerRegistryRepositoryTag = { + tag: string; + digest: string; + size: number; +}; + +export type ContainerRegistryRepository = { + name: string; + tags: ContainerRegistryRepositoryTag; +}; diff --git a/src/types/database-cluster.type.ts b/src/types/database-cluster.type.ts new file mode 100644 index 0000000..f8381e4 --- /dev/null +++ b/src/types/database-cluster.type.ts @@ -0,0 +1,87 @@ +export interface DatabaseClusterNetworkIp { + type: "ipv4" | "ipv6"; + ip: string; +} + +export interface DatabaseClusterNetwork { + type: "public" | "local"; + ips: DatabaseClusterNetworkIp[] | null; +} + +export interface DatabaseCluster { + id: number; + created_at: string; + location: string | null; + name: string; + networks: DatabaseClusterNetwork[]; + type: string; + hash_type: "caching_sha2" | "mysql_native" | null; + avatar_link: string | null; + port: number | null; + status: string; + preset_id: number; + disk: any | null; + config_parameters: Record; + is_enabled_public_network?: boolean; + availability_zone?: string; + description?: string; + project_id?: number; + [key: string]: any; +} + +export interface DatabaseAdminEntity { + id: number; + created_at: string; + login: string; + password: string; + description: string; + host: string | null; + instances: Array<{ + instance_id: number; + privileges: string[]; + }>; +} + +export interface DatabaseInstanceEntity { + id: number; + created_at: string; + name: string; + description: string; +} + +export interface DatabaseType { + name: string; + version: string; + type: string; + is_available_replication: boolean; + is_deprecated: boolean; + requirements?: { + cpu_min?: number; + ram_min?: number; + disk_min?: number; + }; +} + +export interface DatabaseBackup { + id: number; + name: string; + comment: string | null; + created_at: string; + status: string; + size: number; + type: "manual" | "auto"; + progress: number; +} + +export interface DatabaseAutoBackupSettings { + copy_count?: number; + creation_start_at?: string; + is_enabled: boolean; + interval?: "day" | "week" | "month"; + day_of_week?: number; +} + +export interface DatabaseDeleteResponse { + hash?: string; + is_moved_in_quarantine?: boolean; +} diff --git a/src/types/dedicated-server.type.ts b/src/types/dedicated-server.type.ts new file mode 100644 index 0000000..c2711de --- /dev/null +++ b/src/types/dedicated-server.type.ts @@ -0,0 +1,70 @@ +export type DedicatedServerStatus = "installing" | "installed" | "on" | "off"; + +export type DedicatedServer = { + id: number; + cpu_description: string; + hdd_description: string; + ram_description: string; + created_at: string; + ip: string | null; + ipmi_ip: string | null; + ipmi_login: string | null; + ipmi_password: string | null; + ipv6: string | null; + node_id: number | null; + name: string; + comment: string; + vnc_pass: string | null; + status: DedicatedServerStatus | string; + os_id: number | null; + cp_id: number | null; + bandwidth_id: number | null; + network_drive_id: number | null; + additional_ip_addr_id: number | null; + plan_id: number | null; + price: number; + location: string; + autoinstall_ready?: boolean; + password?: string | null; + avatar_link?: string | null; + is_pre_installed?: boolean; + preset_id: number; + project_id?: number | null; +}; + +export type DedicatedServerPaymentPeriod = "P1M" | "P3M" | "P6M" | "P1Y"; + +export type DedicatedServerLocation = "ru-1" | "ru-2" | "kz-1" | "pl-1"; + +export type DedicatedServerPresetCpu = { + description?: string; + description_short?: string; + count?: number; + [key: string]: any; +}; + +export type DedicatedServerPreset = { + id: number; + description: string; + is_ipmi_enabled?: boolean; + is_pre_installed?: boolean; + cpu?: DedicatedServerPresetCpu; + [key: string]: any; +}; + +export type DedicatedServerAdditionalServicePeriod = + | "P1D" + | "P1M" + | "P3M" + | "P6M" + | "P1Y" + | "forever"; + +export type DedicatedServerAdditionalService = { + id: number; + price: number; + period: DedicatedServerAdditionalServicePeriod | string; + description: string; + short_description: string; + name: string; +}; diff --git a/src/types/dns-record.type.ts b/src/types/dns-record.type.ts new file mode 100644 index 0000000..cad70ca --- /dev/null +++ b/src/types/dns-record.type.ts @@ -0,0 +1,29 @@ +export type DnsRecordType = "TXT" | "SRV" | "CNAME" | "AAAA" | "MX" | "A"; + +export type DnsRecordData = { + priority?: number; + subdomain?: string | null; + value?: string; + host?: string; + port?: number; + service?: string; + protocol?: string; + [key: string]: unknown; +}; + +export type DnsRecord = { + type: DnsRecordType; + id?: number | null; + data: DnsRecordData; + ttl?: number; + [key: string]: unknown; +}; + +export type DnsRecordV2 = { + type: DnsRecordType; + id?: number | null; + fqdn?: string; + data: DnsRecordData; + ttl?: number; + [key: string]: unknown; +}; diff --git a/src/types/domain-name-server.type.ts b/src/types/domain-name-server.type.ts new file mode 100644 index 0000000..eb8aa23 --- /dev/null +++ b/src/types/domain-name-server.type.ts @@ -0,0 +1,10 @@ +export type DomainNameServerItem = { + host: string; + ips: string[]; +}; + +export type DomainNameServer = { + is_delegation_allowed: boolean; + task_status: "done" | "active" | "failed" | string; + items: DomainNameServerItem[]; +}; diff --git a/src/types/domain-request.type.ts b/src/types/domain-request.type.ts new file mode 100644 index 0000000..ae4f53b --- /dev/null +++ b/src/types/domain-request.type.ts @@ -0,0 +1,21 @@ +export type DomainRequest = { + id: number; + account_id?: string; + fqdn: string; + auth_code?: string | null; + date?: string; + domain_bundle_id?: string | null; + error_code_transfer?: string | null; + group_id?: number; + is_antispam_enabled?: boolean; + is_autoprolong_enabled?: boolean; + is_whois_privacy_enabled?: boolean; + message?: string | null; + money_source?: "use" | "bonus" | "invoice" | null; + period?: string; + person_id?: number | null; + prime?: string | null; + status?: string; + type?: "register" | "prolong" | "transfer" | string; + [key: string]: unknown; +}; diff --git a/src/types/domain.type.ts b/src/types/domain.type.ts new file mode 100644 index 0000000..5161bf5 --- /dev/null +++ b/src/types/domain.type.ts @@ -0,0 +1,39 @@ +export type DomainAllowedBuyPeriod = { + period: string; + price: number; +}; + +export type DomainLinkedIp = { + ip?: string | null; + service_type?: string | null; + resource_id?: number | string | null; + [key: string]: unknown; +}; + +export type Domain = { + id: number; + fqdn: string; + domain_status: string; + expiration: string; + days_left?: number; + avatar_link?: string | null; + is_autoprolong_enabled?: boolean | null; + is_premium?: boolean; + is_prolong_allowed?: boolean; + is_technical?: boolean; + is_whois_privacy_enabled?: boolean; + linked_ip?: string | DomainLinkedIp | null; + person_id?: number | null; + provider?: string | null; + registrar?: string | null; + subdomains?: DomainSubdomain[]; + allowed_buy_periods?: DomainAllowedBuyPeriod[]; + [key: string]: unknown; +}; + +export type DomainSubdomain = { + id: number; + fqdn: string; + linked_ip?: string | null; + [key: string]: unknown; +}; diff --git a/src/types/dto/add-bucket-certificate-request.dto.ts b/src/types/dto/add-bucket-certificate-request.dto.ts new file mode 100644 index 0000000..556103d --- /dev/null +++ b/src/types/dto/add-bucket-certificate-request.dto.ts @@ -0,0 +1,3 @@ +export type AddBucketCertificateRequestDto = { + subdomain: string; +}; diff --git a/src/types/dto/add-bucket-subdomains-request.dto.ts b/src/types/dto/add-bucket-subdomains-request.dto.ts new file mode 100644 index 0000000..c86136e --- /dev/null +++ b/src/types/dto/add-bucket-subdomains-request.dto.ts @@ -0,0 +1,3 @@ +export type AddBucketSubdomainsRequestDto = { + subdomains: string[]; +}; diff --git a/src/types/dto/add-bucket-subdomains-response.dto.ts b/src/types/dto/add-bucket-subdomains-response.dto.ts new file mode 100644 index 0000000..c8d2d34 --- /dev/null +++ b/src/types/dto/add-bucket-subdomains-response.dto.ts @@ -0,0 +1,7 @@ +import { AddedBucketSubdomain } from "../bucket-subdomain.type"; + +export type AddBucketSubdomainsResponseDto = { + subdomains: AddedBucketSubdomain[]; + meta: any; + response_id?: string; +}; diff --git a/src/types/dto/add-resource-to-project-request.dto.ts b/src/types/dto/add-resource-to-project-request.dto.ts new file mode 100644 index 0000000..b040bd9 --- /dev/null +++ b/src/types/dto/add-resource-to-project-request.dto.ts @@ -0,0 +1,3 @@ +export type AddResourceToProjectRequestDto = { + resource_id: number; +}; diff --git a/src/types/dto/add-ssh-keys-to-server-request.dto.ts b/src/types/dto/add-ssh-keys-to-server-request.dto.ts new file mode 100644 index 0000000..7d90147 --- /dev/null +++ b/src/types/dto/add-ssh-keys-to-server-request.dto.ts @@ -0,0 +1,3 @@ +export interface AddSshKeysToServerRequestDto { + ssh_key_ids: number[]; +} diff --git a/src/types/dto/add-subdomain-response.dto.ts b/src/types/dto/add-subdomain-response.dto.ts new file mode 100644 index 0000000..85884da --- /dev/null +++ b/src/types/dto/add-subdomain-response.dto.ts @@ -0,0 +1,5 @@ +import { DomainSubdomain } from "../domain.type"; + +export type AddSubdomainResponseDto = { + subdomain: DomainSubdomain; +}; diff --git a/src/types/dto/add-token-package-request.dto.ts b/src/types/dto/add-token-package-request.dto.ts new file mode 100644 index 0000000..fe5277f --- /dev/null +++ b/src/types/dto/add-token-package-request.dto.ts @@ -0,0 +1,3 @@ +export type AddTokenPackageRequestDto = { + count?: number; +}; diff --git a/src/types/dto/auto-backup-response.dto.ts b/src/types/dto/auto-backup-response.dto.ts new file mode 100644 index 0000000..f823602 --- /dev/null +++ b/src/types/dto/auto-backup-response.dto.ts @@ -0,0 +1,6 @@ +import { AutoBackupSettings } from "../auto-backup.type"; + +export type AutoBackupResponseDto = { + auto_backups_settings: AutoBackupSettings; + response_id?: string; +}; diff --git a/src/types/dto/balancer-ips-request.dto.ts b/src/types/dto/balancer-ips-request.dto.ts new file mode 100644 index 0000000..904ea7b --- /dev/null +++ b/src/types/dto/balancer-ips-request.dto.ts @@ -0,0 +1,3 @@ +export type BalancerIpsRequestDto = { + ips: string[]; +}; diff --git a/src/types/dto/balancer-rule-response.dto.ts b/src/types/dto/balancer-rule-response.dto.ts new file mode 100644 index 0000000..886b766 --- /dev/null +++ b/src/types/dto/balancer-rule-response.dto.ts @@ -0,0 +1,6 @@ +import { BalancerRule } from "../balancer.type"; + +export type BalancerRuleResponseDto = { + rule: BalancerRule; + response_id?: string; +}; diff --git a/src/types/dto/batch-create-mailboxes-request.dto.ts b/src/types/dto/batch-create-mailboxes-request.dto.ts new file mode 100644 index 0000000..5e1d428 --- /dev/null +++ b/src/types/dto/batch-create-mailboxes-request.dto.ts @@ -0,0 +1,22 @@ +export type BatchMailboxV1Item = { + login: string; + password: string; + owner_full_name?: string; + comment?: string; +}; + +export type BatchCreateMailboxesV1RequestDto = { + mailboxes: BatchMailboxV1Item[]; +}; + +export type BatchMailboxV2Item = { + login: string; + password: string; + owner_full_name?: string; + comment?: string; + filter_status?: boolean; + filter_action?: "directory" | "label"; +}; + +// v2 body — массив напрямую (не объект) +export type BatchCreateMailboxesV2RequestDto = BatchMailboxV2Item[]; diff --git a/src/types/dto/batch-create-mailboxes-response.dto.ts b/src/types/dto/batch-create-mailboxes-response.dto.ts new file mode 100644 index 0000000..30e3f52 --- /dev/null +++ b/src/types/dto/batch-create-mailboxes-response.dto.ts @@ -0,0 +1,11 @@ +import { Mailbox, MailboxesBatchV2 } from "../mailbox.type"; + +export type BatchCreateMailboxesV1ResponseDto = { + mailboxes: Mailbox[]; + response_id?: string; +}; + +export type BatchCreateMailboxesV2ResponseDto = { + mailboxes_batch: MailboxesBatchV2; + response_id?: string; +}; diff --git a/src/types/dto/bind-floating-ip-request.dto.ts b/src/types/dto/bind-floating-ip-request.dto.ts new file mode 100644 index 0000000..6dae0cb --- /dev/null +++ b/src/types/dto/bind-floating-ip-request.dto.ts @@ -0,0 +1,6 @@ +import { FloatingIpResourceType } from "../floating-ip.type"; + +export interface BindFloatingIpRequestDto { + resource_type: FloatingIpResourceType; + resource_id: number | string; +} diff --git a/src/types/dto/check-domain-response.dto.ts b/src/types/dto/check-domain-response.dto.ts new file mode 100644 index 0000000..f435ac7 --- /dev/null +++ b/src/types/dto/check-domain-response.dto.ts @@ -0,0 +1,4 @@ +export type CheckDomainResponseDto = { + is_domain_available: boolean; + response_id?: string; +}; diff --git a/src/types/dto/create-ai-agent-request.dto.ts b/src/types/dto/create-ai-agent-request.dto.ts new file mode 100644 index 0000000..c1dd0a7 --- /dev/null +++ b/src/types/dto/create-ai-agent-request.dto.ts @@ -0,0 +1,11 @@ +import { AgentSettings } from "../ai-agent.type"; + +export type CreateAiAgentRequestDto = { + name: string; + description?: string; + access_type: "public" | "private"; + model_id: number; + token_package_id: number; + settings: AgentSettings; + project_id?: number; +}; diff --git a/src/types/dto/create-api-key-request.dto.ts b/src/types/dto/create-api-key-request.dto.ts new file mode 100644 index 0000000..8173c4b --- /dev/null +++ b/src/types/dto/create-api-key-request.dto.ts @@ -0,0 +1,7 @@ +export interface CreateApiKeyRequestDto { + name: string; + expire?: string; + is_able_to_delete?: boolean; + roles?: any; + projects?: number[] | null; +} diff --git a/src/types/dto/create-api-key-response.dto.ts b/src/types/dto/create-api-key-response.dto.ts new file mode 100644 index 0000000..b698f77 --- /dev/null +++ b/src/types/dto/create-api-key-response.dto.ts @@ -0,0 +1,5 @@ +import { CreatedApiKey } from "../api-key.type"; + +export interface CreateApiKeyResponseDto { + api_key: CreatedApiKey; +} diff --git a/src/types/dto/create-balancer-request.dto.ts b/src/types/dto/create-balancer-request.dto.ts new file mode 100644 index 0000000..65d34ff --- /dev/null +++ b/src/types/dto/create-balancer-request.dto.ts @@ -0,0 +1,40 @@ +import { BalancerAlgo, BalancerProto } from "../balancer.type"; + +export type CreateBalancerCertificate = { + type: "lets_encrypt" | "custom"; + fqdn?: string; + cert_data?: string; + key_data?: string; +}; + +export type CreateBalancerNetwork = { + id: string; + floating_ip?: string; + local_ip?: string; +}; + +export type CreateBalancerRequestDto = { + name: string; + algo: BalancerAlgo; + is_sticky: boolean; + is_use_proxy: boolean; + is_ssl: boolean; + is_keepalive: boolean; + proto: BalancerProto; + port?: number; + path: string; + inter: number; + timeout: number; + fall: number; + rise: number; + maxconn?: number; + connect_timeout?: number; + client_timeout?: number; + server_timeout?: number; + httprequest_timeout?: number; + preset_id: number; + network?: CreateBalancerNetwork; + availability_zone?: string; + project_id?: number; + certificates?: CreateBalancerCertificate; +}; diff --git a/src/types/dto/create-balancer-rule-request.dto.ts b/src/types/dto/create-balancer-rule-request.dto.ts new file mode 100644 index 0000000..4a47e88 --- /dev/null +++ b/src/types/dto/create-balancer-rule-request.dto.ts @@ -0,0 +1,10 @@ +import { BalancerProto } from "../balancer.type"; + +export type CreateBalancerRuleRequestDto = { + balancer_proto: BalancerProto; + balancer_port: number; + server_proto: BalancerProto; + server_port: number; +}; + +export type UpdateBalancerRuleRequestDto = CreateBalancerRuleRequestDto; diff --git a/src/types/dto/create-bucket-request.dto.ts b/src/types/dto/create-bucket-request.dto.ts new file mode 100644 index 0000000..ff484d5 --- /dev/null +++ b/src/types/dto/create-bucket-request.dto.ts @@ -0,0 +1,13 @@ +import { BucketType } from "../bucket.type"; + +export type CreateBucketRequestDto = { + name: string; + type: BucketType; + description?: string; + preset_id?: number; + configurator?: { + id?: number; + disk?: number; + }; + project_id?: number; +}; diff --git a/src/types/dto/create-bucket-response.dto.ts b/src/types/dto/create-bucket-response.dto.ts new file mode 100644 index 0000000..c15e736 --- /dev/null +++ b/src/types/dto/create-bucket-response.dto.ts @@ -0,0 +1,6 @@ +import { Bucket } from "../bucket.type"; + +export type CreateBucketResponseDto = { + bucket: Bucket; + response_id?: string; +}; diff --git a/src/types/dto/create-container-registry-request.dto.ts b/src/types/dto/create-container-registry-request.dto.ts new file mode 100644 index 0000000..b3551cf --- /dev/null +++ b/src/types/dto/create-container-registry-request.dto.ts @@ -0,0 +1,10 @@ +export type CreateContainerRegistryRequestDto = { + name: string; + description?: string; + preset_id?: number; + configuration?: { + id: number; + disk: number; + }; + project_id?: number; +}; diff --git a/src/types/dto/create-database-admin-request.dto.ts b/src/types/dto/create-database-admin-request.dto.ts new file mode 100644 index 0000000..63a5ea4 --- /dev/null +++ b/src/types/dto/create-database-admin-request.dto.ts @@ -0,0 +1,8 @@ +export type CreateDatabaseAdminRequestDto = { + login: string; + password: string; + privileges: string[]; + host?: string; + instance_id?: number; + description?: string; +}; diff --git a/src/types/dto/create-database-instance-request.dto.ts b/src/types/dto/create-database-instance-request.dto.ts new file mode 100644 index 0000000..208b20d --- /dev/null +++ b/src/types/dto/create-database-instance-request.dto.ts @@ -0,0 +1,4 @@ +export type CreateDatabaseInstanceRequestDto = { + name: string; + description?: string; +}; diff --git a/src/types/dto/create-dedicated-server-request.dto.ts b/src/types/dto/create-dedicated-server-request.dto.ts new file mode 100644 index 0000000..23be324 --- /dev/null +++ b/src/types/dto/create-dedicated-server-request.dto.ts @@ -0,0 +1,15 @@ +import { DedicatedServerPaymentPeriod } from "../dedicated-server.type"; + +export type CreateDedicatedServerRequestDto = { + preset_id: number; + payment_period: DedicatedServerPaymentPeriod; + name: string; + plan_id?: number | null; + os_id?: number | null; + cp_id?: number | null; + bandwidth_id?: number | null; + network_drive_id?: number; + additional_ip_addr_id?: number | null; + comment?: string | null; + project_id?: number | null; +}; diff --git a/src/types/dto/create-dns-record-request.dto.ts b/src/types/dto/create-dns-record-request.dto.ts new file mode 100644 index 0000000..6b6e658 --- /dev/null +++ b/src/types/dto/create-dns-record-request.dto.ts @@ -0,0 +1,23 @@ +import { DnsRecordType } from "../dns-record.type"; + +export type CreateDnsRecordRequestDto = { + type: DnsRecordType; + value: string; + priority?: number; + subdomain?: string; + ttl?: number; +}; + +export type CreateDnsRecordV2RequestDto = { + type: DnsRecordType; + value?: string; + ttl?: number; + app_id?: number; + subdomain?: string; + priority?: number; + host?: string; + port?: number; + service?: string; + protocol?: string; + [key: string]: unknown; +}; diff --git a/src/types/dto/create-dns-record-response.dto.ts b/src/types/dto/create-dns-record-response.dto.ts new file mode 100644 index 0000000..aed89bb --- /dev/null +++ b/src/types/dto/create-dns-record-response.dto.ts @@ -0,0 +1,9 @@ +import { DnsRecord, DnsRecordV2 } from "../dns-record.type"; + +export type CreateDnsRecordResponseDto = { + dns_record: DnsRecord; +}; + +export type CreateDnsRecordV2ResponseDto = { + dns_record: DnsRecordV2; +}; diff --git a/src/types/dto/create-domain-request-request.dto.ts b/src/types/dto/create-domain-request-request.dto.ts new file mode 100644 index 0000000..6129b87 --- /dev/null +++ b/src/types/dto/create-domain-request-request.dto.ts @@ -0,0 +1,41 @@ +export type DomainRegisterRequest = { + action: "register"; + fqdn: string; + person_id: number; + is_autoprolong_enabled?: boolean; + is_whois_privacy_enabled?: boolean; + period?: string; +}; + +export type DomainProlongRequest = { + action: "prolong"; + fqdn: string; + person_id?: number; + is_antispam_enabled?: boolean; + is_autoprolong_enabled?: boolean; + is_whois_privacy_enabled?: boolean; + period?: string; + prime?: string; +}; + +export type DomainTransferRequest = { + action: "transfer"; + fqdn: string; + auth_code: string; +}; + +export type CreateDomainRequestRequestDto = + | DomainRegisterRequest + | DomainProlongRequest + | DomainTransferRequest; + +export type UpdateDomainRequestBodyDto = + | { money_source: "use"; person_id?: number } + | { + money_source: "invoice"; + payment_type: string; + payer_id: number; + person_id?: number; + } + | { money_source: "free"; auth_code: string; person_id?: number } + | { money_source: "bonus"; bonus_id: number; person_id?: number }; diff --git a/src/types/dto/create-firewall-group-request.dto.ts b/src/types/dto/create-firewall-group-request.dto.ts new file mode 100644 index 0000000..58f1cb6 --- /dev/null +++ b/src/types/dto/create-firewall-group-request.dto.ts @@ -0,0 +1,4 @@ +export interface CreateFirewallGroupRequestDto { + name: string; + description?: string; +} diff --git a/src/types/dto/create-firewall-rule-request.dto.ts b/src/types/dto/create-firewall-rule-request.dto.ts new file mode 100644 index 0000000..854730b --- /dev/null +++ b/src/types/dto/create-firewall-rule-request.dto.ts @@ -0,0 +1,12 @@ +import { + FirewallRuleDirection, + FirewallRuleProtocol, +} from "../firewall-rule.type"; + +export interface CreateFirewallRuleRequestDto { + direction: FirewallRuleDirection; + protocol: FirewallRuleProtocol; + description?: string; + port?: string; + cidr?: string; +} diff --git a/src/types/dto/create-image-download-request.dto.ts b/src/types/dto/create-image-download-request.dto.ts new file mode 100644 index 0000000..93930c8 --- /dev/null +++ b/src/types/dto/create-image-download-request.dto.ts @@ -0,0 +1,14 @@ +import { ImageUrlType } from "../image-download.type"; + +export type ImageUrlAuth = { + access_token: string; + refresh_token?: string; + expiry?: string; + token_type?: string; +}; + +export type CreateImageDownloadRequestDto = { + type?: ImageUrlType | string; + filename?: string; + auth?: ImageUrlAuth; +}; diff --git a/src/types/dto/create-image-request.dto.ts b/src/types/dto/create-image-request.dto.ts new file mode 100644 index 0000000..62e40a8 --- /dev/null +++ b/src/types/dto/create-image-request.dto.ts @@ -0,0 +1,10 @@ +import { ImageLocation, ImageOS } from "../image.type"; + +export type CreateImageRequestDto = { + os: ImageOS | string; + location: ImageLocation | string; + name?: string; + description?: string; + disk_id?: number; + upload_url?: string; +}; diff --git a/src/types/dto/create-k8s-cluster-request.dto.ts b/src/types/dto/create-k8s-cluster-request.dto.ts new file mode 100644 index 0000000..754e22a --- /dev/null +++ b/src/types/dto/create-k8s-cluster-request.dto.ts @@ -0,0 +1,56 @@ +export type K8sClusterConfiguration = { + configurator_id: number; + disk: number; + cpu: number; + ram: number; +}; + +export type K8sMaintenanceSlot = { + type: "any_time" | "fixed_time"; + from?: string; + to?: string; +}; + +export type K8sOidcProvider = { + name: string; + issuer_url: string; + client_id: string; + username_claim?: string; + groups_claim?: string; +}; + +export type K8sClusterNetworkCidr = { + pods_network?: string; + services_network?: string; +}; + +export type K8sWorkerGroupIn = { + name: string; + node_count: number; + preset_id?: number; + configuration?: K8sClusterConfiguration & { gpu?: number }; + labels?: Array<{ key: string; value: string }>; + is_autoscaling?: boolean; + "min-size"?: number; + "max-size"?: number; + is_autohealing?: boolean; +}; + +export type CreateK8sClusterRequestDto = { + name: string; + k8s_version: string; + network_driver: "kuberouter" | "calico" | "flannel" | "cilium"; + description?: string; + availability_zone?: "spb-3" | "msk-1" | "ams-1" | "fra-1"; + is_ingress?: boolean; + is_k8s_dashboard?: boolean; + preset_id?: number; + configuration?: K8sClusterConfiguration; + master_nodes_count?: number; + worker_groups?: K8sWorkerGroupIn[]; + network_id?: string; + project_id?: number; + maintenance_slot?: K8sMaintenanceSlot; + oidc_provider?: K8sOidcProvider; + cluster_network_cidr?: K8sClusterNetworkCidr; +}; diff --git a/src/types/dto/create-k8s-node-group-request.dto.ts b/src/types/dto/create-k8s-node-group-request.dto.ts new file mode 100644 index 0000000..1f2db28 --- /dev/null +++ b/src/types/dto/create-k8s-node-group-request.dto.ts @@ -0,0 +1,19 @@ +export type K8sNodeGroupConfiguration = { + configurator_id: number; + disk: number; + cpu: number; + ram: number; + gpu?: number; +}; + +export type CreateK8sNodeGroupRequestDto = { + name: string; + node_count: number; + preset_id?: number; + configuration?: K8sNodeGroupConfiguration; + labels?: Array<{ key: string; value: string }>; + is_autoscaling?: boolean; + "min-size"?: number; + "max-size"?: number; + is_autohealing?: boolean; +}; diff --git a/src/types/dto/create-knowledge-base-request.dto.ts b/src/types/dto/create-knowledge-base-request.dto.ts new file mode 100644 index 0000000..7c02907 --- /dev/null +++ b/src/types/dto/create-knowledge-base-request.dto.ts @@ -0,0 +1,8 @@ +export type CreateKnowledgeBaseRequestDto = { + name: string; + description?: string; + dbaas_preset_id: number; + network_id: string; + token_package_id: number; + project_id?: number; +}; diff --git a/src/types/dto/create-mailbox-request.dto.ts b/src/types/dto/create-mailbox-request.dto.ts new file mode 100644 index 0000000..0b1c174 --- /dev/null +++ b/src/types/dto/create-mailbox-request.dto.ts @@ -0,0 +1,14 @@ +export type CreateMailboxV1RequestDto = { + mailbox: string; + password: string; + comment?: string; +}; + +export type CreateMailboxV2RequestDto = { + mailbox: string; + password: string; + comment?: string; + owner_full_name?: string; + filter_status?: boolean; + filter_action?: "directory" | "label"; +}; diff --git a/src/types/dto/create-mailbox-response.dto.ts b/src/types/dto/create-mailbox-response.dto.ts new file mode 100644 index 0000000..6e4d739 --- /dev/null +++ b/src/types/dto/create-mailbox-response.dto.ts @@ -0,0 +1,11 @@ +import { Mailbox, MailboxV2 } from "../mailbox.type"; + +export type CreateMailboxV1ResponseDto = { + mailbox: Mailbox; + response_id?: string; +}; + +export type CreateMailboxV2ResponseDto = { + mailbox: MailboxV2; + response_id?: string; +}; diff --git a/src/types/dto/create-network-drive-request.dto.ts b/src/types/dto/create-network-drive-request.dto.ts new file mode 100644 index 0000000..7e4e821 --- /dev/null +++ b/src/types/dto/create-network-drive-request.dto.ts @@ -0,0 +1,6 @@ +export type CreateNetworkDriveRequestDto = { + name: string; + size: number; + preset_id: number; + comment?: string | null; +}; diff --git a/src/types/dto/create-network-drive-response.dto.ts b/src/types/dto/create-network-drive-response.dto.ts new file mode 100644 index 0000000..70df899 --- /dev/null +++ b/src/types/dto/create-network-drive-response.dto.ts @@ -0,0 +1,6 @@ +import { NetworkDrive } from "../network-drive.type"; + +export type CreateNetworkDriveResponseDto = { + network_drive: NetworkDrive; + response_id?: string; +}; diff --git a/src/types/dto/create-project-request.dto.ts b/src/types/dto/create-project-request.dto.ts new file mode 100644 index 0000000..868fd86 --- /dev/null +++ b/src/types/dto/create-project-request.dto.ts @@ -0,0 +1,5 @@ +export type CreateProjectRequestDto = { + name: string; + description?: string | null; + avatar_id?: string | null; +}; diff --git a/src/types/dto/create-server-disk-backup-response.dto.ts b/src/types/dto/create-server-disk-backup-response.dto.ts new file mode 100644 index 0000000..e5731f4 --- /dev/null +++ b/src/types/dto/create-server-disk-backup-response.dto.ts @@ -0,0 +1,5 @@ +import { ServerBackup } from "../server-backup.type"; + +export type CreateServerDiskBackupResponseDto = { + backup: ServerBackup; +}; diff --git a/src/types/dto/create-server-disk-request.dto.ts b/src/types/dto/create-server-disk-request.dto.ts new file mode 100644 index 0000000..d34e332 --- /dev/null +++ b/src/types/dto/create-server-disk-request.dto.ts @@ -0,0 +1,3 @@ +export type CreateServerDiskRequestDto = { + size: number; +}; diff --git a/src/types/dto/create-server-request.dto.ts b/src/types/dto/create-server-request.dto.ts new file mode 100644 index 0000000..d497acf --- /dev/null +++ b/src/types/dto/create-server-request.dto.ts @@ -0,0 +1,33 @@ +export type CreateServerConfigurator = { + configurator_id: number; + disk: number; + cpu: number; + ram: number; + gpu?: number; +}; + +export type CreateServerNetwork = { + id?: string; + floating_ip?: string; + local_ip?: string; + network_drive_ids?: string[]; +}; + +export type CreateServerRequestDto = { + name: string; + os_id?: number; + image_id?: string; + software_id?: number; + preset_id?: number; + configuration?: CreateServerConfigurator; + bandwidth?: number; + avatar_id?: string; + comment?: string; + ssh_keys_ids?: number[]; + is_ddos_guard?: boolean; + network?: CreateServerNetwork; + cloud_init?: string; + availability_zone?: string; + project_id?: number; + hostname?: string; +}; diff --git a/src/types/dto/create-server-response.dto.ts b/src/types/dto/create-server-response.dto.ts new file mode 100644 index 0000000..05114ab --- /dev/null +++ b/src/types/dto/create-server-response.dto.ts @@ -0,0 +1,6 @@ +import { Server } from "../server.type"; + +export type CreateServerResponseDto = { + server: Server; + response_id?: string; +}; diff --git a/src/types/dto/create-ssh-key-request.dto.ts b/src/types/dto/create-ssh-key-request.dto.ts new file mode 100644 index 0000000..e3e953d --- /dev/null +++ b/src/types/dto/create-ssh-key-request.dto.ts @@ -0,0 +1,5 @@ +export interface CreateSshKeyRequestDto { + name: string; + body: string; + is_default: boolean; +} diff --git a/src/types/dto/create-ssh-key-response.dto.ts b/src/types/dto/create-ssh-key-response.dto.ts new file mode 100644 index 0000000..51c8c01 --- /dev/null +++ b/src/types/dto/create-ssh-key-response.dto.ts @@ -0,0 +1,5 @@ +import { SshKey } from "../ssh-key.type"; + +export interface CreateSshKeyResponseDto { + ssh_key: SshKey; +} diff --git a/src/types/dto/database-admin-response.dto.ts b/src/types/dto/database-admin-response.dto.ts new file mode 100644 index 0000000..bc6d715 --- /dev/null +++ b/src/types/dto/database-admin-response.dto.ts @@ -0,0 +1,5 @@ +import { DatabaseAdminEntity } from "../database-cluster.type"; + +export type DatabaseAdminResponseDto = { + admin: DatabaseAdminEntity; +}; diff --git a/src/types/dto/database-auto-backups-response.dto.ts b/src/types/dto/database-auto-backups-response.dto.ts new file mode 100644 index 0000000..2521b5a --- /dev/null +++ b/src/types/dto/database-auto-backups-response.dto.ts @@ -0,0 +1,6 @@ +import { DatabaseAutoBackupSettings } from "../database-cluster.type"; + +export type DatabaseAutoBackupsResponseDto = { + meta: { total: number }; + auto_backups_settings: DatabaseAutoBackupSettings[]; +}; diff --git a/src/types/dto/database-backup-response.dto.ts b/src/types/dto/database-backup-response.dto.ts new file mode 100644 index 0000000..2f0572b --- /dev/null +++ b/src/types/dto/database-backup-response.dto.ts @@ -0,0 +1,5 @@ +import { DatabaseBackup } from "../database-cluster.type"; + +export type DatabaseBackupResponseDto = { + backup: DatabaseBackup; +}; diff --git a/src/types/dto/database-instance-response.dto.ts b/src/types/dto/database-instance-response.dto.ts new file mode 100644 index 0000000..5026780 --- /dev/null +++ b/src/types/dto/database-instance-response.dto.ts @@ -0,0 +1,5 @@ +import { DatabaseInstanceEntity } from "../database-cluster.type"; + +export type DatabaseInstanceResponseDto = { + instance: DatabaseInstanceEntity; +}; diff --git a/src/types/dto/delete-balancer-response.dto.ts b/src/types/dto/delete-balancer-response.dto.ts new file mode 100644 index 0000000..30ef78f --- /dev/null +++ b/src/types/dto/delete-balancer-response.dto.ts @@ -0,0 +1,6 @@ +import { DeleteBalancerResult } from "../balancer.type"; + +export type DeleteBalancerResponseDto = { + balancer_delete: DeleteBalancerResult; + response_id?: string; +}; diff --git a/src/types/dto/delete-bucket-response.dto.ts b/src/types/dto/delete-bucket-response.dto.ts new file mode 100644 index 0000000..e6dd703 --- /dev/null +++ b/src/types/dto/delete-bucket-response.dto.ts @@ -0,0 +1,6 @@ +import { BucketDeleteResponse } from "../bucket-delete-response.type"; + +export type DeleteBucketResponseDto = { + bucket_delete: BucketDeleteResponse; + response_id?: string; +}; diff --git a/src/types/dto/delete-bucket-subdomains-request.dto.ts b/src/types/dto/delete-bucket-subdomains-request.dto.ts new file mode 100644 index 0000000..a4b9e9a --- /dev/null +++ b/src/types/dto/delete-bucket-subdomains-request.dto.ts @@ -0,0 +1,3 @@ +export type DeleteBucketSubdomainsRequestDto = { + subdomains: string[]; +}; diff --git a/src/types/dto/delete-bucket-subdomains-response.dto.ts b/src/types/dto/delete-bucket-subdomains-response.dto.ts new file mode 100644 index 0000000..4b9c452 --- /dev/null +++ b/src/types/dto/delete-bucket-subdomains-response.dto.ts @@ -0,0 +1,7 @@ +import { AddedBucketSubdomain } from "../bucket-subdomain.type"; + +export type DeleteBucketSubdomainsResponseDto = { + subdomains: AddedBucketSubdomain[]; + meta: any; + response_id?: string; +}; diff --git a/src/types/dto/delete-database-response.dto.ts b/src/types/dto/delete-database-response.dto.ts new file mode 100644 index 0000000..4e8bcb7 --- /dev/null +++ b/src/types/dto/delete-database-response.dto.ts @@ -0,0 +1,9 @@ +import { DatabaseDeleteResponse } from "../database-cluster.type"; + +export type DeleteDatabaseClusterResponseDto = { + hash?: string; +}; + +export type DeleteDatabaseResponseDto = { + database_delete?: DatabaseDeleteResponse; +}; diff --git a/src/types/dto/delete-k8s-cluster-response.dto.ts b/src/types/dto/delete-k8s-cluster-response.dto.ts new file mode 100644 index 0000000..c644c3d --- /dev/null +++ b/src/types/dto/delete-k8s-cluster-response.dto.ts @@ -0,0 +1,7 @@ +export type DeleteK8sClusterResponseDto = { + cluster_delete: { + hash?: string; + is_moved_in_quarantine?: boolean; + }; + response_id?: string; +}; diff --git a/src/types/dto/delete-server-response.dto.ts b/src/types/dto/delete-server-response.dto.ts new file mode 100644 index 0000000..54cf1b8 --- /dev/null +++ b/src/types/dto/delete-server-response.dto.ts @@ -0,0 +1,7 @@ +export type DeleteServerResponseDto = { + server_delete: { + hash?: string; + is_moved_in_quarantine?: boolean; + }; + response_id?: string; +}; diff --git a/src/types/dto/domain-name-servers-response.dto.ts b/src/types/dto/domain-name-servers-response.dto.ts new file mode 100644 index 0000000..10fd901 --- /dev/null +++ b/src/types/dto/domain-name-servers-response.dto.ts @@ -0,0 +1,6 @@ +import { DomainNameServer } from "../domain-name-server.type"; + +export type DomainNameServersResponseDto = { + name_servers: DomainNameServer[]; + meta: { total: number }; +}; diff --git a/src/types/dto/edit-api-key-request.dto.ts b/src/types/dto/edit-api-key-request.dto.ts new file mode 100644 index 0000000..5cb14cf --- /dev/null +++ b/src/types/dto/edit-api-key-request.dto.ts @@ -0,0 +1,4 @@ +export interface EditApiKeyRequestDto { + name?: string; + is_able_to_delete?: boolean; +} diff --git a/src/types/dto/edit-api-key-response.dto.ts b/src/types/dto/edit-api-key-response.dto.ts new file mode 100644 index 0000000..08ee6c8 --- /dev/null +++ b/src/types/dto/edit-api-key-response.dto.ts @@ -0,0 +1,5 @@ +import { ApiKey } from "../api-key.type"; + +export interface EditApiKeyResponseDto { + api_key: ApiKey; +} diff --git a/src/types/dto/edit-k8s-cluster-request.dto.ts b/src/types/dto/edit-k8s-cluster-request.dto.ts new file mode 100644 index 0000000..15cc14d --- /dev/null +++ b/src/types/dto/edit-k8s-cluster-request.dto.ts @@ -0,0 +1,7 @@ +import { K8sOidcProvider } from "./create-k8s-cluster-request.dto"; + +export type EditK8sClusterRequestDto = { + name?: string; + description?: string; + oidc_provider?: K8sOidcProvider; +}; diff --git a/src/types/dto/get-account-status-response.dto.ts b/src/types/dto/get-account-status-response.dto.ts new file mode 100644 index 0000000..e1ee816 --- /dev/null +++ b/src/types/dto/get-account-status-response.dto.ts @@ -0,0 +1,5 @@ +import { AccountStatus } from "../finances.type"; + +export type GetAccountStatusResponseDto = { + status: AccountStatus; +}; diff --git a/src/types/dto/get-agent-statistic-response.dto.ts b/src/types/dto/get-agent-statistic-response.dto.ts new file mode 100644 index 0000000..532aee6 --- /dev/null +++ b/src/types/dto/get-agent-statistic-response.dto.ts @@ -0,0 +1,7 @@ +import { TokenStatistic } from "../token-statistic.type"; + +export type GetAgentStatisticResponseDto = { + agent_statistics: TokenStatistic[]; + meta: { total: number }; + response_id?: string; +}; diff --git a/src/types/dto/get-ai-agent-response.dto.ts b/src/types/dto/get-ai-agent-response.dto.ts new file mode 100644 index 0000000..625f72f --- /dev/null +++ b/src/types/dto/get-ai-agent-response.dto.ts @@ -0,0 +1,6 @@ +import { AiAgent } from "../ai-agent.type"; + +export type GetAiAgentResponseDto = { + agent: AiAgent; + response_id?: string; +}; diff --git a/src/types/dto/get-balancer-response.dto.ts b/src/types/dto/get-balancer-response.dto.ts new file mode 100644 index 0000000..badbf0e --- /dev/null +++ b/src/types/dto/get-balancer-response.dto.ts @@ -0,0 +1,6 @@ +import { Balancer } from "../balancer.type"; + +export type GetBalancerResponseDto = { + balancer: Balancer; + response_id?: string; +}; diff --git a/src/types/dto/get-bucket-presets-response.dto.ts b/src/types/dto/get-bucket-presets-response.dto.ts new file mode 100644 index 0000000..937b88b --- /dev/null +++ b/src/types/dto/get-bucket-presets-response.dto.ts @@ -0,0 +1,7 @@ +import { BucketPreset } from "../bucket-preset.type"; + +export type GetBucketPresetsResponseDto = { + storages_presets: BucketPreset[]; + meta: any; + response_id?: string; +}; diff --git a/src/types/dto/get-bucket-response.dto.ts b/src/types/dto/get-bucket-response.dto.ts new file mode 100644 index 0000000..d847ac4 --- /dev/null +++ b/src/types/dto/get-bucket-response.dto.ts @@ -0,0 +1,6 @@ +import { Bucket } from "../bucket.type"; + +export type GetBucketResponseDto = { + bucket: Bucket; + response_id?: string; +}; diff --git a/src/types/dto/get-bucket-transfer-status-response.dto.ts b/src/types/dto/get-bucket-transfer-status-response.dto.ts new file mode 100644 index 0000000..f935dd7 --- /dev/null +++ b/src/types/dto/get-bucket-transfer-status-response.dto.ts @@ -0,0 +1,6 @@ +import { BucketTransferStatus } from "../bucket-transfer-status.type"; + +export type GetBucketTransferStatusResponseDto = { + transfer_status: BucketTransferStatus; + response_id?: string; +}; diff --git a/src/types/dto/get-container-registry-response.dto.ts b/src/types/dto/get-container-registry-response.dto.ts new file mode 100644 index 0000000..ffac00b --- /dev/null +++ b/src/types/dto/get-container-registry-response.dto.ts @@ -0,0 +1,5 @@ +import { ContainerRegistry } from "../container-registry.type"; + +export type GetContainerRegistryResponseDto = { + container_registry: ContainerRegistry; +}; diff --git a/src/types/dto/get-database-cluster-response.dto.ts b/src/types/dto/get-database-cluster-response.dto.ts new file mode 100644 index 0000000..affe618 --- /dev/null +++ b/src/types/dto/get-database-cluster-response.dto.ts @@ -0,0 +1,5 @@ +import { DatabaseCluster } from "../database-cluster.type"; + +export type GetDatabaseClusterResponseDto = { + db: DatabaseCluster; +}; diff --git a/src/types/dto/get-database-parameters-response.dto.ts b/src/types/dto/get-database-parameters-response.dto.ts new file mode 100644 index 0000000..66b1d96 --- /dev/null +++ b/src/types/dto/get-database-parameters-response.dto.ts @@ -0,0 +1,3 @@ +export type GetDatabaseParametersResponseDto = { + [dbType: string]: string[] | any; +}; diff --git a/src/types/dto/get-database-response.dto.ts b/src/types/dto/get-database-response.dto.ts new file mode 100644 index 0000000..2d53a53 --- /dev/null +++ b/src/types/dto/get-database-response.dto.ts @@ -0,0 +1,5 @@ +import { Database } from "../database.type"; + +export type GetDatabaseResponseDto = { + db: Database; +}; diff --git a/src/types/dto/get-dedicated-server-response.dto.ts b/src/types/dto/get-dedicated-server-response.dto.ts new file mode 100644 index 0000000..9cf6f37 --- /dev/null +++ b/src/types/dto/get-dedicated-server-response.dto.ts @@ -0,0 +1,5 @@ +import { DedicatedServer } from "../dedicated-server.type"; + +export type GetDedicatedServerResponseDto = { + dedicated_server: DedicatedServer; +}; diff --git a/src/types/dto/get-domain-response.dto.ts b/src/types/dto/get-domain-response.dto.ts new file mode 100644 index 0000000..1630850 --- /dev/null +++ b/src/types/dto/get-domain-response.dto.ts @@ -0,0 +1,5 @@ +import { Domain } from "../domain.type"; + +export type GetDomainResponseDto = { + domain: Domain; +}; diff --git a/src/types/dto/get-finances-response.dto.ts b/src/types/dto/get-finances-response.dto.ts new file mode 100644 index 0000000..c5902d8 --- /dev/null +++ b/src/types/dto/get-finances-response.dto.ts @@ -0,0 +1,5 @@ +import { Finances } from "../finances.type"; + +export type GetFinancesResponseDto = { + finances: Finances; +}; diff --git a/src/types/dto/get-firewall-group-response.dto.ts b/src/types/dto/get-firewall-group-response.dto.ts new file mode 100644 index 0000000..02d7a59 --- /dev/null +++ b/src/types/dto/get-firewall-group-response.dto.ts @@ -0,0 +1,6 @@ +import { FirewallGroup } from "../firewall-group.type"; + +export interface GetFirewallGroupResponseDto { + group: FirewallGroup; + response_id?: string; +} diff --git a/src/types/dto/get-firewall-rule-response.dto.ts b/src/types/dto/get-firewall-rule-response.dto.ts new file mode 100644 index 0000000..bb9349d --- /dev/null +++ b/src/types/dto/get-firewall-rule-response.dto.ts @@ -0,0 +1,6 @@ +import { FirewallRule } from "../firewall-rule.type"; + +export interface GetFirewallRuleResponseDto { + rule: FirewallRule; + response_id?: string; +} diff --git a/src/types/dto/get-floating-ip-response.dto.ts b/src/types/dto/get-floating-ip-response.dto.ts new file mode 100644 index 0000000..0316234 --- /dev/null +++ b/src/types/dto/get-floating-ip-response.dto.ts @@ -0,0 +1,5 @@ +import { FloatingIp } from "../floating-ip.type"; + +export interface GetFloatingIpResponseDto { + ip: FloatingIp; +} diff --git a/src/types/dto/get-image-download-response.dto.ts b/src/types/dto/get-image-download-response.dto.ts new file mode 100644 index 0000000..73aadc7 --- /dev/null +++ b/src/types/dto/get-image-download-response.dto.ts @@ -0,0 +1,5 @@ +import { ImageDownload } from "../image-download.type"; + +export type GetImageDownloadResponseDto = { + download: ImageDownload; +}; diff --git a/src/types/dto/get-image-response.dto.ts b/src/types/dto/get-image-response.dto.ts new file mode 100644 index 0000000..1e8dcd5 --- /dev/null +++ b/src/types/dto/get-image-response.dto.ts @@ -0,0 +1,5 @@ +import { Image } from "../image.type"; + +export type GetImageResponseDto = { + image: Image; +}; diff --git a/src/types/dto/get-k8s-cluster-response.dto.ts b/src/types/dto/get-k8s-cluster-response.dto.ts new file mode 100644 index 0000000..e190ee5 --- /dev/null +++ b/src/types/dto/get-k8s-cluster-response.dto.ts @@ -0,0 +1,6 @@ +import { K8sCluster } from "../k8s-cluster.type"; + +export type GetK8sClusterResponseDto = { + cluster: K8sCluster; + response_id?: string; +}; diff --git a/src/types/dto/get-k8s-node-group-response.dto.ts b/src/types/dto/get-k8s-node-group-response.dto.ts new file mode 100644 index 0000000..323ff2f --- /dev/null +++ b/src/types/dto/get-k8s-node-group-response.dto.ts @@ -0,0 +1,6 @@ +import { K8sNodeGroup } from "../k8s-node-group.type"; + +export type GetK8sNodeGroupResponseDto = { + node_group: K8sNodeGroup; + response_id?: string; +}; diff --git a/src/types/dto/get-k8s-resources-response.dto.ts b/src/types/dto/get-k8s-resources-response.dto.ts new file mode 100644 index 0000000..d2f94e4 --- /dev/null +++ b/src/types/dto/get-k8s-resources-response.dto.ts @@ -0,0 +1,6 @@ +import { K8sResources } from "../k8s-resources.type"; + +export type GetK8sResourcesResponseDto = { + resources: K8sResources; + response_id?: string; +}; diff --git a/src/types/dto/get-knowledge-base-response.dto.ts b/src/types/dto/get-knowledge-base-response.dto.ts new file mode 100644 index 0000000..0d6ecb3 --- /dev/null +++ b/src/types/dto/get-knowledge-base-response.dto.ts @@ -0,0 +1,6 @@ +import { KnowledgeBase } from "../knowledge-base.type"; + +export type GetKnowledgeBaseResponseDto = { + knowledgebase: KnowledgeBase; + response_id?: string; +}; diff --git a/src/types/dto/get-knowledge-base-statistic-response.dto.ts b/src/types/dto/get-knowledge-base-statistic-response.dto.ts new file mode 100644 index 0000000..db489a2 --- /dev/null +++ b/src/types/dto/get-knowledge-base-statistic-response.dto.ts @@ -0,0 +1,7 @@ +import { TokenStatistic } from "../token-statistic.type"; + +export type GetKnowledgeBaseStatisticResponseDto = { + knowledgebase_statistics: TokenStatistic[]; + meta: { total: number }; + response_id?: string; +}; diff --git a/src/types/dto/get-mail-domain-info-response.dto.ts b/src/types/dto/get-mail-domain-info-response.dto.ts new file mode 100644 index 0000000..5a4ac06 --- /dev/null +++ b/src/types/dto/get-mail-domain-info-response.dto.ts @@ -0,0 +1,6 @@ +import { MailDomainInfo } from "../mailbox.type"; + +export type GetMailDomainInfoResponseDto = { + domain_info: MailDomainInfo; + response_id?: string; +}; diff --git a/src/types/dto/get-mailbox-response.dto.ts b/src/types/dto/get-mailbox-response.dto.ts new file mode 100644 index 0000000..003d1ba --- /dev/null +++ b/src/types/dto/get-mailbox-response.dto.ts @@ -0,0 +1,11 @@ +import { Mailbox, MailboxV2 } from "../mailbox.type"; + +export type GetMailboxV1ResponseDto = { + mailbox: Mailbox; + response_id?: string; +}; + +export type GetMailboxV2ResponseDto = { + mailbox: MailboxV2; + response_id?: string; +}; diff --git a/src/types/dto/get-network-drive-response.dto.ts b/src/types/dto/get-network-drive-response.dto.ts new file mode 100644 index 0000000..2802a41 --- /dev/null +++ b/src/types/dto/get-network-drive-response.dto.ts @@ -0,0 +1,6 @@ +import { NetworkDrive } from "../network-drive.type"; + +export type GetNetworkDriveResponseDto = { + network_drive: NetworkDrive; + response_id?: string; +}; diff --git a/src/types/dto/get-project-response.dto.ts b/src/types/dto/get-project-response.dto.ts new file mode 100644 index 0000000..7e86261 --- /dev/null +++ b/src/types/dto/get-project-response.dto.ts @@ -0,0 +1,5 @@ +import { Project } from "../project.type"; + +export type GetProjectResponseDto = { + project: Project; +}; diff --git a/src/types/dto/get-server-logs-response.dto.ts b/src/types/dto/get-server-logs-response.dto.ts new file mode 100644 index 0000000..8174f46 --- /dev/null +++ b/src/types/dto/get-server-logs-response.dto.ts @@ -0,0 +1,6 @@ +import { ServerLog } from "../server-log.type"; + +export type GetServerLogsResponseDto = { + server_logs: ServerLog[]; + meta: { total: number }; +}; diff --git a/src/types/dto/get-server-response.dto.ts b/src/types/dto/get-server-response.dto.ts new file mode 100644 index 0000000..34f5fd9 --- /dev/null +++ b/src/types/dto/get-server-response.dto.ts @@ -0,0 +1,5 @@ +import { Server } from "../server.type"; + +export type GetServerResponseDto = { + server: Server; +}; diff --git a/src/types/dto/get-services-cost-response.dto.ts b/src/types/dto/get-services-cost-response.dto.ts new file mode 100644 index 0000000..0cc93f2 --- /dev/null +++ b/src/types/dto/get-services-cost-response.dto.ts @@ -0,0 +1,6 @@ +import { ServicePrice } from "../service-price.type"; + +export type GetServicesCostResponseDto = { + services_costs: ServicePrice[]; + meta: { total: number }; +}; diff --git a/src/types/dto/get-ssh-key-response.dto.ts b/src/types/dto/get-ssh-key-response.dto.ts new file mode 100644 index 0000000..6c6d755 --- /dev/null +++ b/src/types/dto/get-ssh-key-response.dto.ts @@ -0,0 +1,6 @@ +import { SshKey } from "../ssh-key.type"; + +export interface GetSshKeyResponseDto { + ssh_key: SshKey; + meta: { total: number }; +} diff --git a/src/types/dto/get-vpc-response.dto.ts b/src/types/dto/get-vpc-response.dto.ts new file mode 100644 index 0000000..1cd6ebf --- /dev/null +++ b/src/types/dto/get-vpc-response.dto.ts @@ -0,0 +1,5 @@ +import { Vpc } from "../vpc.type"; + +export interface GetVpcResponseDto { + vpc: Vpc; +} diff --git a/src/types/dto/increase-k8s-nodes-request.dto.ts b/src/types/dto/increase-k8s-nodes-request.dto.ts new file mode 100644 index 0000000..f57b123 --- /dev/null +++ b/src/types/dto/increase-k8s-nodes-request.dto.ts @@ -0,0 +1,4 @@ +export type IncreaseK8sNodesRequestDto = { + count: number; + labels?: Array<{ key: string; value: string }>; +}; diff --git a/src/types/dto/install-k8s-addon-request.dto.ts b/src/types/dto/install-k8s-addon-request.dto.ts new file mode 100644 index 0000000..49fa1bb --- /dev/null +++ b/src/types/dto/install-k8s-addon-request.dto.ts @@ -0,0 +1,6 @@ +export type InstallK8sAddonRequestDto = { + type: string; + config_type: "basic" | "custom"; + yaml_config: string; + version: string; +}; diff --git a/src/types/dto/link-firewall-resource-response.dto.ts b/src/types/dto/link-firewall-resource-response.dto.ts new file mode 100644 index 0000000..4894593 --- /dev/null +++ b/src/types/dto/link-firewall-resource-response.dto.ts @@ -0,0 +1,6 @@ +import { FirewallGroupResource } from "../firewall-resource.type"; + +export interface LinkFirewallResourceResponseDto { + resource: FirewallGroupResource; + response_id?: string; +} diff --git a/src/types/dto/list-ai-agents-response.dto.ts b/src/types/dto/list-ai-agents-response.dto.ts new file mode 100644 index 0000000..5548de6 --- /dev/null +++ b/src/types/dto/list-ai-agents-response.dto.ts @@ -0,0 +1,7 @@ +import { AiAgent } from "../ai-agent.type"; + +export type ListAiAgentsResponseDto = { + agents: AiAgent[]; + meta: { total: number }; + response_id?: string; +}; diff --git a/src/types/dto/list-ai-models-response.dto.ts b/src/types/dto/list-ai-models-response.dto.ts new file mode 100644 index 0000000..1bffecd --- /dev/null +++ b/src/types/dto/list-ai-models-response.dto.ts @@ -0,0 +1,7 @@ +import { AiModel } from "../ai-model.type"; + +export type ListAiModelsResponseDto = { + models: AiModel[]; + meta: { total: number }; + response_id?: string; +}; diff --git a/src/types/dto/list-api-keys-response.dto.ts b/src/types/dto/list-api-keys-response.dto.ts new file mode 100644 index 0000000..86ab7cc --- /dev/null +++ b/src/types/dto/list-api-keys-response.dto.ts @@ -0,0 +1,8 @@ +import { ApiKey } from "../api-key.type"; + +export interface ListApiKeysResponseDto { + meta: { + total: number; + }; + api_keys: ApiKey[]; +} diff --git a/src/types/dto/list-balancer-ips-response.dto.ts b/src/types/dto/list-balancer-ips-response.dto.ts new file mode 100644 index 0000000..b74bf3c --- /dev/null +++ b/src/types/dto/list-balancer-ips-response.dto.ts @@ -0,0 +1,5 @@ +export type ListBalancerIpsResponseDto = { + meta: { total: number }; + ips: string[]; + response_id?: string; +}; diff --git a/src/types/dto/list-balancer-presets-response.dto.ts b/src/types/dto/list-balancer-presets-response.dto.ts new file mode 100644 index 0000000..5b08664 --- /dev/null +++ b/src/types/dto/list-balancer-presets-response.dto.ts @@ -0,0 +1,7 @@ +import { BalancerPreset } from "../balancer.type"; + +export type ListBalancerPresetsResponseDto = { + meta: { total: number }; + balancers_presets: BalancerPreset[]; + response_id?: string; +}; diff --git a/src/types/dto/list-balancer-rules-response.dto.ts b/src/types/dto/list-balancer-rules-response.dto.ts new file mode 100644 index 0000000..e1ad131 --- /dev/null +++ b/src/types/dto/list-balancer-rules-response.dto.ts @@ -0,0 +1,7 @@ +import { BalancerRule } from "../balancer.type"; + +export type ListBalancerRulesResponseDto = { + meta: { total: number }; + rules: BalancerRule[]; + response_id?: string; +}; diff --git a/src/types/dto/list-balancers-response.dto.ts b/src/types/dto/list-balancers-response.dto.ts new file mode 100644 index 0000000..cf638c4 --- /dev/null +++ b/src/types/dto/list-balancers-response.dto.ts @@ -0,0 +1,7 @@ +import { Balancer } from "../balancer.type"; + +export type ListBalancersResponseDto = { + meta: { total: number }; + balancers: Balancer[]; + response_id?: string; +}; diff --git a/src/types/dto/list-bucket-subdomains-response.dto.ts b/src/types/dto/list-bucket-subdomains-response.dto.ts new file mode 100644 index 0000000..c090498 --- /dev/null +++ b/src/types/dto/list-bucket-subdomains-response.dto.ts @@ -0,0 +1,7 @@ +import { BucketSubdomain } from "../bucket-subdomain.type"; + +export type ListBucketSubdomainsResponseDto = { + subdomains: BucketSubdomain[]; + meta: any; + response_id?: string; +}; diff --git a/src/types/dto/list-bucket-users-response.dto.ts b/src/types/dto/list-bucket-users-response.dto.ts new file mode 100644 index 0000000..93f445e --- /dev/null +++ b/src/types/dto/list-bucket-users-response.dto.ts @@ -0,0 +1,7 @@ +import { BucketUser } from "../bucket-user.type"; + +export type ListBucketUsersResponseDto = { + users: BucketUser[]; + meta: any; + response_id?: string; +}; diff --git a/src/types/dto/list-buckets-response.dto.ts b/src/types/dto/list-buckets-response.dto.ts new file mode 100644 index 0000000..9fd81d8 --- /dev/null +++ b/src/types/dto/list-buckets-response.dto.ts @@ -0,0 +1,7 @@ +import { Bucket } from "../bucket.type"; + +export type ListBucketsResponseDto = { + buckets: Bucket[]; + meta: any; + response_id?: string; +}; diff --git a/src/types/dto/list-container-registries-response.dto.ts b/src/types/dto/list-container-registries-response.dto.ts new file mode 100644 index 0000000..faf2f31 --- /dev/null +++ b/src/types/dto/list-container-registries-response.dto.ts @@ -0,0 +1,5 @@ +import { ContainerRegistry } from "../container-registry.type"; + +export type ListContainerRegistriesResponseDto = { + container_registry_list: ContainerRegistry[]; +}; diff --git a/src/types/dto/list-container-registry-presets-response.dto.ts b/src/types/dto/list-container-registry-presets-response.dto.ts new file mode 100644 index 0000000..7aa5070 --- /dev/null +++ b/src/types/dto/list-container-registry-presets-response.dto.ts @@ -0,0 +1,5 @@ +import { ContainerRegistryPreset } from "../container-registry.type"; + +export type ListContainerRegistryPresetsResponseDto = { + container_registry_presets: ContainerRegistryPreset[]; +}; diff --git a/src/types/dto/list-container-registry-repositories-response.dto.ts b/src/types/dto/list-container-registry-repositories-response.dto.ts new file mode 100644 index 0000000..790ba41 --- /dev/null +++ b/src/types/dto/list-container-registry-repositories-response.dto.ts @@ -0,0 +1,6 @@ +import { ContainerRegistryRepository } from "../container-registry.type"; + +export type ListContainerRegistryRepositoriesResponseDto = { + meta: { total: number }; + container_registries_repositories: ContainerRegistryRepository[]; +}; diff --git a/src/types/dto/list-database-admins-response.dto.ts b/src/types/dto/list-database-admins-response.dto.ts new file mode 100644 index 0000000..5575b99 --- /dev/null +++ b/src/types/dto/list-database-admins-response.dto.ts @@ -0,0 +1,6 @@ +import { DatabaseAdminEntity } from "../database-cluster.type"; + +export type ListDatabaseAdminsResponseDto = { + meta: { total: number }; + admins: DatabaseAdminEntity[]; +}; diff --git a/src/types/dto/list-database-backups-response.dto.ts b/src/types/dto/list-database-backups-response.dto.ts new file mode 100644 index 0000000..1039f97 --- /dev/null +++ b/src/types/dto/list-database-backups-response.dto.ts @@ -0,0 +1,6 @@ +import { DatabaseBackup } from "../database-cluster.type"; + +export type ListDatabaseBackupsResponseDto = { + meta: { total: number }; + backups: DatabaseBackup[]; +}; diff --git a/src/types/dto/list-database-clusters-response.dto.ts b/src/types/dto/list-database-clusters-response.dto.ts new file mode 100644 index 0000000..07cdf87 --- /dev/null +++ b/src/types/dto/list-database-clusters-response.dto.ts @@ -0,0 +1,6 @@ +import { DatabaseCluster } from "../database-cluster.type"; + +export type ListDatabaseClustersResponseDto = { + meta: { total: number }; + dbs: DatabaseCluster[]; +}; diff --git a/src/types/dto/list-database-instances-response.dto.ts b/src/types/dto/list-database-instances-response.dto.ts new file mode 100644 index 0000000..8852532 --- /dev/null +++ b/src/types/dto/list-database-instances-response.dto.ts @@ -0,0 +1,6 @@ +import { DatabaseInstanceEntity } from "../database-cluster.type"; + +export type ListDatabaseInstancesResponseDto = { + meta: { total: number }; + instances: DatabaseInstanceEntity[]; +}; diff --git a/src/types/dto/list-database-types-response.dto.ts b/src/types/dto/list-database-types-response.dto.ts new file mode 100644 index 0000000..1f8c405 --- /dev/null +++ b/src/types/dto/list-database-types-response.dto.ts @@ -0,0 +1,6 @@ +import { DatabaseType } from "../database-cluster.type"; + +export type ListDatabaseTypesResponseDto = { + meta: { total: number }; + types: DatabaseType[]; +}; diff --git a/src/types/dto/list-databases-response.dto.ts b/src/types/dto/list-databases-response.dto.ts new file mode 100644 index 0000000..7071fea --- /dev/null +++ b/src/types/dto/list-databases-response.dto.ts @@ -0,0 +1,6 @@ +import { Database } from "../database.type"; + +export type ListDatabasesResponseDto = { + meta: { total: number }; + dbs: Database[]; +}; diff --git a/src/types/dto/list-dedicated-server-additional-services-response.dto.ts b/src/types/dto/list-dedicated-server-additional-services-response.dto.ts new file mode 100644 index 0000000..adf0281 --- /dev/null +++ b/src/types/dto/list-dedicated-server-additional-services-response.dto.ts @@ -0,0 +1,6 @@ +import { DedicatedServerAdditionalService } from "../dedicated-server.type"; + +export type ListDedicatedServerAdditionalServicesResponseDto = { + meta: { total: number }; + dedicated_server_additional_services: DedicatedServerAdditionalService[]; +}; diff --git a/src/types/dto/list-dedicated-server-presets-response.dto.ts b/src/types/dto/list-dedicated-server-presets-response.dto.ts new file mode 100644 index 0000000..6680d0f --- /dev/null +++ b/src/types/dto/list-dedicated-server-presets-response.dto.ts @@ -0,0 +1,6 @@ +import { DedicatedServerPreset } from "../dedicated-server.type"; + +export type ListDedicatedServerPresetsResponseDto = { + meta: { total: number }; + dedicated_servers_presets: DedicatedServerPreset[]; +}; diff --git a/src/types/dto/list-dedicated-servers-response.dto.ts b/src/types/dto/list-dedicated-servers-response.dto.ts new file mode 100644 index 0000000..49a45a3 --- /dev/null +++ b/src/types/dto/list-dedicated-servers-response.dto.ts @@ -0,0 +1,6 @@ +import { DedicatedServer } from "../dedicated-server.type"; + +export type ListDedicatedServersResponseDto = { + meta: { total: number }; + dedicated_servers: DedicatedServer[]; +}; diff --git a/src/types/dto/list-dns-records-response.dto.ts b/src/types/dto/list-dns-records-response.dto.ts new file mode 100644 index 0000000..99999ca --- /dev/null +++ b/src/types/dto/list-dns-records-response.dto.ts @@ -0,0 +1,6 @@ +import { DnsRecord } from "../dns-record.type"; + +export type ListDnsRecordsResponseDto = { + dns_records: DnsRecord[]; + meta: { total: number }; +}; diff --git a/src/types/dto/list-domain-requests-response.dto.ts b/src/types/dto/list-domain-requests-response.dto.ts new file mode 100644 index 0000000..97f0de1 --- /dev/null +++ b/src/types/dto/list-domain-requests-response.dto.ts @@ -0,0 +1,10 @@ +import { DomainRequest } from "../domain-request.type"; + +export type ListDomainRequestsResponseDto = { + requests: DomainRequest[]; + meta: { total: number }; +}; + +export type GetDomainRequestResponseDto = { + request: DomainRequest; +}; diff --git a/src/types/dto/list-domains-response.dto.ts b/src/types/dto/list-domains-response.dto.ts new file mode 100644 index 0000000..8df5543 --- /dev/null +++ b/src/types/dto/list-domains-response.dto.ts @@ -0,0 +1,6 @@ +import { Domain } from "../domain.type"; + +export type ListDomainsResponseDto = { + domains: Domain[]; + meta: { total: number }; +}; diff --git a/src/types/dto/list-firewall-group-resources-response.dto.ts b/src/types/dto/list-firewall-group-resources-response.dto.ts new file mode 100644 index 0000000..49730a0 --- /dev/null +++ b/src/types/dto/list-firewall-group-resources-response.dto.ts @@ -0,0 +1,9 @@ +import { FirewallGroupResource } from "../firewall-resource.type"; + +export interface ListFirewallGroupResourcesResponseDto { + resources: FirewallGroupResource[]; + meta: { + total: number; + }; + response_id?: string; +} diff --git a/src/types/dto/list-firewall-groups-response.dto.ts b/src/types/dto/list-firewall-groups-response.dto.ts new file mode 100644 index 0000000..9ecfd0b --- /dev/null +++ b/src/types/dto/list-firewall-groups-response.dto.ts @@ -0,0 +1,9 @@ +import { FirewallGroup } from "../firewall-group.type"; + +export interface ListFirewallGroupsResponseDto { + groups: FirewallGroup[]; + meta: { + total: number; + }; + response_id?: string; +} diff --git a/src/types/dto/list-firewall-rules-response.dto.ts b/src/types/dto/list-firewall-rules-response.dto.ts new file mode 100644 index 0000000..fefc97f --- /dev/null +++ b/src/types/dto/list-firewall-rules-response.dto.ts @@ -0,0 +1,9 @@ +import { FirewallRule } from "../firewall-rule.type"; + +export interface ListFirewallRulesResponseDto { + rules: FirewallRule[]; + meta: { + total: number; + }; + response_id?: string; +} diff --git a/src/types/dto/list-floating-ips-response.dto.ts b/src/types/dto/list-floating-ips-response.dto.ts new file mode 100644 index 0000000..f06c4a9 --- /dev/null +++ b/src/types/dto/list-floating-ips-response.dto.ts @@ -0,0 +1,8 @@ +import { FloatingIp } from "../floating-ip.type"; + +export interface ListFloatingIpsResponseDto { + meta: { + total: number; + }; + ips: FloatingIp[]; +} diff --git a/src/types/dto/list-image-downloads-response.dto.ts b/src/types/dto/list-image-downloads-response.dto.ts new file mode 100644 index 0000000..a715466 --- /dev/null +++ b/src/types/dto/list-image-downloads-response.dto.ts @@ -0,0 +1,6 @@ +import { ImageDownload } from "../image-download.type"; + +export type ListImageDownloadsResponseDto = { + downloads: ImageDownload[]; + meta: { total: number }; +}; diff --git a/src/types/dto/list-images-response.dto.ts b/src/types/dto/list-images-response.dto.ts new file mode 100644 index 0000000..1fca741 --- /dev/null +++ b/src/types/dto/list-images-response.dto.ts @@ -0,0 +1,6 @@ +import { Image } from "../image.type"; + +export type ListImagesResponseDto = { + images: Image[]; + meta: { total: number }; +}; diff --git a/src/types/dto/list-k8s-addon-configs-response.dto.ts b/src/types/dto/list-k8s-addon-configs-response.dto.ts new file mode 100644 index 0000000..8e451bf --- /dev/null +++ b/src/types/dto/list-k8s-addon-configs-response.dto.ts @@ -0,0 +1,7 @@ +import { K8sAddonConfig } from "../k8s-addon.type"; + +export type ListK8sAddonConfigsResponseDto = { + meta: { total: number }; + k8s_addons: K8sAddonConfig[]; + response_id?: string; +}; diff --git a/src/types/dto/list-k8s-addons-response.dto.ts b/src/types/dto/list-k8s-addons-response.dto.ts new file mode 100644 index 0000000..1ba4157 --- /dev/null +++ b/src/types/dto/list-k8s-addons-response.dto.ts @@ -0,0 +1,7 @@ +import { K8sAddon } from "../k8s-addon.type"; + +export type ListK8sAddonsResponseDto = { + meta: { total: number }; + addons: K8sAddon[]; + response_id?: string; +}; diff --git a/src/types/dto/list-k8s-clusters-response.dto.ts b/src/types/dto/list-k8s-clusters-response.dto.ts new file mode 100644 index 0000000..6c67f3f --- /dev/null +++ b/src/types/dto/list-k8s-clusters-response.dto.ts @@ -0,0 +1,7 @@ +import { K8sCluster } from "../k8s-cluster.type"; + +export type ListK8sClustersResponseDto = { + meta: { total: number }; + clusters: K8sCluster[]; + response_id?: string; +}; diff --git a/src/types/dto/list-k8s-network-drivers-response.dto.ts b/src/types/dto/list-k8s-network-drivers-response.dto.ts new file mode 100644 index 0000000..b81a752 --- /dev/null +++ b/src/types/dto/list-k8s-network-drivers-response.dto.ts @@ -0,0 +1,5 @@ +export type ListK8sNetworkDriversResponseDto = { + meta: { total: number }; + network_drivers: string[]; + response_id?: string; +}; diff --git a/src/types/dto/list-k8s-node-groups-response.dto.ts b/src/types/dto/list-k8s-node-groups-response.dto.ts new file mode 100644 index 0000000..daa63b2 --- /dev/null +++ b/src/types/dto/list-k8s-node-groups-response.dto.ts @@ -0,0 +1,7 @@ +import { K8sNodeGroup } from "../k8s-node-group.type"; + +export type ListK8sNodeGroupsResponseDto = { + meta: { total: number }; + node_groups: K8sNodeGroup[]; + response_id?: string; +}; diff --git a/src/types/dto/list-k8s-nodes-response.dto.ts b/src/types/dto/list-k8s-nodes-response.dto.ts new file mode 100644 index 0000000..c3e78d3 --- /dev/null +++ b/src/types/dto/list-k8s-nodes-response.dto.ts @@ -0,0 +1,7 @@ +import { K8sNode } from "../k8s-node.type"; + +export type ListK8sNodesResponseDto = { + meta: { total: number }; + nodes: K8sNode[]; + response_id?: string; +}; diff --git a/src/types/dto/list-k8s-presets-response.dto.ts b/src/types/dto/list-k8s-presets-response.dto.ts new file mode 100644 index 0000000..53ed8c5 --- /dev/null +++ b/src/types/dto/list-k8s-presets-response.dto.ts @@ -0,0 +1,7 @@ +import { K8sPreset } from "../k8s-preset.type"; + +export type ListK8sPresetsResponseDto = { + meta: { total: number }; + k8s_presets: K8sPreset[]; + response_id?: string; +}; diff --git a/src/types/dto/list-k8s-versions-response.dto.ts b/src/types/dto/list-k8s-versions-response.dto.ts new file mode 100644 index 0000000..b96a667 --- /dev/null +++ b/src/types/dto/list-k8s-versions-response.dto.ts @@ -0,0 +1,5 @@ +export type ListK8sVersionsResponseDto = { + meta: { total: number }; + k8s_versions: string[]; + response_id?: string; +}; diff --git a/src/types/dto/list-knowledge-base-documents-response.dto.ts b/src/types/dto/list-knowledge-base-documents-response.dto.ts new file mode 100644 index 0000000..8f6b964 --- /dev/null +++ b/src/types/dto/list-knowledge-base-documents-response.dto.ts @@ -0,0 +1,7 @@ +import { KnowledgeBaseDocument } from "../knowledge-base.type"; + +export type ListKnowledgeBaseDocumentsResponseDto = { + knowledgebase_documents: KnowledgeBaseDocument[]; + meta: { total: number; limit: number; offset: number }; + response_id?: string; +}; diff --git a/src/types/dto/list-knowledge-bases-response.dto.ts b/src/types/dto/list-knowledge-bases-response.dto.ts new file mode 100644 index 0000000..ff925f6 --- /dev/null +++ b/src/types/dto/list-knowledge-bases-response.dto.ts @@ -0,0 +1,7 @@ +import { KnowledgeBase } from "../knowledge-base.type"; + +export type ListKnowledgeBasesResponseDto = { + knowledgebases: KnowledgeBase[]; + meta: { total: number }; + response_id?: string; +}; diff --git a/src/types/dto/list-locations-response.dto.ts b/src/types/dto/list-locations-response.dto.ts new file mode 100644 index 0000000..c19c915 --- /dev/null +++ b/src/types/dto/list-locations-response.dto.ts @@ -0,0 +1,6 @@ +import { Location } from "../location.type"; + +export type ListLocationsResponseDto = { + locations: Location[]; + meta: { total: number }; +}; diff --git a/src/types/dto/list-mailboxes-response.dto.ts b/src/types/dto/list-mailboxes-response.dto.ts new file mode 100644 index 0000000..01182b5 --- /dev/null +++ b/src/types/dto/list-mailboxes-response.dto.ts @@ -0,0 +1,13 @@ +import { Mailbox, MailboxV2 } from "../mailbox.type"; + +export type ListMailboxesV1ResponseDto = { + meta: { total: number }; + mailboxes: Mailbox[]; + response_id?: string; +}; + +export type ListMailboxesV2ResponseDto = { + meta: { total: number }; + mailboxes: MailboxV2[]; + response_id?: string; +}; diff --git a/src/types/dto/list-network-drive-available-resources-response.dto.ts b/src/types/dto/list-network-drive-available-resources-response.dto.ts new file mode 100644 index 0000000..6017bba --- /dev/null +++ b/src/types/dto/list-network-drive-available-resources-response.dto.ts @@ -0,0 +1,7 @@ +import { NetworkDriveAvailableResource } from "../network-drive-available-resource.type"; + +export type ListNetworkDriveAvailableResourcesResponseDto = { + meta: any; + available_resources: NetworkDriveAvailableResource[]; + response_id?: string; +}; diff --git a/src/types/dto/list-network-drive-presets-response.dto.ts b/src/types/dto/list-network-drive-presets-response.dto.ts new file mode 100644 index 0000000..53b7e47 --- /dev/null +++ b/src/types/dto/list-network-drive-presets-response.dto.ts @@ -0,0 +1,7 @@ +import { NetworkDrivePreset } from "../network-drive-preset.type"; + +export type ListNetworkDrivePresetsResponseDto = { + meta: any; + network_drive_presets: NetworkDrivePreset[]; + response_id?: string; +}; diff --git a/src/types/dto/list-network-drives-response.dto.ts b/src/types/dto/list-network-drives-response.dto.ts new file mode 100644 index 0000000..47b8fd8 --- /dev/null +++ b/src/types/dto/list-network-drives-response.dto.ts @@ -0,0 +1,7 @@ +import { NetworkDrive } from "../network-drive.type"; + +export type ListNetworkDrivesResponseDto = { + meta: any; + network_drives: NetworkDrive[]; + response_id?: string; +}; diff --git a/src/types/dto/list-project-resources-response.dto.ts b/src/types/dto/list-project-resources-response.dto.ts new file mode 100644 index 0000000..fa5e7fd --- /dev/null +++ b/src/types/dto/list-project-resources-response.dto.ts @@ -0,0 +1,11 @@ +// GET /api/v1/projects/{project_id}/resources — все ресурсы проекта. +// Схема Timeweb permissive: сервер/БД/хранилище/кластер/балансировщик/выделенный сервер. +export type ListProjectResourcesResponseDto = { + servers?: any[]; + balancers?: any[]; + buckets?: any[]; + clusters?: any[]; + databases?: any[]; + dedicated_servers?: any[]; + meta?: { total?: number }; +}; diff --git a/src/types/dto/list-projects-response.dto.ts b/src/types/dto/list-projects-response.dto.ts new file mode 100644 index 0000000..31f9262 --- /dev/null +++ b/src/types/dto/list-projects-response.dto.ts @@ -0,0 +1,6 @@ +import { Project } from "../project.type"; + +export type ListProjectsResponseDto = { + projects: Project[]; + meta: { total: number }; +}; diff --git a/src/types/dto/list-resources-response.dto.ts b/src/types/dto/list-resources-response.dto.ts new file mode 100644 index 0000000..918b274 --- /dev/null +++ b/src/types/dto/list-resources-response.dto.ts @@ -0,0 +1,33 @@ +// Ответы списков конкретных типов ресурсов (и в проекте, и на аккаунте). +// Используем permissive any[] — точные схемы для каждого ресурса уже могут +// быть покрыты собственными API-группами (servers.ts и т.д.). + +export type ListResourceServersResponseDto = { + servers: any[]; + meta: { total: number }; +}; + +export type ListResourceBalancersResponseDto = { + balancers: any[]; + meta: { total: number }; +}; + +export type ListResourceBucketsResponseDto = { + buckets: any[]; + meta: { total: number }; +}; + +export type ListResourceClustersResponseDto = { + clusters: any[]; + meta: { total: number }; +}; + +export type ListResourceDatabasesResponseDto = { + databases: any[]; + meta: { total: number }; +}; + +export type ListResourceDedicatedResponseDto = { + dedicated_servers: any[]; + meta: { total: number }; +}; diff --git a/src/types/dto/list-server-configurators-response.dto.ts b/src/types/dto/list-server-configurators-response.dto.ts new file mode 100644 index 0000000..18a725d --- /dev/null +++ b/src/types/dto/list-server-configurators-response.dto.ts @@ -0,0 +1,6 @@ +import { ServerConfigurator } from "../server-configurator.type"; + +export type ListServerConfiguratorsResponseDto = { + server_configurators: ServerConfigurator[]; + meta: { total: number }; +}; diff --git a/src/types/dto/list-server-disk-backups-response.dto.ts b/src/types/dto/list-server-disk-backups-response.dto.ts new file mode 100644 index 0000000..3bedf2b --- /dev/null +++ b/src/types/dto/list-server-disk-backups-response.dto.ts @@ -0,0 +1,6 @@ +import { ServerBackup } from "../server-backup.type"; + +export type ListServerDiskBackupsResponseDto = { + backups: ServerBackup[]; + meta: { total: number }; +}; diff --git a/src/types/dto/list-server-disks-response.dto.ts b/src/types/dto/list-server-disks-response.dto.ts new file mode 100644 index 0000000..c561be3 --- /dev/null +++ b/src/types/dto/list-server-disks-response.dto.ts @@ -0,0 +1,6 @@ +import { ServerDisk } from "../server-disk.type"; + +export type ListServerDisksResponseDto = { + server_disks: ServerDisk[]; + meta: { total: number }; +}; diff --git a/src/types/dto/list-server-ips-response.dto.ts b/src/types/dto/list-server-ips-response.dto.ts new file mode 100644 index 0000000..d9990d6 --- /dev/null +++ b/src/types/dto/list-server-ips-response.dto.ts @@ -0,0 +1,7 @@ +import { ServerIp } from "../server-ip.type"; + +export type ListServerIpsResponseDto = { + meta: { total: number }; + server_ips: ServerIp[]; + response_id?: string; +}; diff --git a/src/types/dto/list-server-os-response.dto.ts b/src/types/dto/list-server-os-response.dto.ts new file mode 100644 index 0000000..b0de6f2 --- /dev/null +++ b/src/types/dto/list-server-os-response.dto.ts @@ -0,0 +1,6 @@ +import { ServerOs } from "../server-os.type"; + +export type ListServerOsResponseDto = { + servers_os: ServerOs[]; + meta: { total: number }; +}; diff --git a/src/types/dto/list-server-presets-response.dto.ts b/src/types/dto/list-server-presets-response.dto.ts new file mode 100644 index 0000000..650e0f5 --- /dev/null +++ b/src/types/dto/list-server-presets-response.dto.ts @@ -0,0 +1,6 @@ +import { ServerPreset } from "../server-preset.type"; + +export type ListServerPresetsResponseDto = { + server_presets: ServerPreset[]; + meta: { total: number }; +}; diff --git a/src/types/dto/list-server-software-response.dto.ts b/src/types/dto/list-server-software-response.dto.ts new file mode 100644 index 0000000..102e4a1 --- /dev/null +++ b/src/types/dto/list-server-software-response.dto.ts @@ -0,0 +1,6 @@ +import { ServerSoftware } from "../server-software.type"; + +export type ListServerSoftwareResponseDto = { + servers_software: ServerSoftware[]; + meta: { total: number }; +}; diff --git a/src/types/dto/list-servers-response.dto.ts b/src/types/dto/list-servers-response.dto.ts new file mode 100644 index 0000000..f3c9155 --- /dev/null +++ b/src/types/dto/list-servers-response.dto.ts @@ -0,0 +1,6 @@ +import { Server } from "../server.type"; + +export type ListServersResponseDto = { + servers: Server[]; + meta: { total: number }; +}; diff --git a/src/types/dto/list-ssh-keys-response.dto.ts b/src/types/dto/list-ssh-keys-response.dto.ts new file mode 100644 index 0000000..782a120 --- /dev/null +++ b/src/types/dto/list-ssh-keys-response.dto.ts @@ -0,0 +1,6 @@ +import { SshKey } from "../ssh-key.type"; + +export interface ListSshKeysResponseDto { + ssh_keys: SshKey[]; + meta: { total: number }; +} diff --git a/src/types/dto/list-tlds-response.dto.ts b/src/types/dto/list-tlds-response.dto.ts new file mode 100644 index 0000000..874b3fc --- /dev/null +++ b/src/types/dto/list-tlds-response.dto.ts @@ -0,0 +1,10 @@ +import { TopLevelDomain } from "../top-level-domain.type"; + +export type ListTldsResponseDto = { + top_level_domains: TopLevelDomain[]; + meta: { total: number }; +}; + +export type GetTldResponseDto = { + top_level_domain: TopLevelDomain; +}; diff --git a/src/types/dto/list-token-packages-response.dto.ts b/src/types/dto/list-token-packages-response.dto.ts new file mode 100644 index 0000000..4956e3e --- /dev/null +++ b/src/types/dto/list-token-packages-response.dto.ts @@ -0,0 +1,7 @@ +import { TokenPackage } from "../token-package.type"; + +export type ListTokenPackagesResponseDto = { + token_packages: TokenPackage[]; + meta: { total: number }; + response_id?: string; +}; diff --git a/src/types/dto/list-vpc-ports-response.dto.ts b/src/types/dto/list-vpc-ports-response.dto.ts new file mode 100644 index 0000000..0d1aa2c --- /dev/null +++ b/src/types/dto/list-vpc-ports-response.dto.ts @@ -0,0 +1,8 @@ +import { VpcPort } from "../vpc-port.type"; + +export interface ListVpcPortsResponseDto { + meta: { + total: number; + }; + vpc_ports: VpcPort[]; +} diff --git a/src/types/dto/list-vpc-services-response.dto.ts b/src/types/dto/list-vpc-services-response.dto.ts new file mode 100644 index 0000000..dbe1c2b --- /dev/null +++ b/src/types/dto/list-vpc-services-response.dto.ts @@ -0,0 +1,8 @@ +import { VpcService } from "../vpc-service.type"; + +export interface ListVpcServicesResponseDto { + meta: { + total: number; + }; + services: VpcService[]; +} diff --git a/src/types/dto/mount-network-drive-request.dto.ts b/src/types/dto/mount-network-drive-request.dto.ts new file mode 100644 index 0000000..20cbb84 --- /dev/null +++ b/src/types/dto/mount-network-drive-request.dto.ts @@ -0,0 +1,4 @@ +export type MountNetworkDriveRequestDto = { + resource_type: "server"; + resource_id: number; +}; diff --git a/src/types/dto/project-resource-response.dto.ts b/src/types/dto/project-resource-response.dto.ts new file mode 100644 index 0000000..5899e54 --- /dev/null +++ b/src/types/dto/project-resource-response.dto.ts @@ -0,0 +1,5 @@ +import { ProjectResource } from "../project.type"; + +export type ProjectResourceResponseDto = { + resource: ProjectResource; +}; diff --git a/src/types/dto/reduce-k8s-nodes-request.dto.ts b/src/types/dto/reduce-k8s-nodes-request.dto.ts new file mode 100644 index 0000000..afb8fac --- /dev/null +++ b/src/types/dto/reduce-k8s-nodes-request.dto.ts @@ -0,0 +1,3 @@ +export type ReduceK8sNodesRequestDto = { + count: number; +}; diff --git a/src/types/dto/refresh-api-key-request.dto.ts b/src/types/dto/refresh-api-key-request.dto.ts new file mode 100644 index 0000000..34229df --- /dev/null +++ b/src/types/dto/refresh-api-key-request.dto.ts @@ -0,0 +1,3 @@ +export interface RefreshApiKeyRequestDto { + expire?: string; +} diff --git a/src/types/dto/refresh-api-key-response.dto.ts b/src/types/dto/refresh-api-key-response.dto.ts new file mode 100644 index 0000000..bcfc751 --- /dev/null +++ b/src/types/dto/refresh-api-key-response.dto.ts @@ -0,0 +1,5 @@ +import { CreatedApiKey } from "../api-key.type"; + +export interface RefreshApiKeyResponseDto { + api_key: CreatedApiKey; +} diff --git a/src/types/dto/server-disk-backup-response.dto.ts b/src/types/dto/server-disk-backup-response.dto.ts new file mode 100644 index 0000000..dc8366d --- /dev/null +++ b/src/types/dto/server-disk-backup-response.dto.ts @@ -0,0 +1,6 @@ +import { ServerBackup } from "../server-backup.type"; + +export type ServerDiskBackupResponseDto = { + backup: ServerBackup; + response_id?: string; +}; diff --git a/src/types/dto/server-disk-response.dto.ts b/src/types/dto/server-disk-response.dto.ts new file mode 100644 index 0000000..6ae16b5 --- /dev/null +++ b/src/types/dto/server-disk-response.dto.ts @@ -0,0 +1,6 @@ +import { ServerDisk } from "../server-disk.type"; + +export type ServerDiskResponseDto = { + server_disk: ServerDisk; + response_id?: string; +}; diff --git a/src/types/dto/server-ip-response.dto.ts b/src/types/dto/server-ip-response.dto.ts new file mode 100644 index 0000000..c890479 --- /dev/null +++ b/src/types/dto/server-ip-response.dto.ts @@ -0,0 +1,6 @@ +import { ServerIp } from "../server-ip.type"; + +export type ServerIpResponseDto = { + server_ip: ServerIp; + response_id?: string; +}; diff --git a/src/types/dto/transfer-bucket-request.dto.ts b/src/types/dto/transfer-bucket-request.dto.ts new file mode 100644 index 0000000..4f08804 --- /dev/null +++ b/src/types/dto/transfer-bucket-request.dto.ts @@ -0,0 +1,9 @@ +export type TransferBucketRequestDto = { + access_key: string; + secret_key: string; + location: string; + is_force_path_style: boolean; + endpoint: string; + bucket_name: string; + new_bucket_name: string; +}; diff --git a/src/types/dto/transfer-project-resource-request.dto.ts b/src/types/dto/transfer-project-resource-request.dto.ts new file mode 100644 index 0000000..d580d83 --- /dev/null +++ b/src/types/dto/transfer-project-resource-request.dto.ts @@ -0,0 +1,7 @@ +import { ProjectResourceTypeEnum } from "../project-resource-type.enum"; + +export type TransferProjectResourceRequestDto = { + to_project: number; + resource_id: number; + resource_type: ProjectResourceTypeEnum; +}; diff --git a/src/types/dto/update-ai-agent-request.dto.ts b/src/types/dto/update-ai-agent-request.dto.ts new file mode 100644 index 0000000..874f29e --- /dev/null +++ b/src/types/dto/update-ai-agent-request.dto.ts @@ -0,0 +1,11 @@ +import { AgentSettings } from "../ai-agent.type"; + +export type UpdateAiAgentRequestDto = { + name?: string; + description?: string; + access_type?: "public" | "private"; + status?: "active" | "suspended"; + token_package_id?: number; + settings?: Partial; + project_id?: number; +}; diff --git a/src/types/dto/update-balancer-request.dto.ts b/src/types/dto/update-balancer-request.dto.ts new file mode 100644 index 0000000..3e1141b --- /dev/null +++ b/src/types/dto/update-balancer-request.dto.ts @@ -0,0 +1,25 @@ +import { BalancerAlgo, BalancerProto } from "../balancer.type"; +import { CreateBalancerCertificate } from "./create-balancer-request.dto"; + +export type UpdateBalancerRequestDto = { + name?: string; + algo?: BalancerAlgo; + is_sticky?: boolean; + is_use_proxy?: boolean; + is_ssl?: boolean; + is_keepalive?: boolean; + proto?: BalancerProto; + port?: number; + path?: string; + inter?: number; + timeout?: number; + fall?: number; + rise?: number; + maxconn?: number; + connect_timeout?: number; + client_timeout?: number; + server_timeout?: number; + httprequest_timeout?: number; + comment?: string; + certificates?: CreateBalancerCertificate; +}; diff --git a/src/types/dto/update-bucket-request.dto.ts b/src/types/dto/update-bucket-request.dto.ts new file mode 100644 index 0000000..af5ab9a --- /dev/null +++ b/src/types/dto/update-bucket-request.dto.ts @@ -0,0 +1,11 @@ +import { BucketType } from "../bucket.type"; + +export type UpdateBucketRequestDto = { + preset_id?: number; + configurator?: { + id?: number; + disk?: number; + }; + bucket_type?: BucketType; + description?: string; +}; diff --git a/src/types/dto/update-bucket-response.dto.ts b/src/types/dto/update-bucket-response.dto.ts new file mode 100644 index 0000000..3e9f108 --- /dev/null +++ b/src/types/dto/update-bucket-response.dto.ts @@ -0,0 +1,6 @@ +import { Bucket } from "../bucket.type"; + +export type UpdateBucketResponseDto = { + bucket: Bucket; + response_id?: string; +}; diff --git a/src/types/dto/update-bucket-user-request.dto.ts b/src/types/dto/update-bucket-user-request.dto.ts new file mode 100644 index 0000000..e6234ee --- /dev/null +++ b/src/types/dto/update-bucket-user-request.dto.ts @@ -0,0 +1,3 @@ +export type UpdateBucketUserRequestDto = { + secret_key: string; +}; diff --git a/src/types/dto/update-bucket-user-response.dto.ts b/src/types/dto/update-bucket-user-response.dto.ts new file mode 100644 index 0000000..417ae58 --- /dev/null +++ b/src/types/dto/update-bucket-user-response.dto.ts @@ -0,0 +1,6 @@ +import { BucketUser } from "../bucket-user.type"; + +export type UpdateBucketUserResponseDto = { + user: BucketUser; + response_id?: string; +}; diff --git a/src/types/dto/update-container-registry-request.dto.ts b/src/types/dto/update-container-registry-request.dto.ts new file mode 100644 index 0000000..0c878f7 --- /dev/null +++ b/src/types/dto/update-container-registry-request.dto.ts @@ -0,0 +1,8 @@ +export type UpdateContainerRegistryRequestDto = { + description?: string; + preset_id?: number; + configuration?: { + id: number; + disk: number; + }; +}; diff --git a/src/types/dto/update-database-admin-request.dto.ts b/src/types/dto/update-database-admin-request.dto.ts new file mode 100644 index 0000000..62b68ad --- /dev/null +++ b/src/types/dto/update-database-admin-request.dto.ts @@ -0,0 +1,6 @@ +export type UpdateDatabaseAdminRequestDto = { + password?: string; + privileges?: string[]; + description?: string; + instance_id?: number; +}; diff --git a/src/types/dto/update-database-auto-backups-request.dto.ts b/src/types/dto/update-database-auto-backups-request.dto.ts new file mode 100644 index 0000000..41a355f --- /dev/null +++ b/src/types/dto/update-database-auto-backups-request.dto.ts @@ -0,0 +1,7 @@ +export type UpdateDatabaseAutoBackupsRequestDto = { + is_enabled: boolean; + copy_count?: number; + creation_start_at?: string; + interval?: "day" | "week" | "month"; + day_of_week?: number; +}; diff --git a/src/types/dto/update-database-cluster-request.dto.ts b/src/types/dto/update-database-cluster-request.dto.ts new file mode 100644 index 0000000..3c90b7d --- /dev/null +++ b/src/types/dto/update-database-cluster-request.dto.ts @@ -0,0 +1,6 @@ +export type UpdateDatabaseClusterRequestDto = { + name?: string; + preset_id?: number; + description?: string; + is_enabled_public_network?: boolean; +}; diff --git a/src/types/dto/update-database-instance-request.dto.ts b/src/types/dto/update-database-instance-request.dto.ts new file mode 100644 index 0000000..d031e50 --- /dev/null +++ b/src/types/dto/update-database-instance-request.dto.ts @@ -0,0 +1,4 @@ +export type UpdateDatabaseInstanceRequestDto = { + name?: string; + description?: string; +}; diff --git a/src/types/dto/update-database-request.dto.ts b/src/types/dto/update-database-request.dto.ts new file mode 100644 index 0000000..f60c036 --- /dev/null +++ b/src/types/dto/update-database-request.dto.ts @@ -0,0 +1,7 @@ +export type UpdateDatabaseRequestDto = { + password?: string; + name?: string; + preset_id?: number; + config_parameters?: Record; + is_external_ip?: boolean; +}; diff --git a/src/types/dto/update-dedicated-server-request.dto.ts b/src/types/dto/update-dedicated-server-request.dto.ts new file mode 100644 index 0000000..52716bc --- /dev/null +++ b/src/types/dto/update-dedicated-server-request.dto.ts @@ -0,0 +1,4 @@ +export type UpdateDedicatedServerRequestDto = { + name?: string; + comment?: string; +}; diff --git a/src/types/dto/update-domain-name-servers-request.dto.ts b/src/types/dto/update-domain-name-servers-request.dto.ts new file mode 100644 index 0000000..e52b6ce --- /dev/null +++ b/src/types/dto/update-domain-name-servers-request.dto.ts @@ -0,0 +1,8 @@ +export type NameServerInput = { + host: string; + ips?: string[]; +}; + +export type UpdateDomainNameServersRequestDto = { + name_servers: NameServerInput[]; +}; diff --git a/src/types/dto/update-domain-request.dto.ts b/src/types/dto/update-domain-request.dto.ts new file mode 100644 index 0000000..20a4583 --- /dev/null +++ b/src/types/dto/update-domain-request.dto.ts @@ -0,0 +1,4 @@ +export type UpdateDomainRequestDto = { + is_autoprolong_enabled?: boolean; + linked_ip?: string | null; +}; diff --git a/src/types/dto/update-firewall-group-request.dto.ts b/src/types/dto/update-firewall-group-request.dto.ts new file mode 100644 index 0000000..6f4c15a --- /dev/null +++ b/src/types/dto/update-firewall-group-request.dto.ts @@ -0,0 +1,4 @@ +export interface UpdateFirewallGroupRequestDto { + name: string; + description?: string; +} diff --git a/src/types/dto/update-firewall-rule-request.dto.ts b/src/types/dto/update-firewall-rule-request.dto.ts new file mode 100644 index 0000000..767df62 --- /dev/null +++ b/src/types/dto/update-firewall-rule-request.dto.ts @@ -0,0 +1,12 @@ +import { + FirewallRuleDirection, + FirewallRuleProtocol, +} from "../firewall-rule.type"; + +export interface UpdateFirewallRuleRequestDto { + direction: FirewallRuleDirection; + protocol: FirewallRuleProtocol; + description?: string; + port?: string; + cidr?: string; +} diff --git a/src/types/dto/update-floating-ip-request.dto.ts b/src/types/dto/update-floating-ip-request.dto.ts new file mode 100644 index 0000000..f2bccc2 --- /dev/null +++ b/src/types/dto/update-floating-ip-request.dto.ts @@ -0,0 +1,4 @@ +export interface UpdateFloatingIpRequestDto { + comment?: string; + ptr?: string; +} diff --git a/src/types/dto/update-floating-ip-response.dto.ts b/src/types/dto/update-floating-ip-response.dto.ts new file mode 100644 index 0000000..3372624 --- /dev/null +++ b/src/types/dto/update-floating-ip-response.dto.ts @@ -0,0 +1,5 @@ +import { FloatingIp } from "../floating-ip.type"; + +export interface UpdateFloatingIpResponseDto { + ip: FloatingIp; +} diff --git a/src/types/dto/update-image-request.dto.ts b/src/types/dto/update-image-request.dto.ts new file mode 100644 index 0000000..5727a58 --- /dev/null +++ b/src/types/dto/update-image-request.dto.ts @@ -0,0 +1,4 @@ +export type UpdateImageRequestDto = { + name?: string; + description?: string; +}; diff --git a/src/types/dto/update-k8s-cluster-version-request.dto.ts b/src/types/dto/update-k8s-cluster-version-request.dto.ts new file mode 100644 index 0000000..a24f878 --- /dev/null +++ b/src/types/dto/update-k8s-cluster-version-request.dto.ts @@ -0,0 +1,3 @@ +export type UpdateK8sClusterVersionRequestDto = { + k8s_version?: string; +}; diff --git a/src/types/dto/update-knowledge-base-request.dto.ts b/src/types/dto/update-knowledge-base-request.dto.ts new file mode 100644 index 0000000..7c20ee3 --- /dev/null +++ b/src/types/dto/update-knowledge-base-request.dto.ts @@ -0,0 +1,4 @@ +export type UpdateKnowledgeBaseRequestDto = { + name?: string; + description?: string; +}; diff --git a/src/types/dto/update-mail-domain-info-request.dto.ts b/src/types/dto/update-mail-domain-info-request.dto.ts new file mode 100644 index 0000000..3c55344 --- /dev/null +++ b/src/types/dto/update-mail-domain-info-request.dto.ts @@ -0,0 +1,3 @@ +export type UpdateMailDomainInfoRequestDto = { + email: string; +}; diff --git a/src/types/dto/update-mail-domain-info-response.dto.ts b/src/types/dto/update-mail-domain-info-response.dto.ts new file mode 100644 index 0000000..15f2fa0 --- /dev/null +++ b/src/types/dto/update-mail-domain-info-response.dto.ts @@ -0,0 +1,6 @@ +import { MailDomainInfo } from "../mailbox.type"; + +export type UpdateMailDomainInfoResponseDto = { + domain_info: MailDomainInfo; + response_id?: string; +}; diff --git a/src/types/dto/update-mailbox-request.dto.ts b/src/types/dto/update-mailbox-request.dto.ts new file mode 100644 index 0000000..e57a297 --- /dev/null +++ b/src/types/dto/update-mailbox-request.dto.ts @@ -0,0 +1,25 @@ +/** + * Тело PATCH /api/v1/mail/domains/{domain}/mailboxes/{mailbox}. + * Оставляем свободным — вложенные блоки имеют oneOf-варианты. + */ +export type UpdateMailboxV1RequestDto = { + comment?: string; + password?: string; + auto_reply?: any; + spam_filter?: any; + forwarding_incoming?: any; + forwarding_outgoing?: any; +}; + +/** + * Тело PATCH /api/v2/mail/domains/{domain}/mailboxes/{mailbox}. + */ +export type UpdateMailboxV2RequestDto = { + password?: string; + comment?: string; + owner_full_name?: string; + spam_protection_settings?: any; + forward_settings?: any; + autoreply_settings?: any; + outgoing_settings?: any; +}; diff --git a/src/types/dto/update-mailbox-response.dto.ts b/src/types/dto/update-mailbox-response.dto.ts new file mode 100644 index 0000000..5342501 --- /dev/null +++ b/src/types/dto/update-mailbox-response.dto.ts @@ -0,0 +1,12 @@ +import { Mailbox } from "../mailbox.type"; + +export type UpdateMailboxV1ResponseDto = { + mailbox: Mailbox; + response_id?: string; +}; + +export type UpdateMailboxV2ResponseDto = { + // API v2 возвращает mailbox-response (облегчённую форму) + mailbox: Record; + response_id?: string; +}; diff --git a/src/types/dto/update-network-drive-request.dto.ts b/src/types/dto/update-network-drive-request.dto.ts new file mode 100644 index 0000000..791c038 --- /dev/null +++ b/src/types/dto/update-network-drive-request.dto.ts @@ -0,0 +1,5 @@ +export type UpdateNetworkDriveRequestDto = { + name?: string; + comment?: string | null; + size?: number; +}; diff --git a/src/types/dto/update-network-drive-response.dto.ts b/src/types/dto/update-network-drive-response.dto.ts new file mode 100644 index 0000000..c33ec53 --- /dev/null +++ b/src/types/dto/update-network-drive-response.dto.ts @@ -0,0 +1,6 @@ +import { NetworkDrive } from "../network-drive.type"; + +export type UpdateNetworkDriveResponseDto = { + network_drive: NetworkDrive; + response_id?: string; +}; diff --git a/src/types/dto/update-project-request.dto.ts b/src/types/dto/update-project-request.dto.ts new file mode 100644 index 0000000..f81262b --- /dev/null +++ b/src/types/dto/update-project-request.dto.ts @@ -0,0 +1,5 @@ +export type UpdateProjectRequestDto = { + name?: string; + description?: string | null; + avatar_id?: string | null; +}; diff --git a/src/types/dto/update-server-request.dto.ts b/src/types/dto/update-server-request.dto.ts new file mode 100644 index 0000000..e520b5c --- /dev/null +++ b/src/types/dto/update-server-request.dto.ts @@ -0,0 +1,6 @@ +export type UpdateServerRequestDto = { + name?: string; + comment?: string; + avatar_id?: string; + cloud_init?: string; +}; diff --git a/src/types/dto/update-ssh-key-request.dto.ts b/src/types/dto/update-ssh-key-request.dto.ts new file mode 100644 index 0000000..0187a2f --- /dev/null +++ b/src/types/dto/update-ssh-key-request.dto.ts @@ -0,0 +1,5 @@ +export interface UpdateSshKeyRequestDto { + name?: string; + body?: string; + is_default?: boolean; +} diff --git a/src/types/dto/update-ssh-key-response.dto.ts b/src/types/dto/update-ssh-key-response.dto.ts new file mode 100644 index 0000000..2e5720c --- /dev/null +++ b/src/types/dto/update-ssh-key-response.dto.ts @@ -0,0 +1,6 @@ +import { SshKey } from "../ssh-key.type"; + +export interface UpdateSshKeyResponseDto { + ssh_key: SshKey; + meta: { total: number }; +} diff --git a/src/types/dto/update-vpc-request.dto.ts b/src/types/dto/update-vpc-request.dto.ts new file mode 100644 index 0000000..d54d65c --- /dev/null +++ b/src/types/dto/update-vpc-request.dto.ts @@ -0,0 +1,4 @@ +export interface UpdateVpcRequestDto { + name?: string; + description?: string; +} diff --git a/src/types/dto/update-vpc-response.dto.ts b/src/types/dto/update-vpc-response.dto.ts new file mode 100644 index 0000000..fd3b970 --- /dev/null +++ b/src/types/dto/update-vpc-response.dto.ts @@ -0,0 +1,5 @@ +import { Vpc } from "../vpc.type"; + +export interface UpdateVpcResponseDto { + vpc: Vpc; +} diff --git a/src/types/finances.type.ts b/src/types/finances.type.ts new file mode 100644 index 0000000..cb3c903 --- /dev/null +++ b/src/types/finances.type.ts @@ -0,0 +1,21 @@ +export type Finances = { + balance: number; + currency: string; + discount_end_date_at: string | null; + discount_percent: number; + hourly_cost: number; + hourly_fee: number; + monthly_cost: number; + monthly_fee: number; + total_paid: number; + hours_left: number | null; + autopay_card_info: string | null; +}; + +export type AccountStatus = { + is_blocked: boolean; + is_permanent_blocked: boolean; + is_send_bill_letters: boolean; + last_password_changed_at: string | null; + bonus_balance?: number; +}; diff --git a/src/types/firewall-group.type.ts b/src/types/firewall-group.type.ts new file mode 100644 index 0000000..4ca45d2 --- /dev/null +++ b/src/types/firewall-group.type.ts @@ -0,0 +1,10 @@ +export type FirewallPolicy = "ACCEPT" | "DROP"; + +export type FirewallGroup = { + id: string; + created_at: string; + updated_at: string; + name: string; + description: string; + policy: FirewallPolicy; +}; diff --git a/src/types/firewall-resource.type.ts b/src/types/firewall-resource.type.ts new file mode 100644 index 0000000..1818e87 --- /dev/null +++ b/src/types/firewall-resource.type.ts @@ -0,0 +1,6 @@ +export type FirewallResourceType = "server"; + +export type FirewallGroupResource = { + id: number; + type: FirewallResourceType; +}; diff --git a/src/types/firewall-rule.type.ts b/src/types/firewall-rule.type.ts new file mode 100644 index 0000000..42e9d93 --- /dev/null +++ b/src/types/firewall-rule.type.ts @@ -0,0 +1,13 @@ +export type FirewallRuleDirection = "ingress" | "egress"; + +export type FirewallRuleProtocol = "tcp" | "udp" | "icmp"; + +export type FirewallRule = { + id: string; + description: string; + direction: FirewallRuleDirection; + protocol: FirewallRuleProtocol; + port?: string; + cidr?: string; + group_id: string; +}; diff --git a/src/types/floating-ip.type.ts b/src/types/floating-ip.type.ts index 8176785..4313f34 100644 --- a/src/types/floating-ip.type.ts +++ b/src/types/floating-ip.type.ts @@ -1,10 +1,15 @@ import { AvailabilityZones } from "./availability-zones.enum"; +export type FloatingIpResourceType = "server" | "balancer" | "database" | "network"; + export interface FloatingIp { id: string; - ip: string; + ip: string | null; is_ddos_guard: boolean; availability_zone: AvailabilityZones; - comment: string; - created_at: string; + resource_type?: FloatingIpResourceType | null; + resource_id?: number | string | null; + comment: string | null; + ptr?: string | null; + created_at?: string; } diff --git a/src/types/image-download.type.ts b/src/types/image-download.type.ts new file mode 100644 index 0000000..eb2e607 --- /dev/null +++ b/src/types/image-download.type.ts @@ -0,0 +1,22 @@ +export enum ImageUrlStatus { + PROCESS = "process", + FAILED = "failed", + FINISHED = "finished", + ALREADY_EXISTS = "already_exists", +} + +export enum ImageUrlType { + TIMEWEB = "timeweb", + GOOGLE_DRIVE = "google_drive", + YANDEX = "yandex", +} + +export type ImageDownload = { + id: string; + created_at: string; + image: string; + type: ImageUrlType | string; + url?: string; + status: ImageUrlStatus | string; + progress: number; +}; diff --git a/src/types/image.type.ts b/src/types/image.type.ts new file mode 100644 index 0000000..19d2bcb --- /dev/null +++ b/src/types/image.type.ts @@ -0,0 +1,50 @@ +export enum ImageStatus { + NEW = "new", + CREATED = "created", + FAILED = "failed", + DELETED = "deleted", +} + +export enum ImageOS { + CENTOS = "centos", + ALMALINUX = "almalinux", + DEBIAN = "debian", + BITRIX = "bitrix", + UBUNTU = "ubuntu", + BRAINYCP = "brainycp", + ARCHLINUX = "archlinux", + ASTRALINUX = "astralinux", + WINDOWS = "windows", + CUSTOM_OS = "custom_os", + OTHER = "other", +} + +export enum ImageLocation { + RU_1 = "ru-1", + RU_2 = "ru-2", + PL_1 = "pl-1", + KZ_1 = "kz-1", + NL_1 = "nl-1", +} + +export enum ImageType { + QCOW2 = "qcow2", + ISO = "iso", +} + +export type Image = { + id: string; + status: ImageStatus | string; + created_at: string; + deleted_at: string | null; + size: number; + virtual_size: number; + name: string; + description: string; + disk_id: number | null; + location: ImageLocation | string; + os: ImageOS | string; + progress: number; + is_custom: boolean; + type: ImageType | string; +}; diff --git a/src/types/k8s-addon.type.ts b/src/types/k8s-addon.type.ts new file mode 100644 index 0000000..d27d245 --- /dev/null +++ b/src/types/k8s-addon.type.ts @@ -0,0 +1,18 @@ +export type K8sAddon = { + id: number; + type: string; + status: string; + created_at: string; + version: string; + config?: Record; + yaml_config: string; + config_type: string; +}; + +export type K8sAddonConfig = { + id: number; + type: string; + version: string; + dependencies: string[]; + yaml_config: string; +}; diff --git a/src/types/k8s-cluster.type.ts b/src/types/k8s-cluster.type.ts new file mode 100644 index 0000000..b0f21aa --- /dev/null +++ b/src/types/k8s-cluster.type.ts @@ -0,0 +1,17 @@ +export type K8sCluster = { + id: number; + name: string; + created_at: string; + status: string; + description: string; + k8s_version: string; + network_driver: string; + ingress: boolean; + preset_id: number; + avatar_link: string | null; + cpu?: number; + ram?: number; + disk?: number; + availability_zone?: string; + project_id?: number; +}; diff --git a/src/types/k8s-node-group.type.ts b/src/types/k8s-node-group.type.ts new file mode 100644 index 0000000..8529b88 --- /dev/null +++ b/src/types/k8s-node-group.type.ts @@ -0,0 +1,7 @@ +export type K8sNodeGroup = { + id: number; + name: string; + created_at: string; + preset_id: number; + node_count: number; +}; diff --git a/src/types/k8s-node.type.ts b/src/types/k8s-node.type.ts new file mode 100644 index 0000000..bb35e60 --- /dev/null +++ b/src/types/k8s-node.type.ts @@ -0,0 +1,13 @@ +export type K8sNode = { + id: number; + created_at: string; + type: string; + group_id: number; + status: string; + preset_id: number; + cpu: number; + ram: number; + disk: number; + network: number; + node_ip: string; +}; diff --git a/src/types/k8s-preset.type.ts b/src/types/k8s-preset.type.ts new file mode 100644 index 0000000..7dcb0c8 --- /dev/null +++ b/src/types/k8s-preset.type.ts @@ -0,0 +1,13 @@ +export type K8sPreset = { + id: number; + description: string; + description_short: string; + price: number; + cpu: number; + ram: number; + disk: number; + network: number; + type: "worker" | "master"; + // Присутствует только у master-пресетов + limit?: number; +}; diff --git a/src/types/k8s-resources.type.ts b/src/types/k8s-resources.type.ts new file mode 100644 index 0000000..7c9b03e --- /dev/null +++ b/src/types/k8s-resources.type.ts @@ -0,0 +1,13 @@ +export type K8sResource = { + requested: number; + allocatable: number; + capacity: number; + used: number; +}; + +export type K8sResources = { + nodes: number; + cores: K8sResource; + memory: K8sResource; + pods: K8sResource; +}; diff --git a/src/types/knowledge-base.type.ts b/src/types/knowledge-base.type.ts new file mode 100644 index 0000000..7ba2e9d --- /dev/null +++ b/src/types/knowledge-base.type.ts @@ -0,0 +1,28 @@ +export type KnowledgeBaseDocument = { + id: number; + name: string; + size: number; + status: "new" | "indexed" | "indexing" | "error"; + indexing_version?: string | null; + status_info?: any; + created_at: string; + updated_at: string; +}; + +export type KnowledgeBase = { + id: number; + name: string; + description?: string | null; + dbaas_id: number; + status: "active" | "blocked" | "creating" | "deleted"; + last_sync?: string | null; + total_tokens: number; + used_tokens: number; + remaining_tokens: number; + token_package_id: number; + subscription_renewal_date: string; + documents?: KnowledgeBaseDocument[]; + documents_count?: number; + agents_ids: number[]; + created_at: string; +}; diff --git a/src/types/location.type.ts b/src/types/location.type.ts new file mode 100644 index 0000000..e0d93eb --- /dev/null +++ b/src/types/location.type.ts @@ -0,0 +1,5 @@ +export type Location = { + location: string; + location_code: string; + availability_zones: string[]; +}; diff --git a/src/types/mailbox.type.ts b/src/types/mailbox.type.ts new file mode 100644 index 0000000..a20b76c --- /dev/null +++ b/src/types/mailbox.type.ts @@ -0,0 +1,79 @@ +/** + * Почтовый ящик (API v1). + * Схема повторяет /components/schemas/mailbox из OpenAPI. + */ +export type Mailbox = { + auto_reply?: { + is_enabled: boolean; + message: string; + subject: string; + }; + spam_filter?: { + is_enabled: boolean; + action: "move_to_directory" | "forward" | "delete" | "tag"; + forward_to: string; + white_list: string[]; + }; + forwarding_incoming?: { + is_enabled: boolean; + is_delete_messages: boolean; + incoming_list: string[]; + }; + forwarding_outgoing?: { + is_enabled: boolean; + outgoing_to: string; + }; + comment?: string; + fqdn?: string; + mailbox?: string; + mailbox_size?: number; + used_space?: number; + webmail?: boolean; + [key: string]: any; +}; + +/** + * Почтовый ящик (API v2). + * Схема повторяет /components/schemas/mailbox-v2 из OpenAPI. + */ +export type MailboxV2 = { + idn_name: string; + autoreply_message: string; + autoreply_status: boolean; + autoreply_subject: string; + comment: string; + filter_action: "directory" | "forward" | "delete" | "tag"; + filter_status: boolean; + forward_list: string[]; + forward_status: boolean; + outgoing_control: boolean; + outgoing_email: string; + password: string; + spambox: string; + white_list: string[]; + webmail?: boolean; + dovecot?: boolean; + fqdn?: string; + leave_messages?: boolean; + mailbox?: string; + owner_full_name?: string; + [key: string]: any; +}; + +/** + * Почтовая информация о домене. + * Схема повторяет /components/schemas/domain-info. + */ +export type MailDomainInfo = { + email: string; + used: number; + [key: string]: any; +}; + +/** + * Результат массового создания почтовых ящиков (API v2). + */ +export type MailboxesBatchV2 = { + mailboxes: MailboxV2[]; + errors: any[]; +}; diff --git a/src/types/network-drive-available-resource.type.ts b/src/types/network-drive-available-resource.type.ts new file mode 100644 index 0000000..7d66b86 --- /dev/null +++ b/src/types/network-drive-available-resource.type.ts @@ -0,0 +1,6 @@ +export type NetworkDriveAvailableResource = { + resource_id: number; + resource_type: "server"; + ip?: string | null; + availability_zone: string; +}; diff --git a/src/types/network-drive-preset.type.ts b/src/types/network-drive-preset.type.ts new file mode 100644 index 0000000..0ffbbc0 --- /dev/null +++ b/src/types/network-drive-preset.type.ts @@ -0,0 +1,17 @@ +import { NetworkDriveType } from "./network-drive.type"; + +export type NetworkDrivePresetIops = { + min?: number; + max?: number; +}; + +export type NetworkDrivePreset = { + id: number; + cost_per_gb: number; + min: number; + max: number; + step: number; + type: NetworkDriveType; + read: NetworkDrivePresetIops; + write: NetworkDrivePresetIops; +}; diff --git a/src/types/network-drive.type.ts b/src/types/network-drive.type.ts new file mode 100644 index 0000000..64c53c7 --- /dev/null +++ b/src/types/network-drive.type.ts @@ -0,0 +1,21 @@ +export type NetworkDriveServiceItem = { + resource_id: number; + resource_type: "server"; +}; + +export type NetworkDriveStatus = "new" | "created" | "failed"; + +export type NetworkDriveType = "nvme" | "hdd"; + +export type NetworkDrive = { + id: string; + name: string; + comment: string | null; + size: number; + service_list: NetworkDriveServiceItem[]; + location: string; + status: NetworkDriveStatus; + availability_zone: string; + type: NetworkDriveType; + preset_id: number; +}; diff --git a/src/types/project-resource-type.enum.ts b/src/types/project-resource-type.enum.ts new file mode 100644 index 0000000..bea2d62 --- /dev/null +++ b/src/types/project-resource-type.enum.ts @@ -0,0 +1,8 @@ +export enum ProjectResourceTypeEnum { + SERVER = "server", + BALANCER = "balancer", + DATABASE = "database", + KUBERNETES = "kubernetes", + STORAGE = "storage", + DEDICATED = "dedicated", +} diff --git a/src/types/project.type.ts b/src/types/project.type.ts new file mode 100644 index 0000000..095cf3d --- /dev/null +++ b/src/types/project.type.ts @@ -0,0 +1,24 @@ +export type Project = { + id: number; + account_id: string; + avatar_id: string | null; + description: string; + name: string; + is_default: boolean; +}; + +export type ProjectResourceType = + | "server" + | "balancer" + | "database" + | "kubernetes" + | "storage" + | "dedicated"; + +export type ProjectResource = { + id: number; + created_at: string; + resource_id: number; + project: Project; + type: ProjectResourceType; +}; diff --git a/src/types/server-backup.type.ts b/src/types/server-backup.type.ts new file mode 100644 index 0000000..5f99035 --- /dev/null +++ b/src/types/server-backup.type.ts @@ -0,0 +1,20 @@ +export enum ServerBackupStatus { + PRECREATE = "precreate", + DELETE = "delete", + SHUTDOWN = "shutdown", + RECOVER = "recover", + CREATE = "create", + FAIL = "fail", + DONE = "done", +} + +export type ServerBackup = { + id: number; + name: string; + comment: string | null; + created_at: string; + status: ServerBackupStatus | string; + size: number; + type: "manual" | "auto"; + progress: number; +}; diff --git a/src/types/server-configurator.type.ts b/src/types/server-configurator.type.ts new file mode 100644 index 0000000..09faf8a --- /dev/null +++ b/src/types/server-configurator.type.ts @@ -0,0 +1,26 @@ +export type ServerConfiguratorRequirements = { + cpu_min: number; + cpu_step: number; + cpu_max: number; + ram_min: number; + ram_step: number; + ram_max: number; + disk_min: number; + disk_step: number; + disk_max: number; + network_bandwidth_min: number; + network_bandwidth_step: number; + network_bandwidth_max: number; + gpu_min: number | null; + gpu_max: number | null; + gpu_step: number | null; +}; + +export type ServerConfigurator = { + id: number; + location: string; + disk_type: string; + is_allowed_local_network: boolean; + cpu_frequency: string; + requirements: ServerConfiguratorRequirements; +}; diff --git a/src/types/server-disk.type.ts b/src/types/server-disk.type.ts new file mode 100644 index 0000000..8a36c07 --- /dev/null +++ b/src/types/server-disk.type.ts @@ -0,0 +1,10 @@ +export type ServerDisk = { + id: number; + size: number; + used: number; + type: string; + is_mounted: boolean; + is_system: boolean; + system_name: string; + status: string; +}; diff --git a/src/types/server-ip.type.ts b/src/types/server-ip.type.ts new file mode 100644 index 0000000..a71f907 --- /dev/null +++ b/src/types/server-ip.type.ts @@ -0,0 +1,6 @@ +export type ServerIp = { + type: "ipv4" | "ipv6" | string; + ip: string; + ptr: string; + is_main: boolean; +}; diff --git a/src/types/server-log.type.ts b/src/types/server-log.type.ts new file mode 100644 index 0000000..4e9d912 --- /dev/null +++ b/src/types/server-log.type.ts @@ -0,0 +1,5 @@ +export type ServerLog = { + id: number; + logged_at: string; + event: string; +}; diff --git a/src/types/server-os.type.ts b/src/types/server-os.type.ts new file mode 100644 index 0000000..39bc37c --- /dev/null +++ b/src/types/server-os.type.ts @@ -0,0 +1,16 @@ +export type ServerOsRequirements = { + cpu_min?: number; + disk_min?: number; + ram_min?: number; + bandwidth_min?: number; +}; + +export type ServerOs = { + id: number; + family: string; + name: string; + version: string; + version_codename?: string; + description?: string; + requirements?: ServerOsRequirements; +}; diff --git a/src/types/server-preset.type.ts b/src/types/server-preset.type.ts new file mode 100644 index 0000000..32804fc --- /dev/null +++ b/src/types/server-preset.type.ts @@ -0,0 +1,15 @@ +export type ServerPreset = { + id: number; + location: string; + price: number; + cpu: number; + cpu_frequency: string; + ram: number; + disk: number; + disk_type: string; + bandwidth: number; + description: string; + description_short: string; + is_allowed_local_network: boolean; + tags: string[]; +}; diff --git a/src/types/server-software.type.ts b/src/types/server-software.type.ts new file mode 100644 index 0000000..e82ecb9 --- /dev/null +++ b/src/types/server-software.type.ts @@ -0,0 +1,15 @@ +export type ServerSoftwareRequirements = { + cpu_min?: number; + disk_min?: number; + ram_min?: number; + bandwidth_min?: number; +}; + +export type ServerSoftware = { + id: number; + name: string; + os_ids: number[]; + description?: string; + installations?: number; + requirements?: ServerSoftwareRequirements; +}; diff --git a/src/types/server.type.ts b/src/types/server.type.ts new file mode 100644 index 0000000..43cdcd9 --- /dev/null +++ b/src/types/server.type.ts @@ -0,0 +1,47 @@ +export enum ServerStatus { + INSTALLING = "installing", + SOFTWARE_INSTALL = "software_install", + REINSTALLING = "reinstalling", + ON = "on", + OFF = "off", + TURNING_ON = "turning_on", + TURNING_OFF = "turning_off", + HARD_TURNING_OFF = "hard_turning_off", + REBOOTING = "rebooting", + HARD_REBOOTING = "hard_rebooting", + REMOVING = "removing", + PERMANENT_BLOCKING = "permanent_blocking", + BLOCK = "block", + UNBLOCK = "unblock", + RESIZE = "resize", + BOOT_FROM_ISO = "boot_from_iso", + TRANSFER = "transfer", + CONFIGURING = "configuring", + ERROR = "error", + NO_PAID = "no_paid", +} + +export type Server = { + id: number; + name: string; + comment?: string; + created_at: string; + os: { + id: number; + name: string; + version: string | null; + }; + software?: { id: number; name: string } | null; + preset_id: number | null; + location: string; + configurator_id: number | null; + boot_mode: string; + status: ServerStatus | string; + cpu: number; + cpu_frequency: string; + ram: number; + disk_stats?: unknown; + main_ipv4?: string | null; + main_ipv6?: string | null; + [key: string]: unknown; +}; diff --git a/src/types/service-price.type.ts b/src/types/service-price.type.ts new file mode 100644 index 0000000..0c58386 --- /dev/null +++ b/src/types/service-price.type.ts @@ -0,0 +1,14 @@ +export type ServicePrice = { + cost: number; + total_cost: number; + type: string; + service_id?: number | string; + project_id?: number | null; + configuration?: { + cpu?: number; + ram?: number; + disk?: number; + [key: string]: unknown; + }; + [key: string]: unknown; +}; diff --git a/src/types/ssh-key.type.ts b/src/types/ssh-key.type.ts new file mode 100644 index 0000000..44579f1 --- /dev/null +++ b/src/types/ssh-key.type.ts @@ -0,0 +1,13 @@ +export interface SshKeyUsedBy { + id: number; + name: string; +} + +export interface SshKey { + id: number; + name: string; + body: string; + created_at: string; + used_by: SshKeyUsedBy[]; + is_default?: boolean; +} diff --git a/src/types/token-package.type.ts b/src/types/token-package.type.ts new file mode 100644 index 0000000..b5be7f0 --- /dev/null +++ b/src/types/token-package.type.ts @@ -0,0 +1,11 @@ +export type TokenPackage = { + id: number; + model_id: number; + name: string; + package_type: "base" | "additional" | "promo"; + type: "agent" | "knowledgebase"; + token_amount: number; + price: number; + duration_days?: number | null; + is_available: boolean; +}; diff --git a/src/types/token-statistic.type.ts b/src/types/token-statistic.type.ts new file mode 100644 index 0000000..2b97da2 --- /dev/null +++ b/src/types/token-statistic.type.ts @@ -0,0 +1,5 @@ +export type TokenStatistic = { + time: string; + ingoing_tokens: number; + outgoing_tokens: number; +}; diff --git a/src/types/tool-names.enum.ts b/src/types/tool-names.enum.ts index bbeb818..fe84fb4 100644 --- a/src/types/tool-names.enum.ts +++ b/src/types/tool-names.enum.ts @@ -7,8 +7,283 @@ export enum ToolNames { GET_VCS_PROVIDER_BY_REPOSITORY_URL = "get_vcs_provider_by_repository_url", GET_DEPLOY_SETTINGS = "get_deploy_settings", CREATE_FLOATING_IP = "create_floating_ip", + LIST_FLOATING_IPS = "list_floating_ips", + GET_FLOATING_IP = "get_floating_ip", + UPDATE_FLOATING_IP = "update_floating_ip", + DELETE_FLOATING_IP = "delete_floating_ip", + BIND_FLOATING_IP = "bind_floating_ip", + UNBIND_FLOATING_IP = "unbind_floating_ip", CREATE_VPC = "create_vpc", GET_VPCS = "get_vpcs", + GET_VPC = "get_vpc", + UPDATE_VPC = "update_vpc", + DELETE_VPC = "delete_vpc", + LIST_VPC_SERVICES = "list_vpc_services", + LIST_VPC_PORTS = "list_vpc_ports", + LIST_API_KEYS = "list_api_keys", + CREATE_API_KEY = "create_api_key", + EDIT_API_KEY = "edit_api_key", + REFRESH_API_KEY = "refresh_api_key", + DELETE_API_KEY = "delete_api_key", CREATE_DATABASE = "create_database", GET_DATABASE_PRESETS = "get_database_presets", + LIST_SERVERS = "list_servers", + GET_SERVER = "get_server", + START_SERVER = "start_server", + SHUTDOWN_SERVER = "shutdown_server", + HARD_SHUTDOWN_SERVER = "hard_shutdown_server", + REBOOT_SERVER = "reboot_server", + HARD_REBOOT_SERVER = "hard_reboot_server", + CLONE_SERVER = "clone_server", + RESIZE_SERVER = "resize_server", + GET_SERVER_LOGS = "get_server_logs", + LIST_SERVER_DISKS = "list_server_disks", + LIST_SERVER_DISK_BACKUPS = "list_server_disk_backups", + CREATE_SERVER_DISK_BACKUP = "create_server_disk_backup", + DELETE_SERVER_DISK_BACKUP = "delete_server_disk_backup", + CREATE_SERVER = "create_server", + DELETE_SERVER = "delete_server", + UPDATE_SERVER = "update_server", + RESET_SERVER_PASSWORD = "reset_server_password", + SET_SERVER_BOOT_MODE = "set_server_boot_mode", + UNMOUNT_SERVER_IMAGE = "unmount_server_image", + SET_SERVER_NAT_MODE = "set_server_nat_mode", + LIST_SERVER_IPS = "list_server_ips", + ADD_SERVER_IP = "add_server_ip", + DELETE_SERVER_IP = "delete_server_ip", + UPDATE_SERVER_IP = "update_server_ip", + CREATE_SERVER_DISK = "create_server_disk", + GET_SERVER_DISK = "get_server_disk", + UPDATE_SERVER_DISK = "update_server_disk", + DELETE_SERVER_DISK = "delete_server_disk", + GET_SERVER_DISK_AUTO_BACKUPS = "get_server_disk_auto_backups", + UPDATE_SERVER_DISK_AUTO_BACKUPS = "update_server_disk_auto_backups", + GET_SERVER_DISK_BACKUP = "get_server_disk_backup", + UPDATE_SERVER_DISK_BACKUP = "update_server_disk_backup", + SERVER_DISK_BACKUP_ACTION = "server_disk_backup_action", + GET_ACCOUNT_FINANCES = "get_account_finances", + GET_ACCOUNT_STATUS = "get_account_status", + GET_ACCOUNT_SERVICES_COST = "get_account_services_cost", + LIST_SERVER_PRESETS = "list_server_presets", + LIST_SERVER_OS = "list_server_os", + LIST_SERVER_CONFIGURATORS = "list_server_configurators", + LIST_SERVER_SOFTWARE = "list_server_software", + LIST_LOCATIONS = "list_locations", + LIST_SSH_KEYS = "list_ssh_keys", + CREATE_SSH_KEY = "create_ssh_key", + GET_SSH_KEY = "get_ssh_key", + UPDATE_SSH_KEY = "update_ssh_key", + DELETE_SSH_KEY = "delete_ssh_key", + ADD_SSH_KEYS_TO_SERVER = "add_ssh_keys_to_server", + REMOVE_SSH_KEY_FROM_SERVER = "remove_ssh_key_from_server", + LIST_BUCKETS = "list_buckets", + CREATE_BUCKET = "create_bucket", + GET_BUCKET = "get_bucket", + UPDATE_BUCKET = "update_bucket", + DELETE_BUCKET = "delete_bucket", + GET_BUCKET_PRESETS = "get_bucket_presets", + LIST_BUCKET_USERS = "list_bucket_users", + UPDATE_BUCKET_USER = "update_bucket_user", + GET_BUCKET_TRANSFER_STATUS = "get_bucket_transfer_status", + TRANSFER_BUCKET = "transfer_bucket", + LIST_BUCKET_SUBDOMAINS = "list_bucket_subdomains", + ADD_BUCKET_SUBDOMAINS = "add_bucket_subdomains", + DELETE_BUCKET_SUBDOMAINS = "delete_bucket_subdomains", + ADD_BUCKET_SUBDOMAIN_CERTIFICATE = "add_bucket_subdomain_certificate", + LIST_DATABASE_CLUSTERS = "list_database_clusters", + GET_DATABASE_CLUSTER = "get_database_cluster", + UPDATE_DATABASE_CLUSTER = "update_database_cluster", + DELETE_DATABASE_CLUSTER = "delete_database_cluster", + LIST_DATABASE_ADMINS = "list_database_admins", + GET_DATABASE_ADMIN = "get_database_admin", + CREATE_DATABASE_ADMIN = "create_database_admin", + UPDATE_DATABASE_ADMIN = "update_database_admin", + DELETE_DATABASE_ADMIN = "delete_database_admin", + LIST_DATABASE_INSTANCES = "list_database_instances", + GET_DATABASE_INSTANCE = "get_database_instance", + CREATE_DATABASE_INSTANCE = "create_database_instance", + UPDATE_DATABASE_INSTANCE = "update_database_instance", + DELETE_DATABASE_INSTANCE = "delete_database_instance", + LIST_DATABASE_TYPES = "list_database_types", + GET_DATABASE_PARAMETERS = "get_database_parameters", + LIST_DATABASES = "list_databases", + GET_DATABASE = "get_database", + UPDATE_DATABASE = "update_database", + DELETE_DATABASE = "delete_database", + GET_DATABASE_AUTO_BACKUPS = "get_database_auto_backups", + UPDATE_DATABASE_AUTO_BACKUPS = "update_database_auto_backups", + LIST_DATABASE_BACKUPS = "list_database_backups", + CREATE_DATABASE_BACKUP = "create_database_backup", + GET_DATABASE_BACKUP = "get_database_backup", + DELETE_DATABASE_BACKUP = "delete_database_backup", + RESTORE_DATABASE_BACKUP = "restore_database_backup", + LIST_DOMAINS = "list_domains", + GET_DOMAIN = "get_domain", + UPDATE_DOMAIN = "update_domain", + DELETE_DOMAIN = "delete_domain", + ADD_DOMAIN = "add_domain", + CHECK_DOMAIN = "check_domain", + LIST_DNS_RECORDS = "list_dns_records", + LIST_DEFAULT_DNS_RECORDS = "list_default_dns_records", + CREATE_DNS_RECORD = "create_dns_record", + UPDATE_DNS_RECORD = "update_dns_record", + DELETE_DNS_RECORD = "delete_dns_record", + ADD_SUBDOMAIN = "add_subdomain", + DELETE_SUBDOMAIN = "delete_subdomain", + GET_DOMAIN_NAME_SERVERS = "get_domain_name_servers", + UPDATE_DOMAIN_NAME_SERVERS = "update_domain_name_servers", + LIST_DOMAIN_REQUESTS = "list_domain_requests", + GET_DOMAIN_REQUEST = "get_domain_request", + CREATE_DOMAIN_REQUEST = "create_domain_request", + UPDATE_DOMAIN_REQUEST = "update_domain_request", + LIST_TLDS = "list_tlds", + GET_TLD = "get_tld", + LIST_IMAGES = "list_images", + CREATE_IMAGE = "create_image", + GET_IMAGE = "get_image", + UPDATE_IMAGE = "update_image", + DELETE_IMAGE = "delete_image", + LIST_IMAGE_DOWNLOADS = "list_image_downloads", + CREATE_IMAGE_DOWNLOAD = "create_image_download", + GET_IMAGE_DOWNLOAD = "get_image_download", + DELETE_IMAGE_DOWNLOAD = "delete_image_download", + LIST_FIREWALL_GROUPS = "list_firewall_groups", + GET_FIREWALL_GROUP = "get_firewall_group", + CREATE_FIREWALL_GROUP = "create_firewall_group", + UPDATE_FIREWALL_GROUP = "update_firewall_group", + DELETE_FIREWALL_GROUP = "delete_firewall_group", + LIST_FIREWALL_GROUP_RESOURCES = "list_firewall_group_resources", + LINK_FIREWALL_RESOURCE = "link_firewall_resource", + UNLINK_FIREWALL_RESOURCE = "unlink_firewall_resource", + LIST_FIREWALL_RULES = "list_firewall_rules", + GET_FIREWALL_RULE = "get_firewall_rule", + CREATE_FIREWALL_RULE = "create_firewall_rule", + UPDATE_FIREWALL_RULE = "update_firewall_rule", + DELETE_FIREWALL_RULE = "delete_firewall_rule", + LIST_FIREWALL_GROUPS_BY_RESOURCE = "list_firewall_groups_by_resource", + LIST_NETWORK_DRIVES = "list_network_drives", + GET_NETWORK_DRIVE = "get_network_drive", + CREATE_NETWORK_DRIVE = "create_network_drive", + UPDATE_NETWORK_DRIVE = "update_network_drive", + DELETE_NETWORK_DRIVE = "delete_network_drive", + MOUNT_NETWORK_DRIVE = "mount_network_drive", + UNMOUNT_NETWORK_DRIVE = "unmount_network_drive", + LIST_NETWORK_DRIVE_AVAILABLE_RESOURCES = "list_network_drive_available_resources", + LIST_NETWORK_DRIVE_PRESETS = "list_network_drive_presets", + LIST_PROJECTS = "list_projects", + GET_PROJECT = "get_project", + CREATE_PROJECT = "create_project", + UPDATE_PROJECT = "update_project", + DELETE_PROJECT = "delete_project", + LIST_PROJECT_RESOURCES = "list_project_resources", + LIST_PROJECT_BALANCERS = "list_project_balancers", + ADD_BALANCER_TO_PROJECT = "add_balancer_to_project", + LIST_PROJECT_BUCKETS = "list_project_buckets", + ADD_BUCKET_TO_PROJECT = "add_bucket_to_project", + LIST_PROJECT_CLUSTERS = "list_project_clusters", + ADD_CLUSTER_TO_PROJECT = "add_cluster_to_project", + LIST_PROJECT_SERVERS = "list_project_servers", + ADD_SERVER_TO_PROJECT = "add_server_to_project", + LIST_PROJECT_DATABASES = "list_project_databases", + ADD_DATABASE_TO_PROJECT = "add_database_to_project", + LIST_PROJECT_DEDICATED = "list_project_dedicated", + ADD_DEDICATED_TO_PROJECT = "add_dedicated_to_project", + LIST_ALL_PROJECT_BALANCERS = "list_all_project_balancers", + LIST_ALL_PROJECT_SERVERS = "list_all_project_servers", + LIST_ALL_PROJECT_BUCKETS = "list_all_project_buckets", + LIST_ALL_PROJECT_CLUSTERS = "list_all_project_clusters", + LIST_ALL_PROJECT_DATABASES = "list_all_project_databases", + LIST_ALL_PROJECT_DEDICATED = "list_all_project_dedicated", + TRANSFER_PROJECT_RESOURCE = "transfer_project_resource", + LIST_K8S_CLUSTERS = "list_k8s_clusters", + CREATE_K8S_CLUSTER = "create_k8s_cluster", + GET_K8S_CLUSTER = "get_k8s_cluster", + DELETE_K8S_CLUSTER = "delete_k8s_cluster", + EDIT_K8S_CLUSTER = "edit_k8s_cluster", + GET_K8S_CLUSTER_RESOURCES = "get_k8s_cluster_resources", + GET_K8S_KUBECONFIG = "get_k8s_kubeconfig", + UPDATE_K8S_CLUSTER_VERSION = "update_k8s_cluster_version", + LIST_K8S_NODE_GROUPS = "list_k8s_node_groups", + CREATE_K8S_NODE_GROUP = "create_k8s_node_group", + GET_K8S_NODE_GROUP = "get_k8s_node_group", + DELETE_K8S_NODE_GROUP = "delete_k8s_node_group", + LIST_K8S_NODE_GROUP_NODES = "list_k8s_node_group_nodes", + INCREASE_K8S_NODE_GROUP_NODES = "increase_k8s_node_group_nodes", + REDUCE_K8S_NODE_GROUP_NODES = "reduce_k8s_node_group_nodes", + LIST_K8S_CLUSTER_NODES = "list_k8s_cluster_nodes", + DELETE_K8S_CLUSTER_NODE = "delete_k8s_cluster_node", + LIST_K8S_VERSIONS = "list_k8s_versions", + LIST_K8S_NETWORK_DRIVERS = "list_k8s_network_drivers", + LIST_K8S_PRESETS = "list_k8s_presets", + LIST_K8S_ADDON_CONFIGS = "list_k8s_addon_configs", + LIST_K8S_ADDONS = "list_k8s_addons", + INSTALL_K8S_ADDON = "install_k8s_addon", + UPDATE_K8S_ADDON = "update_k8s_addon", + UNINSTALL_K8S_ADDON = "uninstall_k8s_addon", + LIST_BALANCERS = "list_balancers", + GET_BALANCER = "get_balancer", + CREATE_BALANCER = "create_balancer", + UPDATE_BALANCER = "update_balancer", + DELETE_BALANCER = "delete_balancer", + LIST_BALANCER_IPS = "list_balancer_ips", + ADD_BALANCER_IPS = "add_balancer_ips", + REMOVE_BALANCER_IPS = "remove_balancer_ips", + LIST_BALANCER_RULES = "list_balancer_rules", + CREATE_BALANCER_RULE = "create_balancer_rule", + UPDATE_BALANCER_RULE = "update_balancer_rule", + DELETE_BALANCER_RULE = "delete_balancer_rule", + LIST_BALANCER_PRESETS = "list_balancer_presets", + LIST_CONTAINER_REGISTRIES = "list_container_registries", + GET_CONTAINER_REGISTRY = "get_container_registry", + CREATE_CONTAINER_REGISTRY = "create_container_registry", + UPDATE_CONTAINER_REGISTRY = "update_container_registry", + DELETE_CONTAINER_REGISTRY = "delete_container_registry", + LIST_CONTAINER_REGISTRY_PRESETS = "list_container_registry_presets", + LIST_CONTAINER_REGISTRY_REPOSITORIES = "list_container_registry_repositories", + LIST_DEDICATED_SERVERS = "list_dedicated_servers", + GET_DEDICATED_SERVER = "get_dedicated_server", + CREATE_DEDICATED_SERVER = "create_dedicated_server", + UPDATE_DEDICATED_SERVER = "update_dedicated_server", + DELETE_DEDICATED_SERVER = "delete_dedicated_server", + LIST_DEDICATED_SERVER_PRESETS = "list_dedicated_server_presets", + LIST_DEDICATED_SERVER_ADDITIONAL_SERVICES = "list_dedicated_server_additional_services", + LIST_MAILBOXES = "list_mailboxes", + LIST_MAILBOXES_V1 = "list_mailboxes_v1", + LIST_MAILBOXES_BY_DOMAIN = "list_mailboxes_by_domain", + GET_MAILBOX = "get_mailbox", + GET_MAILBOX_V1 = "get_mailbox_v1", + CREATE_MAILBOX = "create_mailbox", + CREATE_MAILBOX_V1 = "create_mailbox_v1", + BATCH_CREATE_MAILBOXES = "batch_create_mailboxes", + BATCH_CREATE_MAILBOXES_V1 = "batch_create_mailboxes_v1", + UPDATE_MAILBOX = "update_mailbox", + UPDATE_MAILBOX_V1 = "update_mailbox_v1", + DELETE_MAILBOX = "delete_mailbox", + GET_MAIL_DOMAIN_INFO = "get_mail_domain_info", + UPDATE_MAIL_DOMAIN_INFO = "update_mail_domain_info", + LIST_AI_AGENTS = "list_ai_agents", + GET_AI_AGENT = "get_ai_agent", + CREATE_AI_AGENT = "create_ai_agent", + UPDATE_AI_AGENT = "update_ai_agent", + DELETE_AI_AGENT = "delete_ai_agent", + GET_AI_AGENT_STATISTIC = "get_ai_agent_statistic", + ADD_AI_AGENT_TOKEN_PACKAGE = "add_ai_agent_token_package", + LIST_AI_MODELS = "list_ai_models", + LIST_AI_AGENT_TOKEN_PACKAGES = "list_ai_agent_token_packages", + LIST_KNOWLEDGE_BASE_TOKEN_PACKAGES = "list_knowledge_base_token_packages", + LIST_KNOWLEDGE_BASES = "list_knowledge_bases", + LIST_KNOWLEDGE_BASES_V1 = "list_knowledge_bases_v1", + GET_KNOWLEDGE_BASE = "get_knowledge_base", + CREATE_KNOWLEDGE_BASE = "create_knowledge_base", + UPDATE_KNOWLEDGE_BASE = "update_knowledge_base", + DELETE_KNOWLEDGE_BASE = "delete_knowledge_base", + LINK_KNOWLEDGE_BASE = "link_knowledge_base", + UNLINK_KNOWLEDGE_BASE = "unlink_knowledge_base", + ADD_KNOWLEDGE_BASE_TOKEN_PACKAGE = "add_knowledge_base_token_package", + UPLOAD_KNOWLEDGE_BASE_FILES = "upload_knowledge_base_files", + LIST_KNOWLEDGE_BASE_DOCUMENTS = "list_knowledge_base_documents", + DELETE_KNOWLEDGE_BASE_DOCUMENT = "delete_knowledge_base_document", + DOWNLOAD_KNOWLEDGE_BASE_DOCUMENT = "download_knowledge_base_document", + REINDEX_KNOWLEDGE_BASE_DOCUMENT = "reindex_knowledge_base_document", + GET_KNOWLEDGE_BASE_STATISTIC = "get_knowledge_base_statistic", } diff --git a/src/types/top-level-domain.type.ts b/src/types/top-level-domain.type.ts new file mode 100644 index 0000000..2e96192 --- /dev/null +++ b/src/types/top-level-domain.type.ts @@ -0,0 +1,20 @@ +export type TldAllowedBuyPeriod = { + period: string; + price: number; +}; + +export type TopLevelDomain = { + id: number; + name: string; + price: number; + prolong_price?: number; + registrar?: string; + grace_period?: number; + early_renew_period?: number | null; + is_published?: boolean; + is_registered?: boolean; + is_whois_privacy_default_enabled?: boolean; + is_whois_privacy_enabled?: boolean; + allowed_buy_periods?: TldAllowedBuyPeriod[]; + [key: string]: unknown; +}; diff --git a/src/types/vpc-port.type.ts b/src/types/vpc-port.type.ts new file mode 100644 index 0000000..a3f779d --- /dev/null +++ b/src/types/vpc-port.type.ts @@ -0,0 +1,17 @@ +export type VpcPortNatMode = "dnat_and_snat" | "snat" | "no_nat"; + +export type VpcPortServiceType = "server" | "balancer" | "dbaas"; + +export interface VpcPortService { + id: number; + type: VpcPortServiceType; + name: string; +} + +export interface VpcPort { + id: string; + nat_mode: VpcPortNatMode; + mac: string; + ipv4: string; + service: VpcPortService; +} diff --git a/src/types/vpc-service.type.ts b/src/types/vpc-service.type.ts new file mode 100644 index 0000000..d1dae2f --- /dev/null +++ b/src/types/vpc-service.type.ts @@ -0,0 +1,9 @@ +export type VpcServiceType = "server" | "balancer" | "dbaas"; + +export interface VpcService { + id: number; + name: string; + public_ip?: string; + local_ip?: string; + type: VpcServiceType; +}