@mgsoftwarebv/mg-dashboard-mcp 7.0.6 → 7.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -20,6 +20,7 @@ import { sql } from 'drizzle-orm';
20
20
  import { once } from 'events';
21
21
  import { lookup } from 'dns/promises';
22
22
  import { connect } from 'tls';
23
+ import { pgTable, timestamp, jsonb, uuid, boolean, text, pgEnum, integer, uniqueIndex, index, bigint } from 'drizzle-orm/pg-core';
23
24
  import { tasks } from '@trigger.dev/sdk/v3';
24
25
  import { HeadObjectCommand, S3Client, ListObjectsV2Command, DeleteObjectsCommand, DeleteObjectCommand, CreateMultipartUploadCommand, UploadPartCommand, CompleteMultipartUploadCommand, AbortMultipartUploadCommand, PutObjectCommand, GetObjectCommand, CopyObjectCommand } from '@aws-sdk/client-s3';
25
26
 
@@ -618,6 +619,12 @@ var TERMINAL_STATUSES = /* @__PURE__ */ new Set([
618
619
  "INTERRUPTED",
619
620
  "EXPIRED"
620
621
  ]);
622
+ var EXECUTE_PIPELINE_TASK = "execute-pipeline";
623
+ function validateExecutePipelineTestPayload(payload) {
624
+ const stepIds = payload.stepIds;
625
+ if (Array.isArray(stepIds) && stepIds.length > 0) return null;
626
+ return 'execute-pipeline requires real stepIds from a release row. Use a lightweight task (e.g. "hello-world") for connectivity checks, or pass a payload with releaseId (UUID) and non-empty stepIds.';
627
+ }
621
628
  var TRIGGER_SERVER_ID = "03659d55-e194-400d-b82a-bf6457371ded";
622
629
  var COMPOSE_PROJECT = "mg-dashboard-supabase-trigger";
623
630
  var PG_CONTAINER = `${COMPOSE_PROJECT}-postgres-1`;
@@ -677,10 +684,10 @@ var TRIGGER_TOOL_MODULE_MAP = {
677
684
  "trigger-run": "ci_cd"
678
685
  };
679
686
  async function discoverInstance(projectSlug, conn, proxy, sshExec2) {
680
- const sql28 = `SELECT re.\\"apiKey\\" FROM \\"RuntimeEnvironment\\" re JOIN \\"Project\\" p ON re.\\"projectId\\" = p.id WHERE p.slug='${projectSlug}' AND re.slug='prod' LIMIT 1`;
687
+ const sql29 = `SELECT re.\\"apiKey\\" FROM \\"RuntimeEnvironment\\" re JOIN \\"Project\\" p ON re.\\"projectId\\" = p.id WHERE p.slug='${projectSlug}' AND re.slug='prod' LIMIT 1`;
681
688
  const cmd = [
682
689
  `PORT=$(docker port "${WA_CONTAINER}" 3000/tcp 2>/dev/null | head -1 | sed 's/.*://')`,
683
- `KEY=$(docker exec "${PG_CONTAINER}" psql -U postgres -d main -t -A -c "${sql28}" 2>/dev/null | tr -d '[:space:]')`,
690
+ `KEY=$(docker exec "${PG_CONTAINER}" psql -U postgres -d main -t -A -c "${sql29}" 2>/dev/null | tr -d '[:space:]')`,
684
691
  'echo "$PORT|$KEY"'
685
692
  ].join(" && ");
686
693
  const result = await sshExec2(conn, cmd, proxy);
@@ -701,8 +708,8 @@ async function discoverInstance(projectSlug, conn, proxy, sshExec2) {
701
708
  return { port, apiKey: apiKey2 };
702
709
  }
703
710
  async function fetchRunLogs(runId, conn, proxy, sshExec2) {
704
- const sql28 = `SELECT level, message, \\"isError\\", \\"createdAt\\" FROM \\"TaskEvent\\" WHERE \\"runId\\" = '${runId}' AND level IN ('INFO','WARN','ERROR','DEBUG','LOG','TRACE') ORDER BY \\"startTime\\" ASC LIMIT 200`;
705
- const cmd = `docker exec "${PG_CONTAINER}" psql -U postgres -d main -t -A -c "${sql28}" 2>/dev/null`;
711
+ const sql29 = `SELECT level, message, \\"isError\\", \\"createdAt\\" FROM \\"TaskEvent\\" WHERE \\"runId\\" = '${runId}' AND level IN ('INFO','WARN','ERROR','DEBUG','LOG','TRACE') ORDER BY \\"startTime\\" ASC LIMIT 200`;
712
+ const cmd = `docker exec "${PG_CONTAINER}" psql -U postgres -d main -t -A -c "${sql29}" 2>/dev/null`;
706
713
  const result = await sshExec2(conn, cmd, proxy);
707
714
  const output = result.stdout.trim();
708
715
  if (!output) return "";
@@ -784,8 +791,8 @@ async function handleTriggerTool(name, args2, deps) {
784
791
  switch (name) {
785
792
  // -----------------------------------------------------------------
786
793
  case "trigger-list": {
787
- const sql28 = 'SELECT slug, name FROM \\"Project\\" ORDER BY name';
788
- const cmd = `docker exec "${PG_CONTAINER}" psql -U postgres -d main -t -A -c "${sql28}" 2>/dev/null`;
794
+ const sql29 = 'SELECT slug, name FROM \\"Project\\" ORDER BY name';
795
+ const cmd = `docker exec "${PG_CONTAINER}" psql -U postgres -d main -t -A -c "${sql29}" 2>/dev/null`;
789
796
  const result = await sshExec2(conn, cmd, proxy);
790
797
  const output = result.stdout.trim();
791
798
  if (!output) {
@@ -866,8 +873,15 @@ ${rawJson.substring(0, 500)}` }] };
866
873
  throw new Error(`Invalid JSON payload: ${String(args2.payload).substring(0, 200)}`);
867
874
  }
868
875
  }
876
+ const parsedPayload = JSON.parse(payload);
877
+ if (taskId === EXECUTE_PIPELINE_TASK) {
878
+ const validationError = validateExecutePipelineTestPayload(parsedPayload);
879
+ if (validationError) {
880
+ return { content: [{ type: "text", text: `Error: ${validationError}` }] };
881
+ }
882
+ }
869
883
  const triggerBody = JSON.stringify({
870
- payload: JSON.parse(payload),
884
+ payload: parsedPayload,
871
885
  options: { tags: ["mcp-test"], test: true }
872
886
  });
873
887
  const triggerJson = await triggerApi(
@@ -943,9 +957,9 @@ async function fetchAndFormatRun(conn, proxy, sshExec2, instance, runId) {
943
957
  return { content: [{ type: "text", text: `Invalid API response:
944
958
  ${rawJson.substring(0, 500)}` }] };
945
959
  }
946
- let text = formatRunDetail(run);
947
- if (logs) text += "\n\n--- Logs ---\n" + logs;
948
- return { content: [{ type: "text", text }] };
960
+ let text7 = formatRunDetail(run);
961
+ if (logs) text7 += "\n\n--- Logs ---\n" + logs;
962
+ return { content: [{ type: "text", text: text7 }] };
949
963
  }
950
964
  async function waitForCompletion(conn, proxy, sshExec2, instance, runId, waitSeconds) {
951
965
  const pollInterval = 3e3;
@@ -967,10 +981,10 @@ async function waitForCompletion(conn, proxy, sshExec2, instance, runId, waitSec
967
981
  continue;
968
982
  }
969
983
  if (TERMINAL_STATUSES.has(run.status)) {
970
- let text = formatRunDetail(run);
984
+ let text7 = formatRunDetail(run);
971
985
  const logs = await fetchRunLogs(runId, conn, proxy, sshExec2);
972
- if (logs) text += "\n\n--- Logs ---\n" + logs;
973
- return { content: [{ type: "text", text }] };
986
+ if (logs) text7 += "\n\n--- Logs ---\n" + logs;
987
+ return { content: [{ type: "text", text: text7 }] };
974
988
  }
975
989
  }
976
990
  return {
@@ -3657,10 +3671,10 @@ var ZodObject = class _ZodObject extends ZodType {
3657
3671
  // }) as any;
3658
3672
  // return merged;
3659
3673
  // }
3660
- catchall(index) {
3674
+ catchall(index5) {
3661
3675
  return new _ZodObject({
3662
3676
  ...this._def,
3663
- catchall: index
3677
+ catchall: index5
3664
3678
  });
3665
3679
  }
3666
3680
  pick(mask) {
@@ -3978,9 +3992,9 @@ function mergeValues(a, b) {
3978
3992
  return { valid: false };
3979
3993
  }
3980
3994
  const newArray = [];
3981
- for (let index = 0; index < a.length; index++) {
3982
- const itemA = a[index];
3983
- const itemB = b[index];
3995
+ for (let index5 = 0; index5 < a.length; index5++) {
3996
+ const itemA = a[index5];
3997
+ const itemB = b[index5];
3984
3998
  const sharedValue = mergeValues(itemA, itemB);
3985
3999
  if (!sharedValue.valid) {
3986
4000
  return { valid: false };
@@ -4186,10 +4200,10 @@ var ZodMap = class extends ZodType {
4186
4200
  }
4187
4201
  const keyType = this._def.keyType;
4188
4202
  const valueType = this._def.valueType;
4189
- const pairs = [...ctx.data.entries()].map(([key, value], index) => {
4203
+ const pairs = [...ctx.data.entries()].map(([key, value], index5) => {
4190
4204
  return {
4191
- key: keyType._parse(new ParseInputLazyPath(ctx, key, ctx.path, [index, "key"])),
4192
- value: valueType._parse(new ParseInputLazyPath(ctx, value, ctx.path, [index, "value"]))
4205
+ key: keyType._parse(new ParseInputLazyPath(ctx, key, ctx.path, [index5, "key"])),
4206
+ value: valueType._parse(new ParseInputLazyPath(ctx, value, ctx.path, [index5, "value"]))
4193
4207
  };
4194
4208
  });
4195
4209
  if (ctx.common.async) {
@@ -5103,7 +5117,642 @@ external_exports.array(LitespeedVhostMappingSchema);
5103
5117
  function normalizeVhostDomain(value) {
5104
5118
  return value.trim().replace(/^https?:\/\//, "").replace(/\/.*$/, "").replace(/\.+$/, "").toLowerCase();
5105
5119
  }
5120
+ var users = pgTable("user", {
5121
+ id: uuid("id").primaryKey().defaultRandom(),
5122
+ email: text("email").notNull().unique(),
5123
+ fullName: text("full_name"),
5124
+ avatarUrl: text("avatar_url"),
5125
+ emailVerified: boolean("email_verified").notNull().default(false),
5126
+ roleId: uuid("role_id"),
5127
+ permissions: jsonb("permissions"),
5128
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
5129
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
5130
+ });
5131
+ pgTable("session", {
5132
+ id: uuid("id").primaryKey().defaultRandom(),
5133
+ userId: uuid("user_id").notNull().references(() => users.id, { onDelete: "cascade" }),
5134
+ token: text("token").notNull().unique(),
5135
+ expiresAt: timestamp("expires_at", { withTimezone: true }).notNull(),
5136
+ ipAddress: text("ip_address"),
5137
+ userAgent: text("user_agent"),
5138
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
5139
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
5140
+ });
5141
+ pgTable("account", {
5142
+ id: uuid("id").primaryKey().defaultRandom(),
5143
+ userId: uuid("user_id").notNull().references(() => users.id, { onDelete: "cascade" }),
5144
+ providerId: text("provider_id").notNull(),
5145
+ accountId: text("account_id").notNull(),
5146
+ password: text("password"),
5147
+ accessToken: text("access_token"),
5148
+ refreshToken: text("refresh_token"),
5149
+ accessTokenExpiresAt: timestamp("access_token_expires_at", {
5150
+ withTimezone: true
5151
+ }),
5152
+ refreshTokenExpiresAt: timestamp("refresh_token_expires_at", {
5153
+ withTimezone: true
5154
+ }),
5155
+ scope: text("scope"),
5156
+ idToken: text("id_token"),
5157
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
5158
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
5159
+ });
5160
+ pgTable("verification", {
5161
+ id: uuid("id").primaryKey().defaultRandom(),
5162
+ identifier: text("identifier").notNull(),
5163
+ value: text("value").notNull(),
5164
+ expiresAt: timestamp("expires_at", { withTimezone: true }).notNull(),
5165
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
5166
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
5167
+ });
5168
+ pgTable("two_factor", {
5169
+ id: uuid("id").primaryKey().defaultRandom(),
5170
+ userId: uuid("user_id").notNull().references(() => users.id, { onDelete: "cascade" }),
5171
+ secret: text("secret").notNull(),
5172
+ backupCodes: text("backup_codes")
5173
+ });
5174
+ var managedServerOs = pgEnum("managed_server_os", [
5175
+ "linux",
5176
+ "windows",
5177
+ "unknown"
5178
+ ]);
5179
+ var serverAgentStatus = pgEnum("server_agent_status", [
5180
+ "not_installed",
5181
+ "installing",
5182
+ "online",
5183
+ "degraded",
5184
+ "offline",
5185
+ "error"
5186
+ ]);
5187
+ var resourceKind = pgEnum("resource_kind", [
5188
+ "wordpress",
5189
+ "prestashop",
5190
+ "postgres_cluster",
5191
+ "postgres_database",
5192
+ "mysql_database",
5193
+ "mariadb_database",
5194
+ "boiler_project",
5195
+ "boiler_web_project",
5196
+ "static_site",
5197
+ "docker_app",
5198
+ "domain",
5199
+ "backup_policy",
5200
+ "server_service"
5201
+ ]);
5202
+ var resourceStatus = pgEnum("resource_status", [
5203
+ "unknown",
5204
+ "healthy",
5205
+ "degraded",
5206
+ "failed",
5207
+ "missing",
5208
+ "provisioning",
5209
+ "disabled"
5210
+ ]);
5211
+ var resourceOwnership = pgEnum("resource_ownership", [
5212
+ "managed",
5213
+ "discovered",
5214
+ "external"
5215
+ ]);
5216
+ var operationStatus = pgEnum("operation_status", [
5217
+ "queued",
5218
+ "running",
5219
+ "succeeded",
5220
+ "failed",
5221
+ "cancelled"
5222
+ ]);
5223
+ var alertSeverity = pgEnum("alert_severity", [
5224
+ "info",
5225
+ "warning",
5226
+ "critical"
5227
+ ]);
5228
+ var managedServer = pgTable(
5229
+ "managed_server",
5230
+ {
5231
+ id: uuid("id").primaryKey().defaultRandom(),
5232
+ name: text("name").notNull(),
5233
+ hostname: text("hostname").notNull(),
5234
+ port: integer("port").notNull().default(22),
5235
+ username: text("username").notNull(),
5236
+ authMethod: text("auth_method").notNull().default("ssh_key"),
5237
+ os: managedServerOs("os").notNull().default("unknown"),
5238
+ provider: text("provider"),
5239
+ region: text("region"),
5240
+ tags: jsonb("tags").$type().notNull().default([]),
5241
+ agentStatus: serverAgentStatus("agent_status").notNull().default("not_installed"),
5242
+ agentVersion: text("agent_version"),
5243
+ lastSeenAt: timestamp("last_seen_at", { withTimezone: true }),
5244
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
5245
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
5246
+ },
5247
+ (table) => [
5248
+ uniqueIndex("managed_server_hostname_port_uidx").on(
5249
+ table.hostname,
5250
+ table.port
5251
+ ),
5252
+ index("managed_server_agent_status_idx").on(table.agentStatus)
5253
+ ]
5254
+ );
5255
+ pgTable("server_credential", {
5256
+ serverId: uuid("server_id").primaryKey().references(() => managedServer.id, { onDelete: "cascade" }),
5257
+ passwordEncrypted: text("password_encrypted"),
5258
+ sshKeyEncrypted: text("ssh_key_encrypted"),
5259
+ sshKeyPassphraseEncrypted: text("ssh_key_passphrase_encrypted"),
5260
+ dbRootPasswordEncrypted: text("db_root_password_encrypted"),
5261
+ monitoringApiKeyEncrypted: text("monitoring_api_key_encrypted"),
5262
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
5263
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
5264
+ });
5265
+ pgTable(
5266
+ "server_connection_log",
5267
+ {
5268
+ id: uuid("id").primaryKey().defaultRandom(),
5269
+ serverId: uuid("server_id").notNull().references(() => managedServer.id, { onDelete: "cascade" }),
5270
+ userId: uuid("user_id").notNull(),
5271
+ connectedAt: timestamp("connected_at", { withTimezone: true }).notNull().defaultNow(),
5272
+ disconnectedAt: timestamp("disconnected_at", { withTimezone: true }),
5273
+ durationSeconds: integer("duration_seconds"),
5274
+ status: text("status").notNull(),
5275
+ errorMessage: text("error_message"),
5276
+ clientIp: text("client_ip"),
5277
+ terminalCols: integer("terminal_cols"),
5278
+ terminalRows: integer("terminal_rows"),
5279
+ outputSizeBytes: bigint("output_size_bytes", { mode: "number" }).notNull().default(0),
5280
+ inputSizeBytes: bigint("input_size_bytes", { mode: "number" }).notNull().default(0),
5281
+ commandCount: integer("command_count").notNull().default(0),
5282
+ connectionType: text("connection_type").notNull().default("terminal"),
5283
+ action: text("action"),
5284
+ rawOutput: text("raw_output"),
5285
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow()
5286
+ },
5287
+ (table) => [
5288
+ index("server_connection_log_server_idx").on(table.serverId),
5289
+ index("server_connection_log_user_idx").on(table.userId),
5290
+ index("server_connection_log_connected_idx").on(table.connectedAt),
5291
+ index("server_connection_log_status_idx").on(table.status)
5292
+ ]
5293
+ );
5294
+ pgTable(
5295
+ "mcp_audit_log",
5296
+ {
5297
+ id: uuid("id").primaryKey().defaultRandom(),
5298
+ apiKeyId: uuid("api_key_id"),
5299
+ userId: uuid("user_id"),
5300
+ toolName: text("tool_name"),
5301
+ arguments: jsonb("arguments"),
5302
+ ipAddress: text("ip_address"),
5303
+ serverId: uuid("server_id"),
5304
+ resultStatus: text("result_status").notNull().default("success"),
5305
+ errorMessage: text("error_message"),
5306
+ durationMs: integer("duration_ms"),
5307
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow()
5308
+ },
5309
+ (table) => [
5310
+ index("mcp_audit_log_created_at_idx").on(table.createdAt),
5311
+ index("mcp_audit_log_user_idx").on(table.userId),
5312
+ index("mcp_audit_log_tool_name_idx").on(table.toolName),
5313
+ index("mcp_audit_log_server_idx").on(table.serverId),
5314
+ index("mcp_audit_log_api_key_idx").on(table.apiKeyId),
5315
+ index("mcp_audit_log_result_status_idx").on(table.resultStatus)
5316
+ ]
5317
+ );
5318
+ var resource = pgTable(
5319
+ "resource",
5320
+ {
5321
+ id: uuid("id").primaryKey().defaultRandom(),
5322
+ serverId: uuid("server_id").notNull().references(() => managedServer.id, { onDelete: "cascade" }),
5323
+ parentResourceId: uuid("parent_resource_id"),
5324
+ kind: resourceKind("kind").notNull(),
5325
+ slug: text("slug").notNull(),
5326
+ displayName: text("display_name").notNull(),
5327
+ spec: jsonb("spec").$type().notNull().default({}),
5328
+ state: jsonb("state").$type().notNull().default({}),
5329
+ status: resourceStatus("status").notNull().default("unknown"),
5330
+ ownership: resourceOwnership("ownership").notNull().default("managed"),
5331
+ lastDetectedAt: timestamp("last_detected_at", { withTimezone: true }),
5332
+ lastEventId: uuid("last_event_id"),
5333
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
5334
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
5335
+ },
5336
+ (table) => [
5337
+ uniqueIndex("resource_server_kind_slug_uidx").on(
5338
+ table.serverId,
5339
+ table.kind,
5340
+ table.slug
5341
+ ),
5342
+ index("resource_server_idx").on(table.serverId),
5343
+ index("resource_parent_idx").on(table.parentResourceId),
5344
+ index("resource_kind_status_idx").on(table.kind, table.status)
5345
+ ]
5346
+ );
5347
+ pgTable(
5348
+ "resource_event",
5349
+ {
5350
+ id: uuid("id").primaryKey().defaultRandom(),
5351
+ resourceId: uuid("resource_id").notNull().references(() => resource.id, { onDelete: "cascade" }),
5352
+ kind: text("kind").notNull(),
5353
+ before: jsonb("before").$type(),
5354
+ after: jsonb("after").$type(),
5355
+ actorUserId: text("actor_user_id"),
5356
+ operationId: uuid("operation_id"),
5357
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow()
5358
+ },
5359
+ (table) => [
5360
+ index("resource_event_resource_created_idx").on(
5361
+ table.resourceId,
5362
+ table.createdAt
5363
+ ),
5364
+ index("resource_event_operation_idx").on(table.operationId)
5365
+ ]
5366
+ );
5367
+ var operation = pgTable(
5368
+ "operation",
5369
+ {
5370
+ id: uuid("id").primaryKey().defaultRandom(),
5371
+ kind: text("kind").notNull(),
5372
+ resourceId: uuid("resource_id").references(() => resource.id, {
5373
+ onDelete: "set null"
5374
+ }),
5375
+ serverId: uuid("server_id").references(() => managedServer.id, {
5376
+ onDelete: "set null"
5377
+ }),
5378
+ status: operationStatus("status").notNull().default("queued"),
5379
+ steps: jsonb("steps").$type().notNull().default([]),
5380
+ idempotencyKey: text("idempotency_key").notNull(),
5381
+ triggerRunId: text("trigger_run_id"),
5382
+ logsR2Key: text("logs_r2_key"),
5383
+ logs: text("logs"),
5384
+ startedBy: text("started_by"),
5385
+ startedAt: timestamp("started_at", { withTimezone: true }),
5386
+ endedAt: timestamp("ended_at", { withTimezone: true }),
5387
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
5388
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
5389
+ },
5390
+ (table) => [
5391
+ uniqueIndex("operation_idempotency_uidx").on(table.idempotencyKey),
5392
+ index("operation_resource_idx").on(table.resourceId),
5393
+ index("operation_server_idx").on(table.serverId),
5394
+ index("operation_status_created_idx").on(table.status, table.createdAt)
5395
+ ]
5396
+ );
5397
+ pgTable(
5398
+ "agent_installation",
5399
+ {
5400
+ id: uuid("id").primaryKey().defaultRandom(),
5401
+ serverId: uuid("server_id").notNull().references(() => managedServer.id, { onDelete: "cascade" }),
5402
+ agentId: text("agent_id"),
5403
+ version: text("version").notNull(),
5404
+ installPath: text("install_path").notNull().default("/usr/local/bin/mg-agent"),
5405
+ configHash: text("config_hash").notNull(),
5406
+ status: serverAgentStatus("status").notNull().default("installing"),
5407
+ lastHeartbeatAt: timestamp("last_heartbeat_at", { withTimezone: true }),
5408
+ lastError: text("last_error"),
5409
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
5410
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
5411
+ },
5412
+ (table) => [
5413
+ uniqueIndex("agent_installation_server_uidx").on(table.serverId),
5414
+ index("agent_installation_status_idx").on(table.status)
5415
+ ]
5416
+ );
5417
+ pgTable(
5418
+ "monitoring_sample",
5419
+ {
5420
+ id: uuid("id").primaryKey().defaultRandom(),
5421
+ serverId: uuid("server_id").notNull().references(() => managedServer.id, { onDelete: "cascade" }),
5422
+ resourceId: uuid("resource_id").references(() => resource.id, {
5423
+ onDelete: "cascade"
5424
+ }),
5425
+ metric: text("metric").notNull(),
5426
+ value: integer("value").notNull(),
5427
+ unit: text("unit").notNull(),
5428
+ tags: jsonb("tags").$type().notNull().default({}),
5429
+ sampledAt: timestamp("sampled_at", { withTimezone: true }).notNull().defaultNow()
5430
+ },
5431
+ (table) => [
5432
+ index("monitoring_sample_server_metric_time_idx").on(
5433
+ table.serverId,
5434
+ table.metric,
5435
+ table.sampledAt
5436
+ ),
5437
+ // Descending on sampled_at so "latest metric per (server, metric)" lookups
5438
+ // (DISTINCT ON ... ORDER BY sampled_at DESC) are served by an index-only
5439
+ // scan instead of a full-table sort. The migration also adds
5440
+ // INCLUDE (value, unit) to make it covering for the overview snapshot query
5441
+ // (Drizzle 0.44 can't express INCLUDE here). See migration 20260529210000.
5442
+ index("monitoring_sample_server_metric_time_desc_idx").on(
5443
+ table.serverId,
5444
+ table.metric,
5445
+ table.sampledAt.desc()
5446
+ ),
5447
+ index("monitoring_sample_resource_metric_time_idx").on(
5448
+ table.resourceId,
5449
+ table.metric,
5450
+ table.sampledAt
5451
+ )
5452
+ ]
5453
+ );
5454
+ var appLogSource = pgTable(
5455
+ "app_log_source",
5456
+ {
5457
+ id: uuid("id").primaryKey().defaultRandom(),
5458
+ serverId: uuid("server_id").notNull().references(() => managedServer.id, { onDelete: "cascade" }),
5459
+ resourceId: uuid("resource_id").references(() => resource.id, {
5460
+ onDelete: "set null"
5461
+ }),
5462
+ sourceType: text("source_type").notNull(),
5463
+ sourceKey: text("source_key").notNull(),
5464
+ displayName: text("display_name").notNull(),
5465
+ path: text("path").notNull(),
5466
+ enabled: boolean("enabled").notNull().default(true),
5467
+ mutedUntil: timestamp("muted_until", { withTimezone: true }),
5468
+ metadata: jsonb("metadata").$type().notNull().default({}),
5469
+ lastSeenAt: timestamp("last_seen_at", { withTimezone: true }).notNull().defaultNow(),
5470
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
5471
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
5472
+ },
5473
+ (table) => [
5474
+ uniqueIndex("app_log_source_server_type_key_uidx").on(
5475
+ table.serverId,
5476
+ table.sourceType,
5477
+ table.sourceKey
5478
+ ),
5479
+ index("app_log_source_server_idx").on(table.serverId),
5480
+ index("app_log_source_resource_idx").on(table.resourceId),
5481
+ index("app_log_source_type_seen_idx").on(
5482
+ table.sourceType,
5483
+ table.lastSeenAt
5484
+ )
5485
+ ]
5486
+ );
5487
+ pgTable(
5488
+ "app_error_event",
5489
+ {
5490
+ id: uuid("id").primaryKey().defaultRandom(),
5491
+ serverId: uuid("server_id").notNull().references(() => managedServer.id, { onDelete: "cascade" }),
5492
+ resourceId: uuid("resource_id").references(() => resource.id, {
5493
+ onDelete: "set null"
5494
+ }),
5495
+ logSourceId: uuid("log_source_id").references(() => appLogSource.id, {
5496
+ onDelete: "set null"
5497
+ }),
5498
+ fingerprint: text("fingerprint").notNull(),
5499
+ severity: text("severity").notNull().default("critical"),
5500
+ category: text("category").notNull(),
5501
+ sourceType: text("source_type").notNull(),
5502
+ sourcePath: text("source_path").notNull(),
5503
+ sampleMessage: text("sample_message").notNull(),
5504
+ sampleLines: jsonb("sample_lines").$type().notNull().default([]),
5505
+ signals: jsonb("signals").$type().notNull().default({}),
5506
+ occurrences: integer("occurrences").notNull().default(1),
5507
+ firstSeenAt: timestamp("first_seen_at", { withTimezone: true }).notNull().defaultNow(),
5508
+ lastSeenAt: timestamp("last_seen_at", { withTimezone: true }).notNull().defaultNow(),
5509
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow()
5510
+ },
5511
+ (table) => [
5512
+ index("app_error_event_fingerprint_created_idx").on(
5513
+ table.fingerprint,
5514
+ table.createdAt
5515
+ ),
5516
+ index("app_error_event_server_created_idx").on(
5517
+ table.serverId,
5518
+ table.createdAt
5519
+ ),
5520
+ index("app_error_event_resource_created_idx").on(
5521
+ table.resourceId,
5522
+ table.createdAt
5523
+ ),
5524
+ index("app_error_event_severity_created_idx").on(
5525
+ table.severity,
5526
+ table.createdAt
5527
+ )
5528
+ ]
5529
+ );
5530
+ pgTable(
5531
+ "app_error_alert",
5532
+ {
5533
+ id: uuid("id").primaryKey().defaultRandom(),
5534
+ fingerprint: text("fingerprint").notNull(),
5535
+ serverId: uuid("server_id").notNull().references(() => managedServer.id, { onDelete: "cascade" }),
5536
+ resourceId: uuid("resource_id").references(() => resource.id, {
5537
+ onDelete: "set null"
5538
+ }),
5539
+ logSourceId: uuid("log_source_id").references(() => appLogSource.id, {
5540
+ onDelete: "set null"
5541
+ }),
5542
+ severity: text("severity").notNull().default("critical"),
5543
+ status: text("status").notNull().default("open"),
5544
+ category: text("category").notNull(),
5545
+ title: text("title").notNull(),
5546
+ lastError: text("last_error").notNull(),
5547
+ sampleLines: jsonb("sample_lines").$type().notNull().default([]),
5548
+ signals: jsonb("signals").$type().notNull().default({}),
5549
+ failureCount: integer("failure_count").notNull().default(1),
5550
+ firstSeenAt: timestamp("first_seen_at", { withTimezone: true }).notNull().defaultNow(),
5551
+ lastSeenAt: timestamp("last_seen_at", { withTimezone: true }).notNull().defaultNow(),
5552
+ lastAlertAt: timestamp("last_alert_at", { withTimezone: true }),
5553
+ resolvedAt: timestamp("resolved_at", { withTimezone: true }),
5554
+ mutedUntil: timestamp("muted_until", { withTimezone: true }),
5555
+ cursorPrompt: text("cursor_prompt"),
5556
+ telegramChatId: text("telegram_chat_id"),
5557
+ telegramMessageId: bigint("telegram_message_id", { mode: "number" }),
5558
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
5559
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
5560
+ },
5561
+ (table) => [
5562
+ uniqueIndex("app_error_alert_fingerprint_uidx").on(table.fingerprint),
5563
+ index("app_error_alert_status_seen_idx").on(
5564
+ table.status,
5565
+ table.lastSeenAt
5566
+ ),
5567
+ index("app_error_alert_server_seen_idx").on(
5568
+ table.serverId,
5569
+ table.lastSeenAt
5570
+ ),
5571
+ index("app_error_alert_resource_seen_idx").on(
5572
+ table.resourceId,
5573
+ table.lastSeenAt
5574
+ ),
5575
+ index("app_error_alert_alerted_idx").on(table.lastAlertAt)
5576
+ ]
5577
+ );
5578
+ pgTable(
5579
+ "alert_rule",
5580
+ {
5581
+ id: uuid("id").primaryKey().defaultRandom(),
5582
+ serverId: uuid("server_id").references(() => managedServer.id, {
5583
+ onDelete: "cascade"
5584
+ }),
5585
+ resourceId: uuid("resource_id").references(() => resource.id, {
5586
+ onDelete: "cascade"
5587
+ }),
5588
+ metric: text("metric").notNull(),
5589
+ expression: text("expression").notNull(),
5590
+ severity: alertSeverity("severity").notNull().default("warning"),
5591
+ cooldownSeconds: integer("cooldown_seconds").notNull().default(900),
5592
+ enabled: boolean("enabled").notNull().default(true),
5593
+ routes: jsonb("routes").$type().notNull().default({}),
5594
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
5595
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
5596
+ },
5597
+ (table) => [
5598
+ index("alert_rule_server_idx").on(table.serverId),
5599
+ index("alert_rule_resource_idx").on(table.resourceId),
5600
+ index("alert_rule_enabled_severity_idx").on(table.enabled, table.severity)
5601
+ ]
5602
+ );
5603
+ pgTable(
5604
+ "deployment_project_server",
5605
+ {
5606
+ id: uuid("id").primaryKey().defaultRandom(),
5607
+ releaseProfileStageId: uuid("release_profile_stage_id").notNull(),
5608
+ sshServerId: uuid("ssh_server_id").notNull(),
5609
+ deployPath: text("deploy_path").notNull(),
5610
+ deployPathNormalized: text("deploy_path_normalized"),
5611
+ pm2PortBase: integer("pm2_port_base").notNull(),
5612
+ postgresHost: text("postgres_host"),
5613
+ postgresPort: integer("postgres_port"),
5614
+ buildFilters: text("build_filters"),
5615
+ envSymlinkDirs: jsonb("env_symlink_dirs"),
5616
+ litespeedVhosts: jsonb("litespeed_vhosts"),
5617
+ litespeedVhostsCheckedAt: timestamp("litespeed_vhosts_checked_at", {
5618
+ withTimezone: true
5619
+ }),
5620
+ litespeedVhostsCheckOk: boolean("litespeed_vhosts_check_ok"),
5621
+ ecosystemConfig: text("ecosystem_config").notNull().default("ecosystem.config.cjs"),
5622
+ usePipelineDeploy: boolean("use_pipeline_deploy").notNull().default(true),
5623
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
5624
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
5625
+ },
5626
+ (table) => [
5627
+ uniqueIndex("deployment_project_server_stage_server_uidx").on(
5628
+ table.releaseProfileStageId,
5629
+ table.sshServerId
5630
+ ),
5631
+ uniqueIndex("deployment_project_server_server_path_uidx").on(
5632
+ table.sshServerId,
5633
+ table.deployPathNormalized
5634
+ ),
5635
+ uniqueIndex("deployment_project_server_server_port_uidx").on(
5636
+ table.sshServerId,
5637
+ table.pm2PortBase
5638
+ )
5639
+ ]
5640
+ );
5641
+ var dnsMigrationStatus = pgEnum("dns_migration_status", [
5642
+ "pending",
5643
+ "scanned",
5644
+ "imported",
5645
+ "verified"
5646
+ ]);
5647
+ var dnsMigration = pgTable(
5648
+ "dns_migration",
5649
+ {
5650
+ id: uuid("id").primaryKey().defaultRandom(),
5651
+ domain: text("domain").notNull(),
5652
+ sourceProvider: text("source_provider").notNull().default("hostnet"),
5653
+ status: dnsMigrationStatus("status").notNull().default("pending"),
5654
+ scannedRecords: jsonb("scanned_records").$type().notNull().default([]),
5655
+ sourceNameservers: jsonb("source_nameservers").$type().notNull().default([]),
5656
+ currentNameservers: jsonb("current_nameservers").$type().notNull().default([]),
5657
+ importResult: jsonb("import_result").$type(),
5658
+ emailChecklist: jsonb("email_checklist").$type().notNull().default({}),
5659
+ directadminHost: text("directadmin_host"),
5660
+ directadminUsername: text("directadmin_username"),
5661
+ directadminPasswordEncrypted: text("directadmin_password_encrypted"),
5662
+ syncServerId: uuid("sync_server_id").references(() => managedServer.id, {
5663
+ onDelete: "set null"
5664
+ }),
5665
+ syncOperationId: uuid("sync_operation_id").references(() => operation.id, {
5666
+ onDelete: "set null"
5667
+ }),
5668
+ mailRecordsImportedAt: timestamp("mail_records_imported_at", {
5669
+ withTimezone: true
5670
+ }),
5671
+ notes: text("notes"),
5672
+ lastError: text("last_error"),
5673
+ lastScannedAt: timestamp("last_scanned_at", { withTimezone: true }),
5674
+ importedAt: timestamp("imported_at", { withTimezone: true }),
5675
+ verifiedAt: timestamp("verified_at", { withTimezone: true }),
5676
+ createdBy: text("created_by"),
5677
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
5678
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
5679
+ },
5680
+ (table) => [
5681
+ index("dns_migration_domain_idx").on(table.domain),
5682
+ index("dns_migration_status_created_idx").on(
5683
+ table.status,
5684
+ table.createdAt
5685
+ )
5686
+ ]
5687
+ );
5688
+ var dnsMigrationMailboxStatus = pgEnum(
5689
+ "dns_migration_mailbox_status",
5690
+ ["pending", "provisioned", "syncing", "synced", "delta_synced", "failed"]
5691
+ );
5692
+ pgTable(
5693
+ "dns_migration_mailbox",
5694
+ {
5695
+ id: uuid("id").primaryKey().defaultRandom(),
5696
+ migrationId: uuid("migration_id").notNull().references(() => dnsMigration.id, { onDelete: "cascade" }),
5697
+ address: text("address").notNull(),
5698
+ sourcePasswordEncrypted: text("source_password_encrypted"),
5699
+ destPasswordEncrypted: text("dest_password_encrypted"),
5700
+ status: dnsMigrationMailboxStatus("status").notNull().default("pending"),
5701
+ syncStats: jsonb("sync_stats").$type(),
5702
+ lastError: text("last_error"),
5703
+ provisionedAt: timestamp("provisioned_at", { withTimezone: true }),
5704
+ lastSyncedAt: timestamp("last_synced_at", { withTimezone: true }),
5705
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
5706
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
5707
+ },
5708
+ (table) => [
5709
+ uniqueIndex("dns_migration_mailbox_migration_address_uidx").on(
5710
+ table.migrationId,
5711
+ table.address
5712
+ ),
5713
+ index("dns_migration_mailbox_migration_idx").on(table.migrationId)
5714
+ ]
5715
+ );
5716
+ pgTable(
5717
+ "github_token",
5718
+ {
5719
+ id: uuid("id").primaryKey().defaultRandom(),
5720
+ label: text("label").notNull(),
5721
+ owner: text("owner"),
5722
+ notes: text("notes"),
5723
+ tokenEncrypted: text("token_encrypted").notNull(),
5724
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
5725
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
5726
+ },
5727
+ (table) => [
5728
+ index("github_token_label_idx").on(table.label),
5729
+ index("github_token_owner_idx").on(table.owner)
5730
+ ]
5731
+ );
5732
+ pgTable(
5733
+ "github_webhook_secret",
5734
+ {
5735
+ id: uuid("id").primaryKey().defaultRandom(),
5736
+ label: text("label").notNull(),
5737
+ owner: text("owner"),
5738
+ notes: text("notes"),
5739
+ secretEncrypted: text("secret_encrypted").notNull(),
5740
+ enabled: boolean("enabled").notNull().default(true),
5741
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
5742
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
5743
+ },
5744
+ (table) => [
5745
+ index("github_webhook_secret_label_idx").on(table.label),
5746
+ index("github_webhook_secret_owner_idx").on(table.owner)
5747
+ ]
5748
+ );
5749
+ function assertPipelinePayload(payload) {
5750
+ if (!payload.stepIds?.length) {
5751
+ throw new Error("Cannot trigger execute-pipeline: stepIds is empty");
5752
+ }
5753
+ }
5106
5754
  async function triggerPipeline(payload) {
5755
+ assertPipelinePayload(payload);
5107
5756
  return tasks.trigger(
5108
5757
  "execute-pipeline",
5109
5758
  payload
@@ -5555,6 +6204,24 @@ async function createReleaseForStage(userId, params) {
5555
6204
  if (!triggerAuthorName && userId) {
5556
6205
  triggerAuthorName = await resolveUserDisplayName(userId);
5557
6206
  }
6207
+ const enabledSteps = buildStepList(
6208
+ stage,
6209
+ profile,
6210
+ await resolveBuildStepListOptions({
6211
+ profile,
6212
+ triggerSha,
6213
+ githubToken: token,
6214
+ isManual: triggerType === "manual" || triggerType === "mcp",
6215
+ stageId: params.stageId,
6216
+ deployRetryScripts: stage.deploy_retry_scripts
6217
+ })
6218
+ );
6219
+ if (enabledSteps.length === 0) {
6220
+ throw new CreateReleaseError(
6221
+ "No pipeline steps configured for this stage (enable a PM2/Docker stage_app or deployment_project_server)",
6222
+ "PRECONDITION_FAILED"
6223
+ );
6224
+ }
5558
6225
  const initialStatus = "running";
5559
6226
  let release;
5560
6227
  try {
@@ -5588,18 +6255,6 @@ async function createReleaseForStage(userId, params) {
5588
6255
  "INTERNAL_SERVER_ERROR"
5589
6256
  );
5590
6257
  }
5591
- const enabledSteps = buildStepList(
5592
- stage,
5593
- profile,
5594
- await resolveBuildStepListOptions({
5595
- profile,
5596
- triggerSha,
5597
- githubToken: token,
5598
- isManual: triggerType === "manual" || triggerType === "mcp",
5599
- stageId: params.stageId,
5600
- deployRetryScripts: stage.deploy_retry_scripts
5601
- })
5602
- );
5603
6258
  const stepIds = [];
5604
6259
  try {
5605
6260
  stepIds.push(...await insertReleaseSteps(release.id, enabledSteps));
@@ -5667,10 +6322,10 @@ function inferDeployMethod(folderName, hasNextConfig, hasDockerfile, hasPm2Ecosy
5667
6322
  function toLabel(folderName) {
5668
6323
  return folderName.charAt(0).toUpperCase() + folderName.slice(1);
5669
6324
  }
5670
- async function scanRepoForApps(repoFullName, githubToken, ref = "main") {
6325
+ async function scanRepoForApps(repoFullName, githubToken2, ref = "main") {
5671
6326
  const headers = {
5672
6327
  Accept: "application/vnd.github.v3+json",
5673
- Authorization: `Bearer ${githubToken}`,
6328
+ Authorization: `Bearer ${githubToken2}`,
5674
6329
  "Content-Type": "application/json"
5675
6330
  };
5676
6331
  async function fetchContents(path) {
@@ -5816,10 +6471,10 @@ function toStageApps(apps) {
5816
6471
  enabled: a.enabled
5817
6472
  }));
5818
6473
  }
5819
- async function ensureGitHubBranchExists(repoFullName, branchName, fromBranch, githubToken) {
6474
+ async function ensureGitHubBranchExists(repoFullName, branchName, fromBranch, githubToken2) {
5820
6475
  const headers = {
5821
6476
  Accept: "application/vnd.github.v3+json",
5822
- Authorization: `Bearer ${githubToken}`,
6477
+ Authorization: `Bearer ${githubToken2}`,
5823
6478
  "Content-Type": "application/json"
5824
6479
  };
5825
6480
  const checkRes = await fetch(
@@ -6822,7 +7477,7 @@ function getEncryptionKey() {
6822
7477
  throw new Error("ENCRYPTION_KEY must be a 64-character hex string");
6823
7478
  return buf;
6824
7479
  }
6825
- function encrypt(text) {
7480
+ function encrypt(text7) {
6826
7481
  const key = getEncryptionKey();
6827
7482
  const iv = randomBytes(ENC_IV_LENGTH);
6828
7483
  const cipher = createCipheriv(
@@ -6830,7 +7485,7 @@ function encrypt(text) {
6830
7485
  new Uint8Array(key),
6831
7486
  new Uint8Array(iv)
6832
7487
  );
6833
- let encrypted = cipher.update(text, "utf8", "hex");
7488
+ let encrypted = cipher.update(text7, "utf8", "hex");
6834
7489
  encrypted += cipher.final("hex");
6835
7490
  const authTag = cipher.getAuthTag();
6836
7491
  return Buffer.concat([
@@ -7550,10 +8205,10 @@ async function r2GetObjectRange(bucket, key, range) {
7550
8205
  const body = result.Body;
7551
8206
  if (!body?.transformToString)
7552
8207
  throw new Error("R2 returned no readable body");
7553
- const text = await body.transformToString();
8208
+ const text7 = await body.transformToString();
7554
8209
  const header = `# range: bytes ${range.offset}-${end} of ${size} (${effectiveLen} bytes)`;
7555
8210
  return `${header}
7556
- ${text}`;
8211
+ ${text7}`;
7557
8212
  } catch (e) {
7558
8213
  throw r2WrapError(bucket, key, e);
7559
8214
  }
@@ -7916,15 +8571,15 @@ async function sftpRead(opts, filePath, proxy, options) {
7916
8571
  clearTimeout(timer);
7917
8572
  cleanup?.();
7918
8573
  cleanup = void 0;
7919
- const text = Buffer.concat(
8574
+ const text7 = Buffer.concat(
7920
8575
  chunks.map((ch) => new Uint8Array(ch))
7921
8576
  ).toString("utf-8");
7922
8577
  if (!isWholeFileRequest) {
7923
8578
  const header = `# range: bytes ${offset}-${offset + effectiveLen - 1} of ${total} (${effectiveLen} bytes)`;
7924
8579
  resolve(`${header}
7925
- ${text}`);
8580
+ ${text7}`);
7926
8581
  } else {
7927
- resolve(text);
8582
+ resolve(text7);
7928
8583
  }
7929
8584
  });
7930
8585
  rs.on("error", (e) => {
@@ -8054,11 +8709,11 @@ function getKnownContainers(serverId, maxAgeMs = 5 * 6e4) {
8054
8709
  if (Date.now() - e.capturedAt > maxAgeMs) return void 0;
8055
8710
  return e.names;
8056
8711
  }
8057
- function truncateForLLM(text, maxBytes) {
8058
- const totalBytes = Buffer.byteLength(text, "utf8");
8712
+ function truncateForLLM(text7, maxBytes) {
8713
+ const totalBytes = Buffer.byteLength(text7, "utf8");
8059
8714
  if (totalBytes <= maxBytes)
8060
- return { text, truncated: false, totalBytes, shownBytes: totalBytes };
8061
- const buf = Buffer.from(text, "utf8");
8715
+ return { text: text7, truncated: false, totalBytes, shownBytes: totalBytes };
8716
+ const buf = Buffer.from(text7, "utf8");
8062
8717
  let cut = maxBytes;
8063
8718
  while (cut > 0 && (buf[cut] & 192) === 128) cut--;
8064
8719
  const head = buf.subarray(0, cut).toString("utf8");
@@ -8088,10 +8743,10 @@ function isTransientSshError(stderr, exitCode) {
8088
8743
  function postprocessResult(result, meta) {
8089
8744
  if (!result.content?.length) return result;
8090
8745
  const block = result.content[0];
8091
- let text = String(block.text ?? "");
8092
- const trunc = truncateForLLM(text, RESPONSE_MAX_BYTES);
8746
+ let text7 = String(block.text ?? "");
8747
+ const trunc = truncateForLLM(text7, RESPONSE_MAX_BYTES);
8093
8748
  if (trunc.truncated) {
8094
- text = trunc.text + "\n\n... " + buildTruncationHint(
8749
+ text7 = trunc.text + "\n\n... " + buildTruncationHint(
8095
8750
  meta.toolName,
8096
8751
  meta.args,
8097
8752
  trunc.totalBytes,
@@ -8105,11 +8760,11 @@ function postprocessResult(result, meta) {
8105
8760
  const parts = [`took ${tookStr}`, sizeStr];
8106
8761
  if (meta.serverIdLabel) parts.push(`server: ${meta.serverIdLabel}`);
8107
8762
  if (meta.cached) parts.push("cached");
8108
- text = `${text}
8763
+ text7 = `${text7}
8109
8764
 
8110
8765
  [${parts.join(", ")}]`;
8111
8766
  }
8112
- return { ...result, content: [{ ...block, text }] };
8767
+ return { ...result, content: [{ ...block, text: text7 }] };
8113
8768
  }
8114
8769
  function buildPipelineScript(commands, shell, marker, stopOnError) {
8115
8770
  if (shell === "powershell") {
@@ -8895,11 +9550,11 @@ CREATE TABLE IF NOT EXISTS _mcp_migrations (
8895
9550
  applied_by TEXT
8896
9551
  );
8897
9552
  `.trim();
8898
- function normaliseMigrationSql(sql28) {
8899
- return sql28.replace(/\r\n/g, "\n").trim() + "\n";
9553
+ function normaliseMigrationSql(sql29) {
9554
+ return sql29.replace(/\r\n/g, "\n").trim() + "\n";
8900
9555
  }
8901
- function migrationSha256(sql28) {
8902
- return createHash("sha256").update(normaliseMigrationSql(sql28), "utf8").digest("hex");
9556
+ function migrationSha256(sql29) {
9557
+ return createHash("sha256").update(normaliseMigrationSql(sql29), "utf8").digest("hex");
8903
9558
  }
8904
9559
  function dollarQuoteTag(value) {
8905
9560
  let tag = "_mcp";
@@ -11164,8 +11819,8 @@ ${sample.join("\n")}${files.length > 5 ? `
11164
11819
  };
11165
11820
  const filtered = sortRows(applyFilter(only.rows));
11166
11821
  if (format === "json") {
11167
- const text2 = filtered.map((c) => JSON.stringify(c)).join("\n") || "(no containers)";
11168
- return { content: [{ type: "text", text: text2 }] };
11822
+ const text8 = filtered.map((c) => JSON.stringify(c)).join("\n") || "(no containers)";
11823
+ return { content: [{ type: "text", text: text8 }] };
11169
11824
  }
11170
11825
  if (groupByProject) {
11171
11826
  const groups = /* @__PURE__ */ new Map();
@@ -11192,8 +11847,8 @@ ${sample.join("\n")}${files.length > 5 ? `
11192
11847
  }
11193
11848
  const header = `${"NAMES".padEnd(36)} ${"IMAGE".padEnd(40)} ${"STATUS".padEnd(24)} ${"HEALTH".padEnd(10)} ${"PORTS".padEnd(40)} PROJECT`;
11194
11849
  const body = filtered.map((r) => `${fmtRow(r)} ${r.Project || ""}`);
11195
- const text = filtered.length === 0 ? "(no containers match)" : [header, ...body].join("\n");
11196
- return { content: [{ type: "text", text }] };
11850
+ const text7 = filtered.length === 0 ? "(no containers match)" : [header, ...body].join("\n");
11851
+ return { content: [{ type: "text", text: text7 }] };
11197
11852
  }
11198
11853
  if (format === "json") {
11199
11854
  const lines = [];
@@ -12766,7 +13421,7 @@ ${lines.join("\n\n")}`
12766
13421
  // ----- Domains (mijn.host) -----
12767
13422
  case "domain-list": {
12768
13423
  const res = await mijnhostFetch(
12769
- "/domains"
13424
+ "/domains/"
12770
13425
  );
12771
13426
  const domains = res.data.domains;
12772
13427
  if (!domains.length) {