postgresai 0.14.0-dev.86 → 0.14.0-dev.87

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.
@@ -13064,7 +13064,7 @@ var {
13064
13064
  // package.json
13065
13065
  var package_default = {
13066
13066
  name: "postgresai",
13067
- version: "0.14.0-dev.86",
13067
+ version: "0.14.0-dev.87",
13068
13068
  description: "postgres_ai CLI",
13069
13069
  license: "Apache-2.0",
13070
13070
  private: false,
@@ -15889,7 +15889,7 @@ var Result = import_lib.default.Result;
15889
15889
  var TypeOverrides = import_lib.default.TypeOverrides;
15890
15890
  var defaults = import_lib.default.defaults;
15891
15891
  // package.json
15892
- var version = "0.14.0-dev.86";
15892
+ var version = "0.14.0-dev.87";
15893
15893
  var package_default2 = {
15894
15894
  name: "postgresai",
15895
15895
  version,
@@ -28093,8 +28093,6 @@ function unwrapRpcResponse(parsed) {
28093
28093
  var HTTP_TIMEOUT_MS = 30000;
28094
28094
  async function postRpc(params) {
28095
28095
  const { apiKey, apiBaseUrl, rpcName, bodyObj, timeoutMs = HTTP_TIMEOUT_MS } = params;
28096
- if (!apiKey)
28097
- throw new Error("API key is required");
28098
28096
  const base = normalizeBaseUrl(apiBaseUrl);
28099
28097
  const url = new URL3(`${base}/rpc/${rpcName}`);
28100
28098
  const body = JSON.stringify(bodyObj);
@@ -28227,6 +28225,249 @@ async function uploadCheckupReportJson(params) {
28227
28225
  }
28228
28226
  return { reportChunkId: chunkId };
28229
28227
  }
28228
+ async function convertCheckupReportJsonToMarkdown(params) {
28229
+ const { apiKey, apiBaseUrl, checkId, jsonPayload, reportType } = params;
28230
+ const bodyObj = {
28231
+ check_id: checkId,
28232
+ json_payload: jsonPayload,
28233
+ access_token: apiKey
28234
+ };
28235
+ if (reportType) {
28236
+ bodyObj.report_type = reportType;
28237
+ }
28238
+ const resp = await postRpc({
28239
+ apiKey,
28240
+ apiBaseUrl,
28241
+ rpcName: "checkup_report_json_to_markdown",
28242
+ bodyObj
28243
+ });
28244
+ return resp;
28245
+ }
28246
+
28247
+ // lib/checkup-summary.ts
28248
+ function generateCheckSummary(checkId, report) {
28249
+ const nodeIds = Object.keys(report.results || {});
28250
+ if (nodeIds.length === 0) {
28251
+ return { status: "info", message: "No data" };
28252
+ }
28253
+ const nodeData = report.results[nodeIds[0]];
28254
+ switch (checkId) {
28255
+ case "H001":
28256
+ return summarizeH001(nodeData);
28257
+ case "H002":
28258
+ return summarizeH002(nodeData);
28259
+ case "H004":
28260
+ return summarizeH004(nodeData);
28261
+ case "A002":
28262
+ return summarizeA002(nodeData);
28263
+ case "A013":
28264
+ return summarizeA013(nodeData);
28265
+ case "A003":
28266
+ return summarizeA003(nodeData);
28267
+ case "A004":
28268
+ return summarizeA004(nodeData);
28269
+ case "A007":
28270
+ return summarizeA007(nodeData);
28271
+ case "D001":
28272
+ return summarizeD001(nodeData);
28273
+ case "D004":
28274
+ return summarizeD004(nodeData);
28275
+ case "F001":
28276
+ return summarizeF001(nodeData);
28277
+ case "G001":
28278
+ return summarizeG001(nodeData);
28279
+ case "G003":
28280
+ return summarizeG003(nodeData);
28281
+ default:
28282
+ return { status: "info", message: "Check completed" };
28283
+ }
28284
+ }
28285
+ function summarizeA003(nodeData) {
28286
+ const data = nodeData?.data || {};
28287
+ const settingsCount = Object.keys(data).length;
28288
+ if (settingsCount === 0) {
28289
+ return { status: "info", message: "No settings found" };
28290
+ }
28291
+ return {
28292
+ status: "info",
28293
+ message: `${settingsCount} setting${settingsCount > 1 ? "s" : ""} collected`
28294
+ };
28295
+ }
28296
+ function summarizeA004(nodeData) {
28297
+ const data = nodeData?.data;
28298
+ if (!data) {
28299
+ return { status: "info", message: "Cluster information collected" };
28300
+ }
28301
+ const dbCount = Object.keys(data.database_sizes || {}).length;
28302
+ if (dbCount > 0) {
28303
+ return { status: "info", message: `${dbCount} database${dbCount > 1 ? "s" : ""} analyzed` };
28304
+ }
28305
+ return { status: "info", message: "Cluster information collected" };
28306
+ }
28307
+ function summarizeA007(nodeData) {
28308
+ const data = nodeData?.data || {};
28309
+ const alteredCount = Object.keys(data).length;
28310
+ if (alteredCount === 0) {
28311
+ return { status: "ok", message: "No altered settings" };
28312
+ }
28313
+ return {
28314
+ status: "info",
28315
+ message: `${alteredCount} setting${alteredCount > 1 ? "s" : ""} altered from defaults`
28316
+ };
28317
+ }
28318
+ function formatBytes2(bytes) {
28319
+ if (bytes === 0)
28320
+ return "0 B";
28321
+ if (bytes < 1024)
28322
+ return `${bytes} B`;
28323
+ if (bytes < 1024 * 1024)
28324
+ return `${(bytes / 1024).toFixed(0)} KiB`;
28325
+ if (bytes < 1024 * 1024 * 1024)
28326
+ return `${(bytes / (1024 * 1024)).toFixed(0)} MiB`;
28327
+ return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} GiB`;
28328
+ }
28329
+ function summarizeH001(nodeData) {
28330
+ const data = nodeData?.data || {};
28331
+ let totalCount = 0;
28332
+ let totalSize = 0;
28333
+ for (const dbData of Object.values(data)) {
28334
+ const dbEntry = dbData;
28335
+ totalCount += dbEntry.total_count || 0;
28336
+ totalSize += dbEntry.total_size_bytes || 0;
28337
+ }
28338
+ if (totalCount === 0) {
28339
+ return { status: "ok", message: "No invalid indexes" };
28340
+ }
28341
+ return {
28342
+ status: "warning",
28343
+ message: `Found ${totalCount} invalid index${totalCount > 1 ? "es" : ""} (${formatBytes2(totalSize)})`
28344
+ };
28345
+ }
28346
+ function summarizeH002(nodeData) {
28347
+ const data = nodeData?.data || {};
28348
+ let totalCount = 0;
28349
+ let totalSize = 0;
28350
+ for (const dbData of Object.values(data)) {
28351
+ const dbEntry = dbData;
28352
+ totalCount += dbEntry.total_count || 0;
28353
+ totalSize += dbEntry.total_size_bytes || 0;
28354
+ }
28355
+ if (totalCount === 0) {
28356
+ return { status: "ok", message: "All indexes utilized" };
28357
+ }
28358
+ return {
28359
+ status: "warning",
28360
+ message: `Found ${totalCount} unused index${totalCount > 1 ? "es" : ""} (${formatBytes2(totalSize)})`
28361
+ };
28362
+ }
28363
+ function summarizeH004(nodeData) {
28364
+ const data = nodeData?.data || {};
28365
+ let totalCount = 0;
28366
+ let totalSize = 0;
28367
+ for (const dbData of Object.values(data)) {
28368
+ const dbEntry = dbData;
28369
+ totalCount += dbEntry.total_count || 0;
28370
+ totalSize += dbEntry.total_size_bytes || 0;
28371
+ }
28372
+ if (totalCount === 0) {
28373
+ return { status: "ok", message: "No redundant indexes" };
28374
+ }
28375
+ return {
28376
+ status: "warning",
28377
+ message: `Found ${totalCount} redundant index${totalCount > 1 ? "es" : ""} (${formatBytes2(totalSize)})`
28378
+ };
28379
+ }
28380
+ function summarizeA002(nodeData) {
28381
+ const ver = nodeData?.data?.version;
28382
+ if (!ver) {
28383
+ return { status: "info", message: "Version checked" };
28384
+ }
28385
+ const major = parseInt(ver.server_major_ver, 10);
28386
+ if (major >= 17) {
28387
+ return { status: "ok", message: `PostgreSQL ${major}` };
28388
+ }
28389
+ if (major >= 15) {
28390
+ return { status: "info", message: `PostgreSQL ${major}` };
28391
+ }
28392
+ return {
28393
+ status: "warning",
28394
+ message: `PostgreSQL ${major} (consider upgrading)`
28395
+ };
28396
+ }
28397
+ function summarizeA013(nodeData) {
28398
+ const ver = nodeData?.data?.version;
28399
+ if (!ver) {
28400
+ return { status: "info", message: "Minor version checked" };
28401
+ }
28402
+ const current = ver.version || "";
28403
+ return {
28404
+ status: "info",
28405
+ message: `Version ${current}`
28406
+ };
28407
+ }
28408
+ function summarizeD001(nodeData) {
28409
+ const data = nodeData?.data || {};
28410
+ const settingsCount = Object.keys(data).length;
28411
+ if (settingsCount === 0) {
28412
+ return { status: "info", message: "No logging settings found" };
28413
+ }
28414
+ return {
28415
+ status: "info",
28416
+ message: `${settingsCount} logging setting${settingsCount > 1 ? "s" : ""} collected`
28417
+ };
28418
+ }
28419
+ function summarizeD004(nodeData) {
28420
+ const data = nodeData?.data || {};
28421
+ const settingsCount = Object.keys(data).length;
28422
+ if (settingsCount === 0) {
28423
+ return { status: "info", message: "No pg_stat_statements settings found" };
28424
+ }
28425
+ return {
28426
+ status: "info",
28427
+ message: `${settingsCount} pg_stat_statements setting${settingsCount > 1 ? "s" : ""} collected`
28428
+ };
28429
+ }
28430
+ function summarizeF001(nodeData) {
28431
+ const data = nodeData?.data || {};
28432
+ const settingsCount = Object.keys(data).length;
28433
+ if (settingsCount === 0) {
28434
+ return { status: "info", message: "No autovacuum settings found" };
28435
+ }
28436
+ return {
28437
+ status: "info",
28438
+ message: `${settingsCount} autovacuum setting${settingsCount > 1 ? "s" : ""} collected`
28439
+ };
28440
+ }
28441
+ function summarizeG001(nodeData) {
28442
+ const data = nodeData?.data || {};
28443
+ const settingsCount = Object.keys(data).length;
28444
+ if (settingsCount === 0) {
28445
+ return { status: "info", message: "No memory settings found" };
28446
+ }
28447
+ return {
28448
+ status: "info",
28449
+ message: `${settingsCount} memory setting${settingsCount > 1 ? "s" : ""} collected`
28450
+ };
28451
+ }
28452
+ function summarizeG003(nodeData) {
28453
+ const data = nodeData?.data || {};
28454
+ const settings = data.settings || {};
28455
+ const deadlockStats = data.deadlock_stats;
28456
+ const settingsCount = Object.keys(settings).length;
28457
+ if (deadlockStats && typeof deadlockStats.deadlocks === "number" && deadlockStats.deadlocks > 0) {
28458
+ return {
28459
+ status: "warning",
28460
+ message: `${deadlockStats.deadlocks} deadlock${deadlockStats.deadlocks > 1 ? "s" : ""} detected`
28461
+ };
28462
+ }
28463
+ if (settingsCount === 0) {
28464
+ return { status: "info", message: "No timeout/lock settings found" };
28465
+ }
28466
+ return {
28467
+ status: "info",
28468
+ message: `${settingsCount} timeout/lock setting${settingsCount > 1 ? "s" : ""} collected`
28469
+ };
28470
+ }
28230
28471
 
28231
28472
  // bin/postgres-ai.ts
28232
28473
  var rl = null;
@@ -28427,7 +28668,6 @@ async function uploadCheckupReports(uploadCfg, reports, spinner, logUpload) {
28427
28668
  logUpload(`[Retry ${attempt}/3] createCheckupReport failed: ${errMsg}, retrying in ${delayMs}ms...`);
28428
28669
  });
28429
28670
  const reportId = created.reportId;
28430
- logUpload(`Created remote checkup report: ${reportId}`);
28431
28671
  const uploaded = [];
28432
28672
  for (const [checkId, report] of Object.entries(reports)) {
28433
28673
  spinner.update(`Uploading ${checkId}.json`);
@@ -28445,7 +28685,6 @@ async function uploadCheckupReports(uploadCfg, reports, spinner, logUpload) {
28445
28685
  });
28446
28686
  uploaded.push({ checkId, filename: `${checkId}.json`, chunkId: r.reportChunkId });
28447
28687
  }
28448
- logUpload("Upload completed");
28449
28688
  return { project: uploadCfg.project, reportId, uploaded };
28450
28689
  }
28451
28690
  function writeReportFiles(reports, outputPath) {
@@ -28455,7 +28694,7 @@ function writeReportFiles(reports, outputPath) {
28455
28694
  console.log(`\u2713 ${checkId}: ${filePath}`);
28456
28695
  }
28457
28696
  }
28458
- function printUploadSummary(summary, projectWasGenerated, useStderr) {
28697
+ function printUploadSummary(summary, projectWasGenerated, useStderr, reports) {
28459
28698
  const out = useStderr ? console.error : console.log;
28460
28699
  out(`
28461
28700
  Checkup report uploaded`);
@@ -28467,11 +28706,28 @@ Checkup report uploaded`);
28467
28706
  out(`Project: ${summary.project}`);
28468
28707
  }
28469
28708
  out(`Report ID: ${summary.reportId}`);
28470
- out("View in Console: console.postgres.ai \u2192 Support \u2192 checkup reports");
28709
+ out("View in Console: console.postgres.ai \u2192 Checkup \u2192 checkup reports");
28471
28710
  out("");
28472
- out("Files:");
28711
+ const summaries = [];
28712
+ let skippedCount = 0;
28473
28713
  for (const item of summary.uploaded) {
28474
- out(`- ${item.checkId}: ${item.filename}`);
28714
+ const report = reports[item.checkId];
28715
+ if (report) {
28716
+ const { status, message } = generateCheckSummary(item.checkId, report);
28717
+ const title = report.checkTitle || item.checkId;
28718
+ const isSignificant = status !== "info" || /\d/.test(message) || message.includes("PostgreSQL") || message.includes("Version");
28719
+ if (isSignificant) {
28720
+ summaries.push({ checkId: item.checkId, title, status, message });
28721
+ } else {
28722
+ skippedCount++;
28723
+ }
28724
+ }
28725
+ }
28726
+ for (const { checkId, title, message } of summaries) {
28727
+ out(` ${checkId} (${title}): ${message}`);
28728
+ }
28729
+ if (skippedCount > 0) {
28730
+ out(` ${skippedCount} other check${skippedCount > 1 ? "s" : ""} completed`);
28475
28731
  }
28476
28732
  }
28477
28733
  function getDefaultMonitoringProjectDir() {
@@ -29498,7 +29754,7 @@ program2.command("unprepare-db [conn]").description("remove monitoring setup: dr
29498
29754
  closeReadline();
29499
29755
  }
29500
29756
  });
29501
- program2.command("checkup [checkIdOrConn] [conn]").description("generate health check reports directly from PostgreSQL (express mode)").option("--check-id <id>", `specific check to run (see list below), or ALL`).option("--node-name <name>", "node name for reports", "node-01").option("--output <path>", "output directory for JSON files").option("--upload", "upload JSON results to PostgresAI (requires API key)").option("--no-upload", "disable upload to PostgresAI").option("--project <project>", "project name or ID for remote upload (used with --upload; defaults to config defaultProject; auto-generated on first run)").option("--json", "output JSON to stdout").addHelpText("after", [
29757
+ program2.command("checkup [checkIdOrConn] [conn]").description("generate health check reports directly from PostgreSQL (express mode)").option("--check-id <id>", `specific check to run (see list below), or ALL`).option("--node-name <name>", "node name for reports", "node-01").option("--output <path>", "output directory for JSON files").option("--upload", "upload JSON results to PostgresAI (requires API key)").option("--no-upload", "disable upload to PostgresAI").option("--project <project>", "project name or ID for remote upload (used with --upload; defaults to config defaultProject; auto-generated on first run)").option("--json", "output JSON to stdout").option("--markdown", "output markdown to stdout").addHelpText("after", [
29502
29758
  "",
29503
29759
  "Available checks:",
29504
29760
  ...Object.entries(CHECK_INFO).map(([id, title]) => ` ${id}: ${title}`),
@@ -29508,7 +29764,8 @@ program2.command("checkup [checkIdOrConn] [conn]").description("generate health
29508
29764
  " postgresai checkup H002 postgresql://user:pass@host:5432/db",
29509
29765
  " postgresai checkup postgresql://user:pass@host:5432/db --check-id H002",
29510
29766
  " postgresai checkup postgresql://user:pass@host:5432/db --output ./reports",
29511
- " postgresai checkup postgresql://user:pass@host:5432/db --no-upload --json"
29767
+ " postgresai checkup postgresql://user:pass@host:5432/db --no-upload --json",
29768
+ " postgresai checkup postgresql://user:pass@host:5432/db --no-upload --markdown"
29512
29769
  ].join(`
29513
29770
  `)).action(async (checkIdOrConn, connArg, opts, cmd) => {
29514
29771
  const checkIdPattern = /^[A-Z]\d{3}$/i;
@@ -29540,7 +29797,13 @@ Usage: postgresai checkup ${checkId} postgresql://user@host:5432/dbname
29540
29797
  return;
29541
29798
  }
29542
29799
  const shouldPrintJson = !!opts.json;
29800
+ const shouldConvertMarkdown = !!opts.markdown;
29543
29801
  const uploadExplicitlyRequested = opts.upload === true;
29802
+ if (shouldPrintJson && shouldConvertMarkdown) {
29803
+ console.error("Error: --json and --markdown are mutually exclusive");
29804
+ process.exitCode = 1;
29805
+ return;
29806
+ }
29544
29807
  const uploadExplicitlyDisabled = opts.upload === false;
29545
29808
  let shouldUpload = !uploadExplicitlyDisabled;
29546
29809
  const outputPath = prepareOutputDirectory(opts.output);
@@ -29562,7 +29825,7 @@ Usage: postgresai checkup ${checkId} postgresql://user@host:5432/dbname
29562
29825
  envPassword: process.env.PGPASSWORD
29563
29826
  });
29564
29827
  let client;
29565
- const spinnerEnabled = !!process.stdout.isTTY && shouldUpload;
29828
+ const spinnerEnabled = !!process.stdout.isTTY && !shouldPrintJson;
29566
29829
  const spinner = createTtySpinner(spinnerEnabled, "Connecting to Postgres");
29567
29830
  try {
29568
29831
  spinner.update("Connecting to Postgres");
@@ -29603,11 +29866,100 @@ Usage: postgresai checkup ${checkId} postgresql://user@host:5432/dbname
29603
29866
  writeReportFiles(reports, outputPath);
29604
29867
  }
29605
29868
  if (uploadSummary) {
29606
- printUploadSummary(uploadSummary, projectWasGenerated, shouldPrintJson);
29869
+ printUploadSummary(uploadSummary, projectWasGenerated, shouldPrintJson || shouldConvertMarkdown, reports);
29607
29870
  }
29608
- if (shouldPrintJson || !shouldUpload && !opts.output) {
29871
+ if (shouldConvertMarkdown) {
29872
+ let apiKey;
29873
+ let apiBaseUrl;
29874
+ try {
29875
+ const configResult = getConfig(rootOpts);
29876
+ apiKey = configResult.apiKey;
29877
+ const cfg = readConfig();
29878
+ apiBaseUrl = resolveBaseUrls2(rootOpts, cfg).apiBaseUrl;
29879
+ } catch (error2) {
29880
+ spinner.stop();
29881
+ console.error("Error: Failed to read configuration for markdown conversion");
29882
+ console.error(error2 instanceof Error ? error2.message : String(error2));
29883
+ process.exitCode = 1;
29884
+ return;
29885
+ }
29886
+ const markdownResults = [];
29887
+ for (const [checkId2, report] of Object.entries(reports)) {
29888
+ try {
29889
+ spinner.update(`Converting ${checkId2} to markdown`);
29890
+ const markdownResult = await convertCheckupReportJsonToMarkdown({
29891
+ apiKey,
29892
+ apiBaseUrl,
29893
+ checkId: checkId2,
29894
+ jsonPayload: report,
29895
+ reportType: checkId2
29896
+ });
29897
+ const markdown = markdownResult?.reports?.[0]?.markdown || markdownResult?.markdown;
29898
+ markdownResults.push({
29899
+ checkId: checkId2,
29900
+ markdown
29901
+ });
29902
+ } catch (error2) {
29903
+ markdownResults.push({
29904
+ checkId: checkId2,
29905
+ error: error2 instanceof Error ? error2 : new Error(String(error2))
29906
+ });
29907
+ }
29908
+ }
29909
+ spinner.stop();
29910
+ for (const result of markdownResults) {
29911
+ if (result.error) {
29912
+ if (result.error instanceof RpcError) {
29913
+ console.error(`Error converting ${result.checkId} to markdown:`);
29914
+ for (const line of formatRpcErrorForDisplay(result.error)) {
29915
+ console.error(line);
29916
+ }
29917
+ } else {
29918
+ console.error(`Error converting ${result.checkId} to markdown: ${result.error.message}`);
29919
+ }
29920
+ } else if (result.markdown) {
29921
+ console.log(result.markdown);
29922
+ if (!result.markdown.endsWith(`
29923
+ `)) {
29924
+ console.log();
29925
+ }
29926
+ } else {
29927
+ console.error(`Warning: No markdown content returned for ${result.checkId}`);
29928
+ }
29929
+ }
29930
+ }
29931
+ if (shouldPrintJson) {
29609
29932
  console.log(JSON.stringify(reports, null, 2));
29610
29933
  }
29934
+ const hadOutput = shouldPrintJson || shouldConvertMarkdown || outputPath || uploadSummary;
29935
+ if (!hadOutput) {
29936
+ const checkCount = Object.keys(reports).length;
29937
+ console.log(`Checkup completed: ${checkCount} check${checkCount > 1 ? "s" : ""}
29938
+ `);
29939
+ const summaries = [];
29940
+ let skippedCount = 0;
29941
+ for (const [checkId2, report] of Object.entries(reports)) {
29942
+ const { status, message } = generateCheckSummary(checkId2, report);
29943
+ const title = report.checkTitle || checkId2;
29944
+ const isSignificant = status !== "info" || /\d/.test(message) || message.includes("PostgreSQL") || message.includes("Version");
29945
+ if (isSignificant) {
29946
+ summaries.push({ checkId: checkId2, title, status, message });
29947
+ } else {
29948
+ skippedCount++;
29949
+ }
29950
+ }
29951
+ for (const { checkId: checkId2, title, message } of summaries) {
29952
+ console.log(` ${checkId2} (${title}): ${message}`);
29953
+ }
29954
+ if (skippedCount > 0) {
29955
+ console.log(` ${skippedCount} other check${skippedCount > 1 ? "s" : ""} completed`);
29956
+ }
29957
+ console.log(`
29958
+ For details:`);
29959
+ console.log(" --json Output JSON");
29960
+ console.log(" --markdown Output markdown");
29961
+ console.log(" --output <dir> Save to directory");
29962
+ }
29611
29963
  } catch (error2) {
29612
29964
  if (error2 instanceof RpcError) {
29613
29965
  for (const line of formatRpcErrorForDisplay(error2)) {
@@ -186,7 +186,11 @@ async function postRpc<T>(params: {
186
186
  timeoutMs?: number;
187
187
  }): Promise<T> {
188
188
  const { apiKey, apiBaseUrl, rpcName, bodyObj, timeoutMs = HTTP_TIMEOUT_MS } = params;
189
- if (!apiKey) throw new Error("API key is required");
189
+
190
+ // NOTE: API key validation removed intentionally to allow markdown conversion without auth.
191
+ // When apiKey is empty, API returns partial markdown (observations only, no full reports).
192
+ // API will return 401/403 for endpoints that require authentication.
193
+
190
194
  const base = normalizeBaseUrl(apiBaseUrl);
191
195
  const url = new URL(`${base}/rpc/${rpcName}`);
192
196
  const body = JSON.stringify(bodyObj);
@@ -384,3 +388,45 @@ export async function uploadCheckupReportJson(params: {
384
388
  }
385
389
  return { reportChunkId: chunkId };
386
390
  }
391
+
392
+ /**
393
+ * Convert a checkup report JSON to markdown format using the PostgresAI API.
394
+ * This calls the v1.checkup_report_json_to_markdown RPC function.
395
+ *
396
+ * @param params - Configuration for the conversion
397
+ * @param params.apiKey - PostgresAI API access token
398
+ * @param params.apiBaseUrl - Base URL of the PostgresAI API
399
+ * @param params.checkId - Check identifier (e.g., "H001", "A003")
400
+ * @param params.jsonPayload - The JSON data from the check report
401
+ * @param params.reportType - Optional report type parameter
402
+ * @returns Promise resolving to the markdown content as JSON
403
+ * @throws {RpcError} On API failures (4xx/5xx responses)
404
+ * @throws {Error} On network errors or unexpected response format
405
+ */
406
+ export async function convertCheckupReportJsonToMarkdown(params: {
407
+ apiKey: string;
408
+ apiBaseUrl: string;
409
+ checkId: string;
410
+ jsonPayload: any;
411
+ reportType?: string;
412
+ }): Promise<any> {
413
+ const { apiKey, apiBaseUrl, checkId, jsonPayload, reportType } = params;
414
+ const bodyObj: Record<string, unknown> = {
415
+ check_id: checkId,
416
+ json_payload: jsonPayload,
417
+ access_token: apiKey,
418
+ };
419
+
420
+ if (reportType) {
421
+ bodyObj.report_type = reportType;
422
+ }
423
+
424
+ const resp = await postRpc<any>({
425
+ apiKey,
426
+ apiBaseUrl,
427
+ rpcName: "checkup_report_json_to_markdown",
428
+ bodyObj,
429
+ });
430
+
431
+ return resp;
432
+ }