kollab 0.1.22 → 0.1.23

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
@@ -12246,8 +12246,8 @@ function buildCreditReservedHint(input) {
12246
12246
  }
12247
12247
 
12248
12248
  // src/lib/api-client.ts
12249
- async function api(creds, method, path13, body) {
12250
- return request(`${creds.api_url}/api${path13}`, method, body, creds.token);
12249
+ async function api(creds, method, path13, body, signal) {
12250
+ return request(`${creds.api_url}/api${path13}`, method, body, creds.token, signal);
12251
12251
  }
12252
12252
  async function apiSse(creds, path13, body, signal) {
12253
12253
  return requestSse(`${creds.api_url}/api${path13}`, body, creds.token, signal);
@@ -12255,29 +12255,29 @@ async function apiSse(creds, path13, body, signal) {
12255
12255
  async function publicApi(apiUrl, method, path13) {
12256
12256
  return request(`${apiUrl}/api${path13}`, method);
12257
12257
  }
12258
- async function request(url, method, body, token) {
12258
+ async function request(url, method, body, token, signal) {
12259
12259
  const headers = {
12260
12260
  "Content-Type": "application/json"
12261
12261
  };
12262
12262
  if (token) {
12263
12263
  headers.Authorization = `Bearer ${token}`;
12264
12264
  }
12265
- const init = { method, headers };
12265
+ const init = { method, headers, ...signal ? { signal } : {} };
12266
12266
  if (body) {
12267
12267
  init.body = JSON.stringify(body);
12268
12268
  }
12269
12269
  try {
12270
12270
  const res = await fetch(url, init);
12271
12271
  const text2 = await res.text();
12272
- let data;
12272
+ let data2;
12273
12273
  try {
12274
- data = JSON.parse(text2);
12274
+ data2 = JSON.parse(text2);
12275
12275
  } catch {
12276
12276
  }
12277
12277
  if (res.ok) {
12278
- return { ok: true, data };
12278
+ return { ok: true, data: data2 };
12279
12279
  }
12280
- const errorMsg = data?.message ?? `HTTP ${res.status}`;
12280
+ const errorMsg = data2?.message ?? `HTTP ${res.status}`;
12281
12281
  return { ok: false, error: String(errorMsg), status: res.status };
12282
12282
  } catch (err) {
12283
12283
  return {
@@ -12658,6 +12658,27 @@ function parseStringListOption(raw, label) {
12658
12658
  return trimmed.split(",").map((item) => item.trim()).filter(Boolean);
12659
12659
  }
12660
12660
 
12661
+ // src/lib/hosted-domain-error.ts
12662
+ function domainErrorHint(code) {
12663
+ const hints = {
12664
+ HOSTED_APP_MAX_REQUIRED: "Your workspace plan does not include custom domains. Upgrade the workspace plan, then retry.",
12665
+ HOSTED_APP_DOMAIN_ALREADY_BOUND: "This domain is bound to another app. Ask its owner to remove that binding, or use another domain.",
12666
+ HOSTED_APP_DOMAIN_REMOVE_EXISTING_FIRST: "This app already has another domain. Run `kollab app domain remove --id <appId>` before changing domains.",
12667
+ HOSTED_APP_DOMAIN_RESERVED: "This domain belongs to the platform. Use a domain you own outside the platform domain.",
12668
+ HOSTED_APP_DOMAIN_INVALID: "Enter a hostname such as www.example.com, without https://, a port, or a path.",
12669
+ HOSTED_APP_DOMAIN_NOT_FOUND: "No domain is bound. Run `kollab app domain setup --id <appId> --domain <domain>` first.",
12670
+ HOSTED_APP_DOMAIN_CHANGED: "The binding changed or expired. Read domain status, then run setup again.",
12671
+ HOSTED_APP_CUSTOM_DOMAIN_DISABLED: "Custom domains are not enabled in this environment. Contact your workspace administrator.",
12672
+ HOSTED_APP_CUSTOM_DOMAIN_NOT_CONFIGURED: "The managed domain proxy is not configured. Contact your workspace administrator.",
12673
+ HOSTED_APP_DOMAIN_DNS_MISMATCH: "The routing record was not found or points elsewhere. Set the shown CNAME/A record, use DNS only (gray cloud), and remove conflicting AAAA records.",
12674
+ HOSTED_APP_DOMAIN_DNS_CHALLENGE_MISMATCH: "The ownership TXT is missing or does not match. Copy the current TXT name and value exactly, then wait for DNS propagation.",
12675
+ HOSTED_APP_DOMAIN_DNS_ROUTE_AND_CHALLENGE_MISMATCH: "Both routing and ownership TXT need attention. Copy both records exactly, use DNS only, and wait for propagation.",
12676
+ HOSTED_APP_DOMAIN_DNS_UNAVAILABLE: "DNS could not be checked yet. Wait a few seconds and run setup --wait again.",
12677
+ HOSTED_APP_DOMAIN_DNS_LOOP: "The routing CNAME chain loops or is too long. Point it directly at the shown proxy target."
12678
+ };
12679
+ return hints[code] ?? "Check domain status and retry. If the problem continues, contact your workspace administrator.";
12680
+ }
12681
+
12661
12682
  // src/lib/output.ts
12662
12683
  function buildCliHint(result) {
12663
12684
  const errorText = String(result.error ?? "").toLowerCase();
@@ -12665,6 +12686,7 @@ function buildCliHint(result) {
12665
12686
  if (creditReservedHint) {
12666
12687
  return creditReservedHint;
12667
12688
  }
12689
+ if (/hosted_app_(?:domain_|custom_domain_|max_required)/.test(errorText)) return domainErrorHint(String(result.error));
12668
12690
  if (result.status === 401) {
12669
12691
  return "Authentication failed. Run `kollab login`, or set `KOLLAB_TOKEN`/`KOLLAB_API_TOKEN` together with the correct `KOLLAB_API_URL`.";
12670
12692
  }
@@ -14302,11 +14324,11 @@ async function fetchCanonicalArtifacts(creds, conversationId) {
14302
14324
  );
14303
14325
  return unwrapArtifactsPayload(artifactsResult.data);
14304
14326
  }
14305
- function unwrapMessagesPayload(data) {
14306
- if (Array.isArray(data)) {
14307
- return data.filter(asRecord);
14327
+ function unwrapMessagesPayload(data2) {
14328
+ if (Array.isArray(data2)) {
14329
+ return data2.filter(asRecord);
14308
14330
  }
14309
- const record2 = asRecord(data);
14331
+ const record2 = asRecord(data2);
14310
14332
  if (Array.isArray(record2?.messages)) {
14311
14333
  return record2.messages.filter(asRecord);
14312
14334
  }
@@ -14315,18 +14337,18 @@ function unwrapMessagesPayload(data) {
14315
14337
  }
14316
14338
  return [];
14317
14339
  }
14318
- function unwrapArtifactsPayload(data) {
14319
- if (Array.isArray(data)) {
14320
- return data.filter(asRecord);
14340
+ function unwrapArtifactsPayload(data2) {
14341
+ if (Array.isArray(data2)) {
14342
+ return data2.filter(asRecord);
14321
14343
  }
14322
- const record2 = asRecord(data);
14344
+ const record2 = asRecord(data2);
14323
14345
  if (Array.isArray(record2?.data)) {
14324
14346
  return record2.data.filter(asRecord);
14325
14347
  }
14326
14348
  return [];
14327
14349
  }
14328
- function readGenerationStatus(data) {
14329
- const record2 = asRecord(data);
14350
+ function readGenerationStatus(data2) {
14351
+ const record2 = asRecord(data2);
14330
14352
  const nested = asRecord(record2?.data);
14331
14353
  const value = nested?.generationStatus ?? record2?.generationStatus;
14332
14354
  return typeof value === "string" ? value : null;
@@ -15255,8 +15277,8 @@ function sleep4(ms) {
15255
15277
  function asRecord3(value) {
15256
15278
  return value && typeof value === "object" ? value : null;
15257
15279
  }
15258
- function readGenerationStatus2(data) {
15259
- const record2 = asRecord3(data);
15280
+ function readGenerationStatus2(data2) {
15281
+ const record2 = asRecord3(data2);
15260
15282
  const nested = asRecord3(record2?.data);
15261
15283
  const value = nested?.generationStatus ?? record2?.generationStatus;
15262
15284
  return typeof value === "string" ? value : null;
@@ -15974,15 +15996,15 @@ async function uploadSkillMultipart(apiUrl, token, filePath, name, spaceId) {
15974
15996
  body: form
15975
15997
  });
15976
15998
  const text2 = await res.text();
15977
- let data;
15999
+ let data2;
15978
16000
  try {
15979
- data = JSON.parse(text2);
16001
+ data2 = JSON.parse(text2);
15980
16002
  } catch {
15981
16003
  }
15982
16004
  if (res.ok) {
15983
- return { ok: true, data };
16005
+ return { ok: true, data: data2 };
15984
16006
  }
15985
- const errorMsg = data?.message ?? `HTTP ${res.status}`;
16007
+ const errorMsg = data2?.message ?? `HTTP ${res.status}`;
15986
16008
  return { ok: false, error: String(errorMsg), status: res.status };
15987
16009
  } catch (err) {
15988
16010
  return {
@@ -18729,13 +18751,13 @@ async function standaloneRequest(method, requestPath, body, options = {}) {
18729
18751
  try {
18730
18752
  const response = await fetch(`${apiUrl}/api${requestPath}${query}`, init);
18731
18753
  const text2 = await response.text();
18732
- let data;
18754
+ let data2;
18733
18755
  try {
18734
- data = JSON.parse(text2);
18756
+ data2 = JSON.parse(text2);
18735
18757
  } catch {
18736
18758
  }
18737
- if (response.ok) return { ok: true, status: response.status, data };
18738
- const record2 = data && typeof data === "object" ? data : void 0;
18759
+ if (response.ok) return { ok: true, status: response.status, data: data2 };
18760
+ const record2 = data2 && typeof data2 === "object" ? data2 : void 0;
18739
18761
  const retryHeader = response.headers.get("retry-after");
18740
18762
  const retryAfter = retryHeader ? Number(retryHeader) : void 0;
18741
18763
  const requestId = typeof record2?.request_id === "string" ? record2.request_id : void 0;
@@ -19041,12 +19063,12 @@ async function callStandaloneTool(tool, args, options = {}) {
19041
19063
  requestId,
19042
19064
  clientSource: options.clientSource ?? "mcp"
19043
19065
  });
19044
- let data = result.ok ? result.data ?? {} : void 0;
19066
+ let data2 = result.ok ? result.data ?? {} : void 0;
19045
19067
  let recoveredFromReceipt = false;
19046
19068
  if (!result.ok) {
19047
19069
  if (result.status === 503 && result.requestId) {
19048
19070
  recoveredFromReceipt = true;
19049
- data = await pollStandaloneJob(tool, result.jobId, {
19071
+ data2 = await pollStandaloneJob(tool, result.jobId, {
19050
19072
  apiUrl,
19051
19073
  apiKey: auth.apiKey,
19052
19074
  jwtToken: auth.jwtToken,
@@ -19058,12 +19080,12 @@ async function callStandaloneTool(tool, args, options = {}) {
19058
19080
  throw new Error(result.error ?? `Standalone tool failed: HTTP ${result.status}`);
19059
19081
  }
19060
19082
  }
19061
- const candidate = data && typeof data === "object" ? data : {};
19083
+ const candidate = data2 && typeof data2 === "object" ? data2 : {};
19062
19084
  const jobId = extractJobId(candidate);
19063
19085
  if (jobId && LONG_TASK_TOOLS.has(tool) && !recoveredFromReceipt) {
19064
- data = await pollStandaloneJob(tool, jobId, { apiUrl, apiKey: auth.apiKey, jwtToken: auth.jwtToken, spaceId, requestId });
19086
+ data2 = await pollStandaloneJob(tool, jobId, { apiUrl, apiKey: auth.apiKey, jwtToken: auth.jwtToken, spaceId, requestId });
19065
19087
  }
19066
- const completed = data && typeof data === "object" ? data : {};
19088
+ const completed = data2 && typeof data2 === "object" ? data2 : {};
19067
19089
  const artifacts = collectArtifacts(completed);
19068
19090
  if (artifacts.length > 0) {
19069
19091
  const downloaded = [];
@@ -19081,7 +19103,7 @@ async function callStandaloneTool(tool, args, options = {}) {
19081
19103
  ...downloadErrors.length > 0 ? { download_errors: downloadErrors } : {}
19082
19104
  };
19083
19105
  }
19084
- return data;
19106
+ return data2;
19085
19107
  }
19086
19108
  function redactDownloadError(error) {
19087
19109
  const message = error instanceof Error ? error.message : "Artifact download failed";
@@ -19482,14 +19504,14 @@ function registerMcpCommands(program2) {
19482
19504
  });
19483
19505
  const result = await api(creds, "GET", `/skills/mcp/catalog?${params.toString()}`);
19484
19506
  printResult(
19485
- mapApiData(result, (data) => {
19486
- const entries = (Array.isArray(data?.entries) ? data.entries : []).map(sanitizeCatalogEntry).filter((entry) => entry !== null);
19507
+ mapApiData(result, (data2) => {
19508
+ const entries = (Array.isArray(data2?.entries) ? data2.entries : []).map(sanitizeCatalogEntry).filter((entry) => entry !== null);
19487
19509
  return {
19488
19510
  query,
19489
- total: typeof data?.total === "number" ? data.total : void 0,
19511
+ total: typeof data2?.total === "number" ? data2.total : void 0,
19490
19512
  count: entries.length,
19491
- hasMore: typeof data?.hasMore === "boolean" ? data.hasMore : void 0,
19492
- nextCursor: readString(data?.nextCursor),
19513
+ hasMore: typeof data2?.hasMore === "boolean" ? data2.hasMore : void 0,
19514
+ nextCursor: readString(data2?.nextCursor),
19493
19515
  entries
19494
19516
  };
19495
19517
  })
@@ -20061,6 +20083,153 @@ async function requireHostedAppCredentials() {
20061
20083
  };
20062
20084
  }
20063
20085
 
20086
+ // src/commands/app-domain.ts
20087
+ var import_node_url = require("url");
20088
+ function data(result) {
20089
+ if (!result.ok) throw new Error(result.error ?? "DOMAIN_REQUEST_FAILED");
20090
+ return result.data ?? null;
20091
+ }
20092
+ function domainRecords(view) {
20093
+ if (!view) return [];
20094
+ return [
20095
+ ...view.dnsTarget ? [{ type: view.dnsRecordType, name: view.domain, value: view.dnsTarget, purpose: "routing" }] : [],
20096
+ ...(view.validationRecords ?? []).map((record2) => ({ ...record2, purpose: "ownership" }))
20097
+ ];
20098
+ }
20099
+ function domainOutput(view) {
20100
+ return {
20101
+ domain: view?.domain ?? null,
20102
+ status: view?.domainStatus ?? "none",
20103
+ records: domainRecords(view),
20104
+ nextAction: view?.nextAction ?? (view?.domainStatus === "active" ? view.certificateStatus === "ready" ? "done" : "wait_certificate" : view ? "add_records" : "none"),
20105
+ url: view ? `https://${view.domain}` : null,
20106
+ certificateStatus: view?.certificateStatus ?? "not_started",
20107
+ certificateCheckedAt: view?.certificateCheckedAt ?? null
20108
+ };
20109
+ }
20110
+ function domainInstructions(view, recordsOnly = false) {
20111
+ if (!view) return "No domain is bound. Run `kollab app domain setup --id <appId> --domain <domain>` first.";
20112
+ const lines = domainRecords(view).map((record2) => {
20113
+ const zone = view.dnsZone;
20114
+ const relative3 = zone && record2.name === zone ? "@" : zone && record2.name.endsWith(`.${zone}`) ? record2.name.slice(0, -zone.length - 1) : "(use the full name, or remove your DNS zone suffix)";
20115
+ return `${record2.type} | Full name: ${record2.name} | Host: ${relative3}${zone ? ` (zone: ${zone})` : ""} | Value: ${record2.value} | TTL: 300 seconds (or Auto)`;
20116
+ });
20117
+ if (recordsOnly) return [...lines, "Cloudflare or another proxy DNS provider: choose DNS only / gray cloud. TTL: 300 seconds or Auto."].join("\n");
20118
+ return [
20119
+ ...lines,
20120
+ "Cloudflare or another proxy DNS provider: choose DNS only / gray cloud. Remove conflicting AAAA records.",
20121
+ `Status: ${view.domainStatus}; certificate: ${view.certificateStatus ?? "not_started"}; next: ${domainOutput(view).nextAction}`,
20122
+ ...view.errorCode ? [domainErrorHint(view.errorCode)] : [],
20123
+ ...view.dnsObserved ? [`Observed: ${view.dnsObserved}`] : []
20124
+ ].join("\n");
20125
+ }
20126
+ async function setupDomain(request2, options, progress = () => void 0, clock = { now: () => Date.now(), sleep: (ms) => new Promise((resolve4) => setTimeout(resolve4, ms)) }) {
20127
+ const timeout = options.timeout ?? 600;
20128
+ if (!Number.isSafeInteger(timeout) || timeout <= 0 || timeout > 86400) throw new Error("INVALID_TIMEOUT");
20129
+ const domain = (0, import_node_url.domainToASCII)(options.domain.trim().replace(/\.+$/, "")).toLowerCase();
20130
+ if (!domain || /[/\\:@?#\s%]/.test(options.domain)) throw new Error("HOSTED_APP_DOMAIN_INVALID");
20131
+ let view = data(await request2("GET"));
20132
+ if (view && view.domain !== domain) throw new Error("HOSTED_APP_DOMAIN_REMOVE_EXISTING_FIRST");
20133
+ if (!view) view = data(await request2("POST", "", { domain }));
20134
+ if (!view) throw new Error("HOSTED_APP_DOMAIN_NOT_FOUND");
20135
+ let last = "";
20136
+ const report = () => {
20137
+ const fingerprint = JSON.stringify([view.domainStatus, view.certificateStatus, view.errorCode, view.dnsObserved, view.nextAction]);
20138
+ if (fingerprint !== last) {
20139
+ last = fingerprint;
20140
+ progress(view);
20141
+ }
20142
+ };
20143
+ report();
20144
+ if (!options.wait) return view;
20145
+ const dnsDeadline = clock.now() + timeout * 1e3;
20146
+ let certificateDeadline;
20147
+ let delay = 5e3;
20148
+ for (; ; ) {
20149
+ if (view.nextAction === "upgrade_required") throw new Error("HOSTED_APP_MAX_REQUIRED");
20150
+ if (view.domainStatus === "active" && !view.errorCode) {
20151
+ if (view.certificateStatus === "ready") return view;
20152
+ certificateDeadline ?? (certificateDeadline = clock.now() + 6e4);
20153
+ }
20154
+ const deadline = certificateDeadline ?? dnsDeadline;
20155
+ if (clock.now() >= deadline) {
20156
+ const error = new Error(certificateDeadline ? "CERTIFICATE_TIMEOUT" : "DNS_TIMEOUT");
20157
+ Object.assign(error, { view });
20158
+ throw error;
20159
+ }
20160
+ view = data(await request2("POST", "/verify"));
20161
+ if (!view || view.domain !== domain) throw new Error("HOSTED_APP_DOMAIN_CHANGED");
20162
+ report();
20163
+ if (view.domainStatus === "active" && !view.errorCode && view.certificateStatus === "ready") return view;
20164
+ await clock.sleep(Math.min(delay, Math.max(0, deadline - clock.now())));
20165
+ delay = Math.min(1e4, delay + 1e3);
20166
+ }
20167
+ }
20168
+ function registerHostedAppDomainCommands(app) {
20169
+ const group = app.command("domain").description("Configure a custom domain and wait for trusted HTTPS");
20170
+ for (const name of ["list", "status", "add", "verify", "remove"]) {
20171
+ const command = group.command(name).description(`${name} the custom domain (status includes DNS and certificate readiness)`).requiredOption("--id <appId>", "Hosted App ID (UUID)");
20172
+ if (name === "add") command.requiredOption("--domain <domain>", "Customer-owned hostname or apex domain");
20173
+ command.action(async (options) => {
20174
+ try {
20175
+ const creds = await requireHostedAppCredentials();
20176
+ const method = name === "remove" ? "DELETE" : ["add", "verify"].includes(name) ? "POST" : "GET";
20177
+ printResult(await api(
20178
+ creds,
20179
+ method,
20180
+ `/hosted-apps/${encodeURIComponent(options.id)}/domains${name === "verify" ? "/verify" : ""}`,
20181
+ name === "add" ? { domain: options.domain } : void 0
20182
+ ));
20183
+ } catch (error) {
20184
+ emitError(error instanceof Error ? error.message : String(error));
20185
+ }
20186
+ });
20187
+ }
20188
+ for (const name of ["setup", "records"]) {
20189
+ const command = group.command(name).description(name === "setup" ? "Bind a domain, print DNS records, and optionally wait for HTTPS" : "Print only the required DNS records").requiredOption("--id <appId>", "Hosted App ID (UUID)").option("--json", "Print a stable JSON object");
20190
+ if (name === "setup") command.requiredOption("--domain <domain>", "Customer-owned hostname or apex domain").option("--wait", "Wait for DNS and trusted HTTPS").option("--timeout <seconds>", "DNS wait timeout (1\u201386400 seconds)", "600");
20191
+ command.action(async (options) => {
20192
+ let latest = null;
20193
+ try {
20194
+ const creds = await requireHostedAppCredentials();
20195
+ const request2 = (method, suffix = "", body) => api(creds, method, `/hosted-apps/${encodeURIComponent(options.id)}/domains${suffix}`, body, AbortSignal.timeout(1e4));
20196
+ latest = name === "records" ? data(await request2("GET")) : await setupDomain(
20197
+ request2,
20198
+ { ...options, timeout: Number(options.timeout) },
20199
+ (view) => {
20200
+ const initial = !latest;
20201
+ latest = view;
20202
+ if (!options.json) console.log(initial ? domainInstructions(view) : `Status: ${view.domainStatus}; certificate: ${view.certificateStatus ?? "not_started"}${view.errorCode ? `; ${domainErrorHint(view.errorCode)}` : ""}${view.dnsObserved ? `; Observed: ${view.dnsObserved}` : ""}`);
20203
+ }
20204
+ );
20205
+ if (options.json) console.log(JSON.stringify(domainOutput(latest), null, 2));
20206
+ else if (name === "records") console.log(domainInstructions(latest, true));
20207
+ else if (latest?.domainStatus === "active" && latest.certificateStatus === "ready" && !latest.errorCode)
20208
+ console.log(`HTTPS is ready: https://${latest.domain}`);
20209
+ else console.log("DNS or HTTPS is not ready yet. Add the records, then run setup with --wait.");
20210
+ if (!latest) process.exitCode = 1;
20211
+ } catch (error) {
20212
+ const code = error instanceof Error ? error.message : String(error);
20213
+ const view = error.view ?? latest;
20214
+ const hint = code === "INVALID_TIMEOUT" ? "--timeout must be an integer from 1 to 86400 seconds." : code === "CERTIFICATE_TIMEOUT" ? "DNS is verified, but trusted HTTPS is not ready. Retry setup --wait; check domain status for the certificate error." : code === "DNS_TIMEOUT" ? "DNS is not verified yet. Fix the missing or incorrect records shown in the observations, then retry setup --wait." : domainErrorHint(code);
20215
+ const output = {
20216
+ ...domainOutput(view),
20217
+ ...code === "HOSTED_APP_MAX_REQUIRED" ? { nextAction: "upgrade_required" } : {},
20218
+ error: code,
20219
+ message: hint,
20220
+ dnsObserved: view?.dnsObserved ?? null,
20221
+ dnsErrorCode: view?.errorCode ?? null,
20222
+ certificateErrorCode: view?.certificateErrorCode ?? null
20223
+ };
20224
+ if (options.json) console.log(JSON.stringify(output, null, 2));
20225
+ console.error(options.json ? hint : `${code}: ${hint}
20226
+ ${domainInstructions(view)}`);
20227
+ process.exitCode = 1;
20228
+ }
20229
+ });
20230
+ }
20231
+ }
20232
+
20064
20233
  // src/commands/app.ts
20065
20234
  var MAX_HOSTED_APP_FILE_BYTES = 20 * 1024 * 1024;
20066
20235
  function validateHostedAppFile(filePath, fileSize) {
@@ -20239,41 +20408,7 @@ A .zip needs app.manifest.json, or a plain static site with index.html at its ro
20239
20408
  emitError(error instanceof Error ? error.message : String(error));
20240
20409
  }
20241
20410
  });
20242
- const domain = app.command("domain").description("Bind and manage one custom domain for a Hosted App");
20243
- const listDomain = async (options) => {
20244
- try {
20245
- const creds = await requireHostedAppCredentials();
20246
- printResult(await api(creds, "GET", `/hosted-apps/${encodeURIComponent(options.id)}/domains`));
20247
- } catch (error) {
20248
- emitError(error instanceof Error ? error.message : String(error));
20249
- }
20250
- };
20251
- domain.command("list").description("Show the Hosted App custom domain and DNS records").requiredOption("--id <appId>", "Hosted App ID (UUID)").action(listDomain);
20252
- domain.command("status").description("Show the Hosted App custom domain status").requiredOption("--id <appId>", "Hosted App ID (UUID)").action(listDomain);
20253
- domain.command("add").description("Request a certificate and bind a subdomain or apex domain").requiredOption("--id <appId>", "Hosted App ID (UUID)").requiredOption("--domain <domain>", "Customer-owned hostname or apex domain").action(async (options) => {
20254
- try {
20255
- const creds = await requireHostedAppCredentials();
20256
- printResult(await api(creds, "POST", `/hosted-apps/${encodeURIComponent(options.id)}/domains`, { domain: options.domain }));
20257
- } catch (error) {
20258
- emitError(error instanceof Error ? error.message : String(error));
20259
- }
20260
- });
20261
- domain.command("verify").description("Refresh certificate and CloudFront deployment status").requiredOption("--id <appId>", "Hosted App ID (UUID)").action(async (options) => {
20262
- try {
20263
- const creds = await requireHostedAppCredentials();
20264
- printResult(await api(creds, "POST", `/hosted-apps/${encodeURIComponent(options.id)}/domains/verify`));
20265
- } catch (error) {
20266
- emitError(error instanceof Error ? error.message : String(error));
20267
- }
20268
- });
20269
- domain.command("remove").description("Unbind and release the Hosted App custom domain").requiredOption("--id <appId>", "Hosted App ID (UUID)").action(async (options) => {
20270
- try {
20271
- const creds = await requireHostedAppCredentials();
20272
- printResult(await api(creds, "DELETE", `/hosted-apps/${encodeURIComponent(options.id)}/domains`));
20273
- } catch (error) {
20274
- emitError(error instanceof Error ? error.message : String(error));
20275
- }
20276
- });
20411
+ registerHostedAppDomainCommands(app);
20277
20412
  app.command("ai").description("Pause, resume, or adjust a Hosted App AI budget").requiredOption("--id <appId>", "Hosted App ID (UUID)").option("--action <action>", "pause, resume, or budget").option("--daily-credit-limit <credits>", "Daily AI credit limit", (value) => parseIntegerOption(value, "--daily-credit-limit")).option("--monthly-credit-limit <credits>", "Monthly AI credit limit", (value) => parseIntegerOption(value, "--monthly-credit-limit")).action(async (options) => {
20278
20413
  try {
20279
20414
  if (!options.action && options.dailyCreditLimit === void 0 && options.monthlyCreditLimit === void 0) {
@@ -20418,19 +20553,19 @@ function registerModelCommands(program2) {
20418
20553
  }
20419
20554
  const envelope = result.data ?? {};
20420
20555
  const payload = envelope.data && typeof envelope.data === "object" && !Array.isArray(envelope.data) ? envelope.data : {};
20421
- const data = {
20556
+ const data2 = {
20422
20557
  ...payload,
20423
20558
  ...typeof envelope.requestId === "string" ? { request_id: envelope.requestId } : {}
20424
20559
  };
20425
- const text2 = typeof data.text === "string" ? data.text : "";
20426
- const images = Array.isArray(data.images) ? data.images : [];
20560
+ const text2 = typeof data2.text === "string" ? data2.text : "";
20561
+ const images = Array.isArray(data2.images) ? data2.images : [];
20427
20562
  if (!text2 && images.length === 0) emitError("\u6A21\u578B\u8FD4\u56DE\u4E86\u7A7A\u6587\u5B57");
20428
20563
  const localPaths = await downloadModelImages(images, options.outputDir);
20429
20564
  if (options.outputFile) {
20430
20565
  await (0, import_promises3.writeFile)(options.outputFile, text2, { encoding: "utf8", mode: 384 });
20431
20566
  }
20432
20567
  if (options.json) {
20433
- console.log(JSON.stringify({ ok: true, data: { ...data, ...options.outputFile ? { output_file: options.outputFile } : {}, ...localPaths.length ? { local_paths: localPaths } : {} } }, null, 2));
20568
+ console.log(JSON.stringify({ ok: true, data: { ...data2, ...options.outputFile ? { output_file: options.outputFile } : {}, ...localPaths.length ? { local_paths: localPaths } : {} } }, null, 2));
20434
20569
  } else {
20435
20570
  if (!options.outputFile) process.stdout.write(text2);
20436
20571
  else console.error(`\u5DF2\u5199\u5165 ${options.outputFile}`);
@@ -20512,8 +20647,8 @@ var fs6 = __toESM(require("fs"));
20512
20647
  var path6 = __toESM(require("path"));
20513
20648
  var UNKNOWN_VERSION = "0.0.0";
20514
20649
  function injectedVersion() {
20515
- if ("0.1.22".length > 0) {
20516
- return "0.1.22";
20650
+ if ("0.1.23".length > 0) {
20651
+ return "0.1.23";
20517
20652
  }
20518
20653
  return null;
20519
20654
  }
@@ -21175,8 +21310,8 @@ function runCommand(params) {
21175
21310
 
21176
21311
  // src/local/executor.ts
21177
21312
  var MUTATING_ACTIONS = /* @__PURE__ */ new Set(["write", "mkdir", "mv", "rm", "run", "fetch", "push"]);
21178
- function ok(message, data) {
21179
- return { type: "local_result", commandId: message.commandId, deviceId: message.deviceId, status: "ok", data };
21313
+ function ok(message, data2) {
21314
+ return { type: "local_result", commandId: message.commandId, deviceId: message.deviceId, status: "ok", data: data2 };
21180
21315
  }
21181
21316
  function denied(message, code, text2) {
21182
21317
  return {