From 9d771f67c6ce7e22da67567cbb52cbb6ed2656bb Mon Sep 17 00:00:00 2001 From: Twisha Bansal Date: Fri, 27 Feb 2026 12:43:29 +0530 Subject: [PATCH 01/12] add skills --- gemini-extension.json | 18 - skills/cloudsql-postgres-admin/SKILL.md | 399 ++++++++++ .../assets/clone_instance.yaml | 12 + .../assets/create_backup.yaml | 12 + .../assets/create_database.yaml | 12 + .../assets/create_instance.yaml | 12 + .../assets/create_user.yaml | 12 + .../assets/get_instance.yaml | 12 + .../assets/list_databases.yaml | 12 + .../assets/list_instances.yaml | 12 + .../assets/postgres_upgrade_precheck.yaml | 12 + .../assets/restore_backup.yaml | 12 + .../assets/wait_for_operation.yaml | 17 + .../scripts/clone_instance.js | 52 ++ .../scripts/create_backup.js | 52 ++ .../scripts/create_database.js | 52 ++ .../scripts/create_instance.js | 52 ++ .../scripts/create_user.js | 52 ++ .../scripts/get_instance.js | 52 ++ .../scripts/list_databases.js | 52 ++ .../scripts/list_instances.js | 52 ++ .../scripts/postgres_upgrade_precheck.js | 52 ++ .../scripts/restore_backup.js | 52 ++ .../scripts/wait_for_operation.js | 52 ++ skills/cloudsql-postgres/SKILL.md | 704 ++++++++++++++++++ .../assets/database_overview.yaml | 17 + .../cloudsql-postgres/assets/execute_sql.yaml | 17 + .../assets/get_column_cardinality.yaml | 17 + .../assets/get_query_plan.yaml | 33 + .../assets/list_active_queries.yaml | 17 + .../list_autovacuum_configurations.yaml | 24 + .../assets/list_available_extensions.yaml | 17 + .../assets/list_database_stats.yaml | 17 + .../assets/list_indexes.yaml | 17 + .../assets/list_installed_extensions.yaml | 17 + .../assets/list_invalid_indexes.yaml | 32 + .../cloudsql-postgres/assets/list_locks.yaml | 17 + .../assets/list_memory_configurations.yaml | 36 + .../assets/list_pg_settings.yaml | 17 + .../assets/list_publication_tables.yaml | 17 + .../assets/list_query_stats.yaml | 17 + .../assets/list_replication_slots.yaml | 33 + .../cloudsql-postgres/assets/list_roles.yaml | 17 + .../assets/list_schemas.yaml | 17 + .../assets/list_sequences.yaml | 17 + .../assets/list_stored_procedure.yaml | 17 + .../assets/list_table_stats.yaml | 17 + .../cloudsql-postgres/assets/list_tables.yaml | 17 + .../assets/list_tablespaces.yaml | 17 + .../assets/list_top_bloated_tables.yaml | 47 ++ .../assets/list_triggers.yaml | 17 + .../cloudsql-postgres/assets/list_views.yaml | 17 + .../assets/long_running_transactions.yaml | 17 + .../assets/replication_stats.yaml | 17 + .../scripts/database_overview.js | 52 ++ .../cloudsql-postgres/scripts/execute_sql.js | 52 ++ .../scripts/get_column_cardinality.js | 52 ++ .../scripts/get_query_plan.js | 52 ++ .../scripts/list_active_queries.js | 52 ++ .../scripts/list_autovacuum_configurations.js | 52 ++ .../scripts/list_available_extensions.js | 52 ++ .../scripts/list_database_stats.js | 52 ++ .../cloudsql-postgres/scripts/list_indexes.js | 52 ++ .../scripts/list_installed_extensions.js | 52 ++ .../scripts/list_invalid_indexes.js | 52 ++ .../cloudsql-postgres/scripts/list_locks.js | 52 ++ .../scripts/list_memory_configurations.js | 52 ++ .../scripts/list_pg_settings.js | 52 ++ .../scripts/list_publication_tables.js | 52 ++ .../scripts/list_query_stats.js | 52 ++ .../scripts/list_replication_slots.js | 52 ++ .../cloudsql-postgres/scripts/list_roles.js | 52 ++ .../cloudsql-postgres/scripts/list_schemas.js | 52 ++ .../scripts/list_sequences.js | 52 ++ .../scripts/list_stored_procedure.js | 52 ++ .../scripts/list_table_stats.js | 52 ++ .../cloudsql-postgres/scripts/list_tables.js | 52 ++ .../scripts/list_tablespaces.js | 52 ++ .../scripts/list_top_bloated_tables.js | 52 ++ .../scripts/list_triggers.js | 52 ++ .../cloudsql-postgres/scripts/list_views.js | 52 ++ .../scripts/long_running_transactions.js | 52 ++ .../scripts/replication_stats.js | 52 ++ 83 files changed, 3916 insertions(+), 18 deletions(-) create mode 100644 skills/cloudsql-postgres-admin/SKILL.md create mode 100644 skills/cloudsql-postgres-admin/assets/clone_instance.yaml create mode 100644 skills/cloudsql-postgres-admin/assets/create_backup.yaml create mode 100644 skills/cloudsql-postgres-admin/assets/create_database.yaml create mode 100644 skills/cloudsql-postgres-admin/assets/create_instance.yaml create mode 100644 skills/cloudsql-postgres-admin/assets/create_user.yaml create mode 100644 skills/cloudsql-postgres-admin/assets/get_instance.yaml create mode 100644 skills/cloudsql-postgres-admin/assets/list_databases.yaml create mode 100644 skills/cloudsql-postgres-admin/assets/list_instances.yaml create mode 100644 skills/cloudsql-postgres-admin/assets/postgres_upgrade_precheck.yaml create mode 100644 skills/cloudsql-postgres-admin/assets/restore_backup.yaml create mode 100644 skills/cloudsql-postgres-admin/assets/wait_for_operation.yaml create mode 100755 skills/cloudsql-postgres-admin/scripts/clone_instance.js create mode 100755 skills/cloudsql-postgres-admin/scripts/create_backup.js create mode 100755 skills/cloudsql-postgres-admin/scripts/create_database.js create mode 100755 skills/cloudsql-postgres-admin/scripts/create_instance.js create mode 100755 skills/cloudsql-postgres-admin/scripts/create_user.js create mode 100755 skills/cloudsql-postgres-admin/scripts/get_instance.js create mode 100755 skills/cloudsql-postgres-admin/scripts/list_databases.js create mode 100755 skills/cloudsql-postgres-admin/scripts/list_instances.js create mode 100755 skills/cloudsql-postgres-admin/scripts/postgres_upgrade_precheck.js create mode 100755 skills/cloudsql-postgres-admin/scripts/restore_backup.js create mode 100755 skills/cloudsql-postgres-admin/scripts/wait_for_operation.js create mode 100644 skills/cloudsql-postgres/SKILL.md create mode 100644 skills/cloudsql-postgres/assets/database_overview.yaml create mode 100644 skills/cloudsql-postgres/assets/execute_sql.yaml create mode 100644 skills/cloudsql-postgres/assets/get_column_cardinality.yaml create mode 100644 skills/cloudsql-postgres/assets/get_query_plan.yaml create mode 100644 skills/cloudsql-postgres/assets/list_active_queries.yaml create mode 100644 skills/cloudsql-postgres/assets/list_autovacuum_configurations.yaml create mode 100644 skills/cloudsql-postgres/assets/list_available_extensions.yaml create mode 100644 skills/cloudsql-postgres/assets/list_database_stats.yaml create mode 100644 skills/cloudsql-postgres/assets/list_indexes.yaml create mode 100644 skills/cloudsql-postgres/assets/list_installed_extensions.yaml create mode 100644 skills/cloudsql-postgres/assets/list_invalid_indexes.yaml create mode 100644 skills/cloudsql-postgres/assets/list_locks.yaml create mode 100644 skills/cloudsql-postgres/assets/list_memory_configurations.yaml create mode 100644 skills/cloudsql-postgres/assets/list_pg_settings.yaml create mode 100644 skills/cloudsql-postgres/assets/list_publication_tables.yaml create mode 100644 skills/cloudsql-postgres/assets/list_query_stats.yaml create mode 100644 skills/cloudsql-postgres/assets/list_replication_slots.yaml create mode 100644 skills/cloudsql-postgres/assets/list_roles.yaml create mode 100644 skills/cloudsql-postgres/assets/list_schemas.yaml create mode 100644 skills/cloudsql-postgres/assets/list_sequences.yaml create mode 100644 skills/cloudsql-postgres/assets/list_stored_procedure.yaml create mode 100644 skills/cloudsql-postgres/assets/list_table_stats.yaml create mode 100644 skills/cloudsql-postgres/assets/list_tables.yaml create mode 100644 skills/cloudsql-postgres/assets/list_tablespaces.yaml create mode 100644 skills/cloudsql-postgres/assets/list_top_bloated_tables.yaml create mode 100644 skills/cloudsql-postgres/assets/list_triggers.yaml create mode 100644 skills/cloudsql-postgres/assets/list_views.yaml create mode 100644 skills/cloudsql-postgres/assets/long_running_transactions.yaml create mode 100644 skills/cloudsql-postgres/assets/replication_stats.yaml create mode 100755 skills/cloudsql-postgres/scripts/database_overview.js create mode 100755 skills/cloudsql-postgres/scripts/execute_sql.js create mode 100755 skills/cloudsql-postgres/scripts/get_column_cardinality.js create mode 100755 skills/cloudsql-postgres/scripts/get_query_plan.js create mode 100755 skills/cloudsql-postgres/scripts/list_active_queries.js create mode 100755 skills/cloudsql-postgres/scripts/list_autovacuum_configurations.js create mode 100755 skills/cloudsql-postgres/scripts/list_available_extensions.js create mode 100755 skills/cloudsql-postgres/scripts/list_database_stats.js create mode 100755 skills/cloudsql-postgres/scripts/list_indexes.js create mode 100755 skills/cloudsql-postgres/scripts/list_installed_extensions.js create mode 100755 skills/cloudsql-postgres/scripts/list_invalid_indexes.js create mode 100755 skills/cloudsql-postgres/scripts/list_locks.js create mode 100755 skills/cloudsql-postgres/scripts/list_memory_configurations.js create mode 100755 skills/cloudsql-postgres/scripts/list_pg_settings.js create mode 100755 skills/cloudsql-postgres/scripts/list_publication_tables.js create mode 100755 skills/cloudsql-postgres/scripts/list_query_stats.js create mode 100755 skills/cloudsql-postgres/scripts/list_replication_slots.js create mode 100755 skills/cloudsql-postgres/scripts/list_roles.js create mode 100755 skills/cloudsql-postgres/scripts/list_schemas.js create mode 100755 skills/cloudsql-postgres/scripts/list_sequences.js create mode 100755 skills/cloudsql-postgres/scripts/list_stored_procedure.js create mode 100755 skills/cloudsql-postgres/scripts/list_table_stats.js create mode 100755 skills/cloudsql-postgres/scripts/list_tables.js create mode 100755 skills/cloudsql-postgres/scripts/list_tablespaces.js create mode 100755 skills/cloudsql-postgres/scripts/list_top_bloated_tables.js create mode 100755 skills/cloudsql-postgres/scripts/list_triggers.js create mode 100755 skills/cloudsql-postgres/scripts/list_views.js create mode 100755 skills/cloudsql-postgres/scripts/long_running_transactions.js create mode 100755 skills/cloudsql-postgres/scripts/replication_stats.js diff --git a/gemini-extension.json b/gemini-extension.json index 3c10d49..6b1834a 100644 --- a/gemini-extension.json +++ b/gemini-extension.json @@ -2,24 +2,6 @@ "name": "cloud-sql-postgresql", "version": "0.1.10", "description": "Create, connect, and interact with a Cloud SQL for PostgreSQL database and data.", - "mcpServers": { - "cloud_sql_postgresql_admin": { - "command": "${extensionPath}${/}toolbox", - "args": [ - "--prebuilt", - "cloud-sql-postgres-admin", - "--stdio" - ] - }, - "cloud_sql_postgresql": { - "command": "${extensionPath}${/}toolbox", - "args": [ - "--prebuilt", - "cloud-sql-postgres", - "--stdio" - ] - } - }, "contextFileName": "CLOUD-SQL-POSTGRESQL.md", "settings": [ { diff --git a/skills/cloudsql-postgres-admin/SKILL.md b/skills/cloudsql-postgres-admin/SKILL.md new file mode 100644 index 0000000..03b50f5 --- /dev/null +++ b/skills/cloudsql-postgres-admin/SKILL.md @@ -0,0 +1,399 @@ +--- +name: cloudsql-postgres-admin +description: skill for performing administrative operations on cloudsql postgres +--- + +## Usage + +All scripts can be executed using Node.js. Replace `` and `` with actual values. + +**Bash:** +`node scripts/.js '{"": ""}'` + +**PowerShell:** +`node scripts/.js '{\"\": \"\"}'` + +## Scripts + + +### clone_instance + +Clone an existing Cloud SQL instance into a new instance. The clone can be a direct copy of the source instance, or a point-in-time-recovery (PITR) clone from a specific timestamp. The call returns a Cloud SQL Operation object. Call wait_for_operation tool after this, make sure to use multiplier as 4 to poll the opertation status till it is marked DONE. + +#### Parameters + +```json +{ + "properties": { + "destinationInstanceName": { + "description": "The name of the new instance that will be created by cloning the source instance.", + "type": "string" + }, + "pointInTime": { + "description": "The timestamp in RFC 3339 format to which the source instance should be cloned.", + "type": "string" + }, + "preferredSecondaryZone": { + "description": "The preferred secondary zone for the new instance.", + "type": "string" + }, + "preferredZone": { + "description": "The preferred zone for the new instance.", + "type": "string" + }, + "project": { + "default": "twisha-dev", + "description": "The GCP project ID. This is pre-configured; do not ask for it unless the user explicitly provides a different one.", + "type": "string" + }, + "sourceInstanceName": { + "description": "The name of the instance to be cloned.", + "type": "string" + } + }, + "required": [ + "sourceInstanceName", + "destinationInstanceName" + ], + "type": "object" +} +``` + +--- + +### create_backup + +Creates a backup on a Cloud SQL instance. + +#### Parameters + +```json +{ + "properties": { + "backup_description": { + "description": "The description of this backup run.", + "type": "string" + }, + "instance": { + "description": "Cloud SQL instance ID. This does not include the project ID.", + "type": "string" + }, + "location": { + "description": "Location of the backup run.", + "type": "string" + }, + "project": { + "default": "twisha-dev", + "description": "The GCP project ID. This is pre-configured; do not ask for it unless the user explicitly provides a different one.", + "type": "string" + } + }, + "required": [ + "instance" + ], + "type": "object" +} +``` + +--- + +### create_database + + + +#### Parameters + +```json +{ + "properties": { + "instance": { + "description": "The ID of the instance where the database will be created.", + "type": "string" + }, + "name": { + "description": "The name for the new database. Must be unique within the instance.", + "type": "string" + }, + "project": { + "default": "twisha-dev", + "description": "The GCP project ID. This is pre-configured; do not ask for it unless the user explicitly provides a different one.", + "type": "string" + } + }, + "required": [ + "instance", + "name" + ], + "type": "object" +} +``` + +--- + +### create_instance + + + +#### Parameters + +```json +{ + "properties": { + "databaseVersion": { + "default": "POSTGRES_17", + "description": "The database version for Postgres. If not specified, defaults to the latest available version (e.g., POSTGRES_17).", + "type": "string" + }, + "editionPreset": { + "default": "Development", + "description": "The edition of the instance. Can be `Production` or `Development`. This determines the default machine type and availability. Defaults to `Development`.", + "type": "string" + }, + "name": { + "description": "The name of the instance", + "type": "string" + }, + "project": { + "default": "twisha-dev", + "description": "The GCP project ID. This is pre-configured; do not ask for it unless the user explicitly provides a different one.", + "type": "string" + }, + "rootPassword": { + "description": "The root password for the instance", + "type": "string" + } + }, + "required": [ + "name", + "rootPassword" + ], + "type": "object" +} +``` + +--- + +### create_user + + + +#### Parameters + +```json +{ + "properties": { + "iamUser": { + "description": "Set to true to create a Cloud IAM user.", + "type": "boolean" + }, + "instance": { + "description": "The ID of the instance where the user will be created.", + "type": "string" + }, + "name": { + "description": "The name for the new user. Must be unique within the instance.", + "type": "string" + }, + "password": { + "description": "A secure password for the new user. Not required for IAM users.", + "type": "string" + }, + "project": { + "default": "twisha-dev", + "description": "The GCP project ID. This is pre-configured; do not ask for it unless the user explicitly provides a different one.", + "type": "string" + } + }, + "required": [ + "instance", + "name", + "iamUser" + ], + "type": "object" +} +``` + +--- + +### get_instance + + + +#### Parameters + +```json +{ + "properties": { + "instanceId": { + "description": "The instance ID", + "type": "string" + }, + "projectId": { + "default": "twisha-dev", + "description": "The GCP project ID. This is pre-configured; do not ask for it unless the user explicitly provides a different one.", + "type": "string" + } + }, + "required": [ + "instanceId" + ], + "type": "object" +} +``` + +--- + +### list_databases + +Lists all databases for a Cloud SQL instance. + +#### Parameters + +```json +{ + "properties": { + "instance": { + "description": "The instance ID", + "type": "string" + }, + "project": { + "default": "twisha-dev", + "description": "The GCP project ID. This is pre-configured; do not ask for it unless the user explicitly provides a different one.", + "type": "string" + } + }, + "required": [ + "instance" + ], + "type": "object" +} +``` + +--- + +### list_instances + +Lists all type of Cloud SQL instances for a project. + +#### Parameters + +```json +{ + "properties": { + "project": { + "default": "twisha-dev", + "description": "The GCP project ID. This is pre-configured; do not ask for it unless the user explicitly provides a different one.", + "type": "string" + } + }, + "type": "object" +} +``` + +--- + +### postgres_upgrade_precheck + +Analyzes a Cloud SQL PostgreSQL instance for major version upgrade readiness. Results are provided to guide customer actions: +ERROR: Action Required. These are critical issues blocking the upgrade. Customers must resolve these using the provided actions_required steps before attempting the upgrade. +WARNING: Review Recommended. These are potential issues. Customers should review the message and actions_required. While not blocking, addressing these is advised to prevent future problems or unexpected behavior post-upgrade. +INFO: No Action Needed. Informational messages only. This pre-check helps customers proactively fix problems, preventing upgrade failures and ensuring a smoother transition. + +#### Parameters + +```json +{ + "properties": { + "instance": { + "description": "The name of the instance to check", + "type": "string" + }, + "project": { + "description": "The project ID", + "type": "string" + }, + "targetDatabaseVersion": { + "default": "POSTGRES_18", + "description": "The target PostgreSQL version for the upgrade (e.g., POSTGRES_18). If not specified, defaults to the PostgreSQL 18.", + "type": "string" + } + }, + "required": [ + "project", + "instance" + ], + "type": "object" +} +``` + +--- + +### restore_backup + +Restores a backup on a Cloud SQL instance. + +#### Parameters + +```json +{ + "properties": { + "backup_id": { + "description": "Identifier of the backup being restored. Can be a BackupRun ID, backup name, or BackupDR backup name. Use the full backup ID as provided, do not try to parse it", + "type": "string" + }, + "source_instance": { + "description": "Cloud SQL instance ID of the instance that the backup belongs to. Only required if the backup_id is a BackupRun ID.", + "type": "string" + }, + "source_project": { + "description": "GCP project ID of the instance that the backup belongs to. Only required if the backup_id is a BackupRun ID.", + "type": "string" + }, + "target_instance": { + "description": "Cloud SQL instance ID of the target instance. This does not include the project ID.", + "type": "string" + }, + "target_project": { + "default": "twisha-dev", + "description": "The GCP project ID. This is pre-configured; do not ask for it unless the user explicitly provides a different one.", + "type": "string" + } + }, + "required": [ + "target_instance", + "backup_id" + ], + "type": "object" +} +``` + +--- + +### wait_for_operation + + + +#### Parameters + +```json +{ + "properties": { + "operation": { + "description": "The operation ID", + "type": "string" + }, + "project": { + "default": "twisha-dev", + "description": "The GCP project ID. This is pre-configured; do not ask for it unless the user explicitly provides a different one.", + "type": "string" + } + }, + "required": [ + "operation" + ], + "type": "object" +} +``` + +--- + diff --git a/skills/cloudsql-postgres-admin/assets/clone_instance.yaml b/skills/cloudsql-postgres-admin/assets/clone_instance.yaml new file mode 100644 index 0000000..71889fe --- /dev/null +++ b/skills/cloudsql-postgres-admin/assets/clone_instance.yaml @@ -0,0 +1,12 @@ +kind: tools +name: clone_instance +type: cloud-sql-clone-instance +description: "" +source: cloud-sql-admin-source +authRequired: [] +--- +kind: sources +name: cloud-sql-admin-source +type: cloud-sql-admin +defaultProject: twisha-dev +useClientOAuth: false diff --git a/skills/cloudsql-postgres-admin/assets/create_backup.yaml b/skills/cloudsql-postgres-admin/assets/create_backup.yaml new file mode 100644 index 0000000..04b6eaf --- /dev/null +++ b/skills/cloudsql-postgres-admin/assets/create_backup.yaml @@ -0,0 +1,12 @@ +kind: tools +name: create_backup +type: cloud-sql-create-backup +description: "" +source: cloud-sql-admin-source +authRequired: [] +--- +kind: sources +name: cloud-sql-admin-source +type: cloud-sql-admin +defaultProject: twisha-dev +useClientOAuth: false diff --git a/skills/cloudsql-postgres-admin/assets/create_database.yaml b/skills/cloudsql-postgres-admin/assets/create_database.yaml new file mode 100644 index 0000000..4672680 --- /dev/null +++ b/skills/cloudsql-postgres-admin/assets/create_database.yaml @@ -0,0 +1,12 @@ +kind: tools +name: create_database +type: cloud-sql-create-database +source: cloud-sql-admin-source +description: "" +authRequired: [] +--- +kind: sources +name: cloud-sql-admin-source +type: cloud-sql-admin +defaultProject: twisha-dev +useClientOAuth: false diff --git a/skills/cloudsql-postgres-admin/assets/create_instance.yaml b/skills/cloudsql-postgres-admin/assets/create_instance.yaml new file mode 100644 index 0000000..2eaf7bc --- /dev/null +++ b/skills/cloudsql-postgres-admin/assets/create_instance.yaml @@ -0,0 +1,12 @@ +kind: tools +name: create_instance +type: cloud-sql-postgres-create-instance +description: "" +source: cloud-sql-admin-source +authRequired: [] +--- +kind: sources +name: cloud-sql-admin-source +type: cloud-sql-admin +defaultProject: twisha-dev +useClientOAuth: false diff --git a/skills/cloudsql-postgres-admin/assets/create_user.yaml b/skills/cloudsql-postgres-admin/assets/create_user.yaml new file mode 100644 index 0000000..f3138ec --- /dev/null +++ b/skills/cloudsql-postgres-admin/assets/create_user.yaml @@ -0,0 +1,12 @@ +kind: tools +name: create_user +type: cloud-sql-create-users +source: cloud-sql-admin-source +description: "" +authRequired: [] +--- +kind: sources +name: cloud-sql-admin-source +type: cloud-sql-admin +defaultProject: twisha-dev +useClientOAuth: false diff --git a/skills/cloudsql-postgres-admin/assets/get_instance.yaml b/skills/cloudsql-postgres-admin/assets/get_instance.yaml new file mode 100644 index 0000000..eaa4099 --- /dev/null +++ b/skills/cloudsql-postgres-admin/assets/get_instance.yaml @@ -0,0 +1,12 @@ +kind: tools +name: get_instance +type: cloud-sql-get-instance +description: "" +source: cloud-sql-admin-source +authRequired: [] +--- +kind: sources +name: cloud-sql-admin-source +type: cloud-sql-admin +defaultProject: twisha-dev +useClientOAuth: false diff --git a/skills/cloudsql-postgres-admin/assets/list_databases.yaml b/skills/cloudsql-postgres-admin/assets/list_databases.yaml new file mode 100644 index 0000000..a7efbe4 --- /dev/null +++ b/skills/cloudsql-postgres-admin/assets/list_databases.yaml @@ -0,0 +1,12 @@ +kind: tools +name: list_databases +type: cloud-sql-list-databases +source: cloud-sql-admin-source +description: "" +authRequired: [] +--- +kind: sources +name: cloud-sql-admin-source +type: cloud-sql-admin +defaultProject: twisha-dev +useClientOAuth: false diff --git a/skills/cloudsql-postgres-admin/assets/list_instances.yaml b/skills/cloudsql-postgres-admin/assets/list_instances.yaml new file mode 100644 index 0000000..3a359a9 --- /dev/null +++ b/skills/cloudsql-postgres-admin/assets/list_instances.yaml @@ -0,0 +1,12 @@ +kind: tools +name: list_instances +type: cloud-sql-list-instances +source: cloud-sql-admin-source +description: "" +authRequired: [] +--- +kind: sources +name: cloud-sql-admin-source +type: cloud-sql-admin +defaultProject: twisha-dev +useClientOAuth: false diff --git a/skills/cloudsql-postgres-admin/assets/postgres_upgrade_precheck.yaml b/skills/cloudsql-postgres-admin/assets/postgres_upgrade_precheck.yaml new file mode 100644 index 0000000..5121b4e --- /dev/null +++ b/skills/cloudsql-postgres-admin/assets/postgres_upgrade_precheck.yaml @@ -0,0 +1,12 @@ +kind: tools +name: postgres_upgrade_precheck +type: postgres-upgrade-precheck +description: "" +source: cloud-sql-admin-source +authRequired: [] +--- +kind: sources +name: cloud-sql-admin-source +type: cloud-sql-admin +defaultProject: twisha-dev +useClientOAuth: false diff --git a/skills/cloudsql-postgres-admin/assets/restore_backup.yaml b/skills/cloudsql-postgres-admin/assets/restore_backup.yaml new file mode 100644 index 0000000..869524c --- /dev/null +++ b/skills/cloudsql-postgres-admin/assets/restore_backup.yaml @@ -0,0 +1,12 @@ +kind: tools +name: restore_backup +type: cloud-sql-restore-backup +description: "" +source: cloud-sql-admin-source +authRequired: [] +--- +kind: sources +name: cloud-sql-admin-source +type: cloud-sql-admin +defaultProject: twisha-dev +useClientOAuth: false diff --git a/skills/cloudsql-postgres-admin/assets/wait_for_operation.yaml b/skills/cloudsql-postgres-admin/assets/wait_for_operation.yaml new file mode 100644 index 0000000..b7a6d3f --- /dev/null +++ b/skills/cloudsql-postgres-admin/assets/wait_for_operation.yaml @@ -0,0 +1,17 @@ +kind: tools +name: wait_for_operation +type: cloud-sql-wait-for-operation +source: cloud-sql-admin-source +description: "" +authRequired: [] +baseURL: "" +delay: "" +maxDelay: "" +multiplier: 4.0 +maxRetries: 0 +--- +kind: sources +name: cloud-sql-admin-source +type: cloud-sql-admin +defaultProject: twisha-dev +useClientOAuth: false diff --git a/skills/cloudsql-postgres-admin/scripts/clone_instance.js b/skills/cloudsql-postgres-admin/scripts/clone_instance.js new file mode 100755 index 0000000..5a5358e --- /dev/null +++ b/skills/cloudsql-postgres-admin/scripts/clone_instance.js @@ -0,0 +1,52 @@ +#!/usr/bin/env node + +const { spawn, execSync } = require('child_process'); +const path = require('path'); +const fs = require('fs'); + +const toolName = "clone_instance"; +const toolsFileName = "clone_instance.yaml"; + +function getToolboxPath() { + try { + const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox'; + const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim(); + if (globalPath) { + return globalPath.split('\n')[0].trim(); + } + } catch (e) { + // Ignore error; + } + const localPath = path.resolve(__dirname, '../../../toolbox'); + if (fs.existsSync(localPath)) { + return localPath; + } + throw new Error("Toolbox binary not found"); +} + +let toolboxBinary; +try { + toolboxBinary = getToolboxPath(); +} catch (err) { + console.error("Error:", err.message); + process.exit(1); +} + +let configArgs = []; +if (toolsFileName) { + configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName)); +} + +const args = process.argv.slice(2); +const toolboxArgs = [...configArgs, "invoke", toolName, ...args]; + +const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' }); + +child.on('close', (code) => { + process.exit(code); +}); + +child.on('error', (err) => { + console.error("Error executing toolbox:", err); + process.exit(1); +}); diff --git a/skills/cloudsql-postgres-admin/scripts/create_backup.js b/skills/cloudsql-postgres-admin/scripts/create_backup.js new file mode 100755 index 0000000..ce20bd7 --- /dev/null +++ b/skills/cloudsql-postgres-admin/scripts/create_backup.js @@ -0,0 +1,52 @@ +#!/usr/bin/env node + +const { spawn, execSync } = require('child_process'); +const path = require('path'); +const fs = require('fs'); + +const toolName = "create_backup"; +const toolsFileName = "create_backup.yaml"; + +function getToolboxPath() { + try { + const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox'; + const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim(); + if (globalPath) { + return globalPath.split('\n')[0].trim(); + } + } catch (e) { + // Ignore error; + } + const localPath = path.resolve(__dirname, '../../../toolbox'); + if (fs.existsSync(localPath)) { + return localPath; + } + throw new Error("Toolbox binary not found"); +} + +let toolboxBinary; +try { + toolboxBinary = getToolboxPath(); +} catch (err) { + console.error("Error:", err.message); + process.exit(1); +} + +let configArgs = []; +if (toolsFileName) { + configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName)); +} + +const args = process.argv.slice(2); +const toolboxArgs = [...configArgs, "invoke", toolName, ...args]; + +const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' }); + +child.on('close', (code) => { + process.exit(code); +}); + +child.on('error', (err) => { + console.error("Error executing toolbox:", err); + process.exit(1); +}); diff --git a/skills/cloudsql-postgres-admin/scripts/create_database.js b/skills/cloudsql-postgres-admin/scripts/create_database.js new file mode 100755 index 0000000..83c6f01 --- /dev/null +++ b/skills/cloudsql-postgres-admin/scripts/create_database.js @@ -0,0 +1,52 @@ +#!/usr/bin/env node + +const { spawn, execSync } = require('child_process'); +const path = require('path'); +const fs = require('fs'); + +const toolName = "create_database"; +const toolsFileName = "create_database.yaml"; + +function getToolboxPath() { + try { + const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox'; + const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim(); + if (globalPath) { + return globalPath.split('\n')[0].trim(); + } + } catch (e) { + // Ignore error; + } + const localPath = path.resolve(__dirname, '../../../toolbox'); + if (fs.existsSync(localPath)) { + return localPath; + } + throw new Error("Toolbox binary not found"); +} + +let toolboxBinary; +try { + toolboxBinary = getToolboxPath(); +} catch (err) { + console.error("Error:", err.message); + process.exit(1); +} + +let configArgs = []; +if (toolsFileName) { + configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName)); +} + +const args = process.argv.slice(2); +const toolboxArgs = [...configArgs, "invoke", toolName, ...args]; + +const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' }); + +child.on('close', (code) => { + process.exit(code); +}); + +child.on('error', (err) => { + console.error("Error executing toolbox:", err); + process.exit(1); +}); diff --git a/skills/cloudsql-postgres-admin/scripts/create_instance.js b/skills/cloudsql-postgres-admin/scripts/create_instance.js new file mode 100755 index 0000000..42a54d6 --- /dev/null +++ b/skills/cloudsql-postgres-admin/scripts/create_instance.js @@ -0,0 +1,52 @@ +#!/usr/bin/env node + +const { spawn, execSync } = require('child_process'); +const path = require('path'); +const fs = require('fs'); + +const toolName = "create_instance"; +const toolsFileName = "create_instance.yaml"; + +function getToolboxPath() { + try { + const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox'; + const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim(); + if (globalPath) { + return globalPath.split('\n')[0].trim(); + } + } catch (e) { + // Ignore error; + } + const localPath = path.resolve(__dirname, '../../../toolbox'); + if (fs.existsSync(localPath)) { + return localPath; + } + throw new Error("Toolbox binary not found"); +} + +let toolboxBinary; +try { + toolboxBinary = getToolboxPath(); +} catch (err) { + console.error("Error:", err.message); + process.exit(1); +} + +let configArgs = []; +if (toolsFileName) { + configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName)); +} + +const args = process.argv.slice(2); +const toolboxArgs = [...configArgs, "invoke", toolName, ...args]; + +const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' }); + +child.on('close', (code) => { + process.exit(code); +}); + +child.on('error', (err) => { + console.error("Error executing toolbox:", err); + process.exit(1); +}); diff --git a/skills/cloudsql-postgres-admin/scripts/create_user.js b/skills/cloudsql-postgres-admin/scripts/create_user.js new file mode 100755 index 0000000..984b355 --- /dev/null +++ b/skills/cloudsql-postgres-admin/scripts/create_user.js @@ -0,0 +1,52 @@ +#!/usr/bin/env node + +const { spawn, execSync } = require('child_process'); +const path = require('path'); +const fs = require('fs'); + +const toolName = "create_user"; +const toolsFileName = "create_user.yaml"; + +function getToolboxPath() { + try { + const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox'; + const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim(); + if (globalPath) { + return globalPath.split('\n')[0].trim(); + } + } catch (e) { + // Ignore error; + } + const localPath = path.resolve(__dirname, '../../../toolbox'); + if (fs.existsSync(localPath)) { + return localPath; + } + throw new Error("Toolbox binary not found"); +} + +let toolboxBinary; +try { + toolboxBinary = getToolboxPath(); +} catch (err) { + console.error("Error:", err.message); + process.exit(1); +} + +let configArgs = []; +if (toolsFileName) { + configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName)); +} + +const args = process.argv.slice(2); +const toolboxArgs = [...configArgs, "invoke", toolName, ...args]; + +const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' }); + +child.on('close', (code) => { + process.exit(code); +}); + +child.on('error', (err) => { + console.error("Error executing toolbox:", err); + process.exit(1); +}); diff --git a/skills/cloudsql-postgres-admin/scripts/get_instance.js b/skills/cloudsql-postgres-admin/scripts/get_instance.js new file mode 100755 index 0000000..2c30096 --- /dev/null +++ b/skills/cloudsql-postgres-admin/scripts/get_instance.js @@ -0,0 +1,52 @@ +#!/usr/bin/env node + +const { spawn, execSync } = require('child_process'); +const path = require('path'); +const fs = require('fs'); + +const toolName = "get_instance"; +const toolsFileName = "get_instance.yaml"; + +function getToolboxPath() { + try { + const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox'; + const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim(); + if (globalPath) { + return globalPath.split('\n')[0].trim(); + } + } catch (e) { + // Ignore error; + } + const localPath = path.resolve(__dirname, '../../../toolbox'); + if (fs.existsSync(localPath)) { + return localPath; + } + throw new Error("Toolbox binary not found"); +} + +let toolboxBinary; +try { + toolboxBinary = getToolboxPath(); +} catch (err) { + console.error("Error:", err.message); + process.exit(1); +} + +let configArgs = []; +if (toolsFileName) { + configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName)); +} + +const args = process.argv.slice(2); +const toolboxArgs = [...configArgs, "invoke", toolName, ...args]; + +const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' }); + +child.on('close', (code) => { + process.exit(code); +}); + +child.on('error', (err) => { + console.error("Error executing toolbox:", err); + process.exit(1); +}); diff --git a/skills/cloudsql-postgres-admin/scripts/list_databases.js b/skills/cloudsql-postgres-admin/scripts/list_databases.js new file mode 100755 index 0000000..eebada3 --- /dev/null +++ b/skills/cloudsql-postgres-admin/scripts/list_databases.js @@ -0,0 +1,52 @@ +#!/usr/bin/env node + +const { spawn, execSync } = require('child_process'); +const path = require('path'); +const fs = require('fs'); + +const toolName = "list_databases"; +const toolsFileName = "list_databases.yaml"; + +function getToolboxPath() { + try { + const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox'; + const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim(); + if (globalPath) { + return globalPath.split('\n')[0].trim(); + } + } catch (e) { + // Ignore error; + } + const localPath = path.resolve(__dirname, '../../../toolbox'); + if (fs.existsSync(localPath)) { + return localPath; + } + throw new Error("Toolbox binary not found"); +} + +let toolboxBinary; +try { + toolboxBinary = getToolboxPath(); +} catch (err) { + console.error("Error:", err.message); + process.exit(1); +} + +let configArgs = []; +if (toolsFileName) { + configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName)); +} + +const args = process.argv.slice(2); +const toolboxArgs = [...configArgs, "invoke", toolName, ...args]; + +const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' }); + +child.on('close', (code) => { + process.exit(code); +}); + +child.on('error', (err) => { + console.error("Error executing toolbox:", err); + process.exit(1); +}); diff --git a/skills/cloudsql-postgres-admin/scripts/list_instances.js b/skills/cloudsql-postgres-admin/scripts/list_instances.js new file mode 100755 index 0000000..cc8aa25 --- /dev/null +++ b/skills/cloudsql-postgres-admin/scripts/list_instances.js @@ -0,0 +1,52 @@ +#!/usr/bin/env node + +const { spawn, execSync } = require('child_process'); +const path = require('path'); +const fs = require('fs'); + +const toolName = "list_instances"; +const toolsFileName = "list_instances.yaml"; + +function getToolboxPath() { + try { + const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox'; + const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim(); + if (globalPath) { + return globalPath.split('\n')[0].trim(); + } + } catch (e) { + // Ignore error; + } + const localPath = path.resolve(__dirname, '../../../toolbox'); + if (fs.existsSync(localPath)) { + return localPath; + } + throw new Error("Toolbox binary not found"); +} + +let toolboxBinary; +try { + toolboxBinary = getToolboxPath(); +} catch (err) { + console.error("Error:", err.message); + process.exit(1); +} + +let configArgs = []; +if (toolsFileName) { + configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName)); +} + +const args = process.argv.slice(2); +const toolboxArgs = [...configArgs, "invoke", toolName, ...args]; + +const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' }); + +child.on('close', (code) => { + process.exit(code); +}); + +child.on('error', (err) => { + console.error("Error executing toolbox:", err); + process.exit(1); +}); diff --git a/skills/cloudsql-postgres-admin/scripts/postgres_upgrade_precheck.js b/skills/cloudsql-postgres-admin/scripts/postgres_upgrade_precheck.js new file mode 100755 index 0000000..f8648f6 --- /dev/null +++ b/skills/cloudsql-postgres-admin/scripts/postgres_upgrade_precheck.js @@ -0,0 +1,52 @@ +#!/usr/bin/env node + +const { spawn, execSync } = require('child_process'); +const path = require('path'); +const fs = require('fs'); + +const toolName = "postgres_upgrade_precheck"; +const toolsFileName = "postgres_upgrade_precheck.yaml"; + +function getToolboxPath() { + try { + const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox'; + const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim(); + if (globalPath) { + return globalPath.split('\n')[0].trim(); + } + } catch (e) { + // Ignore error; + } + const localPath = path.resolve(__dirname, '../../../toolbox'); + if (fs.existsSync(localPath)) { + return localPath; + } + throw new Error("Toolbox binary not found"); +} + +let toolboxBinary; +try { + toolboxBinary = getToolboxPath(); +} catch (err) { + console.error("Error:", err.message); + process.exit(1); +} + +let configArgs = []; +if (toolsFileName) { + configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName)); +} + +const args = process.argv.slice(2); +const toolboxArgs = [...configArgs, "invoke", toolName, ...args]; + +const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' }); + +child.on('close', (code) => { + process.exit(code); +}); + +child.on('error', (err) => { + console.error("Error executing toolbox:", err); + process.exit(1); +}); diff --git a/skills/cloudsql-postgres-admin/scripts/restore_backup.js b/skills/cloudsql-postgres-admin/scripts/restore_backup.js new file mode 100755 index 0000000..b74bf48 --- /dev/null +++ b/skills/cloudsql-postgres-admin/scripts/restore_backup.js @@ -0,0 +1,52 @@ +#!/usr/bin/env node + +const { spawn, execSync } = require('child_process'); +const path = require('path'); +const fs = require('fs'); + +const toolName = "restore_backup"; +const toolsFileName = "restore_backup.yaml"; + +function getToolboxPath() { + try { + const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox'; + const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim(); + if (globalPath) { + return globalPath.split('\n')[0].trim(); + } + } catch (e) { + // Ignore error; + } + const localPath = path.resolve(__dirname, '../../../toolbox'); + if (fs.existsSync(localPath)) { + return localPath; + } + throw new Error("Toolbox binary not found"); +} + +let toolboxBinary; +try { + toolboxBinary = getToolboxPath(); +} catch (err) { + console.error("Error:", err.message); + process.exit(1); +} + +let configArgs = []; +if (toolsFileName) { + configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName)); +} + +const args = process.argv.slice(2); +const toolboxArgs = [...configArgs, "invoke", toolName, ...args]; + +const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' }); + +child.on('close', (code) => { + process.exit(code); +}); + +child.on('error', (err) => { + console.error("Error executing toolbox:", err); + process.exit(1); +}); diff --git a/skills/cloudsql-postgres-admin/scripts/wait_for_operation.js b/skills/cloudsql-postgres-admin/scripts/wait_for_operation.js new file mode 100755 index 0000000..27a09c1 --- /dev/null +++ b/skills/cloudsql-postgres-admin/scripts/wait_for_operation.js @@ -0,0 +1,52 @@ +#!/usr/bin/env node + +const { spawn, execSync } = require('child_process'); +const path = require('path'); +const fs = require('fs'); + +const toolName = "wait_for_operation"; +const toolsFileName = "wait_for_operation.yaml"; + +function getToolboxPath() { + try { + const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox'; + const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim(); + if (globalPath) { + return globalPath.split('\n')[0].trim(); + } + } catch (e) { + // Ignore error; + } + const localPath = path.resolve(__dirname, '../../../toolbox'); + if (fs.existsSync(localPath)) { + return localPath; + } + throw new Error("Toolbox binary not found"); +} + +let toolboxBinary; +try { + toolboxBinary = getToolboxPath(); +} catch (err) { + console.error("Error:", err.message); + process.exit(1); +} + +let configArgs = []; +if (toolsFileName) { + configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName)); +} + +const args = process.argv.slice(2); +const toolboxArgs = [...configArgs, "invoke", toolName, ...args]; + +const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' }); + +child.on('close', (code) => { + process.exit(code); +}); + +child.on('error', (err) => { + console.error("Error executing toolbox:", err); + process.exit(1); +}); diff --git a/skills/cloudsql-postgres/SKILL.md b/skills/cloudsql-postgres/SKILL.md new file mode 100644 index 0000000..ee1d33f --- /dev/null +++ b/skills/cloudsql-postgres/SKILL.md @@ -0,0 +1,704 @@ +--- +name: cloudsql-postgres +description: skill for running tool operations in CloudSql postgres +--- + +## Usage + +All scripts can be executed using Node.js. Replace `` and `` with actual values. + +**Bash:** +`node scripts/.js '{"": ""}'` + +**PowerShell:** +`node scripts/.js '{\"\": \"\"}'` + +## Scripts + + +### database_overview + +Fetches the current state of the PostgreSQL server, returning the version, whether it's a replica, uptime duration, maximum connection limit, number of current connections, number of active connections, and the percentage of connections in use. + + + +--- + +### execute_sql + +Use this tool to execute sql. + +#### Parameters + +```json +{ + "properties": { + "sql": { + "description": "The sql to execute.", + "type": "string" + } + }, + "required": [ + "sql" + ], + "type": "object" +} +``` + +--- + +### get_column_cardinality + +Estimates the number of unique values (cardinality) quickly for one or all columns in a specific PostgreSQL table by using the database's internal statistics, returning the results in descending order of estimated cardinality. Please run ANALYZE on the table before using this tool to get accurate results. The tool returns the column_name and the estimated_cardinality. If the column_name is not provided, the tool returns all columns along with their estimated cardinality. + +#### Parameters + +```json +{ + "properties": { + "column_name": { + "description": "Optional: The column name for which the cardinality is to be found. If not provided, cardinality for all columns will be returned.", + "type": "string" + }, + "schema_name": { + "default": "public", + "description": "Optional: The schema name in which the table is present.", + "type": "string" + }, + "table_name": { + "description": "Required: The table name in which the column is present.", + "type": "string" + } + }, + "required": [ + "table_name" + ], + "type": "object" +} +``` + +--- + +### get_query_plan + +Generate a PostgreSQL EXPLAIN plan in JSON format for a single SQL statement—without executing it. This returns the optimizer's estimated plan, costs, and rows (no ANALYZE, no extra options). Use in production safely for plan inspection, regression checks, and query tuning workflows. + +#### Parameters + +```json +{ + "properties": { + "query": { + "description": "The SQL statement for which you want to generate plan (omit the EXPLAIN keyword).", + "type": "string" + } + }, + "required": [ + "query" + ], + "type": "object" +} +``` + +--- + +### list_active_queries + +List the top N (default 50) currently running queries (state='active') from pg_stat_activity, ordered by longest-running first. Returns pid, user, database, application_name, client_addr, state, wait_event_type/wait_event, backend/xact/query start times, computed query_duration, and the SQL text. + +#### Parameters + +```json +{ + "properties": { + "exclude_application_names": { + "default": "", + "description": "Optional: A comma-separated list of application names to exclude from the query results. This is useful for filtering out queries from specific applications (e.g., 'psql', 'pgAdmin', 'DBeaver'). The match is case-sensitive. Whitespace around commas and names is automatically handled. If this parameter is omitted, no applications are excluded.", + "type": "string" + }, + "limit": { + "default": 50, + "description": "Optional: The maximum number of rows to return.", + "type": "integer" + }, + "min_duration": { + "default": "1 minute", + "description": "Optional: Only show queries running at least this long (e.g., '1 minute', '1 second', '2 seconds').", + "type": "string" + } + }, + "type": "object" +} +``` + +--- + +### list_autovacuum_configurations + +List PostgreSQL autovacuum-related configurations (name and current setting) from pg_settings. + + + +--- + +### list_available_extensions + +Discover all PostgreSQL extensions available for installation on this server, returning name, default_version, and description. + + + +--- + +### list_database_stats + + + +#### Parameters + +```json +{ + "properties": { + "database_name": { + "default": "", + "description": "Optional: A specific database name pattern to search for.", + "type": "string" + }, + "database_owner": { + "default": "", + "description": "Optional: A specific database owner name pattern to search for.", + "type": "string" + }, + "default_tablespace": { + "default": "", + "description": "Optional: A specific default tablespace name pattern to search for.", + "type": "string" + }, + "include_templates": { + "default": false, + "description": "Optional: Whether to include template databases in the results.", + "type": "boolean" + }, + "limit": { + "default": 10, + "description": "Optional: The maximum number of rows to return.", + "type": "integer" + }, + "order_by": { + "default": "", + "description": "Optional: The field to order the results by. Valid values are 'size' and 'commit'.", + "type": "string" + } + }, + "type": "object" +} +``` + +--- + +### list_indexes + +Lists available user indexes in the database, excluding system schemas (pg_catalog, information_schema). For each index, the following properties are returned: schema name, table name, index name, index type (access method), a boolean indicating if it's a unique index, a boolean indicating if it's for a primary key, the index definition, index size in bytes, the number of index scans, the number of index tuples read, the number of table tuples fetched via index scans, and a boolean indicating if the index has been used at least once. + +#### Parameters + +```json +{ + "properties": { + "index_name": { + "default": "", + "description": "Optional: a text to filter results by index name. The input is used within a LIKE clause.", + "type": "string" + }, + "limit": { + "default": 50, + "description": "Optional: The maximum number of rows to return. Default is 50", + "type": "integer" + }, + "only_unused": { + "default": false, + "description": "Optional: If true, only returns indexes that have never been used.", + "type": "boolean" + }, + "schema_name": { + "default": "", + "description": "Optional: a text to filter results by schema name. The input is used within a LIKE clause.", + "type": "string" + }, + "table_name": { + "default": "", + "description": "Optional: a text to filter results by table name. The input is used within a LIKE clause.", + "type": "string" + } + }, + "type": "object" +} +``` + +--- + +### list_installed_extensions + +List all installed PostgreSQL extensions with their name, version, schema, owner, and description. + + + +--- + +### list_invalid_indexes + +Lists all invalid PostgreSQL indexes which are taking up disk space but are unusable by the query planner. Typically created by failed CREATE INDEX CONCURRENTLY operations. + + + +--- + +### list_locks + +Identifies all locks held by active processes showing the process ID, user, query text, and an aggregated list of all transactions and specific locks (relation, mode, grant status) associated with each process. + + + +--- + +### list_memory_configurations + +List PostgreSQL memory-related configurations (name and current setting) from pg_settings. + + + +--- + +### list_pg_settings + + + +#### Parameters + +```json +{ + "properties": { + "limit": { + "default": 50, + "description": "Optional: The maximum number of rows to return.", + "type": "integer" + }, + "setting_name": { + "default": "", + "description": "Optional: A specific configuration parameter name pattern to search for.", + "type": "string" + } + }, + "type": "object" +} +``` + +--- + +### list_publication_tables + + + +#### Parameters + +```json +{ + "properties": { + "limit": { + "default": 50, + "description": "Optional: The maximum number of rows to return.", + "type": "integer" + }, + "publication_names": { + "default": "", + "description": "Optional: Filters by a comma-separated list of publication names.", + "type": "string" + }, + "schema_names": { + "default": "", + "description": "Optional: Filters by a comma-separated list of schema names.", + "type": "string" + }, + "table_names": { + "default": "", + "description": "Optional: Filters by a comma-separated list of table names.", + "type": "string" + } + }, + "type": "object" +} +``` + +--- + +### list_query_stats + +Lists performance statistics for executed queries ordered by total time, filtering by database name pattern if provided. This tool requires the pg_stat_statements extension to be installed. The tool returns the database name, query text, execution count, timing metrics (total, min, max, mean), rows affected, and buffer cache I/O statistics (hits and reads). + +#### Parameters + +```json +{ + "properties": { + "database_name": { + "default": "", + "description": "Optional: The database name to list query stats for.", + "type": "string" + }, + "limit": { + "default": 50, + "description": "Optional: The maximum number of results to return. Defaults to 50.", + "type": "integer" + } + }, + "type": "object" +} +``` + +--- + +### list_replication_slots + +List key details for all PostgreSQL replication slots (e.g., type, database, active status) and calculates the size of the outstanding WAL that is being prevented from removal by the slot. + + + +--- + +### list_roles + +Lists all the user-created roles in the instance . It returns the role name, Object ID, the maximum number of concurrent connections the role can make, along with boolean indicators for: superuser status, privilege inheritance from member roles, ability to create roles, ability to create databases, ability to log in, replication privilege, and the ability to bypass row-level security, the password expiration timestamp, a list of direct members belonging to this role, and a list of other roles/groups that this role is a member of. + +#### Parameters + +```json +{ + "properties": { + "limit": { + "default": 50, + "description": "Optional: The maximum number of rows to return. Default is 10", + "type": "integer" + }, + "role_name": { + "default": "", + "description": "Optional: a text to filter results by role name. The input is used within a LIKE clause.", + "type": "string" + } + }, + "type": "object" +} +``` + +--- + +### list_schemas + +Lists all schemas in the database ordered by schema name and excluding system and temporary schemas. It returns the schema name, schema owner, grants, number of functions, number of tables and number of views within each schema. + +#### Parameters + +```json +{ + "properties": { + "limit": { + "default": 10, + "description": "Optional: The maximum number of schemas to return.", + "type": "integer" + }, + "owner": { + "default": "", + "description": "Optional: A specific schema owner name pattern to search for.", + "type": "string" + }, + "schema_name": { + "default": "", + "description": "Optional: A specific schema name pattern to search for.", + "type": "string" + } + }, + "type": "object" +} +``` + +--- + +### list_sequences + +Lists sequences in the database. Returns sequence name, schema name, sequence owner, data type of the sequence, starting value, minimum value, maximum value of the sequence, the value by which the sequence is incremented, and the last value generated by the sequence in the current session + +#### Parameters + +```json +{ + "properties": { + "limit": { + "default": 50, + "description": "Optional: The maximum number of rows to return. Default is 50", + "type": "integer" + }, + "schema_name": { + "default": "", + "description": "Optional: A specific schema name pattern to search for.", + "type": "string" + }, + "sequence_name": { + "default": "", + "description": "Optional: A specific sequence name pattern to search for.", + "type": "string" + } + }, + "type": "object" +} +``` + +--- + +### list_stored_procedure + +Retrieves stored procedure metadata returning schema name, procedure name, procedure owner, language, definition, and description, filtered by optional role name (procedure owner), schema name, and limit (default 20). + +#### Parameters + +```json +{ + "properties": { + "limit": { + "default": 20, + "description": "Optional: The maximum number of stored procedures to return. Defaults to 20.", + "type": "integer" + }, + "role_name": { + "description": "Optional: The owner name to filter the stored procedures by. Defaults to NULL.", + "type": "string" + }, + "schema_name": { + "description": "Optional: The schema name to filter the stored procedures by. Defaults to NULL.", + "type": "string" + } + }, + "type": "object" +} +``` + +--- + +### list_table_stats + +Lists the user table statistics in the database ordered by number of + sequential scans with a default limit of 50 rows. Returns the following + columns: schema name, table name, table size in bytes, number of + sequential scans, number of index scans, idx_scan_ratio_percent (showing + the percentage of total scans that utilized an index, where a low ratio + indicates missing or ineffective indexes), number of live rows, number + of dead rows, dead_row_ratio_percent (indicating potential table bloat), + total number of rows inserted, updated, and deleted, the timestamps + for the last_vacuum, last_autovacuum, and last_autoanalyze operations. + +#### Parameters + +```json +{ + "properties": { + "limit": { + "default": 50, + "description": "Optional: The maximum number of results to return", + "type": "integer" + }, + "owner": { + "description": "Optional: A specific owner to filter by", + "type": "string" + }, + "schema_name": { + "default": "public", + "description": "Optional: A specific schema name to filter by", + "type": "string" + }, + "sort_by": { + "description": "Optional: The column to sort by", + "type": "string" + }, + "table_name": { + "description": "Optional: A specific table name to filter by", + "type": "string" + } + }, + "type": "object" +} +``` + +--- + +### list_tables + +Lists detailed schema information (object type, columns, constraints, indexes, triggers, owner, comment) as JSON for user-created tables (ordinary or partitioned). Filters by a comma-separated list of names. If names are omitted, lists all tables in user schemas. + +#### Parameters + +```json +{ + "properties": { + "output_format": { + "default": "detailed", + "description": "Optional: Use 'simple' for names only or 'detailed' for full info.", + "type": "string" + }, + "table_names": { + "default": "", + "description": "Optional: A comma-separated list of table names. If empty, details for all tables will be listed.", + "type": "string" + } + }, + "type": "object" +} +``` + +--- + +### list_tablespaces + + + +#### Parameters + +```json +{ + "properties": { + "limit": { + "default": 50, + "description": "Optional: The maximum number of rows to return.", + "type": "integer" + }, + "tablespace_name": { + "default": "", + "description": "Optional: a text to filter results by tablespace name. The input is used within a LIKE clause.", + "type": "string" + } + }, + "type": "object" +} +``` + +--- + +### list_top_bloated_tables + +List the top tables by dead-tuple (approximate bloat signal), returning schema, table, live/dead tuples, percentage, and last vacuum/analyze times. + + +#### Parameters + +```json +{ + "properties": { + "limit": { + "default": 50, + "description": "The maximum number of results to return.", + "type": "integer" + } + }, + "type": "object" +} +``` + +--- + +### list_triggers + +Lists all non-internal triggers in a database. Returns trigger name, schema name, table name, whether its enabled or disabled, timing (e.g BEFORE/AFTER of the event), the events that cause the trigger to fire such as INSERT, UPDATE, or DELETE, whether the trigger activates per ROW or per STATEMENT, the handler function executed by the trigger and full definition. + +#### Parameters + +```json +{ + "properties": { + "limit": { + "default": 50, + "description": "Optional: The maximum number of rows to return.", + "type": "integer" + }, + "schema_name": { + "default": "", + "description": "Optional: A specific schema name pattern to search for.", + "type": "string" + }, + "table_name": { + "default": "", + "description": "Optional: A specific table name pattern to search for.", + "type": "string" + }, + "trigger_name": { + "default": "", + "description": "Optional: A specific trigger name pattern to search for.", + "type": "string" + } + }, + "type": "object" +} +``` + +--- + +### list_views + +Lists views in the database from pg_views with a default limit of 50 rows. Returns schemaname, viewname, ownername and the definition. + +#### Parameters + +```json +{ + "properties": { + "limit": { + "default": 50, + "description": "Optional: The maximum number of rows to return.", + "type": "integer" + }, + "schema_name": { + "default": "", + "description": "Optional: A specific schema name to search for.", + "type": "string" + }, + "view_name": { + "default": "", + "description": "Optional: A specific view name to search for.", + "type": "string" + } + }, + "type": "object" +} +``` + +--- + +### long_running_transactions + +Identifies and lists database transactions that exceed a specified time limit. For each of the long running transactions, the output contains the process id, database name, user name, application name, client address, state, connection age, transaction age, query age, last activity age, wait event type, wait event, and query string. + +#### Parameters + +```json +{ + "properties": { + "limit": { + "default": 20, + "description": "Optional: The maximum number of long-running transactions to return. Defaults to 20.", + "type": "integer" + }, + "min_duration": { + "default": "5 minutes", + "description": "Optional: Only show transactions running at least this long (e.g., '1 minute', '15 minutes', '30 seconds').", + "type": "string" + } + }, + "type": "object" +} +``` + +--- + +### replication_stats + +Lists each replica's process ID, user name, application name, backend_xmin (standby's xmin horizon reported by hot_standby_feedback), client IP address, connection state, and sync_state, along with lag sizes in bytes for sent_lag (primary to sent), write_lag (sent to written), flush_lag (written to flushed), replay_lag (flushed to replayed), and the overall total_lag (primary to replayed). + + + +--- + diff --git a/skills/cloudsql-postgres/assets/database_overview.yaml b/skills/cloudsql-postgres/assets/database_overview.yaml new file mode 100644 index 0000000..67e4b2f --- /dev/null +++ b/skills/cloudsql-postgres/assets/database_overview.yaml @@ -0,0 +1,17 @@ +kind: tools +name: database_overview +type: postgres-database-overview +source: cloudsql-pg-source +description: "" +authRequired: [] +--- +kind: sources +name: cloudsql-pg-source +type: cloud-sql-postgres +project: twisha-dev +region: us-central1 +instance: sdk-testing +ipType: public +database: inventory +user: postgres +password: TestPassword1@ diff --git a/skills/cloudsql-postgres/assets/execute_sql.yaml b/skills/cloudsql-postgres/assets/execute_sql.yaml new file mode 100644 index 0000000..1e08fb4 --- /dev/null +++ b/skills/cloudsql-postgres/assets/execute_sql.yaml @@ -0,0 +1,17 @@ +kind: tools +name: execute_sql +type: postgres-execute-sql +source: cloudsql-pg-source +description: Use this tool to execute sql. +authRequired: [] +--- +kind: sources +name: cloudsql-pg-source +type: cloud-sql-postgres +project: twisha-dev +region: us-central1 +instance: sdk-testing +ipType: public +database: inventory +user: postgres +password: TestPassword1@ diff --git a/skills/cloudsql-postgres/assets/get_column_cardinality.yaml b/skills/cloudsql-postgres/assets/get_column_cardinality.yaml new file mode 100644 index 0000000..7d0d296 --- /dev/null +++ b/skills/cloudsql-postgres/assets/get_column_cardinality.yaml @@ -0,0 +1,17 @@ +kind: tools +name: get_column_cardinality +type: postgres-get-column-cardinality +source: cloudsql-pg-source +description: "" +authRequired: [] +--- +kind: sources +name: cloudsql-pg-source +type: cloud-sql-postgres +project: twisha-dev +region: us-central1 +instance: sdk-testing +ipType: public +database: inventory +user: postgres +password: TestPassword1@ diff --git a/skills/cloudsql-postgres/assets/get_query_plan.yaml b/skills/cloudsql-postgres/assets/get_query_plan.yaml new file mode 100644 index 0000000..d05ce85 --- /dev/null +++ b/skills/cloudsql-postgres/assets/get_query_plan.yaml @@ -0,0 +1,33 @@ +kind: tools +name: get_query_plan +type: postgres-sql +source: cloudsql-pg-source +description: Generate a PostgreSQL EXPLAIN plan in JSON format for a single SQL statement—without executing it. This returns the optimizer's estimated plan, costs, and rows (no ANALYZE, no extra options). Use in production safely for plan inspection, regression checks, and query tuning workflows. +statement: | + EXPLAIN (FORMAT JSON) {{.query}}; +authRequired: [] +parameters: [] +templateParameters: +- name: query + type: string + description: The SQL statement for which you want to generate plan (omit the EXPLAIN keyword). + required: true + allowedValues: [] + excludedValues: [] + authServices: [] + authSources: [] + embeddedBy: "" + valueFromParam: "" + default: null + escape: null +--- +kind: sources +name: cloudsql-pg-source +type: cloud-sql-postgres +project: twisha-dev +region: us-central1 +instance: sdk-testing +ipType: public +database: inventory +user: postgres +password: TestPassword1@ diff --git a/skills/cloudsql-postgres/assets/list_active_queries.yaml b/skills/cloudsql-postgres/assets/list_active_queries.yaml new file mode 100644 index 0000000..477ea77 --- /dev/null +++ b/skills/cloudsql-postgres/assets/list_active_queries.yaml @@ -0,0 +1,17 @@ +kind: tools +name: list_active_queries +type: postgres-list-active-queries +source: cloudsql-pg-source +description: List the top N (default 50) currently running queries (state='active') from pg_stat_activity, ordered by longest-running first. Returns pid, user, database, application_name, client_addr, state, wait_event_type/wait_event, backend/xact/query start times, computed query_duration, and the SQL text. +authRequired: [] +--- +kind: sources +name: cloudsql-pg-source +type: cloud-sql-postgres +project: twisha-dev +region: us-central1 +instance: sdk-testing +ipType: public +database: inventory +user: postgres +password: TestPassword1@ diff --git a/skills/cloudsql-postgres/assets/list_autovacuum_configurations.yaml b/skills/cloudsql-postgres/assets/list_autovacuum_configurations.yaml new file mode 100644 index 0000000..7a6f600 --- /dev/null +++ b/skills/cloudsql-postgres/assets/list_autovacuum_configurations.yaml @@ -0,0 +1,24 @@ +kind: tools +name: list_autovacuum_configurations +type: postgres-sql +source: cloudsql-pg-source +description: List PostgreSQL autovacuum-related configurations (name and current setting) from pg_settings. +statement: | + SELECT name, + setting + FROM pg_settings + WHERE category = 'Autovacuum'; +authRequired: [] +parameters: [] +templateParameters: [] +--- +kind: sources +name: cloudsql-pg-source +type: cloud-sql-postgres +project: twisha-dev +region: us-central1 +instance: sdk-testing +ipType: public +database: inventory +user: postgres +password: TestPassword1@ diff --git a/skills/cloudsql-postgres/assets/list_available_extensions.yaml b/skills/cloudsql-postgres/assets/list_available_extensions.yaml new file mode 100644 index 0000000..04e5bc3 --- /dev/null +++ b/skills/cloudsql-postgres/assets/list_available_extensions.yaml @@ -0,0 +1,17 @@ +kind: tools +name: list_available_extensions +type: postgres-list-available-extensions +source: cloudsql-pg-source +description: Discover all PostgreSQL extensions available for installation on this server, returning name, default_version, and description. +authRequired: [] +--- +kind: sources +name: cloudsql-pg-source +type: cloud-sql-postgres +project: twisha-dev +region: us-central1 +instance: sdk-testing +ipType: public +database: inventory +user: postgres +password: TestPassword1@ diff --git a/skills/cloudsql-postgres/assets/list_database_stats.yaml b/skills/cloudsql-postgres/assets/list_database_stats.yaml new file mode 100644 index 0000000..a7538aa --- /dev/null +++ b/skills/cloudsql-postgres/assets/list_database_stats.yaml @@ -0,0 +1,17 @@ +kind: tools +name: list_database_stats +type: postgres-list-database-stats +source: cloudsql-pg-source +description: "" +authRequired: [] +--- +kind: sources +name: cloudsql-pg-source +type: cloud-sql-postgres +project: twisha-dev +region: us-central1 +instance: sdk-testing +ipType: public +database: inventory +user: postgres +password: TestPassword1@ diff --git a/skills/cloudsql-postgres/assets/list_indexes.yaml b/skills/cloudsql-postgres/assets/list_indexes.yaml new file mode 100644 index 0000000..2def17d --- /dev/null +++ b/skills/cloudsql-postgres/assets/list_indexes.yaml @@ -0,0 +1,17 @@ +kind: tools +name: list_indexes +type: postgres-list-indexes +source: cloudsql-pg-source +description: "" +authRequired: [] +--- +kind: sources +name: cloudsql-pg-source +type: cloud-sql-postgres +project: twisha-dev +region: us-central1 +instance: sdk-testing +ipType: public +database: inventory +user: postgres +password: TestPassword1@ diff --git a/skills/cloudsql-postgres/assets/list_installed_extensions.yaml b/skills/cloudsql-postgres/assets/list_installed_extensions.yaml new file mode 100644 index 0000000..e846819 --- /dev/null +++ b/skills/cloudsql-postgres/assets/list_installed_extensions.yaml @@ -0,0 +1,17 @@ +kind: tools +name: list_installed_extensions +type: postgres-list-installed-extensions +source: cloudsql-pg-source +description: List all installed PostgreSQL extensions with their name, version, schema, owner, and description. +authRequired: [] +--- +kind: sources +name: cloudsql-pg-source +type: cloud-sql-postgres +project: twisha-dev +region: us-central1 +instance: sdk-testing +ipType: public +database: inventory +user: postgres +password: TestPassword1@ diff --git a/skills/cloudsql-postgres/assets/list_invalid_indexes.yaml b/skills/cloudsql-postgres/assets/list_invalid_indexes.yaml new file mode 100644 index 0000000..59258f6 --- /dev/null +++ b/skills/cloudsql-postgres/assets/list_invalid_indexes.yaml @@ -0,0 +1,32 @@ +kind: tools +name: list_invalid_indexes +type: postgres-sql +source: cloudsql-pg-source +description: Lists all invalid PostgreSQL indexes which are taking up disk space but are unusable by the query planner. Typically created by failed CREATE INDEX CONCURRENTLY operations. +statement: | + SELECT + nspname AS schema_name, + indexrelid::regclass AS index_name, + indrelid::regclass AS table_name, + pg_size_pretty(pg_total_relation_size(indexrelid)) AS index_size, + indisready, + indisvalid, + pg_get_indexdef(pg_class.oid) AS index_def + FROM pg_index + JOIN pg_class ON pg_class.oid = pg_index.indexrelid + JOIN pg_namespace ON pg_namespace.oid = pg_class.relnamespace + WHERE indisvalid = FALSE; +authRequired: [] +parameters: [] +templateParameters: [] +--- +kind: sources +name: cloudsql-pg-source +type: cloud-sql-postgres +project: twisha-dev +region: us-central1 +instance: sdk-testing +ipType: public +database: inventory +user: postgres +password: TestPassword1@ diff --git a/skills/cloudsql-postgres/assets/list_locks.yaml b/skills/cloudsql-postgres/assets/list_locks.yaml new file mode 100644 index 0000000..392160c --- /dev/null +++ b/skills/cloudsql-postgres/assets/list_locks.yaml @@ -0,0 +1,17 @@ +kind: tools +name: list_locks +type: postgres-list-locks +source: cloudsql-pg-source +description: Identifies all locks held by active processes showing the process ID, user, query text, and an aggregated list of all transactions and specific locks (relation, mode, grant status) associated with each process. +authRequired: [] +--- +kind: sources +name: cloudsql-pg-source +type: cloud-sql-postgres +project: twisha-dev +region: us-central1 +instance: sdk-testing +ipType: public +database: inventory +user: postgres +password: TestPassword1@ diff --git a/skills/cloudsql-postgres/assets/list_memory_configurations.yaml b/skills/cloudsql-postgres/assets/list_memory_configurations.yaml new file mode 100644 index 0000000..300896e --- /dev/null +++ b/skills/cloudsql-postgres/assets/list_memory_configurations.yaml @@ -0,0 +1,36 @@ +kind: tools +name: list_memory_configurations +type: postgres-sql +source: cloudsql-pg-source +description: List PostgreSQL memory-related configurations (name and current setting) from pg_settings. +statement: | + ( + SELECT + name, + pg_size_pretty((setting::bigint * 1024)::bigint) setting + FROM pg_settings + WHERE name IN ('work_mem', 'maintenance_work_mem') + ) + UNION ALL + ( + SELECT + name, + pg_size_pretty((((setting::bigint) * 8) * 1024)::bigint) + FROM pg_settings + WHERE name IN ('shared_buffers', 'wal_buffers', 'effective_cache_size', 'temp_buffers') + ) + ORDER BY 1 DESC; +authRequired: [] +parameters: [] +templateParameters: [] +--- +kind: sources +name: cloudsql-pg-source +type: cloud-sql-postgres +project: twisha-dev +region: us-central1 +instance: sdk-testing +ipType: public +database: inventory +user: postgres +password: TestPassword1@ diff --git a/skills/cloudsql-postgres/assets/list_pg_settings.yaml b/skills/cloudsql-postgres/assets/list_pg_settings.yaml new file mode 100644 index 0000000..393e919 --- /dev/null +++ b/skills/cloudsql-postgres/assets/list_pg_settings.yaml @@ -0,0 +1,17 @@ +kind: tools +name: list_pg_settings +type: postgres-list-pg-settings +source: cloudsql-pg-source +description: "" +authRequired: [] +--- +kind: sources +name: cloudsql-pg-source +type: cloud-sql-postgres +project: twisha-dev +region: us-central1 +instance: sdk-testing +ipType: public +database: inventory +user: postgres +password: TestPassword1@ diff --git a/skills/cloudsql-postgres/assets/list_publication_tables.yaml b/skills/cloudsql-postgres/assets/list_publication_tables.yaml new file mode 100644 index 0000000..1ece397 --- /dev/null +++ b/skills/cloudsql-postgres/assets/list_publication_tables.yaml @@ -0,0 +1,17 @@ +kind: tools +name: list_publication_tables +type: postgres-list-publication-tables +source: cloudsql-pg-source +description: "" +authRequired: [] +--- +kind: sources +name: cloudsql-pg-source +type: cloud-sql-postgres +project: twisha-dev +region: us-central1 +instance: sdk-testing +ipType: public +database: inventory +user: postgres +password: TestPassword1@ diff --git a/skills/cloudsql-postgres/assets/list_query_stats.yaml b/skills/cloudsql-postgres/assets/list_query_stats.yaml new file mode 100644 index 0000000..19731c5 --- /dev/null +++ b/skills/cloudsql-postgres/assets/list_query_stats.yaml @@ -0,0 +1,17 @@ +kind: tools +name: list_query_stats +type: postgres-list-query-stats +source: cloudsql-pg-source +description: "" +authRequired: [] +--- +kind: sources +name: cloudsql-pg-source +type: cloud-sql-postgres +project: twisha-dev +region: us-central1 +instance: sdk-testing +ipType: public +database: inventory +user: postgres +password: TestPassword1@ diff --git a/skills/cloudsql-postgres/assets/list_replication_slots.yaml b/skills/cloudsql-postgres/assets/list_replication_slots.yaml new file mode 100644 index 0000000..6f17911 --- /dev/null +++ b/skills/cloudsql-postgres/assets/list_replication_slots.yaml @@ -0,0 +1,33 @@ +kind: tools +name: list_replication_slots +type: postgres-sql +source: cloudsql-pg-source +description: List key details for all PostgreSQL replication slots (e.g., type, database, active status) and calculates the size of the outstanding WAL that is being prevented from removal by the slot. +statement: | + SELECT + slot_name, + slot_type, + plugin, + database, + temporary, + active, + restart_lsn, + confirmed_flush_lsn, + xmin, + catalog_xmin, + pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn)) AS retained_wal + FROM pg_replication_slots; +authRequired: [] +parameters: [] +templateParameters: [] +--- +kind: sources +name: cloudsql-pg-source +type: cloud-sql-postgres +project: twisha-dev +region: us-central1 +instance: sdk-testing +ipType: public +database: inventory +user: postgres +password: TestPassword1@ diff --git a/skills/cloudsql-postgres/assets/list_roles.yaml b/skills/cloudsql-postgres/assets/list_roles.yaml new file mode 100644 index 0000000..1ae80db --- /dev/null +++ b/skills/cloudsql-postgres/assets/list_roles.yaml @@ -0,0 +1,17 @@ +kind: tools +name: list_roles +type: postgres-list-roles +source: cloudsql-pg-source +description: "" +authRequired: [] +--- +kind: sources +name: cloudsql-pg-source +type: cloud-sql-postgres +project: twisha-dev +region: us-central1 +instance: sdk-testing +ipType: public +database: inventory +user: postgres +password: TestPassword1@ diff --git a/skills/cloudsql-postgres/assets/list_schemas.yaml b/skills/cloudsql-postgres/assets/list_schemas.yaml new file mode 100644 index 0000000..2012553 --- /dev/null +++ b/skills/cloudsql-postgres/assets/list_schemas.yaml @@ -0,0 +1,17 @@ +kind: tools +name: list_schemas +type: postgres-list-schemas +source: cloudsql-pg-source +description: "" +authRequired: [] +--- +kind: sources +name: cloudsql-pg-source +type: cloud-sql-postgres +project: twisha-dev +region: us-central1 +instance: sdk-testing +ipType: public +database: inventory +user: postgres +password: TestPassword1@ diff --git a/skills/cloudsql-postgres/assets/list_sequences.yaml b/skills/cloudsql-postgres/assets/list_sequences.yaml new file mode 100644 index 0000000..6c7077c --- /dev/null +++ b/skills/cloudsql-postgres/assets/list_sequences.yaml @@ -0,0 +1,17 @@ +kind: tools +name: list_sequences +type: postgres-list-sequences +source: cloudsql-pg-source +description: "" +authRequired: [] +--- +kind: sources +name: cloudsql-pg-source +type: cloud-sql-postgres +project: twisha-dev +region: us-central1 +instance: sdk-testing +ipType: public +database: inventory +user: postgres +password: TestPassword1@ diff --git a/skills/cloudsql-postgres/assets/list_stored_procedure.yaml b/skills/cloudsql-postgres/assets/list_stored_procedure.yaml new file mode 100644 index 0000000..b92efc3 --- /dev/null +++ b/skills/cloudsql-postgres/assets/list_stored_procedure.yaml @@ -0,0 +1,17 @@ +kind: tools +name: list_stored_procedure +type: postgres-list-stored-procedure +source: cloudsql-pg-source +description: "" +authRequired: [] +--- +kind: sources +name: cloudsql-pg-source +type: cloud-sql-postgres +project: twisha-dev +region: us-central1 +instance: sdk-testing +ipType: public +database: inventory +user: postgres +password: TestPassword1@ diff --git a/skills/cloudsql-postgres/assets/list_table_stats.yaml b/skills/cloudsql-postgres/assets/list_table_stats.yaml new file mode 100644 index 0000000..31cd635 --- /dev/null +++ b/skills/cloudsql-postgres/assets/list_table_stats.yaml @@ -0,0 +1,17 @@ +kind: tools +name: list_table_stats +type: postgres-list-table-stats +source: cloudsql-pg-source +description: "" +authRequired: [] +--- +kind: sources +name: cloudsql-pg-source +type: cloud-sql-postgres +project: twisha-dev +region: us-central1 +instance: sdk-testing +ipType: public +database: inventory +user: postgres +password: TestPassword1@ diff --git a/skills/cloudsql-postgres/assets/list_tables.yaml b/skills/cloudsql-postgres/assets/list_tables.yaml new file mode 100644 index 0000000..6772d6b --- /dev/null +++ b/skills/cloudsql-postgres/assets/list_tables.yaml @@ -0,0 +1,17 @@ +kind: tools +name: list_tables +type: postgres-list-tables +source: cloudsql-pg-source +description: Lists detailed schema information (object type, columns, constraints, indexes, triggers, owner, comment) as JSON for user-created tables (ordinary or partitioned). Filters by a comma-separated list of names. If names are omitted, lists all tables in user schemas. +authRequired: [] +--- +kind: sources +name: cloudsql-pg-source +type: cloud-sql-postgres +project: twisha-dev +region: us-central1 +instance: sdk-testing +ipType: public +database: inventory +user: postgres +password: TestPassword1@ diff --git a/skills/cloudsql-postgres/assets/list_tablespaces.yaml b/skills/cloudsql-postgres/assets/list_tablespaces.yaml new file mode 100644 index 0000000..5c3d5cf --- /dev/null +++ b/skills/cloudsql-postgres/assets/list_tablespaces.yaml @@ -0,0 +1,17 @@ +kind: tools +name: list_tablespaces +type: postgres-list-tablespaces +source: cloudsql-pg-source +description: "" +authRequired: [] +--- +kind: sources +name: cloudsql-pg-source +type: cloud-sql-postgres +project: twisha-dev +region: us-central1 +instance: sdk-testing +ipType: public +database: inventory +user: postgres +password: TestPassword1@ diff --git a/skills/cloudsql-postgres/assets/list_top_bloated_tables.yaml b/skills/cloudsql-postgres/assets/list_top_bloated_tables.yaml new file mode 100644 index 0000000..208e351 --- /dev/null +++ b/skills/cloudsql-postgres/assets/list_top_bloated_tables.yaml @@ -0,0 +1,47 @@ +kind: tools +name: list_top_bloated_tables +type: postgres-sql +source: cloudsql-pg-source +description: | + List the top tables by dead-tuple (approximate bloat signal), returning schema, table, live/dead tuples, percentage, and last vacuum/analyze times. +statement: | + SELECT + schemaname AS schema_name, + relname AS relation_name, + n_live_tup AS live_tuples, + n_dead_tup AS dead_tuples, + TRUNC((n_dead_tup::NUMERIC / NULLIF(n_live_tup + n_dead_tup, 0)) * 100, 2) AS dead_tuple_percentage, + last_vacuum, + last_autovacuum, + last_analyze, + last_autoanalyze + FROM pg_stat_user_tables + ORDER BY n_dead_tup DESC + LIMIT COALESCE($1::int, 50); +authRequired: [] +parameters: +- name: limit + type: integer + description: The maximum number of results to return. + required: null + allowedValues: [] + excludedValues: [] + authServices: [] + authSources: [] + embeddedBy: "" + valueFromParam: "" + default: 50 + minValue: null + maxValue: null +templateParameters: [] +--- +kind: sources +name: cloudsql-pg-source +type: cloud-sql-postgres +project: twisha-dev +region: us-central1 +instance: sdk-testing +ipType: public +database: inventory +user: postgres +password: TestPassword1@ diff --git a/skills/cloudsql-postgres/assets/list_triggers.yaml b/skills/cloudsql-postgres/assets/list_triggers.yaml new file mode 100644 index 0000000..14bb61a --- /dev/null +++ b/skills/cloudsql-postgres/assets/list_triggers.yaml @@ -0,0 +1,17 @@ +kind: tools +name: list_triggers +type: postgres-list-triggers +source: cloudsql-pg-source +description: "" +authRequired: [] +--- +kind: sources +name: cloudsql-pg-source +type: cloud-sql-postgres +project: twisha-dev +region: us-central1 +instance: sdk-testing +ipType: public +database: inventory +user: postgres +password: TestPassword1@ diff --git a/skills/cloudsql-postgres/assets/list_views.yaml b/skills/cloudsql-postgres/assets/list_views.yaml new file mode 100644 index 0000000..c1e8a93 --- /dev/null +++ b/skills/cloudsql-postgres/assets/list_views.yaml @@ -0,0 +1,17 @@ +kind: tools +name: list_views +type: postgres-list-views +source: cloudsql-pg-source +description: "" +authRequired: [] +--- +kind: sources +name: cloudsql-pg-source +type: cloud-sql-postgres +project: twisha-dev +region: us-central1 +instance: sdk-testing +ipType: public +database: inventory +user: postgres +password: TestPassword1@ diff --git a/skills/cloudsql-postgres/assets/long_running_transactions.yaml b/skills/cloudsql-postgres/assets/long_running_transactions.yaml new file mode 100644 index 0000000..9f8b430 --- /dev/null +++ b/skills/cloudsql-postgres/assets/long_running_transactions.yaml @@ -0,0 +1,17 @@ +kind: tools +name: long_running_transactions +type: postgres-long-running-transactions +source: cloudsql-pg-source +description: Identifies and lists database transactions that exceed a specified time limit. For each of the long running transactions, the output contains the process id, database name, user name, application name, client address, state, connection age, transaction age, query age, last activity age, wait event type, wait event, and query string. +authRequired: [] +--- +kind: sources +name: cloudsql-pg-source +type: cloud-sql-postgres +project: twisha-dev +region: us-central1 +instance: sdk-testing +ipType: public +database: inventory +user: postgres +password: TestPassword1@ diff --git a/skills/cloudsql-postgres/assets/replication_stats.yaml b/skills/cloudsql-postgres/assets/replication_stats.yaml new file mode 100644 index 0000000..222d745 --- /dev/null +++ b/skills/cloudsql-postgres/assets/replication_stats.yaml @@ -0,0 +1,17 @@ +kind: tools +name: replication_stats +type: postgres-replication-stats +source: cloudsql-pg-source +description: Lists each replica's process ID, user name, application name, backend_xmin (standby's xmin horizon reported by hot_standby_feedback), client IP address, connection state, and sync_state, along with lag sizes in bytes for sent_lag (primary to sent), write_lag (sent to written), flush_lag (written to flushed), replay_lag (flushed to replayed), and the overall total_lag (primary to replayed). +authRequired: [] +--- +kind: sources +name: cloudsql-pg-source +type: cloud-sql-postgres +project: twisha-dev +region: us-central1 +instance: sdk-testing +ipType: public +database: inventory +user: postgres +password: TestPassword1@ diff --git a/skills/cloudsql-postgres/scripts/database_overview.js b/skills/cloudsql-postgres/scripts/database_overview.js new file mode 100755 index 0000000..60b9d79 --- /dev/null +++ b/skills/cloudsql-postgres/scripts/database_overview.js @@ -0,0 +1,52 @@ +#!/usr/bin/env node + +const { spawn, execSync } = require('child_process'); +const path = require('path'); +const fs = require('fs'); + +const toolName = "database_overview"; +const toolsFileName = "database_overview.yaml"; + +function getToolboxPath() { + try { + const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox'; + const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim(); + if (globalPath) { + return globalPath.split('\n')[0].trim(); + } + } catch (e) { + // Ignore error; + } + const localPath = path.resolve(__dirname, '../../../toolbox'); + if (fs.existsSync(localPath)) { + return localPath; + } + throw new Error("Toolbox binary not found"); +} + +let toolboxBinary; +try { + toolboxBinary = getToolboxPath(); +} catch (err) { + console.error("Error:", err.message); + process.exit(1); +} + +let configArgs = []; +if (toolsFileName) { + configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName)); +} + +const args = process.argv.slice(2); +const toolboxArgs = [...configArgs, "invoke", toolName, ...args]; + +const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' }); + +child.on('close', (code) => { + process.exit(code); +}); + +child.on('error', (err) => { + console.error("Error executing toolbox:", err); + process.exit(1); +}); diff --git a/skills/cloudsql-postgres/scripts/execute_sql.js b/skills/cloudsql-postgres/scripts/execute_sql.js new file mode 100755 index 0000000..0bf899a --- /dev/null +++ b/skills/cloudsql-postgres/scripts/execute_sql.js @@ -0,0 +1,52 @@ +#!/usr/bin/env node + +const { spawn, execSync } = require('child_process'); +const path = require('path'); +const fs = require('fs'); + +const toolName = "execute_sql"; +const toolsFileName = "execute_sql.yaml"; + +function getToolboxPath() { + try { + const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox'; + const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim(); + if (globalPath) { + return globalPath.split('\n')[0].trim(); + } + } catch (e) { + // Ignore error; + } + const localPath = path.resolve(__dirname, '../../../toolbox'); + if (fs.existsSync(localPath)) { + return localPath; + } + throw new Error("Toolbox binary not found"); +} + +let toolboxBinary; +try { + toolboxBinary = getToolboxPath(); +} catch (err) { + console.error("Error:", err.message); + process.exit(1); +} + +let configArgs = []; +if (toolsFileName) { + configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName)); +} + +const args = process.argv.slice(2); +const toolboxArgs = [...configArgs, "invoke", toolName, ...args]; + +const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' }); + +child.on('close', (code) => { + process.exit(code); +}); + +child.on('error', (err) => { + console.error("Error executing toolbox:", err); + process.exit(1); +}); diff --git a/skills/cloudsql-postgres/scripts/get_column_cardinality.js b/skills/cloudsql-postgres/scripts/get_column_cardinality.js new file mode 100755 index 0000000..5e4e711 --- /dev/null +++ b/skills/cloudsql-postgres/scripts/get_column_cardinality.js @@ -0,0 +1,52 @@ +#!/usr/bin/env node + +const { spawn, execSync } = require('child_process'); +const path = require('path'); +const fs = require('fs'); + +const toolName = "get_column_cardinality"; +const toolsFileName = "get_column_cardinality.yaml"; + +function getToolboxPath() { + try { + const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox'; + const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim(); + if (globalPath) { + return globalPath.split('\n')[0].trim(); + } + } catch (e) { + // Ignore error; + } + const localPath = path.resolve(__dirname, '../../../toolbox'); + if (fs.existsSync(localPath)) { + return localPath; + } + throw new Error("Toolbox binary not found"); +} + +let toolboxBinary; +try { + toolboxBinary = getToolboxPath(); +} catch (err) { + console.error("Error:", err.message); + process.exit(1); +} + +let configArgs = []; +if (toolsFileName) { + configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName)); +} + +const args = process.argv.slice(2); +const toolboxArgs = [...configArgs, "invoke", toolName, ...args]; + +const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' }); + +child.on('close', (code) => { + process.exit(code); +}); + +child.on('error', (err) => { + console.error("Error executing toolbox:", err); + process.exit(1); +}); diff --git a/skills/cloudsql-postgres/scripts/get_query_plan.js b/skills/cloudsql-postgres/scripts/get_query_plan.js new file mode 100755 index 0000000..4504c2b --- /dev/null +++ b/skills/cloudsql-postgres/scripts/get_query_plan.js @@ -0,0 +1,52 @@ +#!/usr/bin/env node + +const { spawn, execSync } = require('child_process'); +const path = require('path'); +const fs = require('fs'); + +const toolName = "get_query_plan"; +const toolsFileName = "get_query_plan.yaml"; + +function getToolboxPath() { + try { + const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox'; + const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim(); + if (globalPath) { + return globalPath.split('\n')[0].trim(); + } + } catch (e) { + // Ignore error; + } + const localPath = path.resolve(__dirname, '../../../toolbox'); + if (fs.existsSync(localPath)) { + return localPath; + } + throw new Error("Toolbox binary not found"); +} + +let toolboxBinary; +try { + toolboxBinary = getToolboxPath(); +} catch (err) { + console.error("Error:", err.message); + process.exit(1); +} + +let configArgs = []; +if (toolsFileName) { + configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName)); +} + +const args = process.argv.slice(2); +const toolboxArgs = [...configArgs, "invoke", toolName, ...args]; + +const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' }); + +child.on('close', (code) => { + process.exit(code); +}); + +child.on('error', (err) => { + console.error("Error executing toolbox:", err); + process.exit(1); +}); diff --git a/skills/cloudsql-postgres/scripts/list_active_queries.js b/skills/cloudsql-postgres/scripts/list_active_queries.js new file mode 100755 index 0000000..5f4a26b --- /dev/null +++ b/skills/cloudsql-postgres/scripts/list_active_queries.js @@ -0,0 +1,52 @@ +#!/usr/bin/env node + +const { spawn, execSync } = require('child_process'); +const path = require('path'); +const fs = require('fs'); + +const toolName = "list_active_queries"; +const toolsFileName = "list_active_queries.yaml"; + +function getToolboxPath() { + try { + const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox'; + const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim(); + if (globalPath) { + return globalPath.split('\n')[0].trim(); + } + } catch (e) { + // Ignore error; + } + const localPath = path.resolve(__dirname, '../../../toolbox'); + if (fs.existsSync(localPath)) { + return localPath; + } + throw new Error("Toolbox binary not found"); +} + +let toolboxBinary; +try { + toolboxBinary = getToolboxPath(); +} catch (err) { + console.error("Error:", err.message); + process.exit(1); +} + +let configArgs = []; +if (toolsFileName) { + configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName)); +} + +const args = process.argv.slice(2); +const toolboxArgs = [...configArgs, "invoke", toolName, ...args]; + +const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' }); + +child.on('close', (code) => { + process.exit(code); +}); + +child.on('error', (err) => { + console.error("Error executing toolbox:", err); + process.exit(1); +}); diff --git a/skills/cloudsql-postgres/scripts/list_autovacuum_configurations.js b/skills/cloudsql-postgres/scripts/list_autovacuum_configurations.js new file mode 100755 index 0000000..33c8c0f --- /dev/null +++ b/skills/cloudsql-postgres/scripts/list_autovacuum_configurations.js @@ -0,0 +1,52 @@ +#!/usr/bin/env node + +const { spawn, execSync } = require('child_process'); +const path = require('path'); +const fs = require('fs'); + +const toolName = "list_autovacuum_configurations"; +const toolsFileName = "list_autovacuum_configurations.yaml"; + +function getToolboxPath() { + try { + const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox'; + const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim(); + if (globalPath) { + return globalPath.split('\n')[0].trim(); + } + } catch (e) { + // Ignore error; + } + const localPath = path.resolve(__dirname, '../../../toolbox'); + if (fs.existsSync(localPath)) { + return localPath; + } + throw new Error("Toolbox binary not found"); +} + +let toolboxBinary; +try { + toolboxBinary = getToolboxPath(); +} catch (err) { + console.error("Error:", err.message); + process.exit(1); +} + +let configArgs = []; +if (toolsFileName) { + configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName)); +} + +const args = process.argv.slice(2); +const toolboxArgs = [...configArgs, "invoke", toolName, ...args]; + +const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' }); + +child.on('close', (code) => { + process.exit(code); +}); + +child.on('error', (err) => { + console.error("Error executing toolbox:", err); + process.exit(1); +}); diff --git a/skills/cloudsql-postgres/scripts/list_available_extensions.js b/skills/cloudsql-postgres/scripts/list_available_extensions.js new file mode 100755 index 0000000..3bc3726 --- /dev/null +++ b/skills/cloudsql-postgres/scripts/list_available_extensions.js @@ -0,0 +1,52 @@ +#!/usr/bin/env node + +const { spawn, execSync } = require('child_process'); +const path = require('path'); +const fs = require('fs'); + +const toolName = "list_available_extensions"; +const toolsFileName = "list_available_extensions.yaml"; + +function getToolboxPath() { + try { + const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox'; + const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim(); + if (globalPath) { + return globalPath.split('\n')[0].trim(); + } + } catch (e) { + // Ignore error; + } + const localPath = path.resolve(__dirname, '../../../toolbox'); + if (fs.existsSync(localPath)) { + return localPath; + } + throw new Error("Toolbox binary not found"); +} + +let toolboxBinary; +try { + toolboxBinary = getToolboxPath(); +} catch (err) { + console.error("Error:", err.message); + process.exit(1); +} + +let configArgs = []; +if (toolsFileName) { + configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName)); +} + +const args = process.argv.slice(2); +const toolboxArgs = [...configArgs, "invoke", toolName, ...args]; + +const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' }); + +child.on('close', (code) => { + process.exit(code); +}); + +child.on('error', (err) => { + console.error("Error executing toolbox:", err); + process.exit(1); +}); diff --git a/skills/cloudsql-postgres/scripts/list_database_stats.js b/skills/cloudsql-postgres/scripts/list_database_stats.js new file mode 100755 index 0000000..37e0f08 --- /dev/null +++ b/skills/cloudsql-postgres/scripts/list_database_stats.js @@ -0,0 +1,52 @@ +#!/usr/bin/env node + +const { spawn, execSync } = require('child_process'); +const path = require('path'); +const fs = require('fs'); + +const toolName = "list_database_stats"; +const toolsFileName = "list_database_stats.yaml"; + +function getToolboxPath() { + try { + const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox'; + const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim(); + if (globalPath) { + return globalPath.split('\n')[0].trim(); + } + } catch (e) { + // Ignore error; + } + const localPath = path.resolve(__dirname, '../../../toolbox'); + if (fs.existsSync(localPath)) { + return localPath; + } + throw new Error("Toolbox binary not found"); +} + +let toolboxBinary; +try { + toolboxBinary = getToolboxPath(); +} catch (err) { + console.error("Error:", err.message); + process.exit(1); +} + +let configArgs = []; +if (toolsFileName) { + configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName)); +} + +const args = process.argv.slice(2); +const toolboxArgs = [...configArgs, "invoke", toolName, ...args]; + +const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' }); + +child.on('close', (code) => { + process.exit(code); +}); + +child.on('error', (err) => { + console.error("Error executing toolbox:", err); + process.exit(1); +}); diff --git a/skills/cloudsql-postgres/scripts/list_indexes.js b/skills/cloudsql-postgres/scripts/list_indexes.js new file mode 100755 index 0000000..5b8eac1 --- /dev/null +++ b/skills/cloudsql-postgres/scripts/list_indexes.js @@ -0,0 +1,52 @@ +#!/usr/bin/env node + +const { spawn, execSync } = require('child_process'); +const path = require('path'); +const fs = require('fs'); + +const toolName = "list_indexes"; +const toolsFileName = "list_indexes.yaml"; + +function getToolboxPath() { + try { + const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox'; + const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim(); + if (globalPath) { + return globalPath.split('\n')[0].trim(); + } + } catch (e) { + // Ignore error; + } + const localPath = path.resolve(__dirname, '../../../toolbox'); + if (fs.existsSync(localPath)) { + return localPath; + } + throw new Error("Toolbox binary not found"); +} + +let toolboxBinary; +try { + toolboxBinary = getToolboxPath(); +} catch (err) { + console.error("Error:", err.message); + process.exit(1); +} + +let configArgs = []; +if (toolsFileName) { + configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName)); +} + +const args = process.argv.slice(2); +const toolboxArgs = [...configArgs, "invoke", toolName, ...args]; + +const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' }); + +child.on('close', (code) => { + process.exit(code); +}); + +child.on('error', (err) => { + console.error("Error executing toolbox:", err); + process.exit(1); +}); diff --git a/skills/cloudsql-postgres/scripts/list_installed_extensions.js b/skills/cloudsql-postgres/scripts/list_installed_extensions.js new file mode 100755 index 0000000..694e9cb --- /dev/null +++ b/skills/cloudsql-postgres/scripts/list_installed_extensions.js @@ -0,0 +1,52 @@ +#!/usr/bin/env node + +const { spawn, execSync } = require('child_process'); +const path = require('path'); +const fs = require('fs'); + +const toolName = "list_installed_extensions"; +const toolsFileName = "list_installed_extensions.yaml"; + +function getToolboxPath() { + try { + const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox'; + const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim(); + if (globalPath) { + return globalPath.split('\n')[0].trim(); + } + } catch (e) { + // Ignore error; + } + const localPath = path.resolve(__dirname, '../../../toolbox'); + if (fs.existsSync(localPath)) { + return localPath; + } + throw new Error("Toolbox binary not found"); +} + +let toolboxBinary; +try { + toolboxBinary = getToolboxPath(); +} catch (err) { + console.error("Error:", err.message); + process.exit(1); +} + +let configArgs = []; +if (toolsFileName) { + configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName)); +} + +const args = process.argv.slice(2); +const toolboxArgs = [...configArgs, "invoke", toolName, ...args]; + +const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' }); + +child.on('close', (code) => { + process.exit(code); +}); + +child.on('error', (err) => { + console.error("Error executing toolbox:", err); + process.exit(1); +}); diff --git a/skills/cloudsql-postgres/scripts/list_invalid_indexes.js b/skills/cloudsql-postgres/scripts/list_invalid_indexes.js new file mode 100755 index 0000000..18ed057 --- /dev/null +++ b/skills/cloudsql-postgres/scripts/list_invalid_indexes.js @@ -0,0 +1,52 @@ +#!/usr/bin/env node + +const { spawn, execSync } = require('child_process'); +const path = require('path'); +const fs = require('fs'); + +const toolName = "list_invalid_indexes"; +const toolsFileName = "list_invalid_indexes.yaml"; + +function getToolboxPath() { + try { + const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox'; + const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim(); + if (globalPath) { + return globalPath.split('\n')[0].trim(); + } + } catch (e) { + // Ignore error; + } + const localPath = path.resolve(__dirname, '../../../toolbox'); + if (fs.existsSync(localPath)) { + return localPath; + } + throw new Error("Toolbox binary not found"); +} + +let toolboxBinary; +try { + toolboxBinary = getToolboxPath(); +} catch (err) { + console.error("Error:", err.message); + process.exit(1); +} + +let configArgs = []; +if (toolsFileName) { + configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName)); +} + +const args = process.argv.slice(2); +const toolboxArgs = [...configArgs, "invoke", toolName, ...args]; + +const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' }); + +child.on('close', (code) => { + process.exit(code); +}); + +child.on('error', (err) => { + console.error("Error executing toolbox:", err); + process.exit(1); +}); diff --git a/skills/cloudsql-postgres/scripts/list_locks.js b/skills/cloudsql-postgres/scripts/list_locks.js new file mode 100755 index 0000000..bc65ceb --- /dev/null +++ b/skills/cloudsql-postgres/scripts/list_locks.js @@ -0,0 +1,52 @@ +#!/usr/bin/env node + +const { spawn, execSync } = require('child_process'); +const path = require('path'); +const fs = require('fs'); + +const toolName = "list_locks"; +const toolsFileName = "list_locks.yaml"; + +function getToolboxPath() { + try { + const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox'; + const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim(); + if (globalPath) { + return globalPath.split('\n')[0].trim(); + } + } catch (e) { + // Ignore error; + } + const localPath = path.resolve(__dirname, '../../../toolbox'); + if (fs.existsSync(localPath)) { + return localPath; + } + throw new Error("Toolbox binary not found"); +} + +let toolboxBinary; +try { + toolboxBinary = getToolboxPath(); +} catch (err) { + console.error("Error:", err.message); + process.exit(1); +} + +let configArgs = []; +if (toolsFileName) { + configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName)); +} + +const args = process.argv.slice(2); +const toolboxArgs = [...configArgs, "invoke", toolName, ...args]; + +const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' }); + +child.on('close', (code) => { + process.exit(code); +}); + +child.on('error', (err) => { + console.error("Error executing toolbox:", err); + process.exit(1); +}); diff --git a/skills/cloudsql-postgres/scripts/list_memory_configurations.js b/skills/cloudsql-postgres/scripts/list_memory_configurations.js new file mode 100755 index 0000000..8d00221 --- /dev/null +++ b/skills/cloudsql-postgres/scripts/list_memory_configurations.js @@ -0,0 +1,52 @@ +#!/usr/bin/env node + +const { spawn, execSync } = require('child_process'); +const path = require('path'); +const fs = require('fs'); + +const toolName = "list_memory_configurations"; +const toolsFileName = "list_memory_configurations.yaml"; + +function getToolboxPath() { + try { + const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox'; + const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim(); + if (globalPath) { + return globalPath.split('\n')[0].trim(); + } + } catch (e) { + // Ignore error; + } + const localPath = path.resolve(__dirname, '../../../toolbox'); + if (fs.existsSync(localPath)) { + return localPath; + } + throw new Error("Toolbox binary not found"); +} + +let toolboxBinary; +try { + toolboxBinary = getToolboxPath(); +} catch (err) { + console.error("Error:", err.message); + process.exit(1); +} + +let configArgs = []; +if (toolsFileName) { + configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName)); +} + +const args = process.argv.slice(2); +const toolboxArgs = [...configArgs, "invoke", toolName, ...args]; + +const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' }); + +child.on('close', (code) => { + process.exit(code); +}); + +child.on('error', (err) => { + console.error("Error executing toolbox:", err); + process.exit(1); +}); diff --git a/skills/cloudsql-postgres/scripts/list_pg_settings.js b/skills/cloudsql-postgres/scripts/list_pg_settings.js new file mode 100755 index 0000000..b171c68 --- /dev/null +++ b/skills/cloudsql-postgres/scripts/list_pg_settings.js @@ -0,0 +1,52 @@ +#!/usr/bin/env node + +const { spawn, execSync } = require('child_process'); +const path = require('path'); +const fs = require('fs'); + +const toolName = "list_pg_settings"; +const toolsFileName = "list_pg_settings.yaml"; + +function getToolboxPath() { + try { + const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox'; + const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim(); + if (globalPath) { + return globalPath.split('\n')[0].trim(); + } + } catch (e) { + // Ignore error; + } + const localPath = path.resolve(__dirname, '../../../toolbox'); + if (fs.existsSync(localPath)) { + return localPath; + } + throw new Error("Toolbox binary not found"); +} + +let toolboxBinary; +try { + toolboxBinary = getToolboxPath(); +} catch (err) { + console.error("Error:", err.message); + process.exit(1); +} + +let configArgs = []; +if (toolsFileName) { + configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName)); +} + +const args = process.argv.slice(2); +const toolboxArgs = [...configArgs, "invoke", toolName, ...args]; + +const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' }); + +child.on('close', (code) => { + process.exit(code); +}); + +child.on('error', (err) => { + console.error("Error executing toolbox:", err); + process.exit(1); +}); diff --git a/skills/cloudsql-postgres/scripts/list_publication_tables.js b/skills/cloudsql-postgres/scripts/list_publication_tables.js new file mode 100755 index 0000000..271c0ce --- /dev/null +++ b/skills/cloudsql-postgres/scripts/list_publication_tables.js @@ -0,0 +1,52 @@ +#!/usr/bin/env node + +const { spawn, execSync } = require('child_process'); +const path = require('path'); +const fs = require('fs'); + +const toolName = "list_publication_tables"; +const toolsFileName = "list_publication_tables.yaml"; + +function getToolboxPath() { + try { + const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox'; + const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim(); + if (globalPath) { + return globalPath.split('\n')[0].trim(); + } + } catch (e) { + // Ignore error; + } + const localPath = path.resolve(__dirname, '../../../toolbox'); + if (fs.existsSync(localPath)) { + return localPath; + } + throw new Error("Toolbox binary not found"); +} + +let toolboxBinary; +try { + toolboxBinary = getToolboxPath(); +} catch (err) { + console.error("Error:", err.message); + process.exit(1); +} + +let configArgs = []; +if (toolsFileName) { + configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName)); +} + +const args = process.argv.slice(2); +const toolboxArgs = [...configArgs, "invoke", toolName, ...args]; + +const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' }); + +child.on('close', (code) => { + process.exit(code); +}); + +child.on('error', (err) => { + console.error("Error executing toolbox:", err); + process.exit(1); +}); diff --git a/skills/cloudsql-postgres/scripts/list_query_stats.js b/skills/cloudsql-postgres/scripts/list_query_stats.js new file mode 100755 index 0000000..a7bda5d --- /dev/null +++ b/skills/cloudsql-postgres/scripts/list_query_stats.js @@ -0,0 +1,52 @@ +#!/usr/bin/env node + +const { spawn, execSync } = require('child_process'); +const path = require('path'); +const fs = require('fs'); + +const toolName = "list_query_stats"; +const toolsFileName = "list_query_stats.yaml"; + +function getToolboxPath() { + try { + const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox'; + const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim(); + if (globalPath) { + return globalPath.split('\n')[0].trim(); + } + } catch (e) { + // Ignore error; + } + const localPath = path.resolve(__dirname, '../../../toolbox'); + if (fs.existsSync(localPath)) { + return localPath; + } + throw new Error("Toolbox binary not found"); +} + +let toolboxBinary; +try { + toolboxBinary = getToolboxPath(); +} catch (err) { + console.error("Error:", err.message); + process.exit(1); +} + +let configArgs = []; +if (toolsFileName) { + configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName)); +} + +const args = process.argv.slice(2); +const toolboxArgs = [...configArgs, "invoke", toolName, ...args]; + +const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' }); + +child.on('close', (code) => { + process.exit(code); +}); + +child.on('error', (err) => { + console.error("Error executing toolbox:", err); + process.exit(1); +}); diff --git a/skills/cloudsql-postgres/scripts/list_replication_slots.js b/skills/cloudsql-postgres/scripts/list_replication_slots.js new file mode 100755 index 0000000..01d18fc --- /dev/null +++ b/skills/cloudsql-postgres/scripts/list_replication_slots.js @@ -0,0 +1,52 @@ +#!/usr/bin/env node + +const { spawn, execSync } = require('child_process'); +const path = require('path'); +const fs = require('fs'); + +const toolName = "list_replication_slots"; +const toolsFileName = "list_replication_slots.yaml"; + +function getToolboxPath() { + try { + const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox'; + const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim(); + if (globalPath) { + return globalPath.split('\n')[0].trim(); + } + } catch (e) { + // Ignore error; + } + const localPath = path.resolve(__dirname, '../../../toolbox'); + if (fs.existsSync(localPath)) { + return localPath; + } + throw new Error("Toolbox binary not found"); +} + +let toolboxBinary; +try { + toolboxBinary = getToolboxPath(); +} catch (err) { + console.error("Error:", err.message); + process.exit(1); +} + +let configArgs = []; +if (toolsFileName) { + configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName)); +} + +const args = process.argv.slice(2); +const toolboxArgs = [...configArgs, "invoke", toolName, ...args]; + +const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' }); + +child.on('close', (code) => { + process.exit(code); +}); + +child.on('error', (err) => { + console.error("Error executing toolbox:", err); + process.exit(1); +}); diff --git a/skills/cloudsql-postgres/scripts/list_roles.js b/skills/cloudsql-postgres/scripts/list_roles.js new file mode 100755 index 0000000..1c2bc9a --- /dev/null +++ b/skills/cloudsql-postgres/scripts/list_roles.js @@ -0,0 +1,52 @@ +#!/usr/bin/env node + +const { spawn, execSync } = require('child_process'); +const path = require('path'); +const fs = require('fs'); + +const toolName = "list_roles"; +const toolsFileName = "list_roles.yaml"; + +function getToolboxPath() { + try { + const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox'; + const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim(); + if (globalPath) { + return globalPath.split('\n')[0].trim(); + } + } catch (e) { + // Ignore error; + } + const localPath = path.resolve(__dirname, '../../../toolbox'); + if (fs.existsSync(localPath)) { + return localPath; + } + throw new Error("Toolbox binary not found"); +} + +let toolboxBinary; +try { + toolboxBinary = getToolboxPath(); +} catch (err) { + console.error("Error:", err.message); + process.exit(1); +} + +let configArgs = []; +if (toolsFileName) { + configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName)); +} + +const args = process.argv.slice(2); +const toolboxArgs = [...configArgs, "invoke", toolName, ...args]; + +const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' }); + +child.on('close', (code) => { + process.exit(code); +}); + +child.on('error', (err) => { + console.error("Error executing toolbox:", err); + process.exit(1); +}); diff --git a/skills/cloudsql-postgres/scripts/list_schemas.js b/skills/cloudsql-postgres/scripts/list_schemas.js new file mode 100755 index 0000000..a27decd --- /dev/null +++ b/skills/cloudsql-postgres/scripts/list_schemas.js @@ -0,0 +1,52 @@ +#!/usr/bin/env node + +const { spawn, execSync } = require('child_process'); +const path = require('path'); +const fs = require('fs'); + +const toolName = "list_schemas"; +const toolsFileName = "list_schemas.yaml"; + +function getToolboxPath() { + try { + const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox'; + const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim(); + if (globalPath) { + return globalPath.split('\n')[0].trim(); + } + } catch (e) { + // Ignore error; + } + const localPath = path.resolve(__dirname, '../../../toolbox'); + if (fs.existsSync(localPath)) { + return localPath; + } + throw new Error("Toolbox binary not found"); +} + +let toolboxBinary; +try { + toolboxBinary = getToolboxPath(); +} catch (err) { + console.error("Error:", err.message); + process.exit(1); +} + +let configArgs = []; +if (toolsFileName) { + configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName)); +} + +const args = process.argv.slice(2); +const toolboxArgs = [...configArgs, "invoke", toolName, ...args]; + +const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' }); + +child.on('close', (code) => { + process.exit(code); +}); + +child.on('error', (err) => { + console.error("Error executing toolbox:", err); + process.exit(1); +}); diff --git a/skills/cloudsql-postgres/scripts/list_sequences.js b/skills/cloudsql-postgres/scripts/list_sequences.js new file mode 100755 index 0000000..826dbcb --- /dev/null +++ b/skills/cloudsql-postgres/scripts/list_sequences.js @@ -0,0 +1,52 @@ +#!/usr/bin/env node + +const { spawn, execSync } = require('child_process'); +const path = require('path'); +const fs = require('fs'); + +const toolName = "list_sequences"; +const toolsFileName = "list_sequences.yaml"; + +function getToolboxPath() { + try { + const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox'; + const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim(); + if (globalPath) { + return globalPath.split('\n')[0].trim(); + } + } catch (e) { + // Ignore error; + } + const localPath = path.resolve(__dirname, '../../../toolbox'); + if (fs.existsSync(localPath)) { + return localPath; + } + throw new Error("Toolbox binary not found"); +} + +let toolboxBinary; +try { + toolboxBinary = getToolboxPath(); +} catch (err) { + console.error("Error:", err.message); + process.exit(1); +} + +let configArgs = []; +if (toolsFileName) { + configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName)); +} + +const args = process.argv.slice(2); +const toolboxArgs = [...configArgs, "invoke", toolName, ...args]; + +const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' }); + +child.on('close', (code) => { + process.exit(code); +}); + +child.on('error', (err) => { + console.error("Error executing toolbox:", err); + process.exit(1); +}); diff --git a/skills/cloudsql-postgres/scripts/list_stored_procedure.js b/skills/cloudsql-postgres/scripts/list_stored_procedure.js new file mode 100755 index 0000000..fd63a9d --- /dev/null +++ b/skills/cloudsql-postgres/scripts/list_stored_procedure.js @@ -0,0 +1,52 @@ +#!/usr/bin/env node + +const { spawn, execSync } = require('child_process'); +const path = require('path'); +const fs = require('fs'); + +const toolName = "list_stored_procedure"; +const toolsFileName = "list_stored_procedure.yaml"; + +function getToolboxPath() { + try { + const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox'; + const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim(); + if (globalPath) { + return globalPath.split('\n')[0].trim(); + } + } catch (e) { + // Ignore error; + } + const localPath = path.resolve(__dirname, '../../../toolbox'); + if (fs.existsSync(localPath)) { + return localPath; + } + throw new Error("Toolbox binary not found"); +} + +let toolboxBinary; +try { + toolboxBinary = getToolboxPath(); +} catch (err) { + console.error("Error:", err.message); + process.exit(1); +} + +let configArgs = []; +if (toolsFileName) { + configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName)); +} + +const args = process.argv.slice(2); +const toolboxArgs = [...configArgs, "invoke", toolName, ...args]; + +const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' }); + +child.on('close', (code) => { + process.exit(code); +}); + +child.on('error', (err) => { + console.error("Error executing toolbox:", err); + process.exit(1); +}); diff --git a/skills/cloudsql-postgres/scripts/list_table_stats.js b/skills/cloudsql-postgres/scripts/list_table_stats.js new file mode 100755 index 0000000..ace31ba --- /dev/null +++ b/skills/cloudsql-postgres/scripts/list_table_stats.js @@ -0,0 +1,52 @@ +#!/usr/bin/env node + +const { spawn, execSync } = require('child_process'); +const path = require('path'); +const fs = require('fs'); + +const toolName = "list_table_stats"; +const toolsFileName = "list_table_stats.yaml"; + +function getToolboxPath() { + try { + const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox'; + const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim(); + if (globalPath) { + return globalPath.split('\n')[0].trim(); + } + } catch (e) { + // Ignore error; + } + const localPath = path.resolve(__dirname, '../../../toolbox'); + if (fs.existsSync(localPath)) { + return localPath; + } + throw new Error("Toolbox binary not found"); +} + +let toolboxBinary; +try { + toolboxBinary = getToolboxPath(); +} catch (err) { + console.error("Error:", err.message); + process.exit(1); +} + +let configArgs = []; +if (toolsFileName) { + configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName)); +} + +const args = process.argv.slice(2); +const toolboxArgs = [...configArgs, "invoke", toolName, ...args]; + +const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' }); + +child.on('close', (code) => { + process.exit(code); +}); + +child.on('error', (err) => { + console.error("Error executing toolbox:", err); + process.exit(1); +}); diff --git a/skills/cloudsql-postgres/scripts/list_tables.js b/skills/cloudsql-postgres/scripts/list_tables.js new file mode 100755 index 0000000..a1dad4d --- /dev/null +++ b/skills/cloudsql-postgres/scripts/list_tables.js @@ -0,0 +1,52 @@ +#!/usr/bin/env node + +const { spawn, execSync } = require('child_process'); +const path = require('path'); +const fs = require('fs'); + +const toolName = "list_tables"; +const toolsFileName = "list_tables.yaml"; + +function getToolboxPath() { + try { + const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox'; + const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim(); + if (globalPath) { + return globalPath.split('\n')[0].trim(); + } + } catch (e) { + // Ignore error; + } + const localPath = path.resolve(__dirname, '../../../toolbox'); + if (fs.existsSync(localPath)) { + return localPath; + } + throw new Error("Toolbox binary not found"); +} + +let toolboxBinary; +try { + toolboxBinary = getToolboxPath(); +} catch (err) { + console.error("Error:", err.message); + process.exit(1); +} + +let configArgs = []; +if (toolsFileName) { + configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName)); +} + +const args = process.argv.slice(2); +const toolboxArgs = [...configArgs, "invoke", toolName, ...args]; + +const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' }); + +child.on('close', (code) => { + process.exit(code); +}); + +child.on('error', (err) => { + console.error("Error executing toolbox:", err); + process.exit(1); +}); diff --git a/skills/cloudsql-postgres/scripts/list_tablespaces.js b/skills/cloudsql-postgres/scripts/list_tablespaces.js new file mode 100755 index 0000000..1899d47 --- /dev/null +++ b/skills/cloudsql-postgres/scripts/list_tablespaces.js @@ -0,0 +1,52 @@ +#!/usr/bin/env node + +const { spawn, execSync } = require('child_process'); +const path = require('path'); +const fs = require('fs'); + +const toolName = "list_tablespaces"; +const toolsFileName = "list_tablespaces.yaml"; + +function getToolboxPath() { + try { + const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox'; + const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim(); + if (globalPath) { + return globalPath.split('\n')[0].trim(); + } + } catch (e) { + // Ignore error; + } + const localPath = path.resolve(__dirname, '../../../toolbox'); + if (fs.existsSync(localPath)) { + return localPath; + } + throw new Error("Toolbox binary not found"); +} + +let toolboxBinary; +try { + toolboxBinary = getToolboxPath(); +} catch (err) { + console.error("Error:", err.message); + process.exit(1); +} + +let configArgs = []; +if (toolsFileName) { + configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName)); +} + +const args = process.argv.slice(2); +const toolboxArgs = [...configArgs, "invoke", toolName, ...args]; + +const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' }); + +child.on('close', (code) => { + process.exit(code); +}); + +child.on('error', (err) => { + console.error("Error executing toolbox:", err); + process.exit(1); +}); diff --git a/skills/cloudsql-postgres/scripts/list_top_bloated_tables.js b/skills/cloudsql-postgres/scripts/list_top_bloated_tables.js new file mode 100755 index 0000000..27f482c --- /dev/null +++ b/skills/cloudsql-postgres/scripts/list_top_bloated_tables.js @@ -0,0 +1,52 @@ +#!/usr/bin/env node + +const { spawn, execSync } = require('child_process'); +const path = require('path'); +const fs = require('fs'); + +const toolName = "list_top_bloated_tables"; +const toolsFileName = "list_top_bloated_tables.yaml"; + +function getToolboxPath() { + try { + const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox'; + const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim(); + if (globalPath) { + return globalPath.split('\n')[0].trim(); + } + } catch (e) { + // Ignore error; + } + const localPath = path.resolve(__dirname, '../../../toolbox'); + if (fs.existsSync(localPath)) { + return localPath; + } + throw new Error("Toolbox binary not found"); +} + +let toolboxBinary; +try { + toolboxBinary = getToolboxPath(); +} catch (err) { + console.error("Error:", err.message); + process.exit(1); +} + +let configArgs = []; +if (toolsFileName) { + configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName)); +} + +const args = process.argv.slice(2); +const toolboxArgs = [...configArgs, "invoke", toolName, ...args]; + +const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' }); + +child.on('close', (code) => { + process.exit(code); +}); + +child.on('error', (err) => { + console.error("Error executing toolbox:", err); + process.exit(1); +}); diff --git a/skills/cloudsql-postgres/scripts/list_triggers.js b/skills/cloudsql-postgres/scripts/list_triggers.js new file mode 100755 index 0000000..4b0061d --- /dev/null +++ b/skills/cloudsql-postgres/scripts/list_triggers.js @@ -0,0 +1,52 @@ +#!/usr/bin/env node + +const { spawn, execSync } = require('child_process'); +const path = require('path'); +const fs = require('fs'); + +const toolName = "list_triggers"; +const toolsFileName = "list_triggers.yaml"; + +function getToolboxPath() { + try { + const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox'; + const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim(); + if (globalPath) { + return globalPath.split('\n')[0].trim(); + } + } catch (e) { + // Ignore error; + } + const localPath = path.resolve(__dirname, '../../../toolbox'); + if (fs.existsSync(localPath)) { + return localPath; + } + throw new Error("Toolbox binary not found"); +} + +let toolboxBinary; +try { + toolboxBinary = getToolboxPath(); +} catch (err) { + console.error("Error:", err.message); + process.exit(1); +} + +let configArgs = []; +if (toolsFileName) { + configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName)); +} + +const args = process.argv.slice(2); +const toolboxArgs = [...configArgs, "invoke", toolName, ...args]; + +const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' }); + +child.on('close', (code) => { + process.exit(code); +}); + +child.on('error', (err) => { + console.error("Error executing toolbox:", err); + process.exit(1); +}); diff --git a/skills/cloudsql-postgres/scripts/list_views.js b/skills/cloudsql-postgres/scripts/list_views.js new file mode 100755 index 0000000..69ed9a8 --- /dev/null +++ b/skills/cloudsql-postgres/scripts/list_views.js @@ -0,0 +1,52 @@ +#!/usr/bin/env node + +const { spawn, execSync } = require('child_process'); +const path = require('path'); +const fs = require('fs'); + +const toolName = "list_views"; +const toolsFileName = "list_views.yaml"; + +function getToolboxPath() { + try { + const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox'; + const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim(); + if (globalPath) { + return globalPath.split('\n')[0].trim(); + } + } catch (e) { + // Ignore error; + } + const localPath = path.resolve(__dirname, '../../../toolbox'); + if (fs.existsSync(localPath)) { + return localPath; + } + throw new Error("Toolbox binary not found"); +} + +let toolboxBinary; +try { + toolboxBinary = getToolboxPath(); +} catch (err) { + console.error("Error:", err.message); + process.exit(1); +} + +let configArgs = []; +if (toolsFileName) { + configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName)); +} + +const args = process.argv.slice(2); +const toolboxArgs = [...configArgs, "invoke", toolName, ...args]; + +const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' }); + +child.on('close', (code) => { + process.exit(code); +}); + +child.on('error', (err) => { + console.error("Error executing toolbox:", err); + process.exit(1); +}); diff --git a/skills/cloudsql-postgres/scripts/long_running_transactions.js b/skills/cloudsql-postgres/scripts/long_running_transactions.js new file mode 100755 index 0000000..62b034a --- /dev/null +++ b/skills/cloudsql-postgres/scripts/long_running_transactions.js @@ -0,0 +1,52 @@ +#!/usr/bin/env node + +const { spawn, execSync } = require('child_process'); +const path = require('path'); +const fs = require('fs'); + +const toolName = "long_running_transactions"; +const toolsFileName = "long_running_transactions.yaml"; + +function getToolboxPath() { + try { + const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox'; + const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim(); + if (globalPath) { + return globalPath.split('\n')[0].trim(); + } + } catch (e) { + // Ignore error; + } + const localPath = path.resolve(__dirname, '../../../toolbox'); + if (fs.existsSync(localPath)) { + return localPath; + } + throw new Error("Toolbox binary not found"); +} + +let toolboxBinary; +try { + toolboxBinary = getToolboxPath(); +} catch (err) { + console.error("Error:", err.message); + process.exit(1); +} + +let configArgs = []; +if (toolsFileName) { + configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName)); +} + +const args = process.argv.slice(2); +const toolboxArgs = [...configArgs, "invoke", toolName, ...args]; + +const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' }); + +child.on('close', (code) => { + process.exit(code); +}); + +child.on('error', (err) => { + console.error("Error executing toolbox:", err); + process.exit(1); +}); diff --git a/skills/cloudsql-postgres/scripts/replication_stats.js b/skills/cloudsql-postgres/scripts/replication_stats.js new file mode 100755 index 0000000..27d2a30 --- /dev/null +++ b/skills/cloudsql-postgres/scripts/replication_stats.js @@ -0,0 +1,52 @@ +#!/usr/bin/env node + +const { spawn, execSync } = require('child_process'); +const path = require('path'); +const fs = require('fs'); + +const toolName = "replication_stats"; +const toolsFileName = "replication_stats.yaml"; + +function getToolboxPath() { + try { + const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox'; + const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim(); + if (globalPath) { + return globalPath.split('\n')[0].trim(); + } + } catch (e) { + // Ignore error; + } + const localPath = path.resolve(__dirname, '../../../toolbox'); + if (fs.existsSync(localPath)) { + return localPath; + } + throw new Error("Toolbox binary not found"); +} + +let toolboxBinary; +try { + toolboxBinary = getToolboxPath(); +} catch (err) { + console.error("Error:", err.message); + process.exit(1); +} + +let configArgs = []; +if (toolsFileName) { + configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName)); +} + +const args = process.argv.slice(2); +const toolboxArgs = [...configArgs, "invoke", toolName, ...args]; + +const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' }); + +child.on('close', (code) => { + process.exit(code); +}); + +child.on('error', (err) => { + console.error("Error executing toolbox:", err); + process.exit(1); +}); From 836177f2d3b160bba7b148b9ba88f73c886c9d47 Mon Sep 17 00:00:00 2001 From: Twisha Bansal Date: Fri, 27 Feb 2026 12:46:05 +0530 Subject: [PATCH 02/12] add presubmit workflow for skills --- .github/workflows/skills-validate.yml | 64 +++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 .github/workflows/skills-validate.yml diff --git a/.github/workflows/skills-validate.yml b/.github/workflows/skills-validate.yml new file mode 100644 index 0000000..ad2762b --- /dev/null +++ b/.github/workflows/skills-validate.yml @@ -0,0 +1,64 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +name: Validate Skills + +on: + push: + branches: + - main + paths: + - "skills/**" + pull_request: + branches: + - main + paths: + - "skills/**" + workflow_dispatch: + +jobs: + validate: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Checkout agentskills/agentskills + uses: actions/checkout@v4 + with: + repository: agentskills/agentskills + path: agentskills + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.11" + + - name: Install skills-ref + run: | + cd agentskills/skills-ref + pip install . + + - name: Validate Skills + run: | + failed=0 + for skill_dir in skills/*/; do + if [ -d "$skill_dir" ]; then + echo "Validating $skill_dir..." + if ! skills-ref validate "$skill_dir"; then + echo "Validation failed for $skill_dir" + failed=1 + fi + fi + done + exit $failed From 51f2803762a70ce4a69f8c571654b4d740726813 Mon Sep 17 00:00:00 2001 From: Twisha Bansal Date: Fri, 27 Feb 2026 13:08:50 +0530 Subject: [PATCH 03/12] fix workflow --- .github/workflows/skills-validate.yml | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/.github/workflows/skills-validate.yml b/.github/workflows/skills-validate.yml index ad2762b..69dbdc1 100644 --- a/.github/workflows/skills-validate.yml +++ b/.github/workflows/skills-validate.yml @@ -33,12 +33,6 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Checkout agentskills/agentskills - uses: actions/checkout@v4 - with: - repository: agentskills/agentskills - path: agentskills - - name: Set up Python uses: actions/setup-python@v5 with: @@ -46,8 +40,7 @@ jobs: - name: Install skills-ref run: | - cd agentskills/skills-ref - pip install . + pip install "git+https://github.com/agentskills/agentskills.git#subdirectory=skills-ref" - name: Validate Skills run: | From ff9ce70ea7fc044426a19f341374d577a1f326c8 Mon Sep 17 00:00:00 2001 From: Twisha Bansal <58483338+twishabansal@users.noreply.github.com> Date: Fri, 27 Feb 2026 13:12:59 +0530 Subject: [PATCH 04/12] Update skills-validate.yml --- .github/workflows/skills-validate.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/skills-validate.yml b/.github/workflows/skills-validate.yml index 69dbdc1..4070909 100644 --- a/.github/workflows/skills-validate.yml +++ b/.github/workflows/skills-validate.yml @@ -28,7 +28,7 @@ on: workflow_dispatch: jobs: - validate: + skills-validate: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 From ca520683a63b2d46f76dea8dddf3c5a0316f60e0 Mon Sep 17 00:00:00 2001 From: Twisha Bansal Date: Fri, 27 Feb 2026 13:17:16 +0530 Subject: [PATCH 05/12] fix workflows --- .../workflows/skills-validate-fallback.yml | 37 +++++++++++++++++++ .github/workflows/skills-validate.yml | 9 ++--- 2 files changed, 41 insertions(+), 5 deletions(-) create mode 100644 .github/workflows/skills-validate-fallback.yml diff --git a/.github/workflows/skills-validate-fallback.yml b/.github/workflows/skills-validate-fallback.yml new file mode 100644 index 0000000..b49eb62 --- /dev/null +++ b/.github/workflows/skills-validate-fallback.yml @@ -0,0 +1,37 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +name: lint + +on: + push: + paths-ignore: + - "skills/**" + pull_request: + paths-ignore: + - "skills/**" + pull_request_target: + types: [labeled] + paths-ignore: + - "skills/**" + workflow_dispatch: + +jobs: + skills-validate: + runs-on: ubuntu-latest + steps: + - name: Skip Skill Validation + run: | + echo "No changes detected in 'skills/' directory. Skipping validation." + echo "This job ensures the required 'skills-validate' status check passes." diff --git a/.github/workflows/skills-validate.yml b/.github/workflows/skills-validate.yml index 4070909..c831e21 100644 --- a/.github/workflows/skills-validate.yml +++ b/.github/workflows/skills-validate.yml @@ -16,16 +16,15 @@ name: Validate Skills on: push: - branches: - - main paths: - "skills/**" pull_request: - branches: - - main paths: - "skills/**" - workflow_dispatch: + pull_request_target: + types: [labeled] + paths: + - "skills/**" jobs: skills-validate: From 91a801b19dceab41d5d89a81db5b8bd5c6969345 Mon Sep 17 00:00:00 2001 From: Twisha Bansal Date: Fri, 27 Feb 2026 13:20:13 +0530 Subject: [PATCH 06/12] ignore skills dir for license headers --- .licenserc.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.licenserc.yaml b/.licenserc.yaml index 4670661..f1317dc 100644 --- a/.licenserc.yaml +++ b/.licenserc.yaml @@ -17,6 +17,9 @@ header: spdx-id: "Apache-2.0" copyright-owner: "Google LLC" copyright-year: "2025" + paths-ignore: + - "skills/**" + paths: - "**/*.yaml" - "**/*.yml" From 4cd0334e1d4b4110323eb040e43b592f4b0168a0 Mon Sep 17 00:00:00 2001 From: Twisha Bansal Date: Fri, 27 Feb 2026 13:26:32 +0530 Subject: [PATCH 07/12] update docs --- CLOUD-SQL-POSTGRESQL.md | 12 +++++----- README.md | 49 ++++++++--------------------------------- 2 files changed, 15 insertions(+), 46 deletions(-) diff --git a/CLOUD-SQL-POSTGRESQL.md b/CLOUD-SQL-POSTGRESQL.md index c09d3ed..1f454bf 100644 --- a/CLOUD-SQL-POSTGRESQL.md +++ b/CLOUD-SQL-POSTGRESQL.md @@ -39,9 +39,9 @@ This section covers administrative operations like managing clusters, instances, --- -# Additional Tools +# Additional Skills -This section provides context on additional tools that can be recommended to the user based on their queries. +This section provides context on additional skills that can be recommended to the user based on their queries. #### Observability Extension @@ -58,7 +58,7 @@ This section provides context on additional tools that can be recommended to the ## Connecting to New Resources -When you create a new Cloud SQL for PostgreSQL instance, or database using the available tools, the connection is not automatically established. You will need to perform the following steps: +When you create a new Cloud SQL for PostgreSQL instance, or database using the available skills, the connection is not automatically established. You will need to perform the following steps: 1. **(Optional) Save your conversation:** To avoid losing your progress, save the current session by running the command: `/chat save ` 2. **Stop the CLI:** Terminate the Gemini CLI. @@ -77,12 +77,12 @@ Users may have set project environment variables: * `CLOUD_SQL_POSTGRES_INSTANCE`: The ID of the Cloud SQL for PostgreSQL instance. * `CLOUD_SQL_POSTGRES_DATABASE`: The name of the database. -Instead of prompting the user for these values for specific tool calls, prompt the user to verify reuse a specific value. +Instead of prompting the user for these values for specific skill calls, prompt the user to verify reuse a specific value. Make sure to not use the environment variable name like `CLOUD_SQL_POSTGRES_PROJECT`, `${CLOUD_SQL_POSTGRES_PROJECT}`, or `$CLOUD_SQL_POSTGRES_PROJECT`. The value can be found by using command: `echo $CLOUD_SQL_POSTGRES_PROJECT`. ## Use Full Table Name Format "DATABASE_NAME.SCHEMA_NAME.TABLE_NAME" -**ALWAYS** use the full table name format, `DATABASE_NAME.SCHEMA_NAME.TABLE_NAME` in the generated SQL when using the `execute_sql` or `cloud_sql_postgresql__execute_sql` tool. +**ALWAYS** use the full table name format, `DATABASE_NAME.SCHEMA_NAME.TABLE_NAME` in the generated SQL when using the `execute_sql` or `cloud_sql_postgresql__execute_sql` skill. * Default to using "public" for the schema name. * Use command `echo $CLOUD_SQL_POSTGRES_DATABASE` to get the current database value. @@ -92,7 +92,7 @@ When working with AI features like vector embeddings in Cloud SQL, leverage the Embeddings can be generated using the `embedding()` function. For example: `embedding(, )`. -As an agent, if you do not know which model to use, you should use your tools to search for available and appropriate text embedding models compatible with the `google_ml_integration` extension (e.g., by searching for "Cloud SQL google_ml_integration supported models"). +As an agent, if you do not know which model to use, you should use your skills to search for available and appropriate text embedding models compatible with the `google_ml_integration` extension (e.g., by searching for "Cloud SQL google_ml_integration supported models"). When performing similarity searches, remember to cast the result of the `embedding` function to the `vector` type. For example: `ORDER BY description_vector <-> embedding(, $1)::vector` diff --git a/README.md b/README.md index 1bea7d5..3aff45c 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ > [!NOTE] > This extension is currently in beta (pre-v1.0), and may see breaking changes until the first stable release (v1.0). -This Gemini CLI extension provides a set of tools to interact with [Cloud SQL for PostgreSQL](https://cloud.google.com/sql/docs/postgres) instances. It allows you to manage your databases, execute queries, explore schemas, and troubleshoot issues directly from the [Gemini CLI](https://google-gemini.github.io/gemini-cli/), using natural language prompts. +This Gemini CLI extension provides a set of skills to interact with [Cloud SQL for PostgreSQL](https://cloud.google.com/sql/docs/postgres) instances. It allows you to manage your databases, execute queries, explore schemas, and troubleshoot issues directly from the [Gemini CLI](https://google-gemini.github.io/gemini-cli/), using natural language prompts. Learn more about [Gemini CLI Extensions](https://github.com/google-gemini/gemini-cli/blob/main/docs/extensions/index.md). > [!IMPORTANT] @@ -58,7 +58,7 @@ You will be prompted to configure the following settings during installation. Th * `CLOUD_SQL_POSTGRES_IP_TYPE`: (Optional) Type of the IP address: `PUBLIC`, `PRIVATE`, or `PSC`. Defaults to `PUBLIC`. > [!NOTE] -> This configuration is primarily for the Data Plane tools (querying). The Admin toolset does not strictly require these to be pre-set if you provide them in your prompts, but it is recommended for a smoother experience. +> This configuration is primarily for the Data Plane skills (querying). The Admin skillset does not strictly require these to be pre-set if you provide them in your prompts, but it is recommended for a smoother experience. To view or update your configuration: @@ -87,7 +87,7 @@ export CLOUD_SQL_POSTGRES_IP_TYPE="PUBLIC" # Optional: `PUBLIC`, `PRIVATE`, `PSC > [!NOTE] > * Ensure [Application Default Credentials](https://cloud.google.com/docs/authentication/gcloud) are available in your environment. > * If your Cloud SQL for PostgreSQL instance uses private IPs, you must run Gemini CLI in the same Virtual Private Cloud (VPC) network. -> * See [Troubleshooting](#troubleshooting) for debugging your configuration. +> * See [Troubleshooting](#troubleshooting) for debugging your configuration. ### Start Gemini CLI @@ -116,43 +116,12 @@ Interact with Cloud SQL for PostgreSQL using natural language: * **Generate Code:** * "Generate a Python dataclass to represent the 'customers' table." -## Supported Tools - -* **Admin:** - * `clone_instance`: Creates a clone for an existing Cloud SQL for PostgreSQL instance. - * `create_backup`: Creates a backup on a Cloud SQL instance. - * `create_instance`: Use this tool to create an Postgres instance. - * `create_user`: Use this tool to create Postgres-BUILT-IN or IAM-based users. - * `create_database`: Creates a new database in a Cloud SQL instance. - * `get_instance`: Use this tool to get details about an Postgres instance. - * `list_instances`: Use this tool to list instances in a given project and location. - * `list_databases`: Lists all databases for a Cloud SQL instance. - * `restore_backup`: Restores a backup of a Cloud SQL instance. - * `wait_for_operation`: Use this tool to poll the operations API until the operation is done. - -* **Data:** - * `list_tables`: Use this tool to lists tables in the database. - * `database_overview`: Use this tool to fetches the current state of the PostgreSQL server. - * `execute_sql`: Use this tool to executes a SQL query. - * `list_active_queries`: Use this tool to list currently running queries. - * `list_available_extensions`: Use this tool to list available extensions for installation. - * `list_installed_extensions`: Use this tool to list installed extensions. - * `get_query_plan`: Use this tool to get query plan. - * `list_autovacuum_configurations`: Use this tool to list autovacuum configurations and its value. - * `list_database_stats`: Use this tool to lists the key performance and activity statistics for each database in the postgreSQL instance. - * `list_indexes`: Use this tool to list available user indexes in a PostgreSQL database. - * `list_memory_configurations`: Use this tool to list memory configurations and its value. - * `list_pg_settings`: Use this tool to list configuration parameters for the PostgreSQL server. - * `list_publication_tables`: Use this tool to list publication tables in a PostgreSQL database. - * `list_replication_slots`: Use this tool to list replication slots. - * `list_roles`: Use this tool to lists all the user-created roles in PostgreSQL database. - * `list_schemas`: Use this tool to lists schemas in the database. - * `list_sequences`: Use this tool to list sequences in a PostgreSQL database. - * `list_tablespaces`: Use this tool to lists tablespaces in the database. - * `list_top_bloated_tables`: Use this tool to list top bloated tables. - * `list_triggers`: Use this tool to lists triggers in the database. - * `list_views`: Use this tool to lists views in the database from pg_views with a default limit of 50 rows. - * `list_invalid_indexes`: Use this tool to list invalid indexes. +## Supported Skills + +This extension provides the following skills: + +* [Cloud SQL for PostgreSQL Admin](skills/cloudsql-postgres-admin/SKILL.md) - Manage Cloud SQL instances, databases, and users. +* [Cloud SQL for PostgreSQL](skills/cloudsql-postgres/SKILL.md) - Query databases and manage extensions. ## Additional Extensions From cf9b4cb847d304565ffe6dc0e290c69db9953215 Mon Sep 17 00:00:00 2001 From: Twisha Bansal Date: Fri, 27 Feb 2026 13:35:14 +0530 Subject: [PATCH 08/12] fix header check --- .licenserc.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.licenserc.yaml b/.licenserc.yaml index f1317dc..a8e7e1e 100644 --- a/.licenserc.yaml +++ b/.licenserc.yaml @@ -16,7 +16,7 @@ header: license: spdx-id: "Apache-2.0" copyright-owner: "Google LLC" - copyright-year: "2025" + copyright-year: "202[5-6]" paths-ignore: - "skills/**" From af1e0728e6f5b9e3d26c0a8cc3ddf93f01bbe1f3 Mon Sep 17 00:00:00 2001 From: Twisha Bansal Date: Fri, 27 Feb 2026 13:38:37 +0530 Subject: [PATCH 09/12] fix copyright year --- .licenserc.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.licenserc.yaml b/.licenserc.yaml index a8e7e1e..e17c394 100644 --- a/.licenserc.yaml +++ b/.licenserc.yaml @@ -16,7 +16,7 @@ header: license: spdx-id: "Apache-2.0" copyright-owner: "Google LLC" - copyright-year: "202[5-6]" + copyright-year: "2025-2026" paths-ignore: - "skills/**" From e4bad755648c56f7ee7f54737bb61c950b4f9615 Mon Sep 17 00:00:00 2001 From: Twisha Bansal Date: Fri, 27 Feb 2026 13:44:06 +0530 Subject: [PATCH 10/12] test failure for validation workflow --- skills/cloudsql-postgres-admin/SKILL.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/skills/cloudsql-postgres-admin/SKILL.md b/skills/cloudsql-postgres-admin/SKILL.md index 03b50f5..097bc32 100644 --- a/skills/cloudsql-postgres-admin/SKILL.md +++ b/skills/cloudsql-postgres-admin/SKILL.md @@ -1,6 +1,6 @@ --- name: cloudsql-postgres-admin -description: skill for performing administrative operations on cloudsql postgres +descfgfg∂ription: skill for performing administrative operations on cloudsql postgres --- ## Usage From c603ce1af216de9fe03b18259585b9c79dd8c9dd Mon Sep 17 00:00:00 2001 From: Twisha Bansal Date: Fri, 27 Feb 2026 13:45:28 +0530 Subject: [PATCH 11/12] revert skill testing failure --- skills/cloudsql-postgres-admin/SKILL.md | 61 +++++-------------------- 1 file changed, 11 insertions(+), 50 deletions(-) diff --git a/skills/cloudsql-postgres-admin/SKILL.md b/skills/cloudsql-postgres-admin/SKILL.md index 097bc32..e2f62fc 100644 --- a/skills/cloudsql-postgres-admin/SKILL.md +++ b/skills/cloudsql-postgres-admin/SKILL.md @@ -1,6 +1,6 @@ --- name: cloudsql-postgres-admin -descfgfg∂ription: skill for performing administrative operations on cloudsql postgres +description: skill for performing administrative operations on cloudsql postgres --- ## Usage @@ -15,7 +15,6 @@ All scripts can be executed using Node.js. Replace `` and ` Date: Fri, 27 Feb 2026 13:46:26 +0530 Subject: [PATCH 12/12] revert license file changes --- .licenserc.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.licenserc.yaml b/.licenserc.yaml index e17c394..f1317dc 100644 --- a/.licenserc.yaml +++ b/.licenserc.yaml @@ -16,7 +16,7 @@ header: license: spdx-id: "Apache-2.0" copyright-owner: "Google LLC" - copyright-year: "2025-2026" + copyright-year: "2025" paths-ignore: - "skills/**"