postgresai 0.15.0-dev.2 → 0.15.0-dev.4

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.
@@ -27,6 +27,7 @@ var __export = (target, all) => {
27
27
  set: (newValue) => all[name] = () => newValue
28
28
  });
29
29
  };
30
+ var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
30
31
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
31
32
 
32
33
  // node_modules/commander/lib/error.js
@@ -13046,6 +13047,92 @@ var require_dist2 = __commonJS((exports, module) => {
13046
13047
  exports.default = formatsPlugin;
13047
13048
  });
13048
13049
 
13050
+ // lib/util.ts
13051
+ var exports_util2 = {};
13052
+ __export(exports_util2, {
13053
+ resolveBaseUrls: () => resolveBaseUrls2,
13054
+ normalizeBaseUrl: () => normalizeBaseUrl2,
13055
+ maskSecret: () => maskSecret2,
13056
+ formatHttpError: () => formatHttpError2
13057
+ });
13058
+ function isHtmlContent2(text) {
13059
+ const trimmed = text.trim();
13060
+ return trimmed.startsWith("<!DOCTYPE") || trimmed.startsWith("<html") || trimmed.startsWith("<HTML");
13061
+ }
13062
+ function formatHttpError2(operation, status, responseBody) {
13063
+ const statusMessage = HTTP_STATUS_MESSAGES2[status] || "Request failed";
13064
+ let errMsg = `${operation}: HTTP ${status} - ${statusMessage}`;
13065
+ if (responseBody) {
13066
+ if (isHtmlContent2(responseBody)) {
13067
+ return errMsg;
13068
+ }
13069
+ try {
13070
+ const errObj = JSON.parse(responseBody);
13071
+ const message = errObj.message || errObj.error || errObj.detail;
13072
+ if (message && typeof message === "string") {
13073
+ errMsg += `
13074
+ ${message}`;
13075
+ } else {
13076
+ errMsg += `
13077
+ ${JSON.stringify(errObj, null, 2)}`;
13078
+ }
13079
+ } catch {
13080
+ const trimmed = responseBody.trim();
13081
+ if (trimmed.length > 0 && trimmed.length < 500) {
13082
+ errMsg += `
13083
+ ${trimmed}`;
13084
+ }
13085
+ }
13086
+ }
13087
+ return errMsg;
13088
+ }
13089
+ function maskSecret2(secret) {
13090
+ if (!secret)
13091
+ return "";
13092
+ if (secret.length <= 8)
13093
+ return "****";
13094
+ if (secret.length <= 16)
13095
+ return `${secret.slice(0, 4)}${"*".repeat(secret.length - 8)}${secret.slice(-4)}`;
13096
+ return `${secret.slice(0, Math.min(12, secret.length - 8))}${"*".repeat(Math.max(4, secret.length - 16))}${secret.slice(-4)}`;
13097
+ }
13098
+ function normalizeBaseUrl2(value) {
13099
+ const trimmed = (value || "").replace(/\/$/, "");
13100
+ try {
13101
+ new URL(trimmed);
13102
+ } catch {
13103
+ throw new Error(`Invalid base URL: ${value}`);
13104
+ }
13105
+ return trimmed;
13106
+ }
13107
+ function resolveBaseUrls2(opts, cfg, defaults2 = {}) {
13108
+ const defApi = defaults2.apiBaseUrl || "https://postgres.ai/api/general/";
13109
+ const defUi = defaults2.uiBaseUrl || "https://console.postgres.ai";
13110
+ const defStorage = defaults2.storageBaseUrl || "https://postgres.ai/storage";
13111
+ const apiCandidate = opts?.apiBaseUrl || process.env.PGAI_API_BASE_URL || cfg?.baseUrl || defApi;
13112
+ const uiCandidate = opts?.uiBaseUrl || process.env.PGAI_UI_BASE_URL || defUi;
13113
+ const storageCandidate = opts?.storageBaseUrl || process.env.PGAI_STORAGE_BASE_URL || cfg?.storageBaseUrl || defStorage;
13114
+ return {
13115
+ apiBaseUrl: normalizeBaseUrl2(apiCandidate),
13116
+ uiBaseUrl: normalizeBaseUrl2(uiCandidate),
13117
+ storageBaseUrl: normalizeBaseUrl2(storageCandidate)
13118
+ };
13119
+ }
13120
+ var HTTP_STATUS_MESSAGES2;
13121
+ var init_util = __esm(() => {
13122
+ HTTP_STATUS_MESSAGES2 = {
13123
+ 400: "Bad Request",
13124
+ 401: "Unauthorized - check your API key",
13125
+ 403: "Forbidden - access denied",
13126
+ 404: "Not Found",
13127
+ 408: "Request Timeout",
13128
+ 429: "Too Many Requests - rate limited",
13129
+ 500: "Internal Server Error",
13130
+ 502: "Bad Gateway - server temporarily unavailable",
13131
+ 503: "Service Unavailable - server temporarily unavailable",
13132
+ 504: "Gateway Timeout - server temporarily unavailable"
13133
+ };
13134
+ });
13135
+
13049
13136
  // node_modules/commander/esm.mjs
13050
13137
  var import__ = __toESM(require_commander(), 1);
13051
13138
  var {
@@ -13064,7 +13151,7 @@ var {
13064
13151
  // package.json
13065
13152
  var package_default = {
13066
13153
  name: "postgresai",
13067
- version: "0.15.0-dev.2",
13154
+ version: "0.15.0-dev.4",
13068
13155
  description: "postgres_ai CLI",
13069
13156
  license: "Apache-2.0",
13070
13157
  private: false,
@@ -13140,6 +13227,7 @@ function readConfig() {
13140
13227
  const config = {
13141
13228
  apiKey: null,
13142
13229
  baseUrl: null,
13230
+ storageBaseUrl: null,
13143
13231
  orgId: null,
13144
13232
  defaultProject: null,
13145
13233
  projectName: null
@@ -13151,6 +13239,7 @@ function readConfig() {
13151
13239
  const parsed = JSON.parse(content);
13152
13240
  config.apiKey = parsed.apiKey ?? null;
13153
13241
  config.baseUrl = parsed.baseUrl ?? null;
13242
+ config.storageBaseUrl = parsed.storageBaseUrl ?? null;
13154
13243
  config.orgId = parsed.orgId ?? null;
13155
13244
  config.defaultProject = parsed.defaultProject ?? null;
13156
13245
  config.projectName = parsed.projectName ?? null;
@@ -15873,8 +15962,8 @@ var safeLoadAll = renamed("safeLoadAll", "loadAll");
15873
15962
  var safeDump = renamed("safeDump", "dump");
15874
15963
 
15875
15964
  // bin/postgres-ai.ts
15876
- import * as fs5 from "fs";
15877
- import * as path5 from "path";
15965
+ import * as fs6 from "fs";
15966
+ import * as path6 from "path";
15878
15967
  import * as os3 from "os";
15879
15968
  import * as crypto2 from "crypto";
15880
15969
 
@@ -15892,7 +15981,7 @@ var Result = import_lib.default.Result;
15892
15981
  var TypeOverrides = import_lib.default.TypeOverrides;
15893
15982
  var defaults = import_lib.default.defaults;
15894
15983
  // package.json
15895
- var version = "0.15.0-dev.2";
15984
+ var version = "0.15.0-dev.4";
15896
15985
  var package_default2 = {
15897
15986
  name: "postgresai",
15898
15987
  version,
@@ -15971,6 +16060,7 @@ function readConfig2() {
15971
16060
  const config = {
15972
16061
  apiKey: null,
15973
16062
  baseUrl: null,
16063
+ storageBaseUrl: null,
15974
16064
  orgId: null,
15975
16065
  defaultProject: null,
15976
16066
  projectName: null
@@ -15982,6 +16072,7 @@ function readConfig2() {
15982
16072
  const parsed = JSON.parse(content);
15983
16073
  config.apiKey = parsed.apiKey ?? null;
15984
16074
  config.baseUrl = parsed.baseUrl ?? null;
16075
+ config.storageBaseUrl = parsed.storageBaseUrl ?? null;
15985
16076
  config.orgId = parsed.orgId ?? null;
15986
16077
  config.defaultProject = parsed.defaultProject ?? null;
15987
16078
  config.projectName = parsed.projectName ?? null;
@@ -16079,11 +16170,14 @@ function normalizeBaseUrl(value) {
16079
16170
  function resolveBaseUrls(opts, cfg, defaults2 = {}) {
16080
16171
  const defApi = defaults2.apiBaseUrl || "https://postgres.ai/api/general/";
16081
16172
  const defUi = defaults2.uiBaseUrl || "https://console.postgres.ai";
16173
+ const defStorage = defaults2.storageBaseUrl || "https://postgres.ai/storage";
16082
16174
  const apiCandidate = opts?.apiBaseUrl || process.env.PGAI_API_BASE_URL || cfg?.baseUrl || defApi;
16083
16175
  const uiCandidate = opts?.uiBaseUrl || process.env.PGAI_UI_BASE_URL || defUi;
16176
+ const storageCandidate = opts?.storageBaseUrl || process.env.PGAI_STORAGE_BASE_URL || cfg?.storageBaseUrl || defStorage;
16084
16177
  return {
16085
16178
  apiBaseUrl: normalizeBaseUrl(apiCandidate),
16086
- uiBaseUrl: normalizeBaseUrl(uiCandidate)
16179
+ uiBaseUrl: normalizeBaseUrl(uiCandidate),
16180
+ storageBaseUrl: normalizeBaseUrl(storageCandidate)
16087
16181
  };
16088
16182
  }
16089
16183
 
@@ -16115,18 +16209,18 @@ async function fetchIssues(params) {
16115
16209
  };
16116
16210
  if (debug) {
16117
16211
  const debugHeaders = { ...headers, "access-token": maskSecret(apiKey) };
16118
- console.log(`Debug: Resolved API base URL: ${base}`);
16119
- console.log(`Debug: GET URL: ${url.toString()}`);
16120
- console.log(`Debug: Auth scheme: access-token`);
16121
- console.log(`Debug: Request headers: ${JSON.stringify(debugHeaders)}`);
16212
+ console.error(`Debug: Resolved API base URL: ${base}`);
16213
+ console.error(`Debug: GET URL: ${url.toString()}`);
16214
+ console.error(`Debug: Auth scheme: access-token`);
16215
+ console.error(`Debug: Request headers: ${JSON.stringify(debugHeaders)}`);
16122
16216
  }
16123
16217
  const response = await fetch(url.toString(), {
16124
16218
  method: "GET",
16125
16219
  headers
16126
16220
  });
16127
16221
  if (debug) {
16128
- console.log(`Debug: Response status: ${response.status}`);
16129
- console.log(`Debug: Response headers: ${JSON.stringify(Object.fromEntries(response.headers.entries()))}`);
16222
+ console.error(`Debug: Response status: ${response.status}`);
16223
+ console.error(`Debug: Response headers: ${JSON.stringify(Object.fromEntries(response.headers.entries()))}`);
16130
16224
  }
16131
16225
  const data = await response.text();
16132
16226
  if (response.ok) {
@@ -16157,18 +16251,18 @@ async function fetchIssueComments(params) {
16157
16251
  };
16158
16252
  if (debug) {
16159
16253
  const debugHeaders = { ...headers, "access-token": maskSecret(apiKey) };
16160
- console.log(`Debug: Resolved API base URL: ${base}`);
16161
- console.log(`Debug: GET URL: ${url.toString()}`);
16162
- console.log(`Debug: Auth scheme: access-token`);
16163
- console.log(`Debug: Request headers: ${JSON.stringify(debugHeaders)}`);
16254
+ console.error(`Debug: Resolved API base URL: ${base}`);
16255
+ console.error(`Debug: GET URL: ${url.toString()}`);
16256
+ console.error(`Debug: Auth scheme: access-token`);
16257
+ console.error(`Debug: Request headers: ${JSON.stringify(debugHeaders)}`);
16164
16258
  }
16165
16259
  const response = await fetch(url.toString(), {
16166
16260
  method: "GET",
16167
16261
  headers
16168
16262
  });
16169
16263
  if (debug) {
16170
- console.log(`Debug: Response status: ${response.status}`);
16171
- console.log(`Debug: Response headers: ${JSON.stringify(Object.fromEntries(response.headers.entries()))}`);
16264
+ console.error(`Debug: Response status: ${response.status}`);
16265
+ console.error(`Debug: Response headers: ${JSON.stringify(Object.fromEntries(response.headers.entries()))}`);
16172
16266
  }
16173
16267
  const data = await response.text();
16174
16268
  if (response.ok) {
@@ -16202,18 +16296,18 @@ async function fetchIssue(params) {
16202
16296
  };
16203
16297
  if (debug) {
16204
16298
  const debugHeaders = { ...headers, "access-token": maskSecret(apiKey) };
16205
- console.log(`Debug: Resolved API base URL: ${base}`);
16206
- console.log(`Debug: GET URL: ${url.toString()}`);
16207
- console.log(`Debug: Auth scheme: access-token`);
16208
- console.log(`Debug: Request headers: ${JSON.stringify(debugHeaders)}`);
16299
+ console.error(`Debug: Resolved API base URL: ${base}`);
16300
+ console.error(`Debug: GET URL: ${url.toString()}`);
16301
+ console.error(`Debug: Auth scheme: access-token`);
16302
+ console.error(`Debug: Request headers: ${JSON.stringify(debugHeaders)}`);
16209
16303
  }
16210
16304
  const response = await fetch(url.toString(), {
16211
16305
  method: "GET",
16212
16306
  headers
16213
16307
  });
16214
16308
  if (debug) {
16215
- console.log(`Debug: Response status: ${response.status}`);
16216
- console.log(`Debug: Response headers: ${JSON.stringify(Object.fromEntries(response.headers.entries()))}`);
16309
+ console.error(`Debug: Response status: ${response.status}`);
16310
+ console.error(`Debug: Response headers: ${JSON.stringify(Object.fromEntries(response.headers.entries()))}`);
16217
16311
  }
16218
16312
  const data = await response.text();
16219
16313
  if (response.ok) {
@@ -16275,11 +16369,11 @@ async function createIssue(params) {
16275
16369
  };
16276
16370
  if (debug) {
16277
16371
  const debugHeaders = { ...headers, "access-token": maskSecret(apiKey) };
16278
- console.log(`Debug: Resolved API base URL: ${base}`);
16279
- console.log(`Debug: POST URL: ${url.toString()}`);
16280
- console.log(`Debug: Auth scheme: access-token`);
16281
- console.log(`Debug: Request headers: ${JSON.stringify(debugHeaders)}`);
16282
- console.log(`Debug: Request body: ${body}`);
16372
+ console.error(`Debug: Resolved API base URL: ${base}`);
16373
+ console.error(`Debug: POST URL: ${url.toString()}`);
16374
+ console.error(`Debug: Auth scheme: access-token`);
16375
+ console.error(`Debug: Request headers: ${JSON.stringify(debugHeaders)}`);
16376
+ console.error(`Debug: Request body: ${body}`);
16283
16377
  }
16284
16378
  const response = await fetch(url.toString(), {
16285
16379
  method: "POST",
@@ -16287,8 +16381,8 @@ async function createIssue(params) {
16287
16381
  body
16288
16382
  });
16289
16383
  if (debug) {
16290
- console.log(`Debug: Response status: ${response.status}`);
16291
- console.log(`Debug: Response headers: ${JSON.stringify(Object.fromEntries(response.headers.entries()))}`);
16384
+ console.error(`Debug: Response status: ${response.status}`);
16385
+ console.error(`Debug: Response headers: ${JSON.stringify(Object.fromEntries(response.headers.entries()))}`);
16292
16386
  }
16293
16387
  const data = await response.text();
16294
16388
  if (response.ok) {
@@ -16330,11 +16424,11 @@ async function createIssueComment(params) {
16330
16424
  };
16331
16425
  if (debug) {
16332
16426
  const debugHeaders = { ...headers, "access-token": maskSecret(apiKey) };
16333
- console.log(`Debug: Resolved API base URL: ${base}`);
16334
- console.log(`Debug: POST URL: ${url.toString()}`);
16335
- console.log(`Debug: Auth scheme: access-token`);
16336
- console.log(`Debug: Request headers: ${JSON.stringify(debugHeaders)}`);
16337
- console.log(`Debug: Request body: ${body}`);
16427
+ console.error(`Debug: Resolved API base URL: ${base}`);
16428
+ console.error(`Debug: POST URL: ${url.toString()}`);
16429
+ console.error(`Debug: Auth scheme: access-token`);
16430
+ console.error(`Debug: Request headers: ${JSON.stringify(debugHeaders)}`);
16431
+ console.error(`Debug: Request body: ${body}`);
16338
16432
  }
16339
16433
  const response = await fetch(url.toString(), {
16340
16434
  method: "POST",
@@ -16342,8 +16436,8 @@ async function createIssueComment(params) {
16342
16436
  body
16343
16437
  });
16344
16438
  if (debug) {
16345
- console.log(`Debug: Response status: ${response.status}`);
16346
- console.log(`Debug: Response headers: ${JSON.stringify(Object.fromEntries(response.headers.entries()))}`);
16439
+ console.error(`Debug: Response status: ${response.status}`);
16440
+ console.error(`Debug: Response headers: ${JSON.stringify(Object.fromEntries(response.headers.entries()))}`);
16347
16441
  }
16348
16442
  const data = await response.text();
16349
16443
  if (response.ok) {
@@ -16393,11 +16487,11 @@ async function updateIssue(params) {
16393
16487
  };
16394
16488
  if (debug) {
16395
16489
  const debugHeaders = { ...headers, "access-token": maskSecret(apiKey) };
16396
- console.log(`Debug: Resolved API base URL: ${base}`);
16397
- console.log(`Debug: POST URL: ${url.toString()}`);
16398
- console.log(`Debug: Auth scheme: access-token`);
16399
- console.log(`Debug: Request headers: ${JSON.stringify(debugHeaders)}`);
16400
- console.log(`Debug: Request body: ${body}`);
16490
+ console.error(`Debug: Resolved API base URL: ${base}`);
16491
+ console.error(`Debug: POST URL: ${url.toString()}`);
16492
+ console.error(`Debug: Auth scheme: access-token`);
16493
+ console.error(`Debug: Request headers: ${JSON.stringify(debugHeaders)}`);
16494
+ console.error(`Debug: Request body: ${body}`);
16401
16495
  }
16402
16496
  const response = await fetch(url.toString(), {
16403
16497
  method: "POST",
@@ -16405,8 +16499,8 @@ async function updateIssue(params) {
16405
16499
  body
16406
16500
  });
16407
16501
  if (debug) {
16408
- console.log(`Debug: Response status: ${response.status}`);
16409
- console.log(`Debug: Response headers: ${JSON.stringify(Object.fromEntries(response.headers.entries()))}`);
16502
+ console.error(`Debug: Response status: ${response.status}`);
16503
+ console.error(`Debug: Response headers: ${JSON.stringify(Object.fromEntries(response.headers.entries()))}`);
16410
16504
  }
16411
16505
  const data = await response.text();
16412
16506
  if (response.ok) {
@@ -16445,11 +16539,11 @@ async function updateIssueComment(params) {
16445
16539
  };
16446
16540
  if (debug) {
16447
16541
  const debugHeaders = { ...headers, "access-token": maskSecret(apiKey) };
16448
- console.log(`Debug: Resolved API base URL: ${base}`);
16449
- console.log(`Debug: POST URL: ${url.toString()}`);
16450
- console.log(`Debug: Auth scheme: access-token`);
16451
- console.log(`Debug: Request headers: ${JSON.stringify(debugHeaders)}`);
16452
- console.log(`Debug: Request body: ${body}`);
16542
+ console.error(`Debug: Resolved API base URL: ${base}`);
16543
+ console.error(`Debug: POST URL: ${url.toString()}`);
16544
+ console.error(`Debug: Auth scheme: access-token`);
16545
+ console.error(`Debug: Request headers: ${JSON.stringify(debugHeaders)}`);
16546
+ console.error(`Debug: Request body: ${body}`);
16453
16547
  }
16454
16548
  const response = await fetch(url.toString(), {
16455
16549
  method: "POST",
@@ -16457,8 +16551,8 @@ async function updateIssueComment(params) {
16457
16551
  body
16458
16552
  });
16459
16553
  if (debug) {
16460
- console.log(`Debug: Response status: ${response.status}`);
16461
- console.log(`Debug: Response headers: ${JSON.stringify(Object.fromEntries(response.headers.entries()))}`);
16554
+ console.error(`Debug: Response status: ${response.status}`);
16555
+ console.error(`Debug: Response headers: ${JSON.stringify(Object.fromEntries(response.headers.entries()))}`);
16462
16556
  }
16463
16557
  const data = await response.text();
16464
16558
  if (response.ok) {
@@ -16497,18 +16591,18 @@ async function fetchActionItem(params) {
16497
16591
  };
16498
16592
  if (debug) {
16499
16593
  const debugHeaders = { ...headers, "access-token": maskSecret(apiKey) };
16500
- console.log(`Debug: Resolved API base URL: ${base}`);
16501
- console.log(`Debug: GET URL: ${url.toString()}`);
16502
- console.log(`Debug: Auth scheme: access-token`);
16503
- console.log(`Debug: Request headers: ${JSON.stringify(debugHeaders)}`);
16594
+ console.error(`Debug: Resolved API base URL: ${base}`);
16595
+ console.error(`Debug: GET URL: ${url.toString()}`);
16596
+ console.error(`Debug: Auth scheme: access-token`);
16597
+ console.error(`Debug: Request headers: ${JSON.stringify(debugHeaders)}`);
16504
16598
  }
16505
16599
  const response = await fetch(url.toString(), {
16506
16600
  method: "GET",
16507
16601
  headers
16508
16602
  });
16509
16603
  if (debug) {
16510
- console.log(`Debug: Response status: ${response.status}`);
16511
- console.log(`Debug: Response headers: ${JSON.stringify(Object.fromEntries(response.headers.entries()))}`);
16604
+ console.error(`Debug: Response status: ${response.status}`);
16605
+ console.error(`Debug: Response headers: ${JSON.stringify(Object.fromEntries(response.headers.entries()))}`);
16512
16606
  }
16513
16607
  const data = await response.text();
16514
16608
  if (response.ok) {
@@ -16548,18 +16642,18 @@ async function fetchActionItems(params) {
16548
16642
  };
16549
16643
  if (debug) {
16550
16644
  const debugHeaders = { ...headers, "access-token": maskSecret(apiKey) };
16551
- console.log(`Debug: Resolved API base URL: ${base}`);
16552
- console.log(`Debug: GET URL: ${url.toString()}`);
16553
- console.log(`Debug: Auth scheme: access-token`);
16554
- console.log(`Debug: Request headers: ${JSON.stringify(debugHeaders)}`);
16645
+ console.error(`Debug: Resolved API base URL: ${base}`);
16646
+ console.error(`Debug: GET URL: ${url.toString()}`);
16647
+ console.error(`Debug: Auth scheme: access-token`);
16648
+ console.error(`Debug: Request headers: ${JSON.stringify(debugHeaders)}`);
16555
16649
  }
16556
16650
  const response = await fetch(url.toString(), {
16557
16651
  method: "GET",
16558
16652
  headers
16559
16653
  });
16560
16654
  if (debug) {
16561
- console.log(`Debug: Response status: ${response.status}`);
16562
- console.log(`Debug: Response headers: ${JSON.stringify(Object.fromEntries(response.headers.entries()))}`);
16655
+ console.error(`Debug: Response status: ${response.status}`);
16656
+ console.error(`Debug: Response headers: ${JSON.stringify(Object.fromEntries(response.headers.entries()))}`);
16563
16657
  }
16564
16658
  const data = await response.text();
16565
16659
  if (response.ok) {
@@ -16611,11 +16705,11 @@ async function createActionItem(params) {
16611
16705
  };
16612
16706
  if (debug) {
16613
16707
  const debugHeaders = { ...headers, "access-token": maskSecret(apiKey) };
16614
- console.log(`Debug: Resolved API base URL: ${base}`);
16615
- console.log(`Debug: POST URL: ${url.toString()}`);
16616
- console.log(`Debug: Auth scheme: access-token`);
16617
- console.log(`Debug: Request headers: ${JSON.stringify(debugHeaders)}`);
16618
- console.log(`Debug: Request body: ${body}`);
16708
+ console.error(`Debug: Resolved API base URL: ${base}`);
16709
+ console.error(`Debug: POST URL: ${url.toString()}`);
16710
+ console.error(`Debug: Auth scheme: access-token`);
16711
+ console.error(`Debug: Request headers: ${JSON.stringify(debugHeaders)}`);
16712
+ console.error(`Debug: Request body: ${body}`);
16619
16713
  }
16620
16714
  const response = await fetch(url.toString(), {
16621
16715
  method: "POST",
@@ -16623,8 +16717,8 @@ async function createActionItem(params) {
16623
16717
  body
16624
16718
  });
16625
16719
  if (debug) {
16626
- console.log(`Debug: Response status: ${response.status}`);
16627
- console.log(`Debug: Response headers: ${JSON.stringify(Object.fromEntries(response.headers.entries()))}`);
16720
+ console.error(`Debug: Response status: ${response.status}`);
16721
+ console.error(`Debug: Response headers: ${JSON.stringify(Object.fromEntries(response.headers.entries()))}`);
16628
16722
  }
16629
16723
  const data = await response.text();
16630
16724
  if (response.ok) {
@@ -16688,11 +16782,11 @@ async function updateActionItem(params) {
16688
16782
  };
16689
16783
  if (debug) {
16690
16784
  const debugHeaders = { ...headers, "access-token": maskSecret(apiKey) };
16691
- console.log(`Debug: Resolved API base URL: ${base}`);
16692
- console.log(`Debug: POST URL: ${url.toString()}`);
16693
- console.log(`Debug: Auth scheme: access-token`);
16694
- console.log(`Debug: Request headers: ${JSON.stringify(debugHeaders)}`);
16695
- console.log(`Debug: Request body: ${body}`);
16785
+ console.error(`Debug: Resolved API base URL: ${base}`);
16786
+ console.error(`Debug: POST URL: ${url.toString()}`);
16787
+ console.error(`Debug: Auth scheme: access-token`);
16788
+ console.error(`Debug: Request headers: ${JSON.stringify(debugHeaders)}`);
16789
+ console.error(`Debug: Request body: ${body}`);
16696
16790
  }
16697
16791
  const response = await fetch(url.toString(), {
16698
16792
  method: "POST",
@@ -16700,8 +16794,8 @@ async function updateActionItem(params) {
16700
16794
  body
16701
16795
  });
16702
16796
  if (debug) {
16703
- console.log(`Debug: Response status: ${response.status}`);
16704
- console.log(`Debug: Response headers: ${JSON.stringify(Object.fromEntries(response.headers.entries()))}`);
16797
+ console.error(`Debug: Response status: ${response.status}`);
16798
+ console.error(`Debug: Response headers: ${JSON.stringify(Object.fromEntries(response.headers.entries()))}`);
16705
16799
  }
16706
16800
  if (!response.ok) {
16707
16801
  const data = await response.text();
@@ -16761,13 +16855,13 @@ async function fetchReports(params) {
16761
16855
  };
16762
16856
  if (debug) {
16763
16857
  const debugHeaders = { ...headers, "access-token": maskSecret(apiKey) };
16764
- console.log(`Debug: Resolved API base URL: ${base}`);
16765
- console.log(`Debug: GET URL: ${url.toString()}`);
16766
- console.log(`Debug: Request headers: ${JSON.stringify(debugHeaders)}`);
16858
+ console.error(`Debug: Resolved API base URL: ${base}`);
16859
+ console.error(`Debug: GET URL: ${url.toString()}`);
16860
+ console.error(`Debug: Request headers: ${JSON.stringify(debugHeaders)}`);
16767
16861
  }
16768
16862
  const response = await fetch(url.toString(), { method: "GET", headers });
16769
16863
  if (debug) {
16770
- console.log(`Debug: Response status: ${response.status}`);
16864
+ console.error(`Debug: Response status: ${response.status}`);
16771
16865
  }
16772
16866
  const data = await response.text();
16773
16867
  if (response.ok) {
@@ -16828,13 +16922,13 @@ async function fetchReportFiles(params) {
16828
16922
  };
16829
16923
  if (debug) {
16830
16924
  const debugHeaders = { ...headers, "access-token": maskSecret(apiKey) };
16831
- console.log(`Debug: Resolved API base URL: ${base}`);
16832
- console.log(`Debug: GET URL: ${url.toString()}`);
16833
- console.log(`Debug: Request headers: ${JSON.stringify(debugHeaders)}`);
16925
+ console.error(`Debug: Resolved API base URL: ${base}`);
16926
+ console.error(`Debug: GET URL: ${url.toString()}`);
16927
+ console.error(`Debug: Request headers: ${JSON.stringify(debugHeaders)}`);
16834
16928
  }
16835
16929
  const response = await fetch(url.toString(), { method: "GET", headers });
16836
16930
  if (debug) {
16837
- console.log(`Debug: Response status: ${response.status}`);
16931
+ console.error(`Debug: Response status: ${response.status}`);
16838
16932
  }
16839
16933
  const data = await response.text();
16840
16934
  if (response.ok) {
@@ -16875,13 +16969,13 @@ async function fetchReportFileData(params) {
16875
16969
  };
16876
16970
  if (debug) {
16877
16971
  const debugHeaders = { ...headers, "access-token": maskSecret(apiKey) };
16878
- console.log(`Debug: Resolved API base URL: ${base}`);
16879
- console.log(`Debug: GET URL: ${url.toString()}`);
16880
- console.log(`Debug: Request headers: ${JSON.stringify(debugHeaders)}`);
16972
+ console.error(`Debug: Resolved API base URL: ${base}`);
16973
+ console.error(`Debug: GET URL: ${url.toString()}`);
16974
+ console.error(`Debug: Request headers: ${JSON.stringify(debugHeaders)}`);
16881
16975
  }
16882
16976
  const response = await fetch(url.toString(), { method: "GET", headers });
16883
16977
  if (debug) {
16884
- console.log(`Debug: Response status: ${response.status}`);
16978
+ console.error(`Debug: Response status: ${response.status}`);
16885
16979
  }
16886
16980
  const data = await response.text();
16887
16981
  if (response.ok) {
@@ -24264,18 +24358,18 @@ async function fetchIssues2(params) {
24264
24358
  };
24265
24359
  if (debug) {
24266
24360
  const debugHeaders = { ...headers, "access-token": maskSecret(apiKey) };
24267
- console.log(`Debug: Resolved API base URL: ${base}`);
24268
- console.log(`Debug: GET URL: ${url.toString()}`);
24269
- console.log(`Debug: Auth scheme: access-token`);
24270
- console.log(`Debug: Request headers: ${JSON.stringify(debugHeaders)}`);
24361
+ console.error(`Debug: Resolved API base URL: ${base}`);
24362
+ console.error(`Debug: GET URL: ${url.toString()}`);
24363
+ console.error(`Debug: Auth scheme: access-token`);
24364
+ console.error(`Debug: Request headers: ${JSON.stringify(debugHeaders)}`);
24271
24365
  }
24272
24366
  const response = await fetch(url.toString(), {
24273
24367
  method: "GET",
24274
24368
  headers
24275
24369
  });
24276
24370
  if (debug) {
24277
- console.log(`Debug: Response status: ${response.status}`);
24278
- console.log(`Debug: Response headers: ${JSON.stringify(Object.fromEntries(response.headers.entries()))}`);
24371
+ console.error(`Debug: Response status: ${response.status}`);
24372
+ console.error(`Debug: Response headers: ${JSON.stringify(Object.fromEntries(response.headers.entries()))}`);
24279
24373
  }
24280
24374
  const data = await response.text();
24281
24375
  if (response.ok) {
@@ -24306,18 +24400,18 @@ async function fetchIssueComments2(params) {
24306
24400
  };
24307
24401
  if (debug) {
24308
24402
  const debugHeaders = { ...headers, "access-token": maskSecret(apiKey) };
24309
- console.log(`Debug: Resolved API base URL: ${base}`);
24310
- console.log(`Debug: GET URL: ${url.toString()}`);
24311
- console.log(`Debug: Auth scheme: access-token`);
24312
- console.log(`Debug: Request headers: ${JSON.stringify(debugHeaders)}`);
24403
+ console.error(`Debug: Resolved API base URL: ${base}`);
24404
+ console.error(`Debug: GET URL: ${url.toString()}`);
24405
+ console.error(`Debug: Auth scheme: access-token`);
24406
+ console.error(`Debug: Request headers: ${JSON.stringify(debugHeaders)}`);
24313
24407
  }
24314
24408
  const response = await fetch(url.toString(), {
24315
24409
  method: "GET",
24316
24410
  headers
24317
24411
  });
24318
24412
  if (debug) {
24319
- console.log(`Debug: Response status: ${response.status}`);
24320
- console.log(`Debug: Response headers: ${JSON.stringify(Object.fromEntries(response.headers.entries()))}`);
24413
+ console.error(`Debug: Response status: ${response.status}`);
24414
+ console.error(`Debug: Response headers: ${JSON.stringify(Object.fromEntries(response.headers.entries()))}`);
24321
24415
  }
24322
24416
  const data = await response.text();
24323
24417
  if (response.ok) {
@@ -24351,18 +24445,18 @@ async function fetchIssue2(params) {
24351
24445
  };
24352
24446
  if (debug) {
24353
24447
  const debugHeaders = { ...headers, "access-token": maskSecret(apiKey) };
24354
- console.log(`Debug: Resolved API base URL: ${base}`);
24355
- console.log(`Debug: GET URL: ${url.toString()}`);
24356
- console.log(`Debug: Auth scheme: access-token`);
24357
- console.log(`Debug: Request headers: ${JSON.stringify(debugHeaders)}`);
24448
+ console.error(`Debug: Resolved API base URL: ${base}`);
24449
+ console.error(`Debug: GET URL: ${url.toString()}`);
24450
+ console.error(`Debug: Auth scheme: access-token`);
24451
+ console.error(`Debug: Request headers: ${JSON.stringify(debugHeaders)}`);
24358
24452
  }
24359
24453
  const response = await fetch(url.toString(), {
24360
24454
  method: "GET",
24361
24455
  headers
24362
24456
  });
24363
24457
  if (debug) {
24364
- console.log(`Debug: Response status: ${response.status}`);
24365
- console.log(`Debug: Response headers: ${JSON.stringify(Object.fromEntries(response.headers.entries()))}`);
24458
+ console.error(`Debug: Response status: ${response.status}`);
24459
+ console.error(`Debug: Response headers: ${JSON.stringify(Object.fromEntries(response.headers.entries()))}`);
24366
24460
  }
24367
24461
  const data = await response.text();
24368
24462
  if (response.ok) {
@@ -24424,11 +24518,11 @@ async function createIssue2(params) {
24424
24518
  };
24425
24519
  if (debug) {
24426
24520
  const debugHeaders = { ...headers, "access-token": maskSecret(apiKey) };
24427
- console.log(`Debug: Resolved API base URL: ${base}`);
24428
- console.log(`Debug: POST URL: ${url.toString()}`);
24429
- console.log(`Debug: Auth scheme: access-token`);
24430
- console.log(`Debug: Request headers: ${JSON.stringify(debugHeaders)}`);
24431
- console.log(`Debug: Request body: ${body}`);
24521
+ console.error(`Debug: Resolved API base URL: ${base}`);
24522
+ console.error(`Debug: POST URL: ${url.toString()}`);
24523
+ console.error(`Debug: Auth scheme: access-token`);
24524
+ console.error(`Debug: Request headers: ${JSON.stringify(debugHeaders)}`);
24525
+ console.error(`Debug: Request body: ${body}`);
24432
24526
  }
24433
24527
  const response = await fetch(url.toString(), {
24434
24528
  method: "POST",
@@ -24436,8 +24530,8 @@ async function createIssue2(params) {
24436
24530
  body
24437
24531
  });
24438
24532
  if (debug) {
24439
- console.log(`Debug: Response status: ${response.status}`);
24440
- console.log(`Debug: Response headers: ${JSON.stringify(Object.fromEntries(response.headers.entries()))}`);
24533
+ console.error(`Debug: Response status: ${response.status}`);
24534
+ console.error(`Debug: Response headers: ${JSON.stringify(Object.fromEntries(response.headers.entries()))}`);
24441
24535
  }
24442
24536
  const data = await response.text();
24443
24537
  if (response.ok) {
@@ -24479,11 +24573,11 @@ async function createIssueComment2(params) {
24479
24573
  };
24480
24574
  if (debug) {
24481
24575
  const debugHeaders = { ...headers, "access-token": maskSecret(apiKey) };
24482
- console.log(`Debug: Resolved API base URL: ${base}`);
24483
- console.log(`Debug: POST URL: ${url.toString()}`);
24484
- console.log(`Debug: Auth scheme: access-token`);
24485
- console.log(`Debug: Request headers: ${JSON.stringify(debugHeaders)}`);
24486
- console.log(`Debug: Request body: ${body}`);
24576
+ console.error(`Debug: Resolved API base URL: ${base}`);
24577
+ console.error(`Debug: POST URL: ${url.toString()}`);
24578
+ console.error(`Debug: Auth scheme: access-token`);
24579
+ console.error(`Debug: Request headers: ${JSON.stringify(debugHeaders)}`);
24580
+ console.error(`Debug: Request body: ${body}`);
24487
24581
  }
24488
24582
  const response = await fetch(url.toString(), {
24489
24583
  method: "POST",
@@ -24491,8 +24585,8 @@ async function createIssueComment2(params) {
24491
24585
  body
24492
24586
  });
24493
24587
  if (debug) {
24494
- console.log(`Debug: Response status: ${response.status}`);
24495
- console.log(`Debug: Response headers: ${JSON.stringify(Object.fromEntries(response.headers.entries()))}`);
24588
+ console.error(`Debug: Response status: ${response.status}`);
24589
+ console.error(`Debug: Response headers: ${JSON.stringify(Object.fromEntries(response.headers.entries()))}`);
24496
24590
  }
24497
24591
  const data = await response.text();
24498
24592
  if (response.ok) {
@@ -24542,11 +24636,11 @@ async function updateIssue2(params) {
24542
24636
  };
24543
24637
  if (debug) {
24544
24638
  const debugHeaders = { ...headers, "access-token": maskSecret(apiKey) };
24545
- console.log(`Debug: Resolved API base URL: ${base}`);
24546
- console.log(`Debug: POST URL: ${url.toString()}`);
24547
- console.log(`Debug: Auth scheme: access-token`);
24548
- console.log(`Debug: Request headers: ${JSON.stringify(debugHeaders)}`);
24549
- console.log(`Debug: Request body: ${body}`);
24639
+ console.error(`Debug: Resolved API base URL: ${base}`);
24640
+ console.error(`Debug: POST URL: ${url.toString()}`);
24641
+ console.error(`Debug: Auth scheme: access-token`);
24642
+ console.error(`Debug: Request headers: ${JSON.stringify(debugHeaders)}`);
24643
+ console.error(`Debug: Request body: ${body}`);
24550
24644
  }
24551
24645
  const response = await fetch(url.toString(), {
24552
24646
  method: "POST",
@@ -24554,8 +24648,8 @@ async function updateIssue2(params) {
24554
24648
  body
24555
24649
  });
24556
24650
  if (debug) {
24557
- console.log(`Debug: Response status: ${response.status}`);
24558
- console.log(`Debug: Response headers: ${JSON.stringify(Object.fromEntries(response.headers.entries()))}`);
24651
+ console.error(`Debug: Response status: ${response.status}`);
24652
+ console.error(`Debug: Response headers: ${JSON.stringify(Object.fromEntries(response.headers.entries()))}`);
24559
24653
  }
24560
24654
  const data = await response.text();
24561
24655
  if (response.ok) {
@@ -24594,11 +24688,11 @@ async function updateIssueComment2(params) {
24594
24688
  };
24595
24689
  if (debug) {
24596
24690
  const debugHeaders = { ...headers, "access-token": maskSecret(apiKey) };
24597
- console.log(`Debug: Resolved API base URL: ${base}`);
24598
- console.log(`Debug: POST URL: ${url.toString()}`);
24599
- console.log(`Debug: Auth scheme: access-token`);
24600
- console.log(`Debug: Request headers: ${JSON.stringify(debugHeaders)}`);
24601
- console.log(`Debug: Request body: ${body}`);
24691
+ console.error(`Debug: Resolved API base URL: ${base}`);
24692
+ console.error(`Debug: POST URL: ${url.toString()}`);
24693
+ console.error(`Debug: Auth scheme: access-token`);
24694
+ console.error(`Debug: Request headers: ${JSON.stringify(debugHeaders)}`);
24695
+ console.error(`Debug: Request body: ${body}`);
24602
24696
  }
24603
24697
  const response = await fetch(url.toString(), {
24604
24698
  method: "POST",
@@ -24606,8 +24700,8 @@ async function updateIssueComment2(params) {
24606
24700
  body
24607
24701
  });
24608
24702
  if (debug) {
24609
- console.log(`Debug: Response status: ${response.status}`);
24610
- console.log(`Debug: Response headers: ${JSON.stringify(Object.fromEntries(response.headers.entries()))}`);
24703
+ console.error(`Debug: Response status: ${response.status}`);
24704
+ console.error(`Debug: Response headers: ${JSON.stringify(Object.fromEntries(response.headers.entries()))}`);
24611
24705
  }
24612
24706
  const data = await response.text();
24613
24707
  if (response.ok) {
@@ -24646,18 +24740,18 @@ async function fetchActionItem2(params) {
24646
24740
  };
24647
24741
  if (debug) {
24648
24742
  const debugHeaders = { ...headers, "access-token": maskSecret(apiKey) };
24649
- console.log(`Debug: Resolved API base URL: ${base}`);
24650
- console.log(`Debug: GET URL: ${url.toString()}`);
24651
- console.log(`Debug: Auth scheme: access-token`);
24652
- console.log(`Debug: Request headers: ${JSON.stringify(debugHeaders)}`);
24743
+ console.error(`Debug: Resolved API base URL: ${base}`);
24744
+ console.error(`Debug: GET URL: ${url.toString()}`);
24745
+ console.error(`Debug: Auth scheme: access-token`);
24746
+ console.error(`Debug: Request headers: ${JSON.stringify(debugHeaders)}`);
24653
24747
  }
24654
24748
  const response = await fetch(url.toString(), {
24655
24749
  method: "GET",
24656
24750
  headers
24657
24751
  });
24658
24752
  if (debug) {
24659
- console.log(`Debug: Response status: ${response.status}`);
24660
- console.log(`Debug: Response headers: ${JSON.stringify(Object.fromEntries(response.headers.entries()))}`);
24753
+ console.error(`Debug: Response status: ${response.status}`);
24754
+ console.error(`Debug: Response headers: ${JSON.stringify(Object.fromEntries(response.headers.entries()))}`);
24661
24755
  }
24662
24756
  const data = await response.text();
24663
24757
  if (response.ok) {
@@ -24697,18 +24791,18 @@ async function fetchActionItems2(params) {
24697
24791
  };
24698
24792
  if (debug) {
24699
24793
  const debugHeaders = { ...headers, "access-token": maskSecret(apiKey) };
24700
- console.log(`Debug: Resolved API base URL: ${base}`);
24701
- console.log(`Debug: GET URL: ${url.toString()}`);
24702
- console.log(`Debug: Auth scheme: access-token`);
24703
- console.log(`Debug: Request headers: ${JSON.stringify(debugHeaders)}`);
24794
+ console.error(`Debug: Resolved API base URL: ${base}`);
24795
+ console.error(`Debug: GET URL: ${url.toString()}`);
24796
+ console.error(`Debug: Auth scheme: access-token`);
24797
+ console.error(`Debug: Request headers: ${JSON.stringify(debugHeaders)}`);
24704
24798
  }
24705
24799
  const response = await fetch(url.toString(), {
24706
24800
  method: "GET",
24707
24801
  headers
24708
24802
  });
24709
24803
  if (debug) {
24710
- console.log(`Debug: Response status: ${response.status}`);
24711
- console.log(`Debug: Response headers: ${JSON.stringify(Object.fromEntries(response.headers.entries()))}`);
24804
+ console.error(`Debug: Response status: ${response.status}`);
24805
+ console.error(`Debug: Response headers: ${JSON.stringify(Object.fromEntries(response.headers.entries()))}`);
24712
24806
  }
24713
24807
  const data = await response.text();
24714
24808
  if (response.ok) {
@@ -24760,11 +24854,11 @@ async function createActionItem2(params) {
24760
24854
  };
24761
24855
  if (debug) {
24762
24856
  const debugHeaders = { ...headers, "access-token": maskSecret(apiKey) };
24763
- console.log(`Debug: Resolved API base URL: ${base}`);
24764
- console.log(`Debug: POST URL: ${url.toString()}`);
24765
- console.log(`Debug: Auth scheme: access-token`);
24766
- console.log(`Debug: Request headers: ${JSON.stringify(debugHeaders)}`);
24767
- console.log(`Debug: Request body: ${body}`);
24857
+ console.error(`Debug: Resolved API base URL: ${base}`);
24858
+ console.error(`Debug: POST URL: ${url.toString()}`);
24859
+ console.error(`Debug: Auth scheme: access-token`);
24860
+ console.error(`Debug: Request headers: ${JSON.stringify(debugHeaders)}`);
24861
+ console.error(`Debug: Request body: ${body}`);
24768
24862
  }
24769
24863
  const response = await fetch(url.toString(), {
24770
24864
  method: "POST",
@@ -24772,8 +24866,8 @@ async function createActionItem2(params) {
24772
24866
  body
24773
24867
  });
24774
24868
  if (debug) {
24775
- console.log(`Debug: Response status: ${response.status}`);
24776
- console.log(`Debug: Response headers: ${JSON.stringify(Object.fromEntries(response.headers.entries()))}`);
24869
+ console.error(`Debug: Response status: ${response.status}`);
24870
+ console.error(`Debug: Response headers: ${JSON.stringify(Object.fromEntries(response.headers.entries()))}`);
24777
24871
  }
24778
24872
  const data = await response.text();
24779
24873
  if (response.ok) {
@@ -24837,11 +24931,11 @@ async function updateActionItem2(params) {
24837
24931
  };
24838
24932
  if (debug) {
24839
24933
  const debugHeaders = { ...headers, "access-token": maskSecret(apiKey) };
24840
- console.log(`Debug: Resolved API base URL: ${base}`);
24841
- console.log(`Debug: POST URL: ${url.toString()}`);
24842
- console.log(`Debug: Auth scheme: access-token`);
24843
- console.log(`Debug: Request headers: ${JSON.stringify(debugHeaders)}`);
24844
- console.log(`Debug: Request body: ${body}`);
24934
+ console.error(`Debug: Resolved API base URL: ${base}`);
24935
+ console.error(`Debug: POST URL: ${url.toString()}`);
24936
+ console.error(`Debug: Auth scheme: access-token`);
24937
+ console.error(`Debug: Request headers: ${JSON.stringify(debugHeaders)}`);
24938
+ console.error(`Debug: Request body: ${body}`);
24845
24939
  }
24846
24940
  const response = await fetch(url.toString(), {
24847
24941
  method: "POST",
@@ -24849,8 +24943,8 @@ async function updateActionItem2(params) {
24849
24943
  body
24850
24944
  });
24851
24945
  if (debug) {
24852
- console.log(`Debug: Response status: ${response.status}`);
24853
- console.log(`Debug: Response headers: ${JSON.stringify(Object.fromEntries(response.headers.entries()))}`);
24946
+ console.error(`Debug: Response status: ${response.status}`);
24947
+ console.error(`Debug: Response headers: ${JSON.stringify(Object.fromEntries(response.headers.entries()))}`);
24854
24948
  }
24855
24949
  if (!response.ok) {
24856
24950
  const data = await response.text();
@@ -24910,13 +25004,13 @@ async function fetchReports2(params) {
24910
25004
  };
24911
25005
  if (debug) {
24912
25006
  const debugHeaders = { ...headers, "access-token": maskSecret(apiKey) };
24913
- console.log(`Debug: Resolved API base URL: ${base}`);
24914
- console.log(`Debug: GET URL: ${url.toString()}`);
24915
- console.log(`Debug: Request headers: ${JSON.stringify(debugHeaders)}`);
25007
+ console.error(`Debug: Resolved API base URL: ${base}`);
25008
+ console.error(`Debug: GET URL: ${url.toString()}`);
25009
+ console.error(`Debug: Request headers: ${JSON.stringify(debugHeaders)}`);
24916
25010
  }
24917
25011
  const response = await fetch(url.toString(), { method: "GET", headers });
24918
25012
  if (debug) {
24919
- console.log(`Debug: Response status: ${response.status}`);
25013
+ console.error(`Debug: Response status: ${response.status}`);
24920
25014
  }
24921
25015
  const data = await response.text();
24922
25016
  if (response.ok) {
@@ -24977,13 +25071,13 @@ async function fetchReportFiles2(params) {
24977
25071
  };
24978
25072
  if (debug) {
24979
25073
  const debugHeaders = { ...headers, "access-token": maskSecret(apiKey) };
24980
- console.log(`Debug: Resolved API base URL: ${base}`);
24981
- console.log(`Debug: GET URL: ${url.toString()}`);
24982
- console.log(`Debug: Request headers: ${JSON.stringify(debugHeaders)}`);
25074
+ console.error(`Debug: Resolved API base URL: ${base}`);
25075
+ console.error(`Debug: GET URL: ${url.toString()}`);
25076
+ console.error(`Debug: Request headers: ${JSON.stringify(debugHeaders)}`);
24983
25077
  }
24984
25078
  const response = await fetch(url.toString(), { method: "GET", headers });
24985
25079
  if (debug) {
24986
- console.log(`Debug: Response status: ${response.status}`);
25080
+ console.error(`Debug: Response status: ${response.status}`);
24987
25081
  }
24988
25082
  const data = await response.text();
24989
25083
  if (response.ok) {
@@ -25024,13 +25118,13 @@ async function fetchReportFileData2(params) {
25024
25118
  };
25025
25119
  if (debug) {
25026
25120
  const debugHeaders = { ...headers, "access-token": maskSecret(apiKey) };
25027
- console.log(`Debug: Resolved API base URL: ${base}`);
25028
- console.log(`Debug: GET URL: ${url.toString()}`);
25029
- console.log(`Debug: Request headers: ${JSON.stringify(debugHeaders)}`);
25121
+ console.error(`Debug: Resolved API base URL: ${base}`);
25122
+ console.error(`Debug: GET URL: ${url.toString()}`);
25123
+ console.error(`Debug: Request headers: ${JSON.stringify(debugHeaders)}`);
25030
25124
  }
25031
25125
  const response = await fetch(url.toString(), { method: "GET", headers });
25032
25126
  if (debug) {
25033
- console.log(`Debug: Response status: ${response.status}`);
25127
+ console.error(`Debug: Response status: ${response.status}`);
25034
25128
  }
25035
25129
  const data = await response.text();
25036
25130
  if (response.ok) {
@@ -25097,41 +25191,198 @@ function renderMarkdownForTerminal(md) {
25097
25191
  `);
25098
25192
  }
25099
25193
 
25100
- // lib/util.ts
25101
- function maskSecret2(secret) {
25102
- if (!secret)
25103
- return "";
25104
- if (secret.length <= 8)
25105
- return "****";
25106
- if (secret.length <= 16)
25107
- return `${secret.slice(0, 4)}${"*".repeat(secret.length - 8)}${secret.slice(-4)}`;
25108
- return `${secret.slice(0, Math.min(12, secret.length - 8))}${"*".repeat(Math.max(4, secret.length - 16))}${secret.slice(-4)}`;
25109
- }
25110
- function normalizeBaseUrl2(value) {
25111
- const trimmed = (value || "").replace(/\/$/, "");
25112
- try {
25113
- new URL(trimmed);
25114
- } catch {
25115
- throw new Error(`Invalid base URL: ${value}`);
25194
+ // bin/postgres-ai.ts
25195
+ init_util();
25196
+
25197
+ // lib/storage.ts
25198
+ import * as fs3 from "fs";
25199
+ import * as path3 from "path";
25200
+ var MAX_UPLOAD_SIZE = 500 * 1024 * 1024;
25201
+ var MAX_DOWNLOAD_SIZE = 500 * 1024 * 1024;
25202
+ var MIME_TYPES = {
25203
+ ".png": "image/png",
25204
+ ".jpg": "image/jpeg",
25205
+ ".jpeg": "image/jpeg",
25206
+ ".gif": "image/gif",
25207
+ ".webp": "image/webp",
25208
+ ".svg": "image/svg+xml",
25209
+ ".bmp": "image/bmp",
25210
+ ".ico": "image/x-icon",
25211
+ ".pdf": "application/pdf",
25212
+ ".json": "application/json",
25213
+ ".xml": "application/xml",
25214
+ ".zip": "application/zip",
25215
+ ".gz": "application/gzip",
25216
+ ".tar": "application/x-tar",
25217
+ ".csv": "text/csv",
25218
+ ".txt": "text/plain",
25219
+ ".log": "text/plain",
25220
+ ".sql": "application/sql",
25221
+ ".html": "text/html",
25222
+ ".css": "text/css",
25223
+ ".js": "application/javascript",
25224
+ ".ts": "application/typescript",
25225
+ ".md": "text/markdown",
25226
+ ".yaml": "application/x-yaml",
25227
+ ".yml": "application/x-yaml"
25228
+ };
25229
+ async function uploadFile(params) {
25230
+ const { apiKey, storageBaseUrl, filePath, debug } = params;
25231
+ if (!apiKey) {
25232
+ throw new Error("API key is required");
25233
+ }
25234
+ if (!storageBaseUrl) {
25235
+ throw new Error("storageBaseUrl is required");
25236
+ }
25237
+ if (!filePath) {
25238
+ throw new Error("filePath is required");
25239
+ }
25240
+ const resolvedPath = path3.resolve(filePath);
25241
+ if (!fs3.existsSync(resolvedPath)) {
25242
+ throw new Error(`File not found: ${resolvedPath}`);
25243
+ }
25244
+ const stat = fs3.statSync(resolvedPath);
25245
+ if (!stat.isFile()) {
25246
+ throw new Error(`Not a file: ${resolvedPath}`);
25247
+ }
25248
+ if (stat.size > MAX_UPLOAD_SIZE) {
25249
+ throw new Error(`File too large: ${stat.size} bytes (max ${MAX_UPLOAD_SIZE})`);
25250
+ }
25251
+ const base = normalizeBaseUrl(storageBaseUrl);
25252
+ if (new URL(base).protocol === "http:") {
25253
+ console.error("Warning: storage URL uses HTTP — API key will be sent unencrypted");
25254
+ }
25255
+ const url = `${base}/upload`;
25256
+ const fileBuffer = fs3.readFileSync(resolvedPath);
25257
+ const fileName = path3.basename(resolvedPath);
25258
+ const ext = path3.extname(fileName).toLowerCase();
25259
+ const mimeType = MIME_TYPES[ext] || "application/octet-stream";
25260
+ const formData = new FormData;
25261
+ formData.append("file", new Blob([fileBuffer], { type: mimeType }), fileName);
25262
+ const headers = {
25263
+ "access-token": apiKey
25264
+ };
25265
+ if (debug) {
25266
+ const debugHeaders = { ...headers, "access-token": maskSecret(apiKey) };
25267
+ console.error(`Debug: Storage base URL: ${base}`);
25268
+ console.error(`Debug: POST URL: ${url}`);
25269
+ console.error(`Debug: File: ${resolvedPath} (${stat.size} bytes, ${mimeType})`);
25270
+ console.error(`Debug: Request headers: ${JSON.stringify(debugHeaders)}`);
25271
+ }
25272
+ const response = await fetch(url, {
25273
+ method: "POST",
25274
+ headers,
25275
+ body: formData
25276
+ });
25277
+ if (debug) {
25278
+ console.error(`Debug: Response status: ${response.status}`);
25279
+ console.error(`Debug: Response headers: ${JSON.stringify(Object.fromEntries(response.headers.entries()))}`);
25280
+ }
25281
+ const data = await response.text();
25282
+ if (response.ok) {
25283
+ try {
25284
+ return JSON.parse(data);
25285
+ } catch {
25286
+ throw new Error(`Failed to parse upload response: ${data}`);
25287
+ }
25288
+ } else {
25289
+ throw new Error(formatHttpError("Failed to upload file", response.status, data));
25116
25290
  }
25117
- return trimmed;
25118
25291
  }
25119
- function resolveBaseUrls2(opts, cfg, defaults2 = {}) {
25120
- const defApi = defaults2.apiBaseUrl || "https://postgres.ai/api/general/";
25121
- const defUi = defaults2.uiBaseUrl || "https://console.postgres.ai";
25122
- const apiCandidate = opts?.apiBaseUrl || process.env.PGAI_API_BASE_URL || cfg?.baseUrl || defApi;
25123
- const uiCandidate = opts?.uiBaseUrl || process.env.PGAI_UI_BASE_URL || defUi;
25292
+ async function downloadFile(params) {
25293
+ const { apiKey, storageBaseUrl, fileUrl, outputPath, debug } = params;
25294
+ if (!apiKey) {
25295
+ throw new Error("API key is required");
25296
+ }
25297
+ if (!storageBaseUrl) {
25298
+ throw new Error("storageBaseUrl is required");
25299
+ }
25300
+ if (!fileUrl) {
25301
+ throw new Error("fileUrl is required");
25302
+ }
25303
+ const base = normalizeBaseUrl(storageBaseUrl);
25304
+ if (new URL(base).protocol === "http:") {
25305
+ console.error("Warning: storage URL uses HTTP — API key will be sent unencrypted");
25306
+ }
25307
+ let fullUrl;
25308
+ if (fileUrl.startsWith("http://") || fileUrl.startsWith("https://")) {
25309
+ if (!fileUrl.startsWith(base + "/")) {
25310
+ throw new Error(`URL must be under storage base URL: ${base}`);
25311
+ }
25312
+ fullUrl = fileUrl;
25313
+ } else {
25314
+ const relativePath = fileUrl.startsWith("/") ? fileUrl : `/${fileUrl}`;
25315
+ fullUrl = `${base}${relativePath}`;
25316
+ }
25317
+ const urlFilename = path3.basename(new URL(fullUrl).pathname);
25318
+ if (!urlFilename) {
25319
+ throw new Error("Cannot derive filename from URL; please specify --output");
25320
+ }
25321
+ const saveTo = outputPath ? path3.resolve(outputPath) : path3.resolve(urlFilename);
25322
+ if (!outputPath) {
25323
+ const normalizedSave = path3.normalize(saveTo);
25324
+ if (!normalizedSave.startsWith(path3.normalize(process.cwd()))) {
25325
+ throw new Error("Derived output path escapes current directory; please specify --output");
25326
+ }
25327
+ }
25328
+ const headers = {
25329
+ "access-token": apiKey
25330
+ };
25331
+ if (debug) {
25332
+ const debugHeaders = { ...headers, "access-token": maskSecret(apiKey) };
25333
+ console.error(`Debug: Storage base URL: ${base}`);
25334
+ console.error(`Debug: GET URL: ${fullUrl}`);
25335
+ console.error(`Debug: Output: ${saveTo}`);
25336
+ console.error(`Debug: Request headers: ${JSON.stringify(debugHeaders)}`);
25337
+ }
25338
+ const response = await fetch(fullUrl, {
25339
+ method: "GET",
25340
+ headers
25341
+ });
25342
+ if (debug) {
25343
+ console.error(`Debug: Response status: ${response.status}`);
25344
+ console.error(`Debug: Response headers: ${JSON.stringify(Object.fromEntries(response.headers.entries()))}`);
25345
+ }
25346
+ if (!response.ok) {
25347
+ const data = await response.text();
25348
+ throw new Error(formatHttpError("Failed to download file", response.status, data));
25349
+ }
25350
+ const contentLength = response.headers.get("content-length");
25351
+ if (contentLength && parseInt(contentLength, 10) > MAX_DOWNLOAD_SIZE) {
25352
+ throw new Error(`File too large: ${contentLength} bytes (max ${MAX_DOWNLOAD_SIZE})`);
25353
+ }
25354
+ const arrayBuffer = await response.arrayBuffer();
25355
+ const buffer = Buffer.from(arrayBuffer);
25356
+ const parentDir = path3.dirname(saveTo);
25357
+ if (!fs3.existsSync(parentDir)) {
25358
+ fs3.mkdirSync(parentDir, { recursive: true });
25359
+ }
25360
+ fs3.writeFileSync(saveTo, buffer);
25124
25361
  return {
25125
- apiBaseUrl: normalizeBaseUrl2(apiCandidate),
25126
- uiBaseUrl: normalizeBaseUrl2(uiCandidate)
25362
+ savedTo: saveTo,
25363
+ size: buffer.length,
25364
+ mimeType: response.headers.get("content-type")
25127
25365
  };
25128
25366
  }
25367
+ var IMAGE_EXTENSIONS = new Set([".png", ".jpg", ".jpeg", ".gif", ".webp", ".svg", ".bmp", ".ico"]);
25368
+ function buildMarkdownLink(fileUrl, storageBaseUrl, filename) {
25369
+ const base = normalizeBaseUrl(storageBaseUrl);
25370
+ const normalizedFileUrl = fileUrl.startsWith("/") ? fileUrl : `/${fileUrl}`;
25371
+ const fullUrl = fileUrl.startsWith("http://") || fileUrl.startsWith("https://") ? fileUrl : `${base}${normalizedFileUrl}`;
25372
+ const name = filename || path3.basename(new URL(fullUrl).pathname);
25373
+ const safeName = name.replace(/[\[\]()]/g, "\\$&");
25374
+ const ext = path3.extname(name).toLowerCase();
25375
+ if (IMAGE_EXTENSIONS.has(ext)) {
25376
+ return `![${safeName}](${fullUrl})`;
25377
+ }
25378
+ return `[${safeName}](${fullUrl})`;
25379
+ }
25129
25380
 
25130
25381
  // lib/init.ts
25131
25382
  import { randomBytes } from "crypto";
25132
25383
  import { URL as URL2, fileURLToPath } from "url";
25133
- import * as fs3 from "fs";
25134
- import * as path3 from "path";
25384
+ import * as fs4 from "fs";
25385
+ import * as path4 from "path";
25135
25386
  var DEFAULT_MONITORING_USER = "postgres_ai_mon";
25136
25387
  var KNOWN_PROVIDERS = ["self-managed", "supabase"];
25137
25388
  var SKIP_ROLE_CREATION_PROVIDERS = ["supabase"];
@@ -25203,7 +25454,7 @@ async function connectWithSslFallback(ClientClass, adminConn, verbose) {
25203
25454
  throw sslErr;
25204
25455
  }
25205
25456
  if (verbose) {
25206
- console.log("SSL connection failed, retrying without SSL...");
25457
+ console.error("SSL connection failed, retrying without SSL...");
25207
25458
  }
25208
25459
  const noSslConfig = { ...adminConn.clientConfig, ssl: false };
25209
25460
  try {
@@ -25222,21 +25473,21 @@ async function connectWithSslFallback(ClientClass, adminConn, verbose) {
25222
25473
  }
25223
25474
  function sqlDir() {
25224
25475
  const currentFile = fileURLToPath(import.meta.url);
25225
- const currentDir = path3.dirname(currentFile);
25476
+ const currentDir = path4.dirname(currentFile);
25226
25477
  const candidates = [
25227
- path3.resolve(currentDir, "..", "sql"),
25228
- path3.resolve(currentDir, "..", "..", "sql")
25478
+ path4.resolve(currentDir, "..", "sql"),
25479
+ path4.resolve(currentDir, "..", "..", "sql")
25229
25480
  ];
25230
25481
  for (const candidate of candidates) {
25231
- if (fs3.existsSync(candidate)) {
25482
+ if (fs4.existsSync(candidate)) {
25232
25483
  return candidate;
25233
25484
  }
25234
25485
  }
25235
25486
  throw new Error(`SQL directory not found. Searched: ${candidates.join(", ")}`);
25236
25487
  }
25237
25488
  function loadSqlTemplate(filename) {
25238
- const p = path3.join(sqlDir(), filename);
25239
- return fs3.readFileSync(p, "utf8");
25489
+ const p = path4.join(sqlDir(), filename);
25490
+ return fs4.readFileSync(p, "utf8");
25240
25491
  }
25241
25492
  function applyTemplate(sql, vars) {
25242
25493
  return sql.replace(/\{\{([A-Z0-9_]+)\}\}/g, (_, key) => {
@@ -26215,12 +26466,12 @@ function createCallbackServer(port = 0, expectedState = null, timeoutMs = 300000
26215
26466
  let resolveReady;
26216
26467
  let rejectReady;
26217
26468
  let serverInstance = null;
26218
- const promise2 = new Promise((resolve4, reject) => {
26219
- resolveCallback = resolve4;
26469
+ const promise2 = new Promise((resolve5, reject) => {
26470
+ resolveCallback = resolve5;
26220
26471
  rejectCallback = reject;
26221
26472
  });
26222
- const ready = new Promise((resolve4, reject) => {
26223
- resolveReady = resolve4;
26473
+ const ready = new Promise((resolve5, reject) => {
26474
+ resolveReady = resolve5;
26224
26475
  rejectReady = reject;
26225
26476
  });
26226
26477
  let timeoutId = null;
@@ -26406,12 +26657,13 @@ function createCallbackServer(port = 0, expectedState = null, timeoutMs = 300000
26406
26657
  }
26407
26658
 
26408
26659
  // bin/postgres-ai.ts
26660
+ init_util();
26409
26661
  import { createInterface } from "readline";
26410
26662
  import * as childProcess from "child_process";
26411
26663
 
26412
26664
  // lib/checkup.ts
26413
- import * as fs4 from "fs";
26414
- import * as path4 from "path";
26665
+ import * as fs5 from "fs";
26666
+ import * as path5 from "path";
26415
26667
 
26416
26668
  // lib/metrics-embedded.ts
26417
26669
  var METRICS = {
@@ -27844,7 +28096,7 @@ function parseVersionNum(versionNum) {
27844
28096
  };
27845
28097
  } catch (err) {
27846
28098
  const errorMsg = err instanceof Error ? err.message : String(err);
27847
- console.log(`[parseVersionNum] Warning: Failed to parse "${versionNum}": ${errorMsg}`);
28099
+ console.error(`[parseVersionNum] Warning: Failed to parse "${versionNum}": ${errorMsg}`);
27848
28100
  return { major: "", minor: "" };
27849
28101
  }
27850
28102
  }
@@ -28161,7 +28413,7 @@ async function getStatsReset(client, pgMajorVersion = 16) {
28161
28413
  } catch (err) {
28162
28414
  const errorMsg = err instanceof Error ? err.message : String(err);
28163
28415
  postmasterStartupError = `Failed to query postmaster start time: ${errorMsg}`;
28164
- console.log(`[getStatsReset] Warning: ${postmasterStartupError}`);
28416
+ console.error(`[getStatsReset] Warning: ${postmasterStartupError}`);
28165
28417
  }
28166
28418
  const statsResult = {
28167
28419
  stats_reset_epoch: statsResetEpoch,
@@ -28214,7 +28466,7 @@ async function getRedundantIndexes(client, pgMajorVersion = 16) {
28214
28466
  const errorMsg = err instanceof Error ? err.message : String(err);
28215
28467
  const indexName = String(transformed.index_name || "unknown");
28216
28468
  parseError = `Failed to parse redundant_to_json: ${errorMsg}`;
28217
- console.log(`[H004] Warning: ${parseError} for index "${indexName}"`);
28469
+ console.error(`[H004] Warning: ${parseError} for index "${indexName}"`);
28218
28470
  }
28219
28471
  const result2 = {
28220
28472
  schema_name: String(transformed.schema_name || ""),
@@ -28256,7 +28508,7 @@ function createBaseReport(checkId, checkTitle, nodeName) {
28256
28508
  }
28257
28509
  function readTextFileSafe(p) {
28258
28510
  try {
28259
- const value = fs4.readFileSync(p, "utf8").trim();
28511
+ const value = fs5.readFileSync(p, "utf8").trim();
28260
28512
  return value || null;
28261
28513
  } catch {
28262
28514
  return null;
@@ -28269,8 +28521,8 @@ function resolveBuildTs() {
28269
28521
  if (fromFile)
28270
28522
  return fromFile;
28271
28523
  try {
28272
- const pkgRoot = path4.resolve(__dirname, "..");
28273
- const fromPkgFile = readTextFileSafe(path4.join(pkgRoot, "BUILD_TS"));
28524
+ const pkgRoot = path5.resolve(__dirname, "..");
28525
+ const fromPkgFile = readTextFileSafe(path5.join(pkgRoot, "BUILD_TS"));
28274
28526
  if (fromPkgFile)
28275
28527
  return fromPkgFile;
28276
28528
  } catch (err) {
@@ -28278,13 +28530,13 @@ function resolveBuildTs() {
28278
28530
  console.warn(`[resolveBuildTs] Warning: path resolution failed: ${errorMsg}`);
28279
28531
  }
28280
28532
  try {
28281
- const pkgJsonPath = path4.resolve(__dirname, "..", "package.json");
28282
- const st = fs4.statSync(pkgJsonPath);
28533
+ const pkgJsonPath = path5.resolve(__dirname, "..", "package.json");
28534
+ const st = fs5.statSync(pkgJsonPath);
28283
28535
  return st.mtime.toISOString();
28284
28536
  } catch (err) {
28285
28537
  if (process.env.DEBUG) {
28286
28538
  const errorMsg = err instanceof Error ? err.message : String(err);
28287
- console.log(`[resolveBuildTs] Could not stat package.json, using current time: ${errorMsg}`);
28539
+ console.error(`[resolveBuildTs] Could not stat package.json, using current time: ${errorMsg}`);
28288
28540
  }
28289
28541
  return new Date().toISOString();
28290
28542
  }
@@ -28394,7 +28646,7 @@ async function generateD004(client, nodeName) {
28394
28646
  }
28395
28647
  } catch (err) {
28396
28648
  const errorMsg = err instanceof Error ? err.message : String(err);
28397
- console.log(`[D004] Error querying pg_stat_statements: ${errorMsg}`);
28649
+ console.error(`[D004] Error querying pg_stat_statements: ${errorMsg}`);
28398
28650
  pgssError = errorMsg;
28399
28651
  }
28400
28652
  let kcacheAvailable = false;
@@ -28440,7 +28692,7 @@ async function generateD004(client, nodeName) {
28440
28692
  }
28441
28693
  } catch (err) {
28442
28694
  const errorMsg = err instanceof Error ? err.message : String(err);
28443
- console.log(`[D004] Error querying pg_stat_kcache: ${errorMsg}`);
28695
+ console.error(`[D004] Error querying pg_stat_kcache: ${errorMsg}`);
28444
28696
  kcacheError = errorMsg;
28445
28697
  }
28446
28698
  report.results[nodeName] = {
@@ -28551,7 +28803,10 @@ async function generateF004(client, nodeName) {
28551
28803
  });
28552
28804
  } catch (err) {
28553
28805
  const errorMsg = err instanceof Error ? err.message : String(err);
28554
- console.log(`[F004] Error estimating table bloat: ${errorMsg}`);
28806
+ console.error(`[F004] Error estimating table bloat: ${errorMsg}`);
28807
+ if (errorMsg.includes("postgres_ai.")) {
28808
+ console.error(` Hint: Run "postgresai prepare-db <connection>" to create required objects.`);
28809
+ }
28555
28810
  }
28556
28811
  const { datname: dbName, size_bytes: dbSizeBytes } = await getCurrentDatabaseInfo(client, pgMajorVersion);
28557
28812
  const totalCount = bloatedTables.length;
@@ -28625,7 +28880,10 @@ async function generateF005(client, nodeName) {
28625
28880
  });
28626
28881
  } catch (err) {
28627
28882
  const errorMsg = err instanceof Error ? err.message : String(err);
28628
- console.log(`[F005] Error estimating index bloat: ${errorMsg}`);
28883
+ console.error(`[F005] Error estimating index bloat: ${errorMsg}`);
28884
+ if (errorMsg.includes("postgres_ai.")) {
28885
+ console.error(` Hint: Run "postgresai prepare-db <connection>" to create required objects.`);
28886
+ }
28629
28887
  }
28630
28888
  const { datname: dbName, size_bytes: dbSizeBytes } = await getCurrentDatabaseInfo(client, pgMajorVersion);
28631
28889
  const totalCount = bloatedIndexes.length;
@@ -28712,7 +28970,7 @@ async function generateG001(client, nodeName) {
28712
28970
  }
28713
28971
  } catch (err) {
28714
28972
  const errorMsg = err instanceof Error ? err.message : String(err);
28715
- console.log(`[G001] Error calculating memory usage: ${errorMsg}`);
28973
+ console.error(`[G001] Error calculating memory usage: ${errorMsg}`);
28716
28974
  memoryError = errorMsg;
28717
28975
  }
28718
28976
  report.results[nodeName] = {
@@ -28772,7 +29030,7 @@ async function generateG003(client, nodeName) {
28772
29030
  }
28773
29031
  } catch (err) {
28774
29032
  const errorMsg = err instanceof Error ? err.message : String(err);
28775
- console.log(`[G003] Error querying deadlock stats: ${errorMsg}`);
29033
+ console.error(`[G003] Error querying deadlock stats: ${errorMsg}`);
28776
29034
  deadlockError = errorMsg;
28777
29035
  }
28778
29036
  report.results[nodeName] = {
@@ -28878,7 +29136,7 @@ async function withRetry(fn, config2 = {}, onRetry) {
28878
29136
  if (onRetry) {
28879
29137
  onRetry(attempt, err, delayMs);
28880
29138
  }
28881
- await new Promise((resolve5) => setTimeout(resolve5, delayMs));
29139
+ await new Promise((resolve6) => setTimeout(resolve6, delayMs));
28882
29140
  delayMs = Math.min(delayMs * backoffMultiplier, maxDelayMs);
28883
29141
  }
28884
29142
  }
@@ -28948,7 +29206,7 @@ async function postRpc(params) {
28948
29206
  const controller = new AbortController;
28949
29207
  let timeoutId = null;
28950
29208
  let settled = false;
28951
- return new Promise((resolve5, reject) => {
29209
+ return new Promise((resolve6, reject) => {
28952
29210
  const settledReject = (err) => {
28953
29211
  if (settled)
28954
29212
  return;
@@ -28963,7 +29221,7 @@ async function postRpc(params) {
28963
29221
  settled = true;
28964
29222
  if (timeoutId)
28965
29223
  clearTimeout(timeoutId);
28966
- resolve5(value);
29224
+ resolve6(value);
28967
29225
  };
28968
29226
  const req = https.request(url, {
28969
29227
  method: "POST",
@@ -29336,27 +29594,27 @@ function closeReadline() {
29336
29594
  }
29337
29595
  }
29338
29596
  async function execPromise(command) {
29339
- return new Promise((resolve6, reject) => {
29597
+ return new Promise((resolve7, reject) => {
29340
29598
  childProcess.exec(command, (error2, stdout, stderr) => {
29341
29599
  if (error2) {
29342
29600
  const err = error2;
29343
29601
  err.code = typeof error2.code === "number" ? error2.code : 1;
29344
29602
  reject(err);
29345
29603
  } else {
29346
- resolve6({ stdout, stderr });
29604
+ resolve7({ stdout, stderr });
29347
29605
  }
29348
29606
  });
29349
29607
  });
29350
29608
  }
29351
29609
  async function execFilePromise(file, args) {
29352
- return new Promise((resolve6, reject) => {
29610
+ return new Promise((resolve7, reject) => {
29353
29611
  childProcess.execFile(file, args, (error2, stdout, stderr) => {
29354
29612
  if (error2) {
29355
29613
  const err = error2;
29356
29614
  err.code = typeof error2.code === "number" ? error2.code : 1;
29357
29615
  reject(err);
29358
29616
  } else {
29359
- resolve6({ stdout, stderr });
29617
+ resolve7({ stdout, stderr });
29360
29618
  }
29361
29619
  });
29362
29620
  });
@@ -29397,9 +29655,9 @@ function spawn2(cmd, args, options) {
29397
29655
  };
29398
29656
  }
29399
29657
  async function question(prompt) {
29400
- return new Promise((resolve6) => {
29658
+ return new Promise((resolve7) => {
29401
29659
  getReadline().question(prompt, (answer) => {
29402
- resolve6(answer);
29660
+ resolve7(answer);
29403
29661
  });
29404
29662
  });
29405
29663
  }
@@ -29410,7 +29668,7 @@ function expandHomePath(p) {
29410
29668
  if (s === "~")
29411
29669
  return os3.homedir();
29412
29670
  if (s.startsWith("~/") || s.startsWith("~\\")) {
29413
- return path5.join(os3.homedir(), s.slice(2));
29671
+ return path6.join(os3.homedir(), s.slice(2));
29414
29672
  }
29415
29673
  return s;
29416
29674
  }
@@ -29459,10 +29717,10 @@ function prepareOutputDirectory(outputOpt) {
29459
29717
  if (!outputOpt)
29460
29718
  return;
29461
29719
  const outputDir = expandHomePath(outputOpt);
29462
- const outputPath = path5.isAbsolute(outputDir) ? outputDir : path5.resolve(process.cwd(), outputDir);
29463
- if (!fs5.existsSync(outputPath)) {
29720
+ const outputPath = path6.isAbsolute(outputDir) ? outputDir : path6.resolve(process.cwd(), outputDir);
29721
+ if (!fs6.existsSync(outputPath)) {
29464
29722
  try {
29465
- fs5.mkdirSync(outputPath, { recursive: true });
29723
+ fs6.mkdirSync(outputPath, { recursive: true });
29466
29724
  } catch (e) {
29467
29725
  const errAny = e;
29468
29726
  const code = typeof errAny?.code === "string" ? errAny.code : "";
@@ -29541,9 +29799,10 @@ async function uploadCheckupReports(uploadCfg, reports, spinner, logUpload) {
29541
29799
  }
29542
29800
  function writeReportFiles(reports, outputPath) {
29543
29801
  for (const [checkId, report] of Object.entries(reports)) {
29544
- const filePath = path5.join(outputPath, `${checkId}.json`);
29545
- fs5.writeFileSync(filePath, JSON.stringify(report, null, 2), "utf8");
29546
- console.log(`\u2713 ${checkId}: ${filePath}`);
29802
+ const filePath = path6.join(outputPath, `${checkId}.json`);
29803
+ fs6.writeFileSync(filePath, JSON.stringify(report, null, 2), "utf8");
29804
+ const title = report.checkTitle || checkId;
29805
+ console.log(`\u2713 ${checkId} ${title}: ${filePath}`);
29547
29806
  }
29548
29807
  }
29549
29808
  function printUploadSummary(summary, projectWasGenerated, useStderr, reports) {
@@ -29586,7 +29845,7 @@ function getDefaultMonitoringProjectDir() {
29586
29845
  const override = process.env.PGAI_PROJECT_DIR;
29587
29846
  if (override && override.trim())
29588
29847
  return override.trim();
29589
- return path5.join(getConfigDir(), "monitoring");
29848
+ return path6.join(getConfigDir(), "monitoring");
29590
29849
  }
29591
29850
  async function downloadText(url) {
29592
29851
  const controller = new AbortController;
@@ -29603,12 +29862,12 @@ async function downloadText(url) {
29603
29862
  }
29604
29863
  async function ensureDefaultMonitoringProject() {
29605
29864
  const projectDir = getDefaultMonitoringProjectDir();
29606
- const composeFile = path5.resolve(projectDir, "docker-compose.yml");
29607
- const instancesFile = path5.resolve(projectDir, "instances.yml");
29608
- if (!fs5.existsSync(projectDir)) {
29609
- fs5.mkdirSync(projectDir, { recursive: true, mode: 448 });
29865
+ const composeFile = path6.resolve(projectDir, "docker-compose.yml");
29866
+ const instancesFile = path6.resolve(projectDir, "instances.yml");
29867
+ if (!fs6.existsSync(projectDir)) {
29868
+ fs6.mkdirSync(projectDir, { recursive: true, mode: 448 });
29610
29869
  }
29611
- if (!fs5.existsSync(composeFile)) {
29870
+ if (!fs6.existsSync(composeFile)) {
29612
29871
  const refs = [
29613
29872
  process.env.PGAI_PROJECT_REF,
29614
29873
  package_default.version,
@@ -29620,36 +29879,36 @@ async function ensureDefaultMonitoringProject() {
29620
29879
  const url = `https://gitlab.com/postgres-ai/postgres_ai/-/raw/${encodeURIComponent(ref)}/docker-compose.yml`;
29621
29880
  try {
29622
29881
  const text = await downloadText(url);
29623
- fs5.writeFileSync(composeFile, text, { encoding: "utf8", mode: 384 });
29882
+ fs6.writeFileSync(composeFile, text, { encoding: "utf8", mode: 384 });
29624
29883
  break;
29625
29884
  } catch (err) {
29626
29885
  lastErr = err;
29627
29886
  }
29628
29887
  }
29629
- if (!fs5.existsSync(composeFile)) {
29888
+ if (!fs6.existsSync(composeFile)) {
29630
29889
  const msg = lastErr instanceof Error ? lastErr.message : String(lastErr);
29631
29890
  throw new Error(`Failed to bootstrap docker-compose.yml: ${msg}`);
29632
29891
  }
29633
29892
  }
29634
- if (!fs5.existsSync(instancesFile)) {
29893
+ if (!fs6.existsSync(instancesFile)) {
29635
29894
  const header = `# PostgreSQL instances to monitor
29636
29895
  ` + `# Add your instances using: pgai mon targets add <connection-string> <name>
29637
29896
 
29638
29897
  `;
29639
- fs5.writeFileSync(instancesFile, header, { encoding: "utf8", mode: 384 });
29898
+ fs6.writeFileSync(instancesFile, header, { encoding: "utf8", mode: 384 });
29640
29899
  }
29641
- const pgwatchConfig = path5.resolve(projectDir, ".pgwatch-config");
29642
- if (!fs5.existsSync(pgwatchConfig)) {
29643
- fs5.writeFileSync(pgwatchConfig, "", { encoding: "utf8", mode: 384 });
29900
+ const pgwatchConfig = path6.resolve(projectDir, ".pgwatch-config");
29901
+ if (!fs6.existsSync(pgwatchConfig)) {
29902
+ fs6.writeFileSync(pgwatchConfig, "", { encoding: "utf8", mode: 384 });
29644
29903
  }
29645
- const envFile = path5.resolve(projectDir, ".env");
29646
- if (!fs5.existsSync(envFile)) {
29904
+ const envFile = path6.resolve(projectDir, ".env");
29905
+ if (!fs6.existsSync(envFile)) {
29647
29906
  const envText = `PGAI_TAG=${package_default.version}
29648
29907
  # PGAI_REGISTRY=registry.gitlab.com/postgres-ai/postgres_ai
29649
29908
  `;
29650
- fs5.writeFileSync(envFile, envText, { encoding: "utf8", mode: 384 });
29909
+ fs6.writeFileSync(envFile, envText, { encoding: "utf8", mode: 384 });
29651
29910
  }
29652
- return { fs: fs5, path: path5, projectDir, composeFile, instancesFile };
29911
+ return { fs: fs6, path: path6, projectDir, composeFile, instancesFile };
29653
29912
  }
29654
29913
  function getConfig(opts) {
29655
29914
  let apiKey = opts.apiKey || process.env.PGAI_API_KEY || "";
@@ -29680,7 +29939,7 @@ function printResult(result, json2) {
29680
29939
  }
29681
29940
  }
29682
29941
  var program2 = new Command;
29683
- program2.name("postgres-ai").description("PostgresAI CLI").version(package_default.version).option("--api-key <key>", "API key (overrides PGAI_API_KEY)").option("--api-base-url <url>", "API base URL for backend RPC (overrides PGAI_API_BASE_URL)").option("--ui-base-url <url>", "UI base URL for browser routes (overrides PGAI_UI_BASE_URL)");
29942
+ program2.name("postgres-ai").description("PostgresAI CLI").version(package_default.version).option("--api-key <key>", "API key (overrides PGAI_API_KEY)").option("--api-base-url <url>", "API base URL for backend RPC (overrides PGAI_API_BASE_URL)").option("--ui-base-url <url>", "UI base URL for browser routes (overrides PGAI_UI_BASE_URL)").option("--storage-base-url <url>", "Storage base URL for file uploads (overrides PGAI_STORAGE_BASE_URL)");
29684
29943
  program2.command("set-default-project <project>").description("store default project for checkup uploads").action(async (project) => {
29685
29944
  const value = (project || "").trim();
29686
29945
  if (!value) {
@@ -29691,6 +29950,23 @@ program2.command("set-default-project <project>").description("store default pro
29691
29950
  writeConfig({ defaultProject: value });
29692
29951
  console.log(`Default project saved: ${value}`);
29693
29952
  });
29953
+ program2.command("set-storage-url <url>").description("store storage base URL for file uploads").action(async (url) => {
29954
+ const value = (url || "").trim();
29955
+ if (!value) {
29956
+ console.error("Error: url is required");
29957
+ process.exitCode = 1;
29958
+ return;
29959
+ }
29960
+ try {
29961
+ const { normalizeBaseUrl: normalizeBaseUrl3 } = await Promise.resolve().then(() => (init_util(), exports_util2));
29962
+ const normalized = normalizeBaseUrl3(value);
29963
+ writeConfig({ storageBaseUrl: normalized });
29964
+ console.log(`Storage URL saved: ${normalized}`);
29965
+ } catch {
29966
+ console.error(`Error: invalid URL: ${value}`);
29967
+ process.exitCode = 1;
29968
+ }
29969
+ });
29694
29970
  program2.command("prepare-db [conn]").description("prepare database for monitoring: create monitoring user, required view(s), and grant permissions (idempotent)").option("--db-url <url>", "PostgreSQL connection URL (admin) to run the setup against (deprecated; pass it as positional arg)").option("-h, --host <host>", "PostgreSQL host (psql-like)").option("-p, --port <port>", "PostgreSQL port (psql-like)").option("-U, --username <username>", "PostgreSQL user (psql-like)").option("-d, --dbname <dbname>", "PostgreSQL database name (psql-like)").option("--admin-password <password>", "Admin connection password (otherwise uses PGPASSWORD if set)").option("--monitoring-user <name>", "Monitoring role name to create/update", DEFAULT_MONITORING_USER).option("--password <password>", "Monitoring role password (overrides PGAI_MON_PASSWORD)").option("--skip-optional-permissions", "Skip optional permissions (RDS/self-managed extras)", false).option("--provider <provider>", "Database provider (e.g., supabase). Affects which steps are executed.").option("--verify", "Verify that monitoring role/permissions are in place (no changes)", false).option("--reset-password", "Reset monitoring role password only (no other changes)", false).option("--print-sql", "Print SQL plan and exit (no changes applied)", false).option("--print-password", "Print generated monitoring password (DANGEROUS in CI logs)", false).option("--supabase", "Use Supabase Management API instead of direct PostgreSQL connection", false).option("--supabase-access-token <token>", "Supabase Management API access token (or SUPABASE_ACCESS_TOKEN env)").option("--supabase-project-ref <ref>", "Supabase project reference (or SUPABASE_PROJECT_REF env)").option("--json", "Output result as JSON (machine-readable)", false).addHelpText("after", [
29695
29971
  "",
29696
29972
  "Examples:",
@@ -29871,9 +30147,9 @@ program2.command("prepare-db [conn]").description("prepare database for monitori
29871
30147
  } else {
29872
30148
  console.log("\u2713 prepare-db verify: OK");
29873
30149
  if (v.missingOptional.length > 0) {
29874
- console.log("\u26A0 Optional items missing:");
30150
+ console.error("\u26A0 Optional items missing:");
29875
30151
  for (const m of v.missingOptional)
29876
- console.log(`- ${m}`);
30152
+ console.error(`- ${m}`);
29877
30153
  }
29878
30154
  }
29879
30155
  return;
@@ -29994,9 +30270,9 @@ program2.command("prepare-db [conn]").description("prepare database for monitori
29994
30270
  } else {
29995
30271
  console.log(opts.resetPassword ? "\u2713 prepare-db password reset completed" : "\u2713 prepare-db completed");
29996
30272
  if (skippedOptional.length > 0) {
29997
- console.log("\u26A0 Some optional steps were skipped (not supported or insufficient privileges):");
30273
+ console.error("\u26A0 Some optional steps were skipped (not supported or insufficient privileges):");
29998
30274
  for (const s of skippedOptional)
29999
- console.log(`- ${s}`);
30275
+ console.error(`- ${s}`);
30000
30276
  }
30001
30277
  if (process.stdout.isTTY) {
30002
30278
  console.log(`Applied ${applied.length} steps`);
@@ -30154,9 +30430,9 @@ program2.command("prepare-db [conn]").description("prepare database for monitori
30154
30430
  } else {
30155
30431
  console.log(`\u2713 prepare-db verify: OK${opts.provider ? ` (provider: ${opts.provider})` : ""}`);
30156
30432
  if (v.missingOptional.length > 0) {
30157
- console.log("\u26A0 Optional items missing:");
30433
+ console.error("\u26A0 Optional items missing:");
30158
30434
  for (const m of v.missingOptional)
30159
- console.log(`- ${m}`);
30435
+ console.error(`- ${m}`);
30160
30436
  }
30161
30437
  }
30162
30438
  return;
@@ -30272,9 +30548,9 @@ program2.command("prepare-db [conn]").description("prepare database for monitori
30272
30548
  } else {
30273
30549
  console.log(opts.resetPassword ? "\u2713 prepare-db password reset completed" : "\u2713 prepare-db completed");
30274
30550
  if (skippedOptional.length > 0) {
30275
- console.log("\u26A0 Some optional steps were skipped (not supported or insufficient privileges):");
30551
+ console.error("\u26A0 Some optional steps were skipped (not supported or insufficient privileges):");
30276
30552
  for (const s of skippedOptional)
30277
- console.log(`- ${s}`);
30553
+ console.error(`- ${s}`);
30278
30554
  }
30279
30555
  if (process.stdout.isTTY) {
30280
30556
  console.log(`Applied ${applied.length} steps`);
@@ -30474,9 +30750,9 @@ program2.command("unprepare-db [conn]").description("remove monitoring setup: dr
30474
30750
  console.log(`Drop role: ${dropRole}`);
30475
30751
  }
30476
30752
  if (!opts.force && !jsonOutput && !shouldPrintSql) {
30477
- const answer = await new Promise((resolve6) => {
30753
+ const answer = await new Promise((resolve7) => {
30478
30754
  const readline = getReadline();
30479
- readline.question(`This will remove the monitoring setup for user "${opts.monitoringUser}"${dropRole ? " and drop the role" : ""}. Continue? [y/N] `, (ans) => resolve6(ans.trim().toLowerCase()));
30755
+ readline.question(`This will remove the monitoring setup for user "${opts.monitoringUser}"${dropRole ? " and drop the role" : ""}. Continue? [y/N] `, (ans) => resolve7(ans.trim().toLowerCase()));
30480
30756
  });
30481
30757
  if (answer !== "y" && answer !== "yes") {
30482
30758
  console.log("Aborted.");
@@ -30530,11 +30806,11 @@ program2.command("unprepare-db [conn]").description("remove monitoring setup: dr
30530
30806
  console.log("\u2713 unprepare-db completed");
30531
30807
  console.log(`Applied ${applied.length} steps`);
30532
30808
  } else {
30533
- console.log("\u26A0 unprepare-db completed with errors");
30809
+ console.error("\u26A0 unprepare-db completed with errors");
30534
30810
  console.log(`Applied ${applied.length} steps`);
30535
- console.log("Errors:");
30811
+ console.error("Errors:");
30536
30812
  for (const err of errors3) {
30537
- console.log(` - ${err}`);
30813
+ console.error(` - ${err}`);
30538
30814
  }
30539
30815
  process.exitCode = 1;
30540
30816
  }
@@ -30780,7 +31056,7 @@ Usage: postgresai checkup ${checkId} postgresql://user@host:5432/dbname
30780
31056
  }
30781
31057
  }
30782
31058
  }
30783
- if (shouldPrintJson) {
31059
+ if (shouldPrintJson && !outputPath) {
30784
31060
  console.log(JSON.stringify(reports, null, 2));
30785
31061
  }
30786
31062
  const hadOutput = shouldPrintJson || shouldConvertMarkdown || outputPath || uploadSummary;
@@ -30833,12 +31109,12 @@ function resolvePaths() {
30833
31109
  const startDir = process.cwd();
30834
31110
  let currentDir = startDir;
30835
31111
  while (true) {
30836
- const composeFile = path5.resolve(currentDir, "docker-compose.yml");
30837
- if (fs5.existsSync(composeFile)) {
30838
- const instancesFile = path5.resolve(currentDir, "instances.yml");
30839
- return { fs: fs5, path: path5, projectDir: currentDir, composeFile, instancesFile };
31112
+ const composeFile = path6.resolve(currentDir, "docker-compose.yml");
31113
+ if (fs6.existsSync(composeFile)) {
31114
+ const instancesFile = path6.resolve(currentDir, "instances.yml");
31115
+ return { fs: fs6, path: path6, projectDir: currentDir, composeFile, instancesFile };
30840
31116
  }
30841
- const parentDir = path5.dirname(currentDir);
31117
+ const parentDir = path6.dirname(currentDir);
30842
31118
  if (parentDir === currentDir)
30843
31119
  break;
30844
31120
  currentDir = parentDir;
@@ -30886,10 +31162,10 @@ function registerMonitoringInstance(apiKey, projectName, opts) {
30886
31162
  const url = `${apiBaseUrl}/rpc/monitoring_instance_register`;
30887
31163
  const debug = opts?.debug;
30888
31164
  if (debug) {
30889
- console.log(`
31165
+ console.error(`
30890
31166
  Debug: Registering monitoring instance...`);
30891
- console.log(`Debug: POST ${url}`);
30892
- console.log(`Debug: project_name=${projectName}`);
31167
+ console.error(`Debug: POST ${url}`);
31168
+ console.error(`Debug: project_name=${projectName}`);
30893
31169
  }
30894
31170
  fetch(url, {
30895
31171
  method: "POST",
@@ -30904,26 +31180,26 @@ Debug: Registering monitoring instance...`);
30904
31180
  const body = await res.text().catch(() => "");
30905
31181
  if (!res.ok) {
30906
31182
  if (debug) {
30907
- console.log(`Debug: Monitoring registration failed: HTTP ${res.status}`);
30908
- console.log(`Debug: Response: ${body}`);
31183
+ console.error(`Debug: Monitoring registration failed: HTTP ${res.status}`);
31184
+ console.error(`Debug: Response: ${body}`);
30909
31185
  }
30910
31186
  return;
30911
31187
  }
30912
31188
  if (debug) {
30913
- console.log(`Debug: Monitoring registration response: ${body}`);
31189
+ console.error(`Debug: Monitoring registration response: ${body}`);
30914
31190
  }
30915
31191
  }).catch((err) => {
30916
31192
  if (debug) {
30917
- console.log(`Debug: Monitoring registration error: ${err.message}`);
31193
+ console.error(`Debug: Monitoring registration error: ${err.message}`);
30918
31194
  }
30919
31195
  });
30920
31196
  }
30921
31197
  function updatePgwatchConfig(configPath, updates) {
30922
31198
  let lines = [];
30923
- if (fs5.existsSync(configPath)) {
30924
- const stats = fs5.statSync(configPath);
31199
+ if (fs6.existsSync(configPath)) {
31200
+ const stats = fs6.statSync(configPath);
30925
31201
  if (!stats.isDirectory()) {
30926
- const content = fs5.readFileSync(configPath, "utf8");
31202
+ const content = fs6.readFileSync(configPath, "utf8");
30927
31203
  lines = content.split(/\r?\n/).filter((l) => l.trim() !== "");
30928
31204
  }
30929
31205
  }
@@ -30935,7 +31211,7 @@ function updatePgwatchConfig(configPath, updates) {
30935
31211
  lines.push(`${key}=${value}`);
30936
31212
  }
30937
31213
  }
30938
- fs5.writeFileSync(configPath, lines.join(`
31214
+ fs6.writeFileSync(configPath, lines.join(`
30939
31215
  `) + `
30940
31216
  `, { encoding: "utf8", mode: 384 });
30941
31217
  }
@@ -30965,12 +31241,12 @@ async function runCompose(args, grafanaPassword) {
30965
31241
  if (grafanaPassword) {
30966
31242
  env.GF_SECURITY_ADMIN_PASSWORD = grafanaPassword;
30967
31243
  } else {
30968
- const cfgPath = path5.resolve(projectDir, ".pgwatch-config");
30969
- if (fs5.existsSync(cfgPath)) {
31244
+ const cfgPath = path6.resolve(projectDir, ".pgwatch-config");
31245
+ if (fs6.existsSync(cfgPath)) {
30970
31246
  try {
30971
- const stats = fs5.statSync(cfgPath);
31247
+ const stats = fs6.statSync(cfgPath);
30972
31248
  if (!stats.isDirectory()) {
30973
- const content = fs5.readFileSync(cfgPath, "utf8");
31249
+ const content = fs6.readFileSync(cfgPath, "utf8");
30974
31250
  const match = content.match(/^grafana_password=([^\r\n]+)/m);
30975
31251
  if (match) {
30976
31252
  env.GF_SECURITY_ADMIN_PASSWORD = match[1].trim();
@@ -30987,13 +31263,13 @@ async function runCompose(args, grafanaPassword) {
30987
31263
  if (process.platform === "darwin" && args.includes("up")) {
30988
31264
  finalArgs.push("--scale", "self-node-exporter=0");
30989
31265
  }
30990
- return new Promise((resolve6) => {
31266
+ return new Promise((resolve7) => {
30991
31267
  const child = spawn2(cmd[0], [...cmd.slice(1), "-f", composeFile, ...finalArgs], {
30992
31268
  stdio: "inherit",
30993
31269
  env,
30994
31270
  cwd: projectDir
30995
31271
  });
30996
- child.on("close", (code) => resolve6(code || 0));
31272
+ child.on("close", (code) => resolve7(code || 0));
30997
31273
  });
30998
31274
  }
30999
31275
  program2.command("help", { isDefault: true }).description("show help").action(() => {
@@ -31014,16 +31290,16 @@ mon.command("local-install").description("install local monitoring stack (genera
31014
31290
  console.log(`Project directory: ${projectDir}
31015
31291
  `);
31016
31292
  if (opts.project) {
31017
- const cfgPath2 = path5.resolve(projectDir, ".pgwatch-config");
31293
+ const cfgPath2 = path6.resolve(projectDir, ".pgwatch-config");
31018
31294
  updatePgwatchConfig(cfgPath2, { project_name: opts.project });
31019
31295
  console.log(`Using project name: ${opts.project}
31020
31296
  `);
31021
31297
  }
31022
- const envFile = path5.resolve(projectDir, ".env");
31298
+ const envFile = path6.resolve(projectDir, ".env");
31023
31299
  let existingRegistry = null;
31024
31300
  let existingPassword = null;
31025
- if (fs5.existsSync(envFile)) {
31026
- const existingEnv = fs5.readFileSync(envFile, "utf8");
31301
+ if (fs6.existsSync(envFile)) {
31302
+ const existingEnv = fs6.readFileSync(envFile, "utf8");
31027
31303
  const registryMatch = existingEnv.match(/^PGAI_REGISTRY=(.+)$/m);
31028
31304
  if (registryMatch)
31029
31305
  existingRegistry = registryMatch[1].trim();
@@ -31039,7 +31315,7 @@ mon.command("local-install").description("install local monitoring stack (genera
31039
31315
  if (existingPassword) {
31040
31316
  envLines.push(`GF_SECURITY_ADMIN_PASSWORD=${existingPassword}`);
31041
31317
  }
31042
- fs5.writeFileSync(envFile, envLines.join(`
31318
+ fs6.writeFileSync(envFile, envLines.join(`
31043
31319
  `) + `
31044
31320
  `, { encoding: "utf8", mode: 384 });
31045
31321
  if (opts.tag) {
@@ -31047,8 +31323,8 @@ mon.command("local-install").description("install local monitoring stack (genera
31047
31323
  `);
31048
31324
  }
31049
31325
  if (opts.demo && opts.dbUrl) {
31050
- console.log("\u26A0 Both --demo and --db-url provided. Demo mode includes its own database.");
31051
- console.log(`\u26A0 The --db-url will be ignored in demo mode.
31326
+ console.error("\u26A0 Both --demo and --db-url provided. Demo mode includes its own database.");
31327
+ console.error(`\u26A0 The --db-url will be ignored in demo mode.
31052
31328
  `);
31053
31329
  opts.dbUrl = undefined;
31054
31330
  }
@@ -31063,7 +31339,7 @@ Use demo mode without API key: postgres-ai mon local-install --demo`);
31063
31339
  }
31064
31340
  const { running, containers } = checkRunningContainers();
31065
31341
  if (running) {
31066
- console.log(`\u26A0 Monitoring services are already running: ${containers.join(", ")}`);
31342
+ console.error(`\u26A0 Monitoring services are already running: ${containers.join(", ")}`);
31067
31343
  console.log(`Use 'postgres-ai mon restart' to restart them
31068
31344
  `);
31069
31345
  return;
@@ -31075,12 +31351,12 @@ Use demo mode without API key: postgres-ai mon local-install --demo`);
31075
31351
  if (apiKey) {
31076
31352
  console.log("Using API key provided via --api-key parameter");
31077
31353
  writeConfig({ apiKey });
31078
- updatePgwatchConfig(path5.resolve(projectDir, ".pgwatch-config"), { api_key: apiKey });
31354
+ updatePgwatchConfig(path6.resolve(projectDir, ".pgwatch-config"), { api_key: apiKey });
31079
31355
  console.log(`\u2713 API key saved
31080
31356
  `);
31081
31357
  } else if (opts.yes) {
31082
31358
  console.log("Auto-yes mode: no API key provided, skipping API key setup");
31083
- console.log("\u26A0 Reports will be generated locally only");
31359
+ console.error("\u26A0 Reports will be generated locally only");
31084
31360
  console.log(`You can add an API key later with: postgres-ai add-key <api_key>
31085
31361
  `);
31086
31362
  } else {
@@ -31092,23 +31368,23 @@ Use demo mode without API key: postgres-ai mon local-install --demo`);
31092
31368
  const trimmedKey = inputApiKey.trim();
31093
31369
  if (trimmedKey) {
31094
31370
  writeConfig({ apiKey: trimmedKey });
31095
- updatePgwatchConfig(path5.resolve(projectDir, ".pgwatch-config"), { api_key: trimmedKey });
31371
+ updatePgwatchConfig(path6.resolve(projectDir, ".pgwatch-config"), { api_key: trimmedKey });
31096
31372
  apiKey = trimmedKey;
31097
31373
  console.log(`\u2713 API key saved
31098
31374
  `);
31099
31375
  break;
31100
31376
  }
31101
- console.log("\u26A0 API key cannot be empty");
31377
+ console.error("\u26A0 API key cannot be empty");
31102
31378
  const retry = await question("Try again or skip API key setup, retry? (Y/n): ");
31103
31379
  if (retry.toLowerCase() === "n") {
31104
- console.log("\u26A0 Skipping API key setup - reports will be generated locally only");
31380
+ console.error("\u26A0 Skipping API key setup - reports will be generated locally only");
31105
31381
  console.log(`You can add an API key later with: postgres-ai add-key <api_key>
31106
31382
  `);
31107
31383
  break;
31108
31384
  }
31109
31385
  }
31110
31386
  } else {
31111
- console.log("\u26A0 Skipping API key setup - reports will be generated locally only");
31387
+ console.error("\u26A0 Skipping API key setup - reports will be generated locally only");
31112
31388
  console.log(`You can add an API key later with: postgres-ai add-key <api_key>
31113
31389
  `);
31114
31390
  }
@@ -31126,7 +31402,7 @@ Use demo mode without API key: postgres-ai mon local-install --demo`);
31126
31402
  # Add your instances using: postgres-ai mon targets add
31127
31403
 
31128
31404
  `;
31129
- fs5.writeFileSync(instancesPath, emptyInstancesContent, "utf8");
31405
+ fs6.writeFileSync(instancesPath, emptyInstancesContent, "utf8");
31130
31406
  console.log(`Instances file: ${instancesPath}`);
31131
31407
  console.log(`Project directory: ${projectDir2}
31132
31408
  `);
@@ -31158,7 +31434,7 @@ Use demo mode without API key: postgres-ai mon local-install --demo`);
31158
31434
  node_name: ${instanceName}
31159
31435
  sink_type: ~sink_type~
31160
31436
  `;
31161
- fs5.appendFileSync(instancesPath, body, "utf8");
31437
+ fs6.appendFileSync(instancesPath, body, "utf8");
31162
31438
  console.log(`\u2713 Monitoring target '${instanceName}' added
31163
31439
  `);
31164
31440
  console.log("Testing connection to the added instance...");
@@ -31177,7 +31453,7 @@ Use demo mode without API key: postgres-ai mon local-install --demo`);
31177
31453
  }
31178
31454
  } else if (opts.yes) {
31179
31455
  console.log("Auto-yes mode: no database URL provided, skipping database setup");
31180
- console.log("\u26A0 No PostgreSQL instance added");
31456
+ console.error("\u26A0 No PostgreSQL instance added");
31181
31457
  console.log(`You can add one later with: postgres-ai mon targets add
31182
31458
  `);
31183
31459
  } else {
@@ -31195,7 +31471,7 @@ You can provide either:`);
31195
31471
  const m = connStr.match(/^postgresql:\/\/([^:]+):([^@]+)@([^:\/]+)(?::(\d+))?\/(.+)$/);
31196
31472
  if (!m) {
31197
31473
  console.error("\u2717 Invalid connection string format");
31198
- console.log(`\u26A0 Continuing without adding instance
31474
+ console.error(`\u26A0 Continuing without adding instance
31199
31475
  `);
31200
31476
  } else {
31201
31477
  const host = m[3];
@@ -31213,7 +31489,7 @@ You can provide either:`);
31213
31489
  node_name: ${instanceName}
31214
31490
  sink_type: ~sink_type~
31215
31491
  `;
31216
- fs5.appendFileSync(instancesPath, body, "utf8");
31492
+ fs6.appendFileSync(instancesPath, body, "utf8");
31217
31493
  console.log(`\u2713 Monitoring target '${instanceName}' added
31218
31494
  `);
31219
31495
  console.log("Testing connection to the added instance...");
@@ -31232,11 +31508,11 @@ You can provide either:`);
31232
31508
  }
31233
31509
  }
31234
31510
  } else {
31235
- console.log(`\u26A0 No PostgreSQL instance added - you can add one later with: postgres-ai mon targets add
31511
+ console.error(`\u26A0 No PostgreSQL instance added - you can add one later with: postgres-ai mon targets add
31236
31512
  `);
31237
31513
  }
31238
31514
  } else {
31239
- console.log(`\u26A0 No PostgreSQL instance added - you can add one later with: postgres-ai mon targets add
31515
+ console.error(`\u26A0 No PostgreSQL instance added - you can add one later with: postgres-ai mon targets add
31240
31516
  `);
31241
31517
  }
31242
31518
  }
@@ -31253,13 +31529,13 @@ You can provide either:`);
31253
31529
  console.log(`\u2713 Configuration updated
31254
31530
  `);
31255
31531
  console.log(opts.demo ? "Step 4: Configuring Grafana security..." : "Step 4: Configuring Grafana security...");
31256
- const cfgPath = path5.resolve(projectDir, ".pgwatch-config");
31532
+ const cfgPath = path6.resolve(projectDir, ".pgwatch-config");
31257
31533
  let grafanaPassword = "";
31258
31534
  try {
31259
- if (fs5.existsSync(cfgPath)) {
31260
- const stats = fs5.statSync(cfgPath);
31535
+ if (fs6.existsSync(cfgPath)) {
31536
+ const stats = fs6.statSync(cfgPath);
31261
31537
  if (!stats.isDirectory()) {
31262
- const content = fs5.readFileSync(cfgPath, "utf8");
31538
+ const content = fs6.readFileSync(cfgPath, "utf8");
31263
31539
  const match = content.match(/^grafana_password=([^\r\n]+)/m);
31264
31540
  if (match) {
31265
31541
  grafanaPassword = match[1].trim();
@@ -31272,22 +31548,22 @@ You can provide either:`);
31272
31548
  '`);
31273
31549
  grafanaPassword = password.trim();
31274
31550
  let configContent = "";
31275
- if (fs5.existsSync(cfgPath)) {
31276
- const stats = fs5.statSync(cfgPath);
31551
+ if (fs6.existsSync(cfgPath)) {
31552
+ const stats = fs6.statSync(cfgPath);
31277
31553
  if (!stats.isDirectory()) {
31278
- configContent = fs5.readFileSync(cfgPath, "utf8");
31554
+ configContent = fs6.readFileSync(cfgPath, "utf8");
31279
31555
  }
31280
31556
  }
31281
31557
  const lines = configContent.split(/\r?\n/).filter((l) => !/^grafana_password=/.test(l));
31282
31558
  lines.push(`grafana_password=${grafanaPassword}`);
31283
- fs5.writeFileSync(cfgPath, lines.filter(Boolean).join(`
31559
+ fs6.writeFileSync(cfgPath, lines.filter(Boolean).join(`
31284
31560
  `) + `
31285
31561
  `, "utf8");
31286
31562
  }
31287
31563
  console.log(`\u2713 Grafana password configured
31288
31564
  `);
31289
31565
  } catch (error2) {
31290
- console.log("\u26A0 Could not generate Grafana password automatically");
31566
+ console.error("\u26A0 Could not generate Grafana password automatically");
31291
31567
  console.log(`Using default password: demo
31292
31568
  `);
31293
31569
  grafanaPassword = "demo";
@@ -31382,7 +31658,7 @@ mon.command("stop").description("stop monitoring services").action(async () => {
31382
31658
  let code = await runCompose(["down", "--remove-orphans"]);
31383
31659
  if (code !== 0) {
31384
31660
  await removeOrphanedContainers();
31385
- await new Promise((resolve6) => setTimeout(resolve6, NETWORK_CLEANUP_DELAY_MS));
31661
+ await new Promise((resolve7) => setTimeout(resolve7, NETWORK_CLEANUP_DELAY_MS));
31386
31662
  code = await runCompose(["down", "--remove-orphans"]);
31387
31663
  }
31388
31664
  if (code !== 0) {
@@ -31437,7 +31713,7 @@ mon.command("health").description("health check for monitoring services").option
31437
31713
  if (attempt > 1) {
31438
31714
  console.log(`Retrying (attempt ${attempt}/${maxAttempts})...
31439
31715
  `);
31440
- await new Promise((resolve6) => setTimeout(resolve6, 5000));
31716
+ await new Promise((resolve7) => setTimeout(resolve7, 5000));
31441
31717
  }
31442
31718
  allHealthy = true;
31443
31719
  for (const service of services) {
@@ -31485,11 +31761,11 @@ mon.command("config").description("show monitoring services configuration").acti
31485
31761
  console.log(`Project Directory: ${projectDir}`);
31486
31762
  console.log(`Docker Compose File: ${composeFile}`);
31487
31763
  console.log(`Instances File: ${instancesFile}`);
31488
- if (fs5.existsSync(instancesFile)) {
31764
+ if (fs6.existsSync(instancesFile)) {
31489
31765
  console.log(`
31490
31766
  Instances configuration:
31491
31767
  `);
31492
- const text = fs5.readFileSync(instancesFile, "utf8");
31768
+ const text = fs6.readFileSync(instancesFile, "utf8");
31493
31769
  process.stdout.write(text);
31494
31770
  if (!/\n$/.test(text))
31495
31771
  console.log();
@@ -31504,8 +31780,8 @@ mon.command("update").description("update monitoring stack").action(async () =>
31504
31780
  console.log(`Updating PostgresAI monitoring stack...
31505
31781
  `);
31506
31782
  try {
31507
- const gitDir = path5.resolve(process.cwd(), ".git");
31508
- if (!fs5.existsSync(gitDir)) {
31783
+ const gitDir = path6.resolve(process.cwd(), ".git");
31784
+ if (!fs6.existsSync(gitDir)) {
31509
31785
  console.error("Not a git repository. Cannot update.");
31510
31786
  process.exitCode = 1;
31511
31787
  return;
@@ -31601,7 +31877,7 @@ mon.command("clean").description("cleanup monitoring services artifacts (stops s
31601
31877
  if (downCode === 0) {
31602
31878
  console.log("\u2713 Monitoring services stopped and removed");
31603
31879
  } else {
31604
- console.log("\u26A0 Could not stop services (may not be running)");
31880
+ console.error("\u26A0 Could not stop services (may not be running)");
31605
31881
  }
31606
31882
  await removeOrphanedContainers();
31607
31883
  console.log("\u2713 Removed orphaned containers");
@@ -31660,13 +31936,13 @@ mon.command("check").description("monitoring services system readiness check").a
31660
31936
  var targets = mon.command("targets").description("manage databases to monitor");
31661
31937
  targets.command("list").description("list monitoring target databases").action(async () => {
31662
31938
  const { instancesFile: instancesPath, projectDir } = await resolveOrInitPaths();
31663
- if (!fs5.existsSync(instancesPath)) {
31939
+ if (!fs6.existsSync(instancesPath)) {
31664
31940
  console.error(`instances.yml not found in ${projectDir}`);
31665
31941
  process.exitCode = 1;
31666
31942
  return;
31667
31943
  }
31668
31944
  try {
31669
- const content = fs5.readFileSync(instancesPath, "utf8");
31945
+ const content = fs6.readFileSync(instancesPath, "utf8");
31670
31946
  const instances = load(content);
31671
31947
  if (!instances || !Array.isArray(instances) || instances.length === 0) {
31672
31948
  console.log("No monitoring targets configured");
@@ -31715,8 +31991,8 @@ targets.command("add [connStr] [name]").description("add monitoring target datab
31715
31991
  const db = m[5];
31716
31992
  const instanceName = name && name.trim() ? name.trim() : `${host}-${db}`.replace(/[^a-zA-Z0-9-]/g, "-");
31717
31993
  try {
31718
- if (fs5.existsSync(file)) {
31719
- const content2 = fs5.readFileSync(file, "utf8");
31994
+ if (fs6.existsSync(file)) {
31995
+ const content2 = fs6.readFileSync(file, "utf8");
31720
31996
  const instances = load(content2) || [];
31721
31997
  if (Array.isArray(instances)) {
31722
31998
  const exists = instances.some((inst) => inst.name === instanceName);
@@ -31728,7 +32004,7 @@ targets.command("add [connStr] [name]").description("add monitoring target datab
31728
32004
  }
31729
32005
  }
31730
32006
  } catch (err) {
31731
- const content2 = fs5.existsSync(file) ? fs5.readFileSync(file, "utf8") : "";
32007
+ const content2 = fs6.existsSync(file) ? fs6.readFileSync(file, "utf8") : "";
31732
32008
  if (new RegExp(`^- name: ${instanceName}$`, "m").test(content2)) {
31733
32009
  console.error(`Monitoring target '${instanceName}' already exists`);
31734
32010
  process.exitCode = 1;
@@ -31747,20 +32023,20 @@ targets.command("add [connStr] [name]").description("add monitoring target datab
31747
32023
  node_name: ${instanceName}
31748
32024
  sink_type: ~sink_type~
31749
32025
  `;
31750
- const content = fs5.existsSync(file) ? fs5.readFileSync(file, "utf8") : "";
31751
- fs5.appendFileSync(file, (content && !/\n$/.test(content) ? `
32026
+ const content = fs6.existsSync(file) ? fs6.readFileSync(file, "utf8") : "";
32027
+ fs6.appendFileSync(file, (content && !/\n$/.test(content) ? `
31752
32028
  ` : "") + body, "utf8");
31753
32029
  console.log(`Monitoring target '${instanceName}' added`);
31754
32030
  });
31755
32031
  targets.command("remove <name>").description("remove monitoring target database").action(async (name) => {
31756
32032
  const { instancesFile: file } = await resolveOrInitPaths();
31757
- if (!fs5.existsSync(file)) {
32033
+ if (!fs6.existsSync(file)) {
31758
32034
  console.error("instances.yml not found");
31759
32035
  process.exitCode = 1;
31760
32036
  return;
31761
32037
  }
31762
32038
  try {
31763
- const content = fs5.readFileSync(file, "utf8");
32039
+ const content = fs6.readFileSync(file, "utf8");
31764
32040
  const instances = load(content);
31765
32041
  if (!instances || !Array.isArray(instances)) {
31766
32042
  console.error("Invalid instances.yml format");
@@ -31773,7 +32049,7 @@ targets.command("remove <name>").description("remove monitoring target database"
31773
32049
  process.exitCode = 1;
31774
32050
  return;
31775
32051
  }
31776
- fs5.writeFileSync(file, dump(filtered), "utf8");
32052
+ fs6.writeFileSync(file, dump(filtered), "utf8");
31777
32053
  console.log(`Monitoring target '${name}' removed`);
31778
32054
  } catch (err) {
31779
32055
  const message = err instanceof Error ? err.message : String(err);
@@ -31783,13 +32059,13 @@ targets.command("remove <name>").description("remove monitoring target database"
31783
32059
  });
31784
32060
  targets.command("test <name>").description("test monitoring target database connectivity").action(async (name) => {
31785
32061
  const { instancesFile: instancesPath } = await resolveOrInitPaths();
31786
- if (!fs5.existsSync(instancesPath)) {
32062
+ if (!fs6.existsSync(instancesPath)) {
31787
32063
  console.error("instances.yml not found");
31788
32064
  process.exitCode = 1;
31789
32065
  return;
31790
32066
  }
31791
32067
  try {
31792
- const content = fs5.readFileSync(instancesPath, "utf8");
32068
+ const content = fs6.readFileSync(instancesPath, "utf8");
31793
32069
  const instances = load(content);
31794
32070
  if (!instances || !Array.isArray(instances)) {
31795
32071
  console.error("Invalid instances.yml format");
@@ -31850,8 +32126,8 @@ auth.command("login", { isDefault: true }).description("authenticate via browser
31850
32126
  const cfg = readConfig();
31851
32127
  const { apiBaseUrl, uiBaseUrl } = resolveBaseUrls2(rootOpts, cfg);
31852
32128
  if (opts.debug) {
31853
- console.log(`Debug: Resolved API base URL: ${apiBaseUrl}`);
31854
- console.log(`Debug: Resolved UI base URL: ${uiBaseUrl}`);
32129
+ console.error(`Debug: Resolved API base URL: ${apiBaseUrl}`);
32130
+ console.error(`Debug: Resolved UI base URL: ${uiBaseUrl}`);
31855
32131
  }
31856
32132
  try {
31857
32133
  console.log("Starting local callback server...");
@@ -31870,8 +32146,8 @@ auth.command("login", { isDefault: true }).description("authenticate via browser
31870
32146
  });
31871
32147
  const initUrl = new URL(`${apiBaseUrl}/rpc/oauth_init`);
31872
32148
  if (opts.debug) {
31873
- console.log(`Debug: Trying to POST to: ${initUrl.toString()}`);
31874
- console.log(`Debug: Request data: ${initData}`);
32149
+ console.error(`Debug: Trying to POST to: ${initUrl.toString()}`);
32150
+ console.error(`Debug: Request data: ${initData}`);
31875
32151
  }
31876
32152
  let initResponse;
31877
32153
  try {
@@ -31909,7 +32185,7 @@ Please verify the --api-base-url parameter.`);
31909
32185
  }
31910
32186
  const authUrl = `${uiBaseUrl}/cli/auth?state=${encodeURIComponent(params.state)}&code_challenge=${encodeURIComponent(params.codeChallenge)}&code_challenge_method=S256&redirect_uri=${encodeURIComponent(redirectUri)}&api_url=${encodeURIComponent(apiBaseUrl)}`;
31911
32187
  if (opts.debug) {
31912
- console.log(`Debug: Auth URL: ${authUrl}`);
32188
+ console.error(`Debug: Auth URL: ${authUrl}`);
31913
32189
  }
31914
32190
  console.log(`
31915
32191
  Opening browser for authentication...`);
@@ -32042,15 +32318,15 @@ To authenticate, run: pgai auth`);
32042
32318
  });
32043
32319
  auth.command("remove-key").description("remove API key").action(async () => {
32044
32320
  const newConfigPath = getConfigPath();
32045
- const hasNewConfig = fs5.existsSync(newConfigPath);
32321
+ const hasNewConfig = fs6.existsSync(newConfigPath);
32046
32322
  let legacyPath;
32047
32323
  try {
32048
32324
  const { projectDir } = await resolveOrInitPaths();
32049
- legacyPath = path5.resolve(projectDir, ".pgwatch-config");
32325
+ legacyPath = path6.resolve(projectDir, ".pgwatch-config");
32050
32326
  } catch {
32051
- legacyPath = path5.resolve(process.cwd(), ".pgwatch-config");
32327
+ legacyPath = path6.resolve(process.cwd(), ".pgwatch-config");
32052
32328
  }
32053
- const hasLegacyConfig = fs5.existsSync(legacyPath) && fs5.statSync(legacyPath).isFile();
32329
+ const hasLegacyConfig = fs6.existsSync(legacyPath) && fs6.statSync(legacyPath).isFile();
32054
32330
  if (!hasNewConfig && !hasLegacyConfig) {
32055
32331
  console.log("No API key configured");
32056
32332
  return;
@@ -32060,11 +32336,11 @@ auth.command("remove-key").description("remove API key").action(async () => {
32060
32336
  }
32061
32337
  if (hasLegacyConfig) {
32062
32338
  try {
32063
- const content = fs5.readFileSync(legacyPath, "utf8");
32339
+ const content = fs6.readFileSync(legacyPath, "utf8");
32064
32340
  const filtered = content.split(/\r?\n/).filter((l) => !/^api_key=/.test(l)).join(`
32065
32341
  `).replace(/\n+$/g, `
32066
32342
  `);
32067
- fs5.writeFileSync(legacyPath, filtered, "utf8");
32343
+ fs6.writeFileSync(legacyPath, filtered, "utf8");
32068
32344
  } catch (err) {
32069
32345
  console.warn(`Warning: Could not update legacy config: ${err instanceof Error ? err.message : String(err)}`);
32070
32346
  }
@@ -32075,7 +32351,7 @@ To authenticate again, run: pgai auth`);
32075
32351
  });
32076
32352
  mon.command("generate-grafana-password").description("generate Grafana password for monitoring services").action(async () => {
32077
32353
  const { projectDir } = await resolveOrInitPaths();
32078
- const cfgPath = path5.resolve(projectDir, ".pgwatch-config");
32354
+ const cfgPath = path6.resolve(projectDir, ".pgwatch-config");
32079
32355
  try {
32080
32356
  const { stdout: password } = await execPromise(`openssl rand -base64 12 | tr -d '
32081
32357
  '`);
@@ -32086,17 +32362,17 @@ mon.command("generate-grafana-password").description("generate Grafana password
32086
32362
  return;
32087
32363
  }
32088
32364
  let configContent = "";
32089
- if (fs5.existsSync(cfgPath)) {
32090
- const stats = fs5.statSync(cfgPath);
32365
+ if (fs6.existsSync(cfgPath)) {
32366
+ const stats = fs6.statSync(cfgPath);
32091
32367
  if (stats.isDirectory()) {
32092
32368
  console.error(".pgwatch-config is a directory, expected a file. Skipping read.");
32093
32369
  } else {
32094
- configContent = fs5.readFileSync(cfgPath, "utf8");
32370
+ configContent = fs6.readFileSync(cfgPath, "utf8");
32095
32371
  }
32096
32372
  }
32097
32373
  const lines = configContent.split(/\r?\n/).filter((l) => !/^grafana_password=/.test(l));
32098
32374
  lines.push(`grafana_password=${newPassword}`);
32099
- fs5.writeFileSync(cfgPath, lines.filter(Boolean).join(`
32375
+ fs6.writeFileSync(cfgPath, lines.filter(Boolean).join(`
32100
32376
  `) + `
32101
32377
  `, "utf8");
32102
32378
  console.log("\u2713 New Grafana password generated and saved");
@@ -32118,19 +32394,19 @@ Note: This command requires 'openssl' to be installed`);
32118
32394
  });
32119
32395
  mon.command("show-grafana-credentials").description("show Grafana credentials for monitoring services").action(async () => {
32120
32396
  const { projectDir } = await resolveOrInitPaths();
32121
- const cfgPath = path5.resolve(projectDir, ".pgwatch-config");
32122
- if (!fs5.existsSync(cfgPath)) {
32397
+ const cfgPath = path6.resolve(projectDir, ".pgwatch-config");
32398
+ if (!fs6.existsSync(cfgPath)) {
32123
32399
  console.error("Configuration file not found. Run 'postgres-ai mon local-install' first.");
32124
32400
  process.exitCode = 1;
32125
32401
  return;
32126
32402
  }
32127
- const stats = fs5.statSync(cfgPath);
32403
+ const stats = fs6.statSync(cfgPath);
32128
32404
  if (stats.isDirectory()) {
32129
32405
  console.error(".pgwatch-config is a directory, expected a file. Cannot read credentials.");
32130
32406
  process.exitCode = 1;
32131
32407
  return;
32132
32408
  }
32133
- const content = fs5.readFileSync(cfgPath, "utf8");
32409
+ const content = fs6.readFileSync(cfgPath, "utf8");
32134
32410
  const lines = content.split(/\r?\n/);
32135
32411
  let password = "";
32136
32412
  for (const line of lines) {
@@ -32235,11 +32511,11 @@ issues.command("view <issueId>").description("view issue details and comments").
32235
32511
  });
32236
32512
  issues.command("post-comment <issueId> <content>").description("post a new comment to an issue").option("--parent <uuid>", "parent comment id").option("--debug", "enable debug output").option("--json", "output raw JSON").action(async (issueId, content, opts) => {
32237
32513
  if (opts.debug) {
32238
- console.log(`Debug: Original content: ${JSON.stringify(content)}`);
32514
+ console.error(`Debug: Original content: ${JSON.stringify(content)}`);
32239
32515
  }
32240
32516
  content = interpretEscapes2(content);
32241
32517
  if (opts.debug) {
32242
- console.log(`Debug: Interpreted content: ${JSON.stringify(content)}`);
32518
+ console.error(`Debug: Interpreted content: ${JSON.stringify(content)}`);
32243
32519
  }
32244
32520
  const spinner = createTtySpinner(process.stdout.isTTY ?? false, "Posting comment...");
32245
32521
  try {
@@ -32385,11 +32661,11 @@ issues.command("update <issueId>").description("update an existing issue (title/
32385
32661
  });
32386
32662
  issues.command("update-comment <commentId> <content>").description("update an existing issue comment").option("--debug", "enable debug output").option("--json", "output raw JSON").action(async (commentId, content, opts) => {
32387
32663
  if (opts.debug) {
32388
- console.log(`Debug: Original content: ${JSON.stringify(content)}`);
32664
+ console.error(`Debug: Original content: ${JSON.stringify(content)}`);
32389
32665
  }
32390
32666
  content = interpretEscapes2(content);
32391
32667
  if (opts.debug) {
32392
- console.log(`Debug: Interpreted content: ${JSON.stringify(content)}`);
32668
+ console.error(`Debug: Interpreted content: ${JSON.stringify(content)}`);
32393
32669
  }
32394
32670
  const rootOpts = program2.opts();
32395
32671
  const cfg = readConfig();
@@ -32418,6 +32694,74 @@ issues.command("update-comment <commentId> <content>").description("update an ex
32418
32694
  process.exitCode = 1;
32419
32695
  }
32420
32696
  });
32697
+ var issueFiles = issues.command("files").description("upload and download files for issues");
32698
+ issueFiles.command("upload <path>").description("upload a file to storage and get a markdown link").option("--debug", "enable debug output").option("--json", "output raw JSON").action(async (filePath, opts) => {
32699
+ const spinner = createTtySpinner(process.stdout.isTTY ?? false, "Uploading file...");
32700
+ try {
32701
+ const rootOpts = program2.opts();
32702
+ const cfg = readConfig();
32703
+ const { apiKey } = getConfig(rootOpts);
32704
+ if (!apiKey) {
32705
+ spinner.stop();
32706
+ console.error("API key is required. Run 'pgai auth' first or set --api-key.");
32707
+ process.exitCode = 1;
32708
+ return;
32709
+ }
32710
+ const { storageBaseUrl } = resolveBaseUrls2(rootOpts, cfg);
32711
+ const result = await uploadFile({
32712
+ apiKey,
32713
+ storageBaseUrl,
32714
+ filePath,
32715
+ debug: !!opts.debug
32716
+ });
32717
+ spinner.stop();
32718
+ if (opts.json) {
32719
+ printResult(result, true);
32720
+ } else {
32721
+ const md = buildMarkdownLink(result.url, storageBaseUrl, result.metadata.originalName);
32722
+ const displayUrl = result.url.startsWith("/") ? `${storageBaseUrl}${result.url}` : `${storageBaseUrl}/${result.url}`;
32723
+ console.log(`URL: ${displayUrl}`);
32724
+ console.log(`File: ${result.metadata.originalName}`);
32725
+ console.log(`Size: ${result.metadata.size} bytes`);
32726
+ console.log(`Type: ${result.metadata.mimeType}`);
32727
+ console.log(`Markdown: ${md}`);
32728
+ }
32729
+ } catch (err) {
32730
+ spinner.stop();
32731
+ const message = err instanceof Error ? err.message : String(err);
32732
+ console.error(message);
32733
+ process.exitCode = 1;
32734
+ }
32735
+ });
32736
+ issueFiles.command("download <url>").description("download a file from storage").option("-o, --output <path>", "output file path (default: derive from URL)").option("--debug", "enable debug output").action(async (fileUrl, opts) => {
32737
+ const spinner = createTtySpinner(process.stdout.isTTY ?? false, "Downloading file...");
32738
+ try {
32739
+ const rootOpts = program2.opts();
32740
+ const cfg = readConfig();
32741
+ const { apiKey } = getConfig(rootOpts);
32742
+ if (!apiKey) {
32743
+ spinner.stop();
32744
+ console.error("API key is required. Run 'pgai auth' first or set --api-key.");
32745
+ process.exitCode = 1;
32746
+ return;
32747
+ }
32748
+ const { storageBaseUrl } = resolveBaseUrls2(rootOpts, cfg);
32749
+ const result = await downloadFile({
32750
+ apiKey,
32751
+ storageBaseUrl,
32752
+ fileUrl,
32753
+ outputPath: opts.output,
32754
+ debug: !!opts.debug
32755
+ });
32756
+ spinner.stop();
32757
+ console.log(`Saved: ${result.savedTo}`);
32758
+ } catch (err) {
32759
+ spinner.stop();
32760
+ const message = err instanceof Error ? err.message : String(err);
32761
+ console.error(message);
32762
+ process.exitCode = 1;
32763
+ }
32764
+ });
32421
32765
  issues.command("action-items <issueId>").description("list action items for an issue").option("--debug", "enable debug output").option("--json", "output raw JSON").action(async (issueId, opts) => {
32422
32766
  const spinner = createTtySpinner(process.stdout.isTTY ?? false, "Fetching action items...");
32423
32767
  try {
@@ -32591,7 +32935,10 @@ issues.command("update-action-item <actionItemId>").description("update an actio
32591
32935
  }
32592
32936
  });
32593
32937
  var reports = program2.command("reports").description("checkup reports management");
32594
- reports.command("list").description("list checkup reports").option("--project-id <id>", "filter by project id", (v) => parseInt(v, 10)).option("--status <status>", "filter by status (e.g., completed)").option("--limit <n>", "max number of reports to return (default: 20)", (v) => parseInt(v, 10)).option("--before <date>", "show reports created before this date (YYYY-MM-DD, DD.MM.YYYY, etc.)").option("--all", "fetch all reports (paginated automatically)").option("--debug", "enable debug output").option("--json", "output raw JSON").action(async (opts) => {
32938
+ reports.command("list").description("list checkup reports").option("--project-id <id>", "filter by project id", (v) => parseInt(v, 10)).addOption(new Option("--status <status>", "filter by status (e.g., completed)").hideHelp()).option("--limit <n>", "max number of reports to return (default: 20, max: 100)", (v) => {
32939
+ const n = parseInt(v, 10);
32940
+ return Number.isNaN(n) ? 20 : Math.max(1, Math.min(n, 100));
32941
+ }).option("--before <date>", "show reports created before this date (YYYY-MM-DD, DD.MM.YYYY, etc.)").option("--all", "fetch all reports (paginated automatically)").addOption(new Option("--debug", "enable debug output").hideHelp()).option("--json", "output raw JSON").action(async (opts) => {
32595
32942
  const spinner = createTtySpinner(process.stdout.isTTY ?? false, "Fetching reports...");
32596
32943
  try {
32597
32944
  const rootOpts = program2.opts();
@@ -32640,7 +32987,7 @@ reports.command("list").description("list checkup reports").option("--project-id
32640
32987
  process.exitCode = 1;
32641
32988
  }
32642
32989
  });
32643
- reports.command("files [reportId]").description("list files of a checkup report (metadata only, no content)").option("--type <type>", "filter by file type: json, md").option("--check-id <id>", "filter by check ID (e.g., H002)").option("--debug", "enable debug output").option("--json", "output raw JSON").action(async (reportId, opts) => {
32990
+ reports.command("files [reportId]").description("list files of a checkup report (metadata only, no content)").option("--type <type>", "filter by file type: json, md").option("--check-id <id>", "filter by check ID (e.g., H002)").addOption(new Option("--debug", "enable debug output").hideHelp()).option("--json", "output raw JSON").action(async (reportId, opts) => {
32644
32991
  const spinner = createTtySpinner(process.stdout.isTTY ?? false, "Fetching report files...");
32645
32992
  try {
32646
32993
  const rootOpts = program2.opts();
@@ -32686,7 +33033,7 @@ reports.command("files [reportId]").description("list files of a checkup report
32686
33033
  process.exitCode = 1;
32687
33034
  }
32688
33035
  });
32689
- reports.command("data [reportId]").description("get checkup report file data (includes content)").option("--type <type>", "filter by file type: json, md").option("--check-id <id>", "filter by check ID (e.g., H002)").option("--formatted", "render markdown with ANSI styling (experimental)").option("-o, --output <dir>", "save files to directory (uses original filenames)").option("--debug", "enable debug output").option("--json", "output raw JSON").action(async (reportId, opts) => {
33036
+ reports.command("data [reportId]").description("get checkup report file data (includes content)").option("--type <type>", "filter by file type: json, md").option("--check-id <id>", "filter by check ID (e.g., H002)").option("--formatted", "render markdown with ANSI styling (experimental)").option("-o, --output <dir>", "save files to directory (uses original filenames)").addOption(new Option("--debug", "enable debug output").hideHelp()).option("--json", "output raw JSON").action(async (reportId, opts) => {
32690
33037
  const spinner = createTtySpinner(process.stdout.isTTY ?? false, "Fetching report data...");
32691
33038
  try {
32692
33039
  const rootOpts = program2.opts();
@@ -32726,13 +33073,13 @@ reports.command("data [reportId]").description("get checkup report file data (in
32726
33073
  });
32727
33074
  spinner.stop();
32728
33075
  if (opts.output) {
32729
- const dir = path5.resolve(opts.output);
32730
- fs5.mkdirSync(dir, { recursive: true });
33076
+ const dir = path6.resolve(opts.output);
33077
+ fs6.mkdirSync(dir, { recursive: true });
32731
33078
  for (const f of result) {
32732
- const safeName = path5.basename(f.filename);
32733
- const filePath = path5.join(dir, safeName);
33079
+ const safeName = path6.basename(f.filename);
33080
+ const filePath = path6.join(dir, safeName);
32734
33081
  const content = f.type === "json" ? JSON.stringify(tryParseJson(f.data), null, 2) : f.data;
32735
- fs5.writeFileSync(filePath, content, "utf-8");
33082
+ fs6.writeFileSync(filePath, content, "utf-8");
32736
33083
  console.log(filePath);
32737
33084
  }
32738
33085
  } else if (opts.json) {
@@ -32850,29 +33197,29 @@ mcp.command("install [client]").description("install MCP server configuration fo
32850
33197
  let configDir;
32851
33198
  switch (client) {
32852
33199
  case "cursor":
32853
- configPath = path5.join(homeDir, ".cursor", "mcp.json");
32854
- configDir = path5.dirname(configPath);
33200
+ configPath = path6.join(homeDir, ".cursor", "mcp.json");
33201
+ configDir = path6.dirname(configPath);
32855
33202
  break;
32856
33203
  case "windsurf":
32857
- configPath = path5.join(homeDir, ".windsurf", "mcp.json");
32858
- configDir = path5.dirname(configPath);
33204
+ configPath = path6.join(homeDir, ".windsurf", "mcp.json");
33205
+ configDir = path6.dirname(configPath);
32859
33206
  break;
32860
33207
  case "codex":
32861
- configPath = path5.join(homeDir, ".codex", "mcp.json");
32862
- configDir = path5.dirname(configPath);
33208
+ configPath = path6.join(homeDir, ".codex", "mcp.json");
33209
+ configDir = path6.dirname(configPath);
32863
33210
  break;
32864
33211
  default:
32865
33212
  console.error(`Configuration not implemented for: ${client}`);
32866
33213
  process.exitCode = 1;
32867
33214
  return;
32868
33215
  }
32869
- if (!fs5.existsSync(configDir)) {
32870
- fs5.mkdirSync(configDir, { recursive: true });
33216
+ if (!fs6.existsSync(configDir)) {
33217
+ fs6.mkdirSync(configDir, { recursive: true });
32871
33218
  }
32872
33219
  let config2 = { mcpServers: {} };
32873
- if (fs5.existsSync(configPath)) {
33220
+ if (fs6.existsSync(configPath)) {
32874
33221
  try {
32875
- const content = fs5.readFileSync(configPath, "utf8");
33222
+ const content = fs6.readFileSync(configPath, "utf8");
32876
33223
  config2 = JSON.parse(content);
32877
33224
  if (!config2.mcpServers) {
32878
33225
  config2.mcpServers = {};
@@ -32885,7 +33232,7 @@ mcp.command("install [client]").description("install MCP server configuration fo
32885
33232
  command: pgaiPath,
32886
33233
  args: ["mcp", "start"]
32887
33234
  };
32888
- fs5.writeFileSync(configPath, JSON.stringify(config2, null, 2), "utf8");
33235
+ fs6.writeFileSync(configPath, JSON.stringify(config2, null, 2), "utf8");
32889
33236
  console.log(`\u2713 PostgresAI MCP server configured for ${client}`);
32890
33237
  console.log(` Config file: ${configPath}`);
32891
33238
  console.log("");