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 +217 -82
- package/dist/kollab-sidecar.cjs +532 -393
- package/package.json +1 -1
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
|
|
12272
|
+
let data2;
|
|
12273
12273
|
try {
|
|
12274
|
-
|
|
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 =
|
|
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(
|
|
14306
|
-
if (Array.isArray(
|
|
14307
|
-
return
|
|
14327
|
+
function unwrapMessagesPayload(data2) {
|
|
14328
|
+
if (Array.isArray(data2)) {
|
|
14329
|
+
return data2.filter(asRecord);
|
|
14308
14330
|
}
|
|
14309
|
-
const record2 = asRecord(
|
|
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(
|
|
14319
|
-
if (Array.isArray(
|
|
14320
|
-
return
|
|
14340
|
+
function unwrapArtifactsPayload(data2) {
|
|
14341
|
+
if (Array.isArray(data2)) {
|
|
14342
|
+
return data2.filter(asRecord);
|
|
14321
14343
|
}
|
|
14322
|
-
const record2 = asRecord(
|
|
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(
|
|
14329
|
-
const record2 = asRecord(
|
|
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(
|
|
15259
|
-
const record2 = asRecord3(
|
|
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
|
|
15999
|
+
let data2;
|
|
15978
16000
|
try {
|
|
15979
|
-
|
|
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 =
|
|
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
|
|
18754
|
+
let data2;
|
|
18733
18755
|
try {
|
|
18734
|
-
|
|
18756
|
+
data2 = JSON.parse(text2);
|
|
18735
18757
|
} catch {
|
|
18736
18758
|
}
|
|
18737
|
-
if (response.ok) return { ok: true, status: response.status, data };
|
|
18738
|
-
const record2 =
|
|
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
|
|
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
|
-
|
|
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 =
|
|
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
|
-
|
|
19086
|
+
data2 = await pollStandaloneJob(tool, jobId, { apiUrl, apiKey: auth.apiKey, jwtToken: auth.jwtToken, spaceId, requestId });
|
|
19065
19087
|
}
|
|
19066
|
-
const completed =
|
|
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
|
|
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, (
|
|
19486
|
-
const entries = (Array.isArray(
|
|
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
|
|
19511
|
+
total: typeof data2?.total === "number" ? data2.total : void 0,
|
|
19490
19512
|
count: entries.length,
|
|
19491
|
-
hasMore: typeof
|
|
19492
|
-
nextCursor: readString(
|
|
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
|
-
|
|
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
|
|
20556
|
+
const data2 = {
|
|
20422
20557
|
...payload,
|
|
20423
20558
|
...typeof envelope.requestId === "string" ? { request_id: envelope.requestId } : {}
|
|
20424
20559
|
};
|
|
20425
|
-
const text2 = typeof
|
|
20426
|
-
const images = Array.isArray(
|
|
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: { ...
|
|
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.
|
|
20516
|
-
return "0.1.
|
|
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,
|
|
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 {
|