postgresai 0.17.0-dev.0 → 0.17.0-dev.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +236 -8
- package/dist/bin/postgres-ai.js +22280 -15529
- package/dist/sql/01.role.sql +2 -1
- package/dist/sql/02.extensions.sql +1 -1
- package/dist/sql/04.optional_rds.sql +2 -1
- package/dist/sql/06.helpers.sql +29 -8
- package/package.json +2 -2
- package/sql/01.role.sql +2 -1
- package/sql/02.extensions.sql +1 -1
- package/sql/04.optional_rds.sql +2 -1
- package/sql/06.helpers.sql +29 -8
- package/dist/sql/sql/01.role.sql +0 -16
- package/dist/sql/sql/02.extensions.sql +0 -8
- package/dist/sql/sql/03.permissions.sql +0 -86
- package/dist/sql/sql/04.optional_rds.sql +0 -6
- package/dist/sql/sql/05.optional_self_managed.sql +0 -8
- package/dist/sql/sql/06.helpers.sql +0 -317
- package/dist/sql/sql/uninit/01.helpers.sql +0 -5
- package/dist/sql/sql/uninit/02.permissions.sql +0 -30
- package/dist/sql/sql/uninit/03.role.sql +0 -27
package/README.md
CHANGED
|
@@ -76,6 +76,8 @@ Password input options (in priority order):
|
|
|
76
76
|
- `PGAI_MON_PASSWORD` environment variable
|
|
77
77
|
- if not provided: a strong password is generated automatically
|
|
78
78
|
|
|
79
|
+
Monitoring passwords must use printable ASCII characters; non-ASCII passwords are rejected until SASLprep normalization is supported. Role creation and password resets send a SCRAM-SHA-256 verifier instead of the cleartext password, including when the server uses `password_encryption=md5`. Printed SQL redacts the verifier as well. Server statement logging can still record the verifier; treat it as sensitive.
|
|
80
|
+
|
|
79
81
|
By default, the generated password is printed **only in interactive (TTY) mode**. In non-interactive mode, you must either provide the password explicitly, or opt-in to printing it:
|
|
80
82
|
- `--print-password` (dangerous in CI logs)
|
|
81
83
|
|
|
@@ -125,6 +127,52 @@ Notes:
|
|
|
125
127
|
- All standard options work with Supabase mode (`--verify`, `--print-sql`, `--skip-optional-permissions`, etc.)
|
|
126
128
|
- When using `--verify`, the tool checks if all required setup is in place
|
|
127
129
|
|
|
130
|
+
### ClickHouse Managed Postgres
|
|
131
|
+
|
|
132
|
+
Hosts ending in `.pg.clickhouse.cloud` are auto-detected; `--provider clickhouse` forces it.
|
|
133
|
+
The plan is the same superuser plan as self-managed Postgres (`--print-sql` shows it).
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
npx postgresai prepare-db 'postgres://postgres:...@xxx.pg.clickhouse.cloud:5432/postgres?channel_binding=require'
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Before any grant runs, one `-- scope:` line lists exactly what the run grants the
|
|
140
|
+
monitoring role, derived from the steps about to run (so it shrinks under `--skip-optional-permissions`
|
|
141
|
+
and is not printed on `--reset-password`, which grants nothing). With `--json` it goes to stderr.
|
|
142
|
+
|
|
143
|
+
For `prepare-db`, `channel_binding=require` in a URI or conninfo string enables SCRAM-SHA-256-PLUS when the server
|
|
144
|
+
offers it, disables the plaintext retry that `sslmode=prefer` would otherwise do, and is rejected
|
|
145
|
+
together with `sslmode=disable`. The mechanism actually negotiated is not enforced by the driver.
|
|
146
|
+
|
|
147
|
+
The collector cannot do channel binding. `mon targets add`, `mon local-install --db-url`, and
|
|
148
|
+
`pgai connect` remove `channel_binding` from the saved/box URL. With `require`, they refuse
|
|
149
|
+
`sslmode=disable` or `allow`; keep `verify-full` with a warning; and upgrade `require`, `prefer`,
|
|
150
|
+
`verify-ca` or unset to `verify-full` after testing certificate and hostname verification with
|
|
151
|
+
Node's default trust store (or the CA file in `sslrootcert`). Authentication or other errors after
|
|
152
|
+
a verified TLS handshake do not block the upgrade. If verification fails, provide
|
|
153
|
+
`sslrootcert=<CA file>` with `sslmode=verify-full`, or explicitly accept the downgrade by removing
|
|
154
|
+
`channel_binding=require`. Successful upgrades print the collector warning and
|
|
155
|
+
`upgraded to sslmode=verify-full`. `channel_binding=prefer` or `disable` is removed with a note.
|
|
156
|
+
|
|
157
|
+
### ClickHouse Cloud host metrics
|
|
158
|
+
|
|
159
|
+
For a ClickHouse Managed Postgres target, `mon local-install --db-url` and `mon targets add` also set up
|
|
160
|
+
host metrics (CPU, memory, disk, I/O) from the ClickHouse Cloud Prometheus endpoint when these are set:
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
export CLICKHOUSE_ORG_ID='<org-id>' CLICKHOUSE_KEY_ID='<key-id>' CLICKHOUSE_KEY_SECRET='<key-secret>'
|
|
164
|
+
npx postgresai mon local-install --db-url 'postgres://postgres_ai_mon:...@xxx.pg.clickhouse.cloud:5432/postgres?sslmode=require'
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Use an organization API key with the **Basic Service API Reader** role: it is the least privilege that
|
|
168
|
+
works (it can list Postgres services and read `/prometheus`, and cannot change anything or create keys).
|
|
169
|
+
The CLI does not need an Admin key.
|
|
170
|
+
|
|
171
|
+
The key secret is stored in plaintext in `host-metrics/clickhouse-<name>.secret` in the monitoring
|
|
172
|
+
project directory (file 0600, directory 0700), because VictoriaMetrics reads it from a file for basic
|
|
173
|
+
auth. It is never printed or logged. `mon targets remove <name>` deletes it. To rotate the key, re-run
|
|
174
|
+
`mon targets add` with the new key.
|
|
175
|
+
|
|
128
176
|
### Verify and password reset
|
|
129
177
|
|
|
130
178
|
Verify that everything is configured as expected (no changes):
|
|
@@ -141,6 +189,144 @@ npx postgresai prepare-db postgresql://admin@host:5432/dbname --reset-password -
|
|
|
141
189
|
|
|
142
190
|
## Quick start
|
|
143
191
|
|
|
192
|
+
### One command: `pgai connect`
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
pgai connect 'postgresql://postgres:<password>@<host>:5432/postgres'
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
It signs you in if needed, creates the `postgres_ai_mon` role (with an admin URL; otherwise it
|
|
199
|
+
prints the SQL), provisions monitoring in PostgresAI Cloud, runs the express checkup (the checks
|
|
200
|
+
of `pgai checkup`, as `postgres_ai_mon`) while the box starts and prints its findings (in JSON:
|
|
201
|
+
`checkup`; skipped where PostgresAI keeps the role's password: no `checkup` key, no first report),
|
|
202
|
+
waits, and prints the dashboard URL. Safe to re-run; a `--clickhouse-key` given on a
|
|
203
|
+
re-run is checked, and a rejected one is `action_required`. For ClickHouse Managed Postgres add `--clickhouse-key <key-id>:<key-secret>`
|
|
204
|
+
(a Basic Service API Reader key) for CPU, memory and disk. `--self-hosted` runs the stack on this
|
|
205
|
+
machine instead. When stdout is not a terminal the result is JSON with `status`, `dashboard_url`
|
|
206
|
+
and `next`. Then: `pgai databases`, `pgai status <name>`, `pgai disconnect <name>`.
|
|
207
|
+
|
|
208
|
+
With JSON output (`--json`, or stdout not a terminal) stderr is the progress stream: one JSON
|
|
209
|
+
object a line, each with `event`. Besides the steps, any other text is
|
|
210
|
+
`{"event":"log","level":"error"|"warn"|"info"|"debug","message":...}`: an error (also a missing
|
|
211
|
+
argument or a bad option; an unknown option is named without its value), a warning (`warn`: a line
|
|
212
|
+
with `Warning:`, also after a `[F001] ` prefix), the `--debug` request log (`debug`), and with
|
|
213
|
+
`--self-hosted` each line of `mon local-install`
|
|
214
|
+
(`"source":"mon local-install"`; `info` from its stdout, `error` from its stderr; the Grafana and
|
|
215
|
+
VictoriaMetrics logins it prints at its end are masked: `pgai mon show-grafana-credentials` shows them).
|
|
216
|
+
|
|
217
|
+
`pgai init` is the same for a person at a terminal: it signs in, asks for the database URL (and,
|
|
218
|
+
for ClickHouse, the API key; neither is shown as typed), then runs `pgai connect`. Without a
|
|
219
|
+
terminal, or with `--json`, it only points to `pgai connect`.
|
|
220
|
+
|
|
221
|
+
| Option | |
|
|
222
|
+
|---|---|
|
|
223
|
+
| `--provider <provider>` | `clickhouse`, `rds`, `supabase` or `self-managed`; default: detected from the host |
|
|
224
|
+
| `--clickhouse-key <key-id>:<key-secret>` | ClickHouse Cloud API key, for CPU, memory and disk |
|
|
225
|
+
| `--self-hosted` | run the stack on this machine (`mon local-install`) instead of PostgresAI Cloud |
|
|
226
|
+
| `--reset-password` | `postgres_ai_mon` exists and its password is lost: set a new one (see below) |
|
|
227
|
+
| `--wait <minutes>` | how long to wait for the monitoring box; `0` does not wait (default 20) |
|
|
228
|
+
| `-y, --yes` | never prompt; accept a billed box's price (`connect` does not start the browser sign-in; `disconnect` does not ask) |
|
|
229
|
+
| `--coupon <code>` | promotion code for the organization's monitoring subscription |
|
|
230
|
+
| `--json` | JSON output, also on a terminal |
|
|
231
|
+
|
|
232
|
+
Without `--yes`, a non-interactive run for a billed box returns `action_required` with the price
|
|
233
|
+
and asks you to re-run with `--yes` to accept it.
|
|
234
|
+
|
|
235
|
+
| Environment | |
|
|
236
|
+
|---|---|
|
|
237
|
+
| `PGAI_API_KEY` | the API key, instead of signing in (agents, CI) |
|
|
238
|
+
| `PGAI_MON_PASSWORD` | the password of `postgres_ai_mon`. For a new role it is set; for an existing role it is checked by logging in, and never changed. Without it a new role gets a generated password. Not needed for another database on a server PostgresAI already monitors for the organization, with `sslmode=require` or `verify-*` in the URL (see below) |
|
|
239
|
+
| `PGPASSWORD` | the password for a URL without one. With a `postgres_ai_mon` URL it is the password the monitoring box gets, once the server has checked it |
|
|
240
|
+
| `PGSSLMODE` | the `sslmode` for a URL without one (`sslmode` in the URL wins, as in libpq) |
|
|
241
|
+
| `CLICKHOUSE_KEY_ID` + `CLICKHOUSE_KEY_SECRET` | instead of `--clickhouse-key`; read for ClickHouse hosts only |
|
|
242
|
+
|
|
243
|
+
`postgres_ai_mon` is one role for the whole server, so `connect` never changes the password of an
|
|
244
|
+
existing one. If the role exists and you do not have its password (a reconnect after
|
|
245
|
+
`pgai disconnect`, say), `pgai connect <admin-url> --reset-password` sets a new one
|
|
246
|
+
(`PGAI_MON_PASSWORD`, else generated). It is refused while another database on the same server (the same host name, in this
|
|
247
|
+
organization) is monitored with the role, while a box is named `Monitoring <hash>` (the platform
|
|
248
|
+
could not read its URL, so its server is not known), with `--self-hosted`, and for a database
|
|
249
|
+
already connected. After the price is accepted, the run takes the platform's lock on the server (its host
|
|
250
|
+
name and port, in this organization) until the box is requested. A second `--reset-password` for
|
|
251
|
+
the same server exits 3 meanwhile. A run that stopped, or whose box request got no answer, frees the
|
|
252
|
+
server 15 minutes after it took the lock. A platform without the lock answers "set
|
|
253
|
+
`PGAI_MON_PASSWORD`" instead. Anything else that logs in as `postgres_ai_mon` (another organization,
|
|
254
|
+
another host name for the same server, a connect without `--reset-password` running at the same
|
|
255
|
+
time) needs the new password.
|
|
256
|
+
|
|
257
|
+
Another database on a server PostgresAI already monitors for the organization needs neither: with
|
|
258
|
+
`sslmode=require` or `verify-*` in the URL, the role keeps its password, the box's URL carries
|
|
259
|
+
none, and PostgresAI fills in the one it kept from the first `connect` (only over TLS, each query
|
|
260
|
+
parameter once, and only while a box on that server is not deleted, being deleted, or failed to
|
|
261
|
+
delete). The express checkup is skipped then: it runs only as `postgres_ai_mon`, never as the
|
|
262
|
+
admin. The full checkup follows on the box. On a server without TLS the kept password cannot be
|
|
263
|
+
used: set `PGAI_MON_PASSWORD`, or turn TLS on; if nobody has the password, disconnect the server's
|
|
264
|
+
other databases, then `--reset-password` with `PGAI_MON_PASSWORD` set to a new one, and connect
|
|
265
|
+
them again with it (`connect` names them).
|
|
266
|
+
|
|
267
|
+
When preparing an existing role with a supplied password (an admin URL with `PGAI_MON_PASSWORD`,
|
|
268
|
+
or the role's own URL), `connect` also tries a random password as `postgres_ai_mon` to learn
|
|
269
|
+
whether the server checks passwords for this host. Successful PostgresAI Cloud preparation makes
|
|
270
|
+
two attempts: one in the check before the price, and one in preparation. Stopping after the check
|
|
271
|
+
(for example, without accepting the price) makes one. Successful `--self-hosted` preparation
|
|
272
|
+
makes one. Creating or resetting the role with an admin URL, using the platform's stored password,
|
|
273
|
+
or returning an existing box's status makes no random-password attempts. A rejected supplied
|
|
274
|
+
password stops before the random-password probe; that rejection is itself a failed login.
|
|
275
|
+
On a server that checks passwords, each random-password attempt adds one
|
|
276
|
+
`password authentication failed for user "postgres_ai_mon"` line to the server log and counts
|
|
277
|
+
toward failed-login policies (credcheck, fail2ban). On a server that does not (`trust`), `next`
|
|
278
|
+
says that the password was not checked; a password from `PGPASSWORD` is then not used: put it
|
|
279
|
+
in the URL.
|
|
280
|
+
|
|
281
|
+
A role that is not a superuser creates `postgres_ai_mon` only if it can run the whole
|
|
282
|
+
preparation: `CREATEROLE`, `CREATE` on the database, `pg_stat_statements` already installed, and
|
|
283
|
+
on PostgreSQL 16+ `ADMIN OPTION` on `pg_monitor` and `pg_read_all_stats`. Otherwise the SQL is
|
|
284
|
+
printed and nothing is created.
|
|
285
|
+
|
|
286
|
+
The host and the port are the ones in the URL: `host` or `port` in the query string is refused.
|
|
287
|
+
Of the query string, the monitoring box gets `sslmode` and `application_name`; `channel_binding`
|
|
288
|
+
is removed using the collector rule above, before a price is quoted or anything is changed.
|
|
289
|
+
Certificate files (`sslrootcert`, `sslcert`, `sslkey`) are used for the connections from this
|
|
290
|
+
machine only; with `sslmode=verify-ca` or `verify-full` and a private CA in `sslrootcert`, `next`
|
|
291
|
+
says that the box has no copy of that CA.
|
|
292
|
+
|
|
293
|
+
A run that fails does not leave such a role behind. The ClickHouse key and the service state are
|
|
294
|
+
checked before the database is touched. If the platform refuses the launch, or a later step of the
|
|
295
|
+
preparation fails, a role that this run created with a generated password is dropped again, so the
|
|
296
|
+
same command can be run again. (After a platform error that is not a refusal, such as a 5xx or a
|
|
297
|
+
timeout, the role stays: a monitoring box may be starting with it.)
|
|
298
|
+
|
|
299
|
+
An admin URL without a database connects to `PGDATABASE`, or else to the database named like the
|
|
300
|
+
user; the name of the connected database (`<host>[:<port>]/<database>`) uses that database.
|
|
301
|
+
|
|
302
|
+
`pgai connect`, `pgai status` and `pgai databases` use the same words:
|
|
303
|
+
|
|
304
|
+
| `status` | Meaning | Exit code |
|
|
305
|
+
|---|---|---|
|
|
306
|
+
| `connected` | monitoring works; `dashboard_url` is set | 0 |
|
|
307
|
+
| `provisioning` | the monitoring box is being set up; check with `pgai status <name>` | 0 |
|
|
308
|
+
| `disconnecting` | a disconnect is in progress (`pgai status`) | 0 |
|
|
309
|
+
| `disconnected` | the result of `pgai disconnect` | 0 |
|
|
310
|
+
| `action_required` | do what `next` says, then re-run | 3 |
|
|
311
|
+
| `failed` | `next` has the reason | 1 |
|
|
312
|
+
|
|
313
|
+
`pgai init` exits with 130 when cancelled at a prompt (Ctrl-C, Ctrl-D).
|
|
314
|
+
|
|
315
|
+
`--self-hosted` starts `mon local-install` with the monitoring URL, the API key and the ClickHouse
|
|
316
|
+
key in its environment (`PGAI_DB_URL`, `PGAI_API_KEY`, `CLICKHOUSE_*`), not in its arguments.
|
|
317
|
+
`mon local-install` reads `PGAI_DB_URL` like `--db-url`, and `PGAI_API_KEY` only together with
|
|
318
|
+
`PGAI_DB_URL`: an exported `PGAI_API_KEY` alone does not change a plain or `--demo` install.
|
|
319
|
+
`mon targets add [name]` reads `PGAI_DB_URL` when argv has no `postgres://` / `postgresql://` URL
|
|
320
|
+
(a URL in argv wins); with it set, a lone argument other than a plain name (ASCII letters,
|
|
321
|
+
digits, `.`, `_`, `=`, `-`, with no `password=` / `pwd=`) is refused. Its default name is
|
|
322
|
+
`<host>-<database>`. Percent-encode the user name and the password one at a time (all but ASCII
|
|
323
|
+
letters, digits, `-`, `.`, `_` and `~`), and an `@` in the database name or the query. A user name
|
|
324
|
+
or password that pgx would misread or refuse is refused; an `@` after the host is refused, since it
|
|
325
|
+
cannot be told apart from one in a password; so is a control character anywhere in the URL.
|
|
326
|
+
Under sudo, pass `PGAI_DB_URL` on stdin, not with `--preserve-env`: sudo logs the variables it keeps.
|
|
327
|
+
Where sudoers enables I/O logging (`log_input`), sudo records stdin too: read the URL from a file
|
|
328
|
+
of mode 0600 inside the root shell instead.
|
|
329
|
+
|
|
144
330
|
### Authentication
|
|
145
331
|
|
|
146
332
|
Authenticate via browser to obtain API key:
|
|
@@ -250,12 +436,17 @@ postgresai mon health [--wait <sec>] # Check monitoring services health
|
|
|
250
436
|
|
|
251
437
|
When `--instance-id <uuid>` (or `PGAI_INSTANCE_ID`) is set, `local-install` forwards the id to the platform, which **adopts** the already-provisioned monitoring instance instead of self-registering a duplicate under an auto-created `postgres-ai-monitoring` project. The CLI then persists the adopted instance's real project to `.pgwatch-config`, so checkup reports upload alongside the rest of that instance's health data. Adoption is awaited (with one automatic retry); if it fails, the CLI warns and reports fall back to the default project until you re-run `local-install`. Without the flag, the legacy self-registration path is byte-for-byte unchanged.
|
|
252
438
|
|
|
253
|
-
`local-install` writes `.env` in the monitoring directory. It preserves existing `REPLICATOR_PASSWORD` and `
|
|
439
|
+
`local-install` writes `.env` in the monitoring directory. It preserves existing `REPLICATOR_PASSWORD`, `VM_AUTH_*` and the VictoriaMetrics admin-endpoint keys (`VM_DELETE_AUTH_KEY`, `VM_SNAPSHOT_AUTH_KEY`, `VM_FORCE_MERGE_AUTH_KEY`, `VM_PPROF_AUTH_KEY`, added in 0.17) or generates new random ones when missing. The admin keys live on the `sink-prometheus` command line, so `mon update` and `mon update-config` also recreate that container to apply them; `mon restart` (`docker compose restart`) does not; `VM_AUTH_USERNAME` defaults to `vmauth` when absent. The replication password is used by the demo PostgreSQL standby replication user, and the VM auth credentials are required before Docker Compose can provision Grafana datasources. If you run `docker compose` directly or maintain `.env` yourself, set both VM auth values before upgrading. For rotation, run `VM_AUTH_PASSWORD="$(openssl rand -base64 18)" ./scripts/rotate-vm-auth.sh` from the monitoring directory so `.env`, `sink-prometheus`, and `grafana` update together.
|
|
254
440
|
|
|
255
441
|
#### Monitoring target databases (`mon targets` subgroup)
|
|
256
442
|
```bash
|
|
257
443
|
postgresai mon targets list # List databases to monitor
|
|
258
444
|
postgresai mon targets add <conn-string> <name> # Add database to monitor
|
|
445
|
+
# Same, URL kept out of argv and out of the sudo log (read from stdin, not exported),
|
|
446
|
+
# unless sudoers enables I/O logging (log_input), which records stdin:
|
|
447
|
+
printf '%s\n' "$URL" | sudo sh -c 'IFS= read -r PGAI_DB_URL; export PGAI_DB_URL; exec postgresai mon targets add <name>'
|
|
448
|
+
# With log_input, read it from a file of mode 0600 inside the root shell:
|
|
449
|
+
sudo sh -c 'IFS= read -r PGAI_DB_URL < /path/to/db-url; export PGAI_DB_URL; exec postgresai mon targets add <name>'
|
|
259
450
|
postgresai mon targets remove <name> # Remove monitoring target
|
|
260
451
|
postgresai mon targets test <name> # Test target connectivity
|
|
261
452
|
```
|
|
@@ -271,6 +462,35 @@ postgresai mon check # System readiness check
|
|
|
271
462
|
postgresai mon shell <service> # Open shell to monitoring service
|
|
272
463
|
```
|
|
273
464
|
|
|
465
|
+
### PromQL queries (`promql`)
|
|
466
|
+
|
|
467
|
+
Ask a monitoring instance a PromQL question through the platform. The platform
|
|
468
|
+
never connects to the instance: it queues the query as a job, the instance picks
|
|
469
|
+
it up on its next poll, runs it against its own metric store, and posts the
|
|
470
|
+
answer back.
|
|
471
|
+
|
|
472
|
+
```bash
|
|
473
|
+
# instant query
|
|
474
|
+
pgai promql 'up' --instance <instance-uuid>
|
|
475
|
+
|
|
476
|
+
# range query
|
|
477
|
+
pgai promql 'sum(rate(pgwatch_db_stats_xact_commit[5m]))' \
|
|
478
|
+
--instance <instance-uuid> \
|
|
479
|
+
--range --start 2026-09-21T00:00:00Z --end 2026-09-21T01:00:00Z --step 60
|
|
480
|
+
|
|
481
|
+
# on the box itself, --instance is read from .pgwatch-config
|
|
482
|
+
pgai promql 'up'
|
|
483
|
+
```
|
|
484
|
+
|
|
485
|
+
`--at <time>` evaluates an instant query at a given moment (ignored with
|
|
486
|
+
`--range`). `--json` prints every point instead of the first and last per series.
|
|
487
|
+
The wait is sized from the instance's poll pacing; `--timeout` overrides it. A
|
|
488
|
+
result too large for the byte budget is trimmed and flagged `truncated`.
|
|
489
|
+
|
|
490
|
+
Requires platform-all !809
|
|
491
|
+
(https://gitlab.com/postgres-ai/platform-all/-/merge_requests/809); until it is
|
|
492
|
+
deployed the command returns a PGRST202 404.
|
|
493
|
+
|
|
274
494
|
### MCP server (`mcp` group)
|
|
275
495
|
|
|
276
496
|
```bash
|
|
@@ -299,14 +519,15 @@ required** — the server will not assume an organization. Call `orgs_list` (or
|
|
|
299
519
|
run `pgai orgs`) to discover the available ids.
|
|
300
520
|
|
|
301
521
|
Tools exposed:
|
|
302
|
-
- `list_issues`: returns the same JSON as `postgresai issues list` (args: `{ org_id, status?, hidden_only?, limit?, offset?, debug? }`).
|
|
522
|
+
- `list_issues`: returns the same JSON as `postgresai issues list` (args: `{ org_id, status?, hidden_only?, limit?, offset?, debug? }`). Unlike the CLI, omitting `status` returns open and closed issues; pass `status: "open"` to match the CLI default.
|
|
303
523
|
- `view_issue`: view a single issue with its comments (args: `{ issue_id, org_id, debug? }`).
|
|
304
|
-
- `create_issue`: create a new issue (args: `{ title, description?, org_id, attachments?, debug? }`).
|
|
305
|
-
- `update_issue`: update title/description/status/labels (args: `{ issue_id, org_id, title?, description?, status?, labels?, attachments?, debug? }`).
|
|
524
|
+
- `create_issue`: create a new issue (args: `{ title, description?, org_id, project_id?, labels?, attachments?, is_hidden?, debug? }`).
|
|
525
|
+
- `update_issue`: update title/description/status/labels/is_hidden (args: `{ issue_id, org_id, title?, description?, status?, labels?, attachments?, is_hidden?, debug? }`).
|
|
306
526
|
- `post_issue_comment`: post a comment (args: `{ issue_id, org_id, content?, parent_comment_id?, attachments?, debug? }`).
|
|
307
527
|
- `update_issue_comment`: update an existing comment (args: `{ comment_id, org_id, content?, attachments?, debug? }`).
|
|
308
528
|
- `upload_file`: upload a local file and return the storage URL plus a ready-to-paste markdown link (args: `{ path, org_id, debug? }`).
|
|
309
529
|
- `download_file`: download a file from storage (args: `{ url, org_id, output_path?, debug? }`).
|
|
530
|
+
- `connect_database`: `pgai connect` as a tool (args: `{ database_url, org_id, provider?, clickhouse_key?, yes?, coupon?, debug? }`). Returns the same JSON (`status`: `connected`, `provisioning`, `disconnecting`, `action_required` or `failed`; `dashboard_url`; `next`). For a billed box, the tool first returns the price with `action_required`; an explicit call with `yes: true` accepts it. `coupon` supplies a promotion code. It does not wait for the monitoring box: call it again to see the status. `database_url` must carry its password, and only the query parameters `sslmode`, `channel_binding`, `application_name` (and `password`); `PGAI_MON_PASSWORD`, `PGPASSWORD` and `CLICKHOUSE_KEY_ID` + `CLICKHOUSE_KEY_SECRET` of the server process are not used, a TLS failure is not retried in plaintext, and `--self-hosted` is CLI-only. For another database on a server PostgresAI already monitors for the organization, an admin `database_url` with `sslmode=require` (or `verify-*`) is enough: PostgresAI fills in the password of `postgres_ai_mon` it keeps.
|
|
310
531
|
|
|
311
532
|
#### `attachments` parameter (issue/comment tools)
|
|
312
533
|
|
|
@@ -350,11 +571,14 @@ sensitive.
|
|
|
350
571
|
### Issues management (`issues` group)
|
|
351
572
|
|
|
352
573
|
```bash
|
|
353
|
-
postgresai issues list # List issues (shows: id, title, status, created_at; is_hidden only when set)
|
|
574
|
+
postgresai issues list # List OPEN issues (shows: id, title, status, created_at; is_hidden only when set)
|
|
575
|
+
postgresai issues list --status closed # Only closed issues (--status all for both)
|
|
354
576
|
postgresai issues list --hidden-only # Only hidden issues (PostgresAI staff)
|
|
355
577
|
postgresai issues view <issueId> # View issue details and comments
|
|
356
|
-
postgresai issues create --org-id <id>
|
|
578
|
+
postgresai issues create --org-id <id> <title> # Create a new issue
|
|
579
|
+
postgresai issues create --org-id <id> <title> --hidden # Create a hidden issue (PostgresAI staff)
|
|
357
580
|
postgresai issues update <issueId> [--title ... --status ...]# Update an existing issue
|
|
581
|
+
postgresai issues update <issueId> --hidden|--no-hidden # Hide / unhide an issue (PostgresAI staff)
|
|
358
582
|
postgresai issues post-comment <issueId> <content> # Post a comment to an issue
|
|
359
583
|
postgresai issues update-comment <commentId> <content> # Update an existing comment
|
|
360
584
|
postgresai issues files upload <path> # Upload a file, print URL + markdown
|
|
@@ -370,7 +594,11 @@ postgresai issues files download <url> [-o <path>] # Download a file
|
|
|
370
594
|
Hidden issues are staff-internal. `issues list` and `issues view` mark them
|
|
371
595
|
with `is_hidden: true`; the key is omitted entirely otherwise, so ordinary
|
|
372
596
|
issues look exactly as they always have. `--hidden-only` lists just the hidden
|
|
373
|
-
ones, filtered server-side.
|
|
597
|
+
ones, filtered server-side. `issues create --hidden` creates one, and
|
|
598
|
+
`issues update --hidden` / `--no-hidden` hides or unhides an existing issue
|
|
599
|
+
(MCP: `is_hidden` on `create_issue` / `update_issue`). The CLI does no staff
|
|
600
|
+
check of its own: the platform refuses a visibility change for a non-staff
|
|
601
|
+
credential with a plain error, and the CLI prints it and exits non-zero.
|
|
374
602
|
|
|
375
603
|
Staff access is granted per credential, not per person, and a credential that
|
|
376
604
|
does not qualify simply sees nothing — `--hidden-only` returns an empty list
|
|
@@ -556,7 +784,7 @@ PGPASSWORD=... postgresai checkup \
|
|
|
556
784
|
`postgresai checkup <ID> <conn>`); stdout is then a one-key object.
|
|
557
785
|
- **stderr** carries only human-readable diagnostics (progress, warnings,
|
|
558
786
|
errors). It never contains report JSON — machine consumers should read stdout
|
|
559
|
-
only. Do not parse stderr as JSON.
|
|
787
|
+
only. Do not parse stderr of `checkup` as JSON (that of `pgai connect` is JSON lines, see above).
|
|
560
788
|
- **Exit codes**: `0` on success; non-zero when the run fails (connection
|
|
561
789
|
failure, insufficient permissions, an unknown/unavailable check ID, or a
|
|
562
790
|
failing check). On a non-zero exit, no JSON report object is written to
|