@instafy/cli 0.2.0 → 0.2.2
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/README.md +5 -0
- package/dist/cli.js +1547 -309
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -809,7 +809,7 @@ async function resolveOrg(controllerUrl, auth, options, retryCommand) {
|
|
|
809
809
|
}
|
|
810
810
|
const orgSlug = options.orgSlug?.trim() || null;
|
|
811
811
|
const orgName = options.orgName?.trim() || null;
|
|
812
|
-
const studioUrl = resolveConfiguredStudioUrl({ profile: options.profile ?? null }) ?? "https://
|
|
812
|
+
const studioUrl = resolveConfiguredStudioUrl({ profile: options.profile ?? null }) ?? "https://instafy.dev";
|
|
813
813
|
const studioOrgUrl = `${studioUrl.replace(/\/$/, "")}/studio?panel=settings`;
|
|
814
814
|
const allowInteractive = Boolean(
|
|
815
815
|
input2.isTTY && process.stdout.isTTY && options.json !== true && process.env.CI !== "true"
|
|
@@ -1276,7 +1276,7 @@ var org_exports = {};
|
|
|
1276
1276
|
__export(org_exports, {
|
|
1277
1277
|
listOrganizations: () => listOrganizations
|
|
1278
1278
|
});
|
|
1279
|
-
import
|
|
1279
|
+
import kleur17 from "kleur";
|
|
1280
1280
|
function getTeamDisplayName2(name) {
|
|
1281
1281
|
const trimmed = (name ?? "").trim();
|
|
1282
1282
|
if (!trimmed || trimmed === "Personal organization" || trimmed === "Personal team" || trimmed === "Personal workspace") {
|
|
@@ -1314,11 +1314,11 @@ async function listOrganizations(params) {
|
|
|
1314
1314
|
console.log(JSON.stringify(orgs, null, 2));
|
|
1315
1315
|
} else {
|
|
1316
1316
|
if (orgs.length === 0) {
|
|
1317
|
-
console.log(
|
|
1317
|
+
console.log(kleur17.yellow("No teams found for this account."));
|
|
1318
1318
|
} else {
|
|
1319
1319
|
for (const org of orgs) {
|
|
1320
1320
|
const role = org.role ? ` [${org.role}]` : "";
|
|
1321
|
-
console.log(`${
|
|
1321
|
+
console.log(`${kleur17.green(getTeamDisplayName2(org.name))} (${org.id}${role})`);
|
|
1322
1322
|
}
|
|
1323
1323
|
}
|
|
1324
1324
|
}
|
|
@@ -1348,9 +1348,9 @@ var init_hardwareProvider2 = __esm({
|
|
|
1348
1348
|
});
|
|
1349
1349
|
|
|
1350
1350
|
// ../instafy-sdk/src/hardwareNode.ts
|
|
1351
|
-
import
|
|
1351
|
+
import fs13 from "node:fs";
|
|
1352
1352
|
import os5 from "node:os";
|
|
1353
|
-
import
|
|
1353
|
+
import path14 from "node:path";
|
|
1354
1354
|
function uniqueStrings(values) {
|
|
1355
1355
|
const seen = /* @__PURE__ */ new Set();
|
|
1356
1356
|
const result = [];
|
|
@@ -1389,14 +1389,14 @@ function classifySerialPort(fileName, fullPath) {
|
|
|
1389
1389
|
return null;
|
|
1390
1390
|
}
|
|
1391
1391
|
function inspectPort(portPath) {
|
|
1392
|
-
const resolvedPath =
|
|
1392
|
+
const resolvedPath = path14.resolve(portPath);
|
|
1393
1393
|
let exists = false;
|
|
1394
1394
|
let readable = false;
|
|
1395
1395
|
let writable = false;
|
|
1396
1396
|
let isCharacterDevice = false;
|
|
1397
1397
|
let error = null;
|
|
1398
1398
|
try {
|
|
1399
|
-
const stat =
|
|
1399
|
+
const stat = fs13.statSync(resolvedPath);
|
|
1400
1400
|
exists = true;
|
|
1401
1401
|
isCharacterDevice = stat.isCharacterDevice();
|
|
1402
1402
|
} catch (caught) {
|
|
@@ -1404,13 +1404,13 @@ function inspectPort(portPath) {
|
|
|
1404
1404
|
}
|
|
1405
1405
|
if (exists) {
|
|
1406
1406
|
try {
|
|
1407
|
-
|
|
1407
|
+
fs13.accessSync(resolvedPath, fs13.constants.R_OK);
|
|
1408
1408
|
readable = true;
|
|
1409
1409
|
} catch {
|
|
1410
1410
|
readable = false;
|
|
1411
1411
|
}
|
|
1412
1412
|
try {
|
|
1413
|
-
|
|
1413
|
+
fs13.accessSync(resolvedPath, fs13.constants.W_OK);
|
|
1414
1414
|
writable = true;
|
|
1415
1415
|
} catch {
|
|
1416
1416
|
writable = false;
|
|
@@ -1432,12 +1432,12 @@ function listCandidates(scanDirs) {
|
|
|
1432
1432
|
for (const scanDir of scanDirs) {
|
|
1433
1433
|
let entries = [];
|
|
1434
1434
|
try {
|
|
1435
|
-
entries =
|
|
1435
|
+
entries = fs13.readdirSync(scanDir);
|
|
1436
1436
|
} catch {
|
|
1437
1437
|
continue;
|
|
1438
1438
|
}
|
|
1439
1439
|
for (const entry of entries) {
|
|
1440
|
-
const fullPath =
|
|
1440
|
+
const fullPath = path14.join(scanDir, entry);
|
|
1441
1441
|
const kind = classifySerialPort(entry, fullPath);
|
|
1442
1442
|
if (!kind) {
|
|
1443
1443
|
continue;
|
|
@@ -1445,7 +1445,7 @@ function listCandidates(scanDirs) {
|
|
|
1445
1445
|
candidates.push({
|
|
1446
1446
|
path: fullPath,
|
|
1447
1447
|
kind,
|
|
1448
|
-
displayName:
|
|
1448
|
+
displayName: path14.basename(fullPath)
|
|
1449
1449
|
});
|
|
1450
1450
|
}
|
|
1451
1451
|
}
|
|
@@ -1611,37 +1611,37 @@ __export(hardware_exports, {
|
|
|
1611
1611
|
hardwareSerialList: () => hardwareSerialList,
|
|
1612
1612
|
hardwareSerialProbe: () => hardwareSerialProbe
|
|
1613
1613
|
});
|
|
1614
|
-
import
|
|
1614
|
+
import kleur18 from "kleur";
|
|
1615
1615
|
function printSerialPorts(result) {
|
|
1616
1616
|
if (result.ports.length === 0) {
|
|
1617
|
-
console.log(
|
|
1617
|
+
console.log(kleur18.yellow("No local serial devices were discovered."));
|
|
1618
1618
|
return;
|
|
1619
1619
|
}
|
|
1620
|
-
console.log(
|
|
1620
|
+
console.log(kleur18.cyan(`Local serial devices (${result.platform}):`));
|
|
1621
1621
|
for (const port of result.ports) {
|
|
1622
|
-
const status = port.available ?
|
|
1622
|
+
const status = port.available ? kleur18.green("available") : kleur18.yellow("not ready");
|
|
1623
1623
|
console.log(`- ${port.path} (${port.kind}, ${status})`);
|
|
1624
1624
|
}
|
|
1625
1625
|
}
|
|
1626
1626
|
function printProbe(probe) {
|
|
1627
|
-
console.log(
|
|
1627
|
+
console.log(kleur18.cyan(`Serial device: ${probe.path}`));
|
|
1628
1628
|
console.log(`Exists: ${probe.exists ? "yes" : "no"}`);
|
|
1629
1629
|
console.log(`Readable: ${probe.readable ? "yes" : "no"}`);
|
|
1630
1630
|
console.log(`Writable: ${probe.writable ? "yes" : "no"}`);
|
|
1631
1631
|
console.log(`Character device: ${probe.isCharacterDevice ? "yes" : "no"}`);
|
|
1632
|
-
console.log(`Available: ${probe.available ?
|
|
1632
|
+
console.log(`Available: ${probe.available ? kleur18.green("yes") : kleur18.yellow("no")}`);
|
|
1633
1633
|
if (probe.error) {
|
|
1634
1634
|
console.log(`Detail: ${probe.error}`);
|
|
1635
1635
|
}
|
|
1636
1636
|
}
|
|
1637
1637
|
function printIoOpportunities(result) {
|
|
1638
1638
|
if (result.opportunities.length === 0) {
|
|
1639
|
-
console.log(
|
|
1639
|
+
console.log(kleur18.yellow("No local IO opportunities were discovered."));
|
|
1640
1640
|
return;
|
|
1641
1641
|
}
|
|
1642
|
-
console.log(
|
|
1642
|
+
console.log(kleur18.cyan(`Local IO opportunities (${result.platform}):`));
|
|
1643
1643
|
for (const opportunity of result.opportunities) {
|
|
1644
|
-
const status = opportunity.available ?
|
|
1644
|
+
const status = opportunity.available ? kleur18.green("available") : kleur18.yellow("not ready");
|
|
1645
1645
|
console.log(`- ${opportunity.title} (${status})`);
|
|
1646
1646
|
console.log(` Resource: ${opportunity.resource.path}`);
|
|
1647
1647
|
const available = opportunity.actions.filter((action) => action.status === "available").map((action) => action.id);
|
|
@@ -1655,8 +1655,8 @@ function printIoOpportunities(result) {
|
|
|
1655
1655
|
}
|
|
1656
1656
|
}
|
|
1657
1657
|
function printIoActionResult(result) {
|
|
1658
|
-
const status = result.ok ?
|
|
1659
|
-
console.log(
|
|
1658
|
+
const status = result.ok ? kleur18.green("ok") : kleur18.red("failed");
|
|
1659
|
+
console.log(kleur18.cyan(`Local IO action: ${result.actionId} (${status})`));
|
|
1660
1660
|
console.log(result.message);
|
|
1661
1661
|
if (result.serialProbe) {
|
|
1662
1662
|
printProbe(result.serialProbe);
|
|
@@ -1665,11 +1665,11 @@ function printIoActionResult(result) {
|
|
|
1665
1665
|
const exit = result.process.exitCode ?? result.process.signal ?? "unknown";
|
|
1666
1666
|
console.log(`Process exit: ${exit}`);
|
|
1667
1667
|
if (result.process.stdout.trim()) {
|
|
1668
|
-
console.log(
|
|
1668
|
+
console.log(kleur18.dim("stdout:"));
|
|
1669
1669
|
console.log(result.process.stdout.trimEnd());
|
|
1670
1670
|
}
|
|
1671
1671
|
if (result.process.stderr.trim()) {
|
|
1672
|
-
console.log(
|
|
1672
|
+
console.log(kleur18.dim("stderr:"));
|
|
1673
1673
|
console.log(result.process.stderr.trimEnd());
|
|
1674
1674
|
}
|
|
1675
1675
|
}
|
|
@@ -1732,7 +1732,7 @@ var init_hardware = __esm({
|
|
|
1732
1732
|
import { Command, Option } from "commander";
|
|
1733
1733
|
import { pathToFileURL as pathToFileURL2 } from "node:url";
|
|
1734
1734
|
import { createRequire as createRequire3 } from "node:module";
|
|
1735
|
-
import
|
|
1735
|
+
import kleur19 from "kleur";
|
|
1736
1736
|
|
|
1737
1737
|
// src/runtime.ts
|
|
1738
1738
|
import { spawn as spawn2, spawnSync } from "node:child_process";
|
|
@@ -3139,7 +3139,7 @@ async function isStudioHealthy(studioUrl, timeoutMs) {
|
|
|
3139
3139
|
}
|
|
3140
3140
|
}
|
|
3141
3141
|
async function resolveDefaultStudioUrl(controllerUrl) {
|
|
3142
|
-
const hosted = "https://
|
|
3142
|
+
const hosted = "https://instafy.dev";
|
|
3143
3143
|
if (isStagingCli2) {
|
|
3144
3144
|
return hosted;
|
|
3145
3145
|
}
|
|
@@ -3909,7 +3909,7 @@ function normalizeSecretRecord(input3) {
|
|
|
3909
3909
|
}
|
|
3910
3910
|
return out;
|
|
3911
3911
|
};
|
|
3912
|
-
const
|
|
3912
|
+
const toMaybeString2 = (value) => {
|
|
3913
3913
|
if (typeof value !== "string") {
|
|
3914
3914
|
return null;
|
|
3915
3915
|
}
|
|
@@ -3922,10 +3922,10 @@ function normalizeSecretRecord(input3) {
|
|
|
3922
3922
|
description,
|
|
3923
3923
|
agentIds: toStringArray(record["agentIds"]),
|
|
3924
3924
|
agentHandles: toStringArray(record["agentHandles"]),
|
|
3925
|
-
lastUsedAt:
|
|
3926
|
-
revokedAt:
|
|
3927
|
-
createdAt:
|
|
3928
|
-
updatedAt:
|
|
3925
|
+
lastUsedAt: toMaybeString2(record["lastUsedAt"]),
|
|
3926
|
+
revokedAt: toMaybeString2(record["revokedAt"]),
|
|
3927
|
+
createdAt: toMaybeString2(record["createdAt"]),
|
|
3928
|
+
updatedAt: toMaybeString2(record["updatedAt"])
|
|
3929
3929
|
};
|
|
3930
3930
|
}
|
|
3931
3931
|
function normalizeSecretList(payload) {
|
|
@@ -4160,6 +4160,8 @@ init_config();
|
|
|
4160
4160
|
init_controller_fetch();
|
|
4161
4161
|
init_errors();
|
|
4162
4162
|
init_project_manifest();
|
|
4163
|
+
import fs6 from "node:fs";
|
|
4164
|
+
import path7 from "node:path";
|
|
4163
4165
|
import kleur5 from "kleur";
|
|
4164
4166
|
var UUID_PATTERN2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
4165
4167
|
function normalizeUuidParam(raw) {
|
|
@@ -4253,24 +4255,25 @@ function normalizeAutomationRecord(input3) {
|
|
|
4253
4255
|
if (!id || !name)
|
|
4254
4256
|
return null;
|
|
4255
4257
|
const toMaybeNumber = (value) => typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
4256
|
-
const
|
|
4258
|
+
const toMaybeString2 = (value) => typeof value === "string" && value.trim() ? value.trim() : null;
|
|
4257
4259
|
return {
|
|
4258
4260
|
id,
|
|
4259
4261
|
name,
|
|
4260
4262
|
scheduleKind: typeof record.scheduleKind === "string" ? record.scheduleKind : "",
|
|
4261
|
-
runAt:
|
|
4263
|
+
runAt: toMaybeString2(record.runAt),
|
|
4262
4264
|
intervalHours: toMaybeNumber(record.intervalHours),
|
|
4263
4265
|
byDay: Array.isArray(record.byDay) ? record.byDay.filter((entry) => typeof entry === "string") : [],
|
|
4264
4266
|
byHour: toMaybeNumber(record.byHour),
|
|
4265
4267
|
byMinute: toMaybeNumber(record.byMinute),
|
|
4266
4268
|
timezone: typeof record.timezone === "string" ? record.timezone : "UTC",
|
|
4267
4269
|
runtimeMode: typeof record.runtimeMode === "string" ? record.runtimeMode : "auto",
|
|
4268
|
-
runtimeProvider:
|
|
4270
|
+
runtimeProvider: toMaybeString2(record.runtimeProvider),
|
|
4269
4271
|
silentWhenNothingToReport: record.silentWhenNothingToReport === true,
|
|
4272
|
+
resultVisibility: record.resultVisibility === "team" ? "team" : "private",
|
|
4270
4273
|
status: typeof record.status === "string" ? record.status : "active",
|
|
4271
|
-
nextRunAt:
|
|
4272
|
-
lastRunAt:
|
|
4273
|
-
lastError:
|
|
4274
|
+
nextRunAt: toMaybeString2(record.nextRunAt),
|
|
4275
|
+
lastRunAt: toMaybeString2(record.lastRunAt),
|
|
4276
|
+
lastError: toMaybeString2(record.lastError)
|
|
4274
4277
|
};
|
|
4275
4278
|
}
|
|
4276
4279
|
function listToRecords(payload) {
|
|
@@ -4369,9 +4372,10 @@ async function automationsList(options) {
|
|
|
4369
4372
|
const status = record.status === "paused" ? kleur5.gray("paused") : kleur5.green("active");
|
|
4370
4373
|
const next = record.nextRunAt ? kleur5.cyan(record.nextRunAt) : kleur5.gray("n/a");
|
|
4371
4374
|
const delivery = record.silentWhenNothingToReport ? " \xB7 findings only" : "";
|
|
4375
|
+
const sharing = record.resultVisibility === "team" ? ` \xB7 ${kleur5.cyan("team-visible")}` : "";
|
|
4372
4376
|
console.log(`${kleur5.bold(record.name)} ${kleur5.gray(record.id)}`);
|
|
4373
4377
|
console.log(
|
|
4374
|
-
` ${schedule} \xB7 ${record.runtimeMode}${delivery} \xB7 ${status} \xB7 next ${next}`
|
|
4378
|
+
` ${schedule} \xB7 ${record.runtimeMode}${delivery}${sharing} \xB7 ${status} \xB7 next ${next}`
|
|
4375
4379
|
);
|
|
4376
4380
|
if (record.lastError) {
|
|
4377
4381
|
console.log(` ${kleur5.red(record.lastError)}`);
|
|
@@ -4399,6 +4403,7 @@ async function automationsCreate(options) {
|
|
|
4399
4403
|
runtimeMode: options.runtimeMode ?? "auto",
|
|
4400
4404
|
runtimeProvider: options.runtimeProvider?.trim() || void 0,
|
|
4401
4405
|
silentWhenNothingToReport: options.silentWhenNothingToReport ?? false,
|
|
4406
|
+
resultVisibility: options.resultVisibility ?? void 0,
|
|
4402
4407
|
status: options.paused ? "paused" : "active"
|
|
4403
4408
|
};
|
|
4404
4409
|
if (scheduleKind === "once") {
|
|
@@ -4435,6 +4440,138 @@ async function automationsCreate(options) {
|
|
|
4435
4440
|
}
|
|
4436
4441
|
console.log(`${kleur5.green("Created")} ${kleur5.bold(record.name)} (${record.id})`);
|
|
4437
4442
|
}
|
|
4443
|
+
var SCHEDULE_KINDS = /* @__PURE__ */ new Set(["weekly", "hourly", "once"]);
|
|
4444
|
+
var RUNTIME_MODES = /* @__PURE__ */ new Set(["auto", "hosted", "existing"]);
|
|
4445
|
+
var UPDATE_FIELD_FLAGS = "--name, --prompt, --prompt-file, --schedule-kind, --run-at, --interval-hours, --days, --time, --timezone, --runtime-mode, --runtime-provider, --silent-when-nothing-to-report, --no-silent-when-nothing-to-report, --share-results, --no-share-results, --result-visibility";
|
|
4446
|
+
function readUpdatePrompt(options, cwd) {
|
|
4447
|
+
const hasPrompt = typeof options.prompt === "string";
|
|
4448
|
+
const hasPromptFile = typeof options.promptFile === "string";
|
|
4449
|
+
if (hasPrompt && hasPromptFile) {
|
|
4450
|
+
throw new Error("Pass either --prompt or --prompt-file, not both");
|
|
4451
|
+
}
|
|
4452
|
+
if (hasPromptFile) {
|
|
4453
|
+
const promptPath = path7.resolve(cwd, (options.promptFile ?? "").trim());
|
|
4454
|
+
let raw;
|
|
4455
|
+
try {
|
|
4456
|
+
raw = fs6.readFileSync(promptPath, "utf8");
|
|
4457
|
+
} catch (error) {
|
|
4458
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
4459
|
+
throw new Error(`Unable to read --prompt-file ${promptPath}: ${message}`);
|
|
4460
|
+
}
|
|
4461
|
+
const promptText = raw.trim();
|
|
4462
|
+
if (!promptText) {
|
|
4463
|
+
throw new Error(`--prompt-file ${promptPath} is empty`);
|
|
4464
|
+
}
|
|
4465
|
+
return promptText;
|
|
4466
|
+
}
|
|
4467
|
+
if (hasPrompt) {
|
|
4468
|
+
const promptText = (options.prompt ?? "").trim();
|
|
4469
|
+
if (!promptText) {
|
|
4470
|
+
throw new Error("--prompt must not be empty");
|
|
4471
|
+
}
|
|
4472
|
+
return promptText;
|
|
4473
|
+
}
|
|
4474
|
+
return void 0;
|
|
4475
|
+
}
|
|
4476
|
+
function buildAutomationUpdateBody(options, cwd) {
|
|
4477
|
+
const body = {};
|
|
4478
|
+
if (typeof options.name === "string") {
|
|
4479
|
+
const name = options.name.trim();
|
|
4480
|
+
if (!name) {
|
|
4481
|
+
throw new Error("--name must not be empty");
|
|
4482
|
+
}
|
|
4483
|
+
body.name = name;
|
|
4484
|
+
}
|
|
4485
|
+
const promptText = readUpdatePrompt(options, cwd);
|
|
4486
|
+
if (promptText !== void 0) {
|
|
4487
|
+
body.promptText = promptText;
|
|
4488
|
+
}
|
|
4489
|
+
if (typeof options.scheduleKind === "string") {
|
|
4490
|
+
const scheduleKind = options.scheduleKind.trim().toLowerCase();
|
|
4491
|
+
if (!SCHEDULE_KINDS.has(scheduleKind)) {
|
|
4492
|
+
throw new Error("--schedule-kind must be weekly, hourly, or once");
|
|
4493
|
+
}
|
|
4494
|
+
body.scheduleKind = scheduleKind;
|
|
4495
|
+
}
|
|
4496
|
+
if (typeof options.runAt === "string") {
|
|
4497
|
+
const runAt = options.runAt.trim();
|
|
4498
|
+
if (!runAt) {
|
|
4499
|
+
throw new Error("--run-at must not be empty");
|
|
4500
|
+
}
|
|
4501
|
+
body.runAt = runAt;
|
|
4502
|
+
}
|
|
4503
|
+
if (options.intervalHours !== void 0) {
|
|
4504
|
+
const interval = Number(options.intervalHours);
|
|
4505
|
+
if (!Number.isFinite(interval) || interval < 1) {
|
|
4506
|
+
throw new Error("--interval-hours must be >= 1");
|
|
4507
|
+
}
|
|
4508
|
+
body.intervalHours = interval;
|
|
4509
|
+
}
|
|
4510
|
+
if (typeof options.days === "string") {
|
|
4511
|
+
body.byDay = normalizeDays(options.days);
|
|
4512
|
+
}
|
|
4513
|
+
if (typeof options.time === "string") {
|
|
4514
|
+
const { hour, minute } = parseTime(options.time);
|
|
4515
|
+
body.byHour = hour;
|
|
4516
|
+
body.byMinute = minute;
|
|
4517
|
+
}
|
|
4518
|
+
if (typeof options.timezone === "string") {
|
|
4519
|
+
const timezone = options.timezone.trim();
|
|
4520
|
+
if (!timezone) {
|
|
4521
|
+
throw new Error("--timezone must not be empty");
|
|
4522
|
+
}
|
|
4523
|
+
body.timezone = timezone;
|
|
4524
|
+
}
|
|
4525
|
+
if (typeof options.runtimeMode === "string") {
|
|
4526
|
+
const runtimeMode = options.runtimeMode.trim().toLowerCase();
|
|
4527
|
+
if (!RUNTIME_MODES.has(runtimeMode)) {
|
|
4528
|
+
throw new Error("--runtime-mode must be auto, hosted, or existing");
|
|
4529
|
+
}
|
|
4530
|
+
body.runtimeMode = runtimeMode;
|
|
4531
|
+
}
|
|
4532
|
+
if (typeof options.runtimeProvider === "string") {
|
|
4533
|
+
const runtimeProvider = options.runtimeProvider.trim();
|
|
4534
|
+
if (!runtimeProvider) {
|
|
4535
|
+
throw new Error("--runtime-provider must not be empty");
|
|
4536
|
+
}
|
|
4537
|
+
body.runtimeProvider = runtimeProvider;
|
|
4538
|
+
}
|
|
4539
|
+
if (typeof options.silentWhenNothingToReport === "boolean") {
|
|
4540
|
+
body.silentWhenNothingToReport = options.silentWhenNothingToReport;
|
|
4541
|
+
}
|
|
4542
|
+
if (options.resultVisibility !== void 0) {
|
|
4543
|
+
body.resultVisibility = options.resultVisibility;
|
|
4544
|
+
}
|
|
4545
|
+
return body;
|
|
4546
|
+
}
|
|
4547
|
+
async function automationsUpdate(options) {
|
|
4548
|
+
const automationId = normalizeUuidParam(options.automationId);
|
|
4549
|
+
if (!automationId) {
|
|
4550
|
+
throw new Error("automationId must be a UUID");
|
|
4551
|
+
}
|
|
4552
|
+
const cwd = options.cwd ?? process.cwd();
|
|
4553
|
+
const body = buildAutomationUpdateBody(options, cwd);
|
|
4554
|
+
if (Object.keys(body).length === 0) {
|
|
4555
|
+
throw new Error(`Nothing to update. Pass at least one of ${UPDATE_FIELD_FLAGS}.`);
|
|
4556
|
+
}
|
|
4557
|
+
const auth = resolveControllerAuth2(options, "instafy login");
|
|
4558
|
+
const payload = await controllerJsonRequest2(auth, "instafy login", {
|
|
4559
|
+
method: "PATCH",
|
|
4560
|
+
path: `/automations/${automationId}`,
|
|
4561
|
+
body
|
|
4562
|
+
});
|
|
4563
|
+
if (options.json) {
|
|
4564
|
+
console.log(JSON.stringify(payload, null, 2));
|
|
4565
|
+
return;
|
|
4566
|
+
}
|
|
4567
|
+
const record = normalizeAutomationRecord(payload);
|
|
4568
|
+
if (!record) {
|
|
4569
|
+
console.log(kleur5.green("Automation updated."));
|
|
4570
|
+
return;
|
|
4571
|
+
}
|
|
4572
|
+
const sharing = record.resultVisibility === "team" ? " \xB7 results shared with the team" : record.resultVisibility === "private" ? " \xB7 results kept private" : "";
|
|
4573
|
+
console.log(`${kleur5.green("Updated")} ${kleur5.bold(record.name)} (${record.id})${sharing}`);
|
|
4574
|
+
}
|
|
4438
4575
|
async function automationsUpdateStatus(options) {
|
|
4439
4576
|
const auth = resolveControllerAuth2(options, "instafy login");
|
|
4440
4577
|
const automationId = normalizeUuidParam(options.automationId);
|
|
@@ -4485,13 +4622,375 @@ async function automationsDelete(options) {
|
|
|
4485
4622
|
console.log(kleur5.green("Deleted."));
|
|
4486
4623
|
}
|
|
4487
4624
|
|
|
4625
|
+
// src/credentials.ts
|
|
4626
|
+
init_config();
|
|
4627
|
+
init_controller_fetch();
|
|
4628
|
+
init_errors();
|
|
4629
|
+
import kleur6 from "kleur";
|
|
4630
|
+
var promptsModule2 = null;
|
|
4631
|
+
async function loadPrompts2() {
|
|
4632
|
+
promptsModule2 ??= import("@clack/prompts");
|
|
4633
|
+
return promptsModule2;
|
|
4634
|
+
}
|
|
4635
|
+
var RETRY_COMMAND = "instafy login";
|
|
4636
|
+
var SHORT_ID_LENGTH = 8;
|
|
4637
|
+
var TEST_OUTPUT_PREVIEW_CHARS = 300;
|
|
4638
|
+
var CREDENTIAL_TEST_TIMEOUT_MS = 9e4;
|
|
4639
|
+
function resolveControllerAuth3(options) {
|
|
4640
|
+
const cwd = options.cwd ?? process.cwd();
|
|
4641
|
+
const controllerUrl = resolveControllerUrl({
|
|
4642
|
+
controllerUrl: options.controllerUrl ?? null,
|
|
4643
|
+
cwd
|
|
4644
|
+
});
|
|
4645
|
+
const resolved = resolveUserAccessTokenWithSource({
|
|
4646
|
+
accessToken: options.accessToken ?? null,
|
|
4647
|
+
cwd
|
|
4648
|
+
});
|
|
4649
|
+
if (!resolved.token) {
|
|
4650
|
+
throw formatAuthRequiredError({
|
|
4651
|
+
retryCommand: RETRY_COMMAND,
|
|
4652
|
+
advancedHint: "pass --access-token, or set INSTAFY_ACCESS_TOKEN / SUPABASE_ACCESS_TOKEN"
|
|
4653
|
+
});
|
|
4654
|
+
}
|
|
4655
|
+
return {
|
|
4656
|
+
controllerUrl,
|
|
4657
|
+
accessToken: resolved.token,
|
|
4658
|
+
tokenSource: resolved.source,
|
|
4659
|
+
profile: resolved.profile,
|
|
4660
|
+
cwd
|
|
4661
|
+
};
|
|
4662
|
+
}
|
|
4663
|
+
async function controllerJsonRequest3(auth, params) {
|
|
4664
|
+
const url = `${auth.controllerUrl.replace(/\/$/, "")}${params.path}`;
|
|
4665
|
+
const headers = new Headers();
|
|
4666
|
+
headers.set("accept", "application/json");
|
|
4667
|
+
const init = { method: params.method, headers };
|
|
4668
|
+
if (params.timeoutMs !== void 0) {
|
|
4669
|
+
init.signal = AbortSignal.timeout(params.timeoutMs);
|
|
4670
|
+
}
|
|
4671
|
+
const response = (await fetchWithControllerAuth({
|
|
4672
|
+
url,
|
|
4673
|
+
init,
|
|
4674
|
+
accessToken: auth.accessToken,
|
|
4675
|
+
tokenSource: auth.tokenSource,
|
|
4676
|
+
profile: auth.profile,
|
|
4677
|
+
cwd: auth.cwd
|
|
4678
|
+
})).response;
|
|
4679
|
+
const text = await response.text().catch(() => "");
|
|
4680
|
+
if (response.status === 401 || response.status === 403) {
|
|
4681
|
+
throw formatAuthRejectedError({
|
|
4682
|
+
status: response.status,
|
|
4683
|
+
responseBody: text,
|
|
4684
|
+
retryCommand: RETRY_COMMAND,
|
|
4685
|
+
advancedHint: "run `instafy login`, or pass --access-token"
|
|
4686
|
+
});
|
|
4687
|
+
}
|
|
4688
|
+
if (!response.ok) {
|
|
4689
|
+
throw new Error(`Request failed (${response.status} ${response.statusText}): ${text}`);
|
|
4690
|
+
}
|
|
4691
|
+
return text ? JSON.parse(text) : null;
|
|
4692
|
+
}
|
|
4693
|
+
function credentialTestTimeoutMs() {
|
|
4694
|
+
const configured = Number(process.env["INSTAFY_HTTP_TIMEOUT_MS"]);
|
|
4695
|
+
const base = Number.isFinite(configured) && configured > 0 ? configured : 0;
|
|
4696
|
+
return Math.max(base, CREDENTIAL_TEST_TIMEOUT_MS);
|
|
4697
|
+
}
|
|
4698
|
+
function toMaybeString(value) {
|
|
4699
|
+
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
4700
|
+
}
|
|
4701
|
+
function normalizeCredentialRecord(input3) {
|
|
4702
|
+
if (!input3 || typeof input3 !== "object")
|
|
4703
|
+
return null;
|
|
4704
|
+
const record = input3;
|
|
4705
|
+
const id = toMaybeString(record.id);
|
|
4706
|
+
if (!id)
|
|
4707
|
+
return null;
|
|
4708
|
+
const metadata = record.metadata && typeof record.metadata === "object" ? record.metadata : {};
|
|
4709
|
+
return {
|
|
4710
|
+
id,
|
|
4711
|
+
kind: toMaybeString(record.kind) ?? "unknown",
|
|
4712
|
+
label: toMaybeString(record.label),
|
|
4713
|
+
provider: toMaybeString(metadata.provider),
|
|
4714
|
+
defaultModel: toMaybeString(metadata.default_model),
|
|
4715
|
+
isDefault: record.isDefault === true,
|
|
4716
|
+
lastUsedAt: toMaybeString(record.lastUsedAt),
|
|
4717
|
+
revokedAt: toMaybeString(record.revokedAt),
|
|
4718
|
+
createdAt: toMaybeString(record.createdAt),
|
|
4719
|
+
updatedAt: toMaybeString(record.updatedAt)
|
|
4720
|
+
};
|
|
4721
|
+
}
|
|
4722
|
+
function listToRecords2(payload) {
|
|
4723
|
+
if (!Array.isArray(payload))
|
|
4724
|
+
return [];
|
|
4725
|
+
const out = [];
|
|
4726
|
+
for (const item of payload) {
|
|
4727
|
+
const normalized = normalizeCredentialRecord(item);
|
|
4728
|
+
if (normalized)
|
|
4729
|
+
out.push(normalized);
|
|
4730
|
+
}
|
|
4731
|
+
return out;
|
|
4732
|
+
}
|
|
4733
|
+
function normalizeTestResult(payload) {
|
|
4734
|
+
const record = payload && typeof payload === "object" ? payload : {};
|
|
4735
|
+
const elapsed = record.elapsedMs;
|
|
4736
|
+
return {
|
|
4737
|
+
ok: record.ok === true,
|
|
4738
|
+
provider: toMaybeString(record.provider),
|
|
4739
|
+
model: toMaybeString(record.model),
|
|
4740
|
+
output: typeof record.output === "string" ? record.output : null,
|
|
4741
|
+
upstreamEndpoint: toMaybeString(record.upstreamEndpoint),
|
|
4742
|
+
elapsedMs: typeof elapsed === "number" && Number.isFinite(elapsed) ? elapsed : null
|
|
4743
|
+
};
|
|
4744
|
+
}
|
|
4745
|
+
async function fetchCredentialRecords(auth) {
|
|
4746
|
+
const payload = await controllerJsonRequest3(auth, {
|
|
4747
|
+
method: "GET",
|
|
4748
|
+
path: "/me/credentials"
|
|
4749
|
+
});
|
|
4750
|
+
return listToRecords2(payload);
|
|
4751
|
+
}
|
|
4752
|
+
function shortCredentialId(id) {
|
|
4753
|
+
return id.slice(0, SHORT_ID_LENGTH);
|
|
4754
|
+
}
|
|
4755
|
+
function describeCredential(record) {
|
|
4756
|
+
const parts = [shortCredentialId(record.id), record.kind];
|
|
4757
|
+
if (record.provider)
|
|
4758
|
+
parts.push(record.provider);
|
|
4759
|
+
if (record.label)
|
|
4760
|
+
parts.push(`"${record.label}"`);
|
|
4761
|
+
if (record.revokedAt)
|
|
4762
|
+
parts.push("revoked");
|
|
4763
|
+
return parts.join(" \xB7 ");
|
|
4764
|
+
}
|
|
4765
|
+
function resolveCredentialRecord(records, idOrPrefix) {
|
|
4766
|
+
const needle = idOrPrefix.trim().toLowerCase();
|
|
4767
|
+
if (!needle) {
|
|
4768
|
+
throw new Error("Credential id is required. Run `instafy credentials list` to see ids.");
|
|
4769
|
+
}
|
|
4770
|
+
const exact = records.find((record) => record.id.toLowerCase() === needle);
|
|
4771
|
+
if (exact)
|
|
4772
|
+
return exact;
|
|
4773
|
+
const matches = records.filter((record) => record.id.toLowerCase().startsWith(needle));
|
|
4774
|
+
const active = matches.filter((record) => !record.revokedAt);
|
|
4775
|
+
if (active.length === 1) {
|
|
4776
|
+
return active[0];
|
|
4777
|
+
}
|
|
4778
|
+
if (active.length > 1) {
|
|
4779
|
+
const candidates = active.map((record) => ` ${describeCredential(record)}`).join("\n");
|
|
4780
|
+
throw new Error(
|
|
4781
|
+
`Credential id prefix "${idOrPrefix}" is ambiguous; it matches ${active.length} credentials:
|
|
4782
|
+
${candidates}
|
|
4783
|
+
|
|
4784
|
+
Use a longer prefix or the full id.`
|
|
4785
|
+
);
|
|
4786
|
+
}
|
|
4787
|
+
if (matches.length > 0) {
|
|
4788
|
+
throw new Error(
|
|
4789
|
+
`Credential "${idOrPrefix}" only matches revoked credentials. Run \`instafy credentials list --all\` to see them.`
|
|
4790
|
+
);
|
|
4791
|
+
}
|
|
4792
|
+
throw new Error(
|
|
4793
|
+
`No credential matches "${idOrPrefix}". Run \`instafy credentials list\` to see ids.`
|
|
4794
|
+
);
|
|
4795
|
+
}
|
|
4796
|
+
async function resolveCredential(auth, idOrPrefix) {
|
|
4797
|
+
const records = await fetchCredentialRecords(auth);
|
|
4798
|
+
return resolveCredentialRecord(records, idOrPrefix);
|
|
4799
|
+
}
|
|
4800
|
+
async function resolveActiveCredential(auth, idOrPrefix, action) {
|
|
4801
|
+
const record = await resolveCredential(auth, idOrPrefix);
|
|
4802
|
+
if (record.revokedAt) {
|
|
4803
|
+
throw new Error(
|
|
4804
|
+
`Credential ${describeCredential(record)} is revoked and cannot be ${action}. Run \`instafy credentials list\` to see active ids.`
|
|
4805
|
+
);
|
|
4806
|
+
}
|
|
4807
|
+
return record;
|
|
4808
|
+
}
|
|
4809
|
+
function formatTimestamp(value) {
|
|
4810
|
+
if (!value)
|
|
4811
|
+
return "never";
|
|
4812
|
+
const parsed = new Date(value);
|
|
4813
|
+
if (Number.isNaN(parsed.getTime()))
|
|
4814
|
+
return value;
|
|
4815
|
+
return `${parsed.toISOString().slice(0, 16).replace("T", " ")}Z`;
|
|
4816
|
+
}
|
|
4817
|
+
function truncateOutput(output2, limit) {
|
|
4818
|
+
const singleLine = output2.replace(/\s+/g, " ").trim();
|
|
4819
|
+
if (singleLine.length <= limit)
|
|
4820
|
+
return singleLine;
|
|
4821
|
+
return `${singleLine.slice(0, limit)}\u2026`;
|
|
4822
|
+
}
|
|
4823
|
+
function renderTable(headers, rows) {
|
|
4824
|
+
const widths = headers.map(
|
|
4825
|
+
(header, index) => Math.max(header.length, ...rows.map((row) => row[index]?.length ?? 0))
|
|
4826
|
+
);
|
|
4827
|
+
const line = (cells) => cells.map((cell, index) => cell.padEnd(widths[index])).join(" ").trimEnd();
|
|
4828
|
+
return [kleur6.bold(line(headers)), ...rows.map(line)].join("\n");
|
|
4829
|
+
}
|
|
4830
|
+
async function credentialsList(options) {
|
|
4831
|
+
const auth = resolveControllerAuth3(options);
|
|
4832
|
+
const records = await fetchCredentialRecords(auth);
|
|
4833
|
+
const visible = options.all ? records : records.filter((record) => !record.revokedAt);
|
|
4834
|
+
const hiddenRevoked = records.length - visible.length;
|
|
4835
|
+
if (options.json) {
|
|
4836
|
+
console.log(JSON.stringify(visible, null, 2));
|
|
4837
|
+
return;
|
|
4838
|
+
}
|
|
4839
|
+
if (visible.length === 0) {
|
|
4840
|
+
console.log(kleur6.gray(records.length === 0 ? "No credentials." : "No active credentials."));
|
|
4841
|
+
if (hiddenRevoked > 0) {
|
|
4842
|
+
console.log(kleur6.gray(`${hiddenRevoked} revoked hidden (use --all to show).`));
|
|
4843
|
+
}
|
|
4844
|
+
return;
|
|
4845
|
+
}
|
|
4846
|
+
const rows = visible.map((record) => [
|
|
4847
|
+
shortCredentialId(record.id),
|
|
4848
|
+
record.kind,
|
|
4849
|
+
record.provider ?? "-",
|
|
4850
|
+
record.defaultModel ?? "-",
|
|
4851
|
+
record.label ?? "-",
|
|
4852
|
+
record.isDefault ? "*" : "",
|
|
4853
|
+
formatTimestamp(record.lastUsedAt),
|
|
4854
|
+
record.revokedAt ? formatTimestamp(record.revokedAt) : ""
|
|
4855
|
+
]);
|
|
4856
|
+
console.log(
|
|
4857
|
+
renderTable(
|
|
4858
|
+
["ID", "KIND", "PROVIDER", "MODEL", "LABEL", "DEFAULT", "LAST USED", "REVOKED"],
|
|
4859
|
+
rows
|
|
4860
|
+
)
|
|
4861
|
+
);
|
|
4862
|
+
if (hiddenRevoked > 0) {
|
|
4863
|
+
console.log(kleur6.gray(`${hiddenRevoked} revoked hidden (use --all to show).`));
|
|
4864
|
+
}
|
|
4865
|
+
if (!visible.some((record) => record.isDefault && !record.revokedAt)) {
|
|
4866
|
+
console.log(
|
|
4867
|
+
kleur6.yellow(
|
|
4868
|
+
"No default credential. Jobs cannot pick one automatically; run `instafy credentials default <id>`."
|
|
4869
|
+
)
|
|
4870
|
+
);
|
|
4871
|
+
}
|
|
4872
|
+
}
|
|
4873
|
+
async function credentialsTest(options) {
|
|
4874
|
+
const auth = resolveControllerAuth3(options);
|
|
4875
|
+
const record = await resolveActiveCredential(auth, options.idOrPrefix, "tested");
|
|
4876
|
+
if (!options.json) {
|
|
4877
|
+
console.log(
|
|
4878
|
+
kleur6.gray(
|
|
4879
|
+
`Testing ${describeCredential(record)} through the proxy (this calls the upstream provider and may take up to a minute)\u2026`
|
|
4880
|
+
)
|
|
4881
|
+
);
|
|
4882
|
+
}
|
|
4883
|
+
const payload = await controllerJsonRequest3(auth, {
|
|
4884
|
+
method: "POST",
|
|
4885
|
+
path: `/me/credentials/${encodeURIComponent(record.id)}/test`,
|
|
4886
|
+
timeoutMs: credentialTestTimeoutMs()
|
|
4887
|
+
});
|
|
4888
|
+
const result = normalizeTestResult(payload);
|
|
4889
|
+
if (options.json) {
|
|
4890
|
+
console.log(JSON.stringify({ credentialId: record.id, ...result }, null, 2));
|
|
4891
|
+
return result;
|
|
4892
|
+
}
|
|
4893
|
+
const status = result.ok ? kleur6.green("ok") : kleur6.red("failed");
|
|
4894
|
+
console.log(`${status} ${shortCredentialId(record.id)}`);
|
|
4895
|
+
console.log(` provider ${result.provider ?? "-"} \xB7 model ${result.model ?? "-"}`);
|
|
4896
|
+
if (result.upstreamEndpoint) {
|
|
4897
|
+
console.log(` upstream ${result.upstreamEndpoint}`);
|
|
4898
|
+
}
|
|
4899
|
+
if (result.elapsedMs !== null) {
|
|
4900
|
+
console.log(` elapsed ${result.elapsedMs} ms`);
|
|
4901
|
+
}
|
|
4902
|
+
if (result.output) {
|
|
4903
|
+
const preview = truncateOutput(result.output, TEST_OUTPUT_PREVIEW_CHARS);
|
|
4904
|
+
console.log(` output ${result.ok ? preview : kleur6.red(preview)}`);
|
|
4905
|
+
}
|
|
4906
|
+
return result;
|
|
4907
|
+
}
|
|
4908
|
+
async function credentialsSetDefault(options) {
|
|
4909
|
+
const auth = resolveControllerAuth3(options);
|
|
4910
|
+
const record = await resolveActiveCredential(auth, options.idOrPrefix, "made the default");
|
|
4911
|
+
const payload = await controllerJsonRequest3(auth, {
|
|
4912
|
+
method: "POST",
|
|
4913
|
+
path: `/me/credentials/${encodeURIComponent(record.id)}/default`
|
|
4914
|
+
});
|
|
4915
|
+
const response = payload && typeof payload === "object" ? payload : {};
|
|
4916
|
+
if (options.json) {
|
|
4917
|
+
console.log(
|
|
4918
|
+
JSON.stringify(
|
|
4919
|
+
{
|
|
4920
|
+
ok: true,
|
|
4921
|
+
credentialId: toMaybeString(response.credentialId) ?? record.id,
|
|
4922
|
+
kind: toMaybeString(response.kind) ?? record.kind,
|
|
4923
|
+
isDefault: response.isDefault !== false
|
|
4924
|
+
},
|
|
4925
|
+
null,
|
|
4926
|
+
2
|
|
4927
|
+
)
|
|
4928
|
+
);
|
|
4929
|
+
return;
|
|
4930
|
+
}
|
|
4931
|
+
console.log(`${kleur6.green("Default set:")} ${describeCredential(record)}`);
|
|
4932
|
+
}
|
|
4933
|
+
async function credentialsClearDefault(options) {
|
|
4934
|
+
const auth = resolveControllerAuth3(options);
|
|
4935
|
+
await controllerJsonRequest3(auth, {
|
|
4936
|
+
method: "DELETE",
|
|
4937
|
+
path: "/me/credentials/default"
|
|
4938
|
+
});
|
|
4939
|
+
if (options.json) {
|
|
4940
|
+
console.log(JSON.stringify({ ok: true, hasDefaultCredential: false }, null, 2));
|
|
4941
|
+
return;
|
|
4942
|
+
}
|
|
4943
|
+
console.log(kleur6.green("Default cleared."));
|
|
4944
|
+
console.log(kleur6.gray("Jobs will not pick a credential automatically until you set a new default."));
|
|
4945
|
+
}
|
|
4946
|
+
async function confirmRevoke(record, json) {
|
|
4947
|
+
const interactive = Boolean(
|
|
4948
|
+
process.stdin.isTTY && process.stdout.isTTY && json !== true && process.env.CI !== "true"
|
|
4949
|
+
);
|
|
4950
|
+
if (!interactive) {
|
|
4951
|
+
throw new Error(
|
|
4952
|
+
`Refusing to revoke ${describeCredential(record)} without confirmation. Re-run with --yes.`
|
|
4953
|
+
);
|
|
4954
|
+
}
|
|
4955
|
+
const { confirm, isCancel } = await loadPrompts2();
|
|
4956
|
+
console.log(kleur6.yellow(`Revoke ${describeCredential(record)} (${record.id})?`));
|
|
4957
|
+
console.log(kleur6.gray("Agents bound to this credential are disconnected and jobs stop using it."));
|
|
4958
|
+
const answer = await confirm({ message: "Revoke this credential?", initialValue: false });
|
|
4959
|
+
if (isCancel(answer) || !answer) {
|
|
4960
|
+
throw new Error("Cancelled.");
|
|
4961
|
+
}
|
|
4962
|
+
}
|
|
4963
|
+
async function credentialsRevoke(options) {
|
|
4964
|
+
const auth = resolveControllerAuth3(options);
|
|
4965
|
+
const record = await resolveActiveCredential(auth, options.idOrPrefix, "revoked again");
|
|
4966
|
+
if (!options.yes) {
|
|
4967
|
+
await confirmRevoke(record, options.json);
|
|
4968
|
+
}
|
|
4969
|
+
await controllerJsonRequest3(auth, {
|
|
4970
|
+
method: "DELETE",
|
|
4971
|
+
path: `/me/credentials/${encodeURIComponent(record.id)}`
|
|
4972
|
+
});
|
|
4973
|
+
if (options.json) {
|
|
4974
|
+
console.log(JSON.stringify({ ok: true, credentialId: record.id }, null, 2));
|
|
4975
|
+
return;
|
|
4976
|
+
}
|
|
4977
|
+
console.log(`${kleur6.green("Revoked:")} ${describeCredential(record)}`);
|
|
4978
|
+
if (record.isDefault) {
|
|
4979
|
+
console.log(
|
|
4980
|
+
kleur6.yellow(
|
|
4981
|
+
"This was the default credential. Set a new one with `instafy credentials default <id>`."
|
|
4982
|
+
)
|
|
4983
|
+
);
|
|
4984
|
+
}
|
|
4985
|
+
}
|
|
4986
|
+
|
|
4488
4987
|
// src/tunnel.ts
|
|
4489
|
-
import
|
|
4988
|
+
import fs7 from "node:fs";
|
|
4490
4989
|
import os4 from "node:os";
|
|
4491
|
-
import
|
|
4990
|
+
import path8 from "node:path";
|
|
4492
4991
|
import { spawn as spawn3 } from "node:child_process";
|
|
4493
4992
|
import { randomUUID } from "node:crypto";
|
|
4494
|
-
import
|
|
4993
|
+
import kleur7 from "kleur";
|
|
4495
4994
|
init_config();
|
|
4496
4995
|
init_errors();
|
|
4497
4996
|
init_controller_fetch();
|
|
@@ -4551,10 +5050,10 @@ function resolveRuntimeBoundControllerUrl(credential, selectedControllerUrl) {
|
|
|
4551
5050
|
}
|
|
4552
5051
|
|
|
4553
5052
|
// src/tunnel.ts
|
|
4554
|
-
var INSTAFY_DIR3 =
|
|
4555
|
-
var TUNNEL_STATE_FILE =
|
|
4556
|
-
var TUNNEL_LOG_DIR =
|
|
4557
|
-
var TUNNEL_WORKDIR_DIR =
|
|
5053
|
+
var INSTAFY_DIR3 = path8.join(os4.homedir(), ".instafy");
|
|
5054
|
+
var TUNNEL_STATE_FILE = path8.join(INSTAFY_DIR3, "cli-tunnel-state.json");
|
|
5055
|
+
var TUNNEL_LOG_DIR = path8.join(INSTAFY_DIR3, "cli-tunnel-logs");
|
|
5056
|
+
var TUNNEL_WORKDIR_DIR = path8.join(INSTAFY_DIR3, "cli-tunnel-workdirs");
|
|
4558
5057
|
var RATHOLE_ENVIRONMENT_KEYS = [
|
|
4559
5058
|
"PATH",
|
|
4560
5059
|
"HOME",
|
|
@@ -4636,7 +5135,7 @@ function resolveProject(opts) {
|
|
|
4636
5135
|
);
|
|
4637
5136
|
}
|
|
4638
5137
|
function writeProjectManifest(manifestPath, manifest) {
|
|
4639
|
-
|
|
5138
|
+
fs7.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2), "utf8");
|
|
4640
5139
|
}
|
|
4641
5140
|
function resolveTunnelAlias(opts, projectId) {
|
|
4642
5141
|
const name = normalizeTunnelPurpose(opts.name?.trim() ?? "") ?? "web";
|
|
@@ -4678,7 +5177,7 @@ function persistTunnelAliasResult(config, hostname, url) {
|
|
|
4678
5177
|
if (!config.manifestPath)
|
|
4679
5178
|
return;
|
|
4680
5179
|
try {
|
|
4681
|
-
const raw =
|
|
5180
|
+
const raw = fs7.readFileSync(config.manifestPath, "utf8");
|
|
4682
5181
|
const parsed = JSON.parse(raw);
|
|
4683
5182
|
if (!parsed?.tunnels || typeof parsed.tunnels !== "object") {
|
|
4684
5183
|
return;
|
|
@@ -4752,7 +5251,7 @@ function resolvePort(opts) {
|
|
|
4752
5251
|
return opts.port ?? (Number.isFinite(parsedEnv) ? parsedEnv : 3e3);
|
|
4753
5252
|
}
|
|
4754
5253
|
function ensureDir(dir) {
|
|
4755
|
-
|
|
5254
|
+
fs7.mkdirSync(dir, { recursive: true });
|
|
4756
5255
|
}
|
|
4757
5256
|
function safePathSegment(value) {
|
|
4758
5257
|
const trimmed = value.trim();
|
|
@@ -4762,15 +5261,15 @@ function safePathSegment(value) {
|
|
|
4762
5261
|
}
|
|
4763
5262
|
function writeStateFile(state) {
|
|
4764
5263
|
ensureDir(INSTAFY_DIR3);
|
|
4765
|
-
|
|
5264
|
+
fs7.writeFileSync(TUNNEL_STATE_FILE, JSON.stringify(state, null, 2), "utf8");
|
|
4766
5265
|
try {
|
|
4767
|
-
|
|
5266
|
+
fs7.chmodSync(TUNNEL_STATE_FILE, 384);
|
|
4768
5267
|
} catch {
|
|
4769
5268
|
}
|
|
4770
5269
|
}
|
|
4771
5270
|
function readStateFile() {
|
|
4772
5271
|
try {
|
|
4773
|
-
const raw =
|
|
5272
|
+
const raw = fs7.readFileSync(TUNNEL_STATE_FILE, "utf8");
|
|
4774
5273
|
const parsed = JSON.parse(raw);
|
|
4775
5274
|
if (!parsed || typeof parsed !== "object")
|
|
4776
5275
|
return { version: 1, tunnels: [] };
|
|
@@ -4934,8 +5433,8 @@ async function startTunnelSession(opts) {
|
|
|
4934
5433
|
env: process.env,
|
|
4935
5434
|
version: process.env.RATHOLE_VERSION ?? null,
|
|
4936
5435
|
cacheDir: process.env.RATHOLE_CACHE_DIR ?? null,
|
|
4937
|
-
logger: (message) => console.log(
|
|
4938
|
-
warn: (message) => console.warn(
|
|
5436
|
+
logger: (message) => console.log(kleur7.cyan(`[rathole] ${message}`)),
|
|
5437
|
+
warn: (message) => console.warn(kleur7.yellow(message))
|
|
4939
5438
|
});
|
|
4940
5439
|
if (!rathole) {
|
|
4941
5440
|
throw new Error(
|
|
@@ -4947,9 +5446,9 @@ async function startTunnelSession(opts) {
|
|
|
4947
5446
|
persistTunnelAliasResult(alias, grant.hostname, grant.url ?? `https://${grant.hostname}`);
|
|
4948
5447
|
const creds = grant.credentials && typeof grant.credentials === "object" ? grant.credentials : {};
|
|
4949
5448
|
const configBody = buildRatholeConfig(creds, port);
|
|
4950
|
-
const workdir =
|
|
4951
|
-
const configPath2 =
|
|
4952
|
-
|
|
5449
|
+
const workdir = fs7.mkdtempSync(path8.join(os4.tmpdir(), "instafy-cli-tunnel-"));
|
|
5450
|
+
const configPath2 = path8.join(workdir, "rathole.toml");
|
|
5451
|
+
fs7.writeFileSync(configPath2, configBody, { encoding: "utf8", mode: 384 });
|
|
4953
5452
|
const child = spawn3(rathole, ["-c", configPath2], {
|
|
4954
5453
|
stdio: "inherit",
|
|
4955
5454
|
cwd: workdir,
|
|
@@ -4961,11 +5460,11 @@ async function startTunnelSession(opts) {
|
|
|
4961
5460
|
cleanedUp = true;
|
|
4962
5461
|
child.kill("SIGTERM");
|
|
4963
5462
|
await revokeTunnel(controllerUrl, controllerToken, projectId, grant.tunnelId);
|
|
4964
|
-
|
|
5463
|
+
fs7.rmSync(workdir, { recursive: true, force: true });
|
|
4965
5464
|
};
|
|
4966
5465
|
child.on("exit", () => {
|
|
4967
5466
|
void cleanup().catch((error) => {
|
|
4968
|
-
console.warn(
|
|
5467
|
+
console.warn(kleur7.yellow(`Tunnel cleanup failed: ${String(error)}`));
|
|
4969
5468
|
});
|
|
4970
5469
|
});
|
|
4971
5470
|
return {
|
|
@@ -4978,7 +5477,7 @@ async function startTunnelSession(opts) {
|
|
|
4978
5477
|
async function runTunnelCommand(opts, options) {
|
|
4979
5478
|
const session = await startTunnelSession(opts);
|
|
4980
5479
|
console.log(
|
|
4981
|
-
|
|
5480
|
+
kleur7.green(`Tunnel ready: ${session.url} (tunnelId=${session.tunnelId})`)
|
|
4982
5481
|
);
|
|
4983
5482
|
const timeoutMs = options?.timeoutMs ?? null;
|
|
4984
5483
|
await new Promise((resolve) => {
|
|
@@ -5012,8 +5511,8 @@ async function startTunnelDetached(opts) {
|
|
|
5012
5511
|
env: process.env,
|
|
5013
5512
|
version: process.env.RATHOLE_VERSION ?? null,
|
|
5014
5513
|
cacheDir: process.env.RATHOLE_CACHE_DIR ?? null,
|
|
5015
|
-
logger: (message) => console.log(
|
|
5016
|
-
warn: (message) => console.warn(
|
|
5514
|
+
logger: (message) => console.log(kleur7.cyan(`[rathole] ${message}`)),
|
|
5515
|
+
warn: (message) => console.warn(kleur7.yellow(message))
|
|
5017
5516
|
});
|
|
5018
5517
|
if (!rathole) {
|
|
5019
5518
|
throw new Error(
|
|
@@ -5026,14 +5525,14 @@ async function startTunnelDetached(opts) {
|
|
|
5026
5525
|
ensureDir(TUNNEL_WORKDIR_DIR);
|
|
5027
5526
|
ensureDir(TUNNEL_LOG_DIR);
|
|
5028
5527
|
const tunnelIdSafe = safePathSegment(grant.tunnelId);
|
|
5029
|
-
const workdir =
|
|
5528
|
+
const workdir = path8.join(TUNNEL_WORKDIR_DIR, tunnelIdSafe);
|
|
5030
5529
|
ensureDir(workdir);
|
|
5031
5530
|
const creds = grant.credentials && typeof grant.credentials === "object" ? grant.credentials : {};
|
|
5032
5531
|
const configBody = buildRatholeConfig(creds, port);
|
|
5033
|
-
const configPath2 =
|
|
5034
|
-
|
|
5035
|
-
const logFile = opts.logFile?.trim() ?
|
|
5036
|
-
const logFd =
|
|
5532
|
+
const configPath2 = path8.join(workdir, "rathole.toml");
|
|
5533
|
+
fs7.writeFileSync(configPath2, configBody, { encoding: "utf8", mode: 384 });
|
|
5534
|
+
const logFile = opts.logFile?.trim() ? path8.resolve(opts.logFile.trim()) : path8.join(TUNNEL_LOG_DIR, `tunnel-${tunnelIdSafe}.log`);
|
|
5535
|
+
const logFd = fs7.openSync(logFile, "a");
|
|
5037
5536
|
const child = spawn3(rathole, ["-c", configPath2], {
|
|
5038
5537
|
stdio: ["ignore", logFd, logFd],
|
|
5039
5538
|
cwd: workdir,
|
|
@@ -5050,7 +5549,7 @@ async function startTunnelDetached(opts) {
|
|
|
5050
5549
|
if (exitedEarly || !isProcessAlive2(child.pid ?? -1)) {
|
|
5051
5550
|
const logTail = (() => {
|
|
5052
5551
|
try {
|
|
5053
|
-
const text =
|
|
5552
|
+
const text = fs7.readFileSync(logFile, "utf8");
|
|
5054
5553
|
const lines = text.split(/\r?\n/).filter(Boolean);
|
|
5055
5554
|
return lines.slice(-20).join("\n");
|
|
5056
5555
|
} catch {
|
|
@@ -5133,7 +5632,7 @@ async function stopTunnelSession(opts) {
|
|
|
5133
5632
|
throw error;
|
|
5134
5633
|
}
|
|
5135
5634
|
try {
|
|
5136
|
-
|
|
5635
|
+
fs7.rmSync(entry.workdir, { recursive: true, force: true });
|
|
5137
5636
|
} catch {
|
|
5138
5637
|
}
|
|
5139
5638
|
return { ok: true, tunnelId: entry.tunnelId };
|
|
@@ -5165,7 +5664,7 @@ async function tailTunnelLogs(options) {
|
|
|
5165
5664
|
return;
|
|
5166
5665
|
}
|
|
5167
5666
|
if (!follow) {
|
|
5168
|
-
const raw =
|
|
5667
|
+
const raw = fs7.existsSync(logFile) ? fs7.readFileSync(logFile, "utf8") : "";
|
|
5169
5668
|
const rows = raw.split(/\r?\n/);
|
|
5170
5669
|
const tail = rows.slice(Math.max(0, rows.length - lineCount));
|
|
5171
5670
|
console.log(tail.join("\n"));
|
|
@@ -5194,7 +5693,7 @@ async function tailTunnelLogs(options) {
|
|
|
5194
5693
|
// src/config-command.ts
|
|
5195
5694
|
init_config();
|
|
5196
5695
|
init_config();
|
|
5197
|
-
import
|
|
5696
|
+
import kleur8 from "kleur";
|
|
5198
5697
|
function normalizeKey(raw) {
|
|
5199
5698
|
const key = raw.trim().toLowerCase().replace(/_/g, "-");
|
|
5200
5699
|
if (key === "controller-url" || key === "controllerurl" || key === "server-url") {
|
|
@@ -5238,12 +5737,12 @@ function clearConfig(key) {
|
|
|
5238
5737
|
}
|
|
5239
5738
|
}
|
|
5240
5739
|
function configPath(options) {
|
|
5241
|
-
const
|
|
5740
|
+
const path15 = getInstafyConfigPath();
|
|
5242
5741
|
if (options?.json) {
|
|
5243
|
-
console.log(JSON.stringify({ path:
|
|
5742
|
+
console.log(JSON.stringify({ path: path15 }, null, 2));
|
|
5244
5743
|
return;
|
|
5245
5744
|
}
|
|
5246
|
-
console.log(
|
|
5745
|
+
console.log(path15);
|
|
5247
5746
|
}
|
|
5248
5747
|
function configList(options) {
|
|
5249
5748
|
const config = readInstafyCliConfig();
|
|
@@ -5260,13 +5759,13 @@ function configList(options) {
|
|
|
5260
5759
|
console.log(JSON.stringify(payload, null, 2));
|
|
5261
5760
|
return;
|
|
5262
5761
|
}
|
|
5263
|
-
console.log(
|
|
5762
|
+
console.log(kleur8.green("Instafy CLI config"));
|
|
5264
5763
|
console.log(`Path: ${payload.path}`);
|
|
5265
|
-
console.log(`controller-url: ${payload.controllerUrl ??
|
|
5764
|
+
console.log(`controller-url: ${payload.controllerUrl ?? kleur8.yellow("(not set)")}`);
|
|
5266
5765
|
console.log(`controller-url (effective): ${payload.effectiveControllerUrl}`);
|
|
5267
|
-
console.log(`studio-url: ${payload.studioUrl ??
|
|
5268
|
-
console.log(`access-token: ${payload.accessTokenSet ?
|
|
5269
|
-
console.log(`refresh-token: ${payload.refreshTokenSet ?
|
|
5766
|
+
console.log(`studio-url: ${payload.studioUrl ?? kleur8.yellow("(not set)")}`);
|
|
5767
|
+
console.log(`access-token: ${payload.accessTokenSet ? kleur8.green("(set)") : kleur8.yellow("(not set)")}`);
|
|
5768
|
+
console.log(`refresh-token: ${payload.refreshTokenSet ? kleur8.green("(set)") : kleur8.yellow("(not set)")}`);
|
|
5270
5769
|
if (payload.updatedAt) {
|
|
5271
5770
|
console.log(`updated-at: ${payload.updatedAt}`);
|
|
5272
5771
|
}
|
|
@@ -5295,7 +5794,7 @@ function configSet(params) {
|
|
|
5295
5794
|
console.log(JSON.stringify({ key, value, path: getInstafyConfigPath() }, null, 2));
|
|
5296
5795
|
return;
|
|
5297
5796
|
}
|
|
5298
|
-
console.log(
|
|
5797
|
+
console.log(kleur8.green(`Set ${key}`));
|
|
5299
5798
|
console.log(value);
|
|
5300
5799
|
}
|
|
5301
5800
|
function configUnset(params) {
|
|
@@ -5305,7 +5804,7 @@ function configUnset(params) {
|
|
|
5305
5804
|
console.log(JSON.stringify({ ok: true, key }, null, 2));
|
|
5306
5805
|
return;
|
|
5307
5806
|
}
|
|
5308
|
-
console.log(
|
|
5807
|
+
console.log(kleur8.green(`Unset ${key}`));
|
|
5309
5808
|
}
|
|
5310
5809
|
|
|
5311
5810
|
// src/index.ts
|
|
@@ -5314,28 +5813,28 @@ init_config();
|
|
|
5314
5813
|
// src/git-wrapper.ts
|
|
5315
5814
|
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
5316
5815
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
5317
|
-
import
|
|
5318
|
-
import
|
|
5319
|
-
import
|
|
5816
|
+
import fs8 from "node:fs";
|
|
5817
|
+
import path9 from "node:path";
|
|
5818
|
+
import kleur9 from "kleur";
|
|
5320
5819
|
function pathExists(candidate) {
|
|
5321
5820
|
try {
|
|
5322
|
-
|
|
5821
|
+
fs8.statSync(candidate);
|
|
5323
5822
|
return true;
|
|
5324
5823
|
} catch {
|
|
5325
5824
|
return false;
|
|
5326
5825
|
}
|
|
5327
5826
|
}
|
|
5328
5827
|
function findInstafyGitContext(startDir) {
|
|
5329
|
-
let current =
|
|
5330
|
-
const root =
|
|
5828
|
+
let current = path9.resolve(startDir);
|
|
5829
|
+
const root = path9.parse(current).root;
|
|
5331
5830
|
while (true) {
|
|
5332
|
-
const gitDir =
|
|
5831
|
+
const gitDir = path9.join(current, ".instafy", ".git");
|
|
5333
5832
|
if (pathExists(gitDir)) {
|
|
5334
5833
|
return { workTree: current, gitDir };
|
|
5335
5834
|
}
|
|
5336
5835
|
if (current === root)
|
|
5337
5836
|
break;
|
|
5338
|
-
current =
|
|
5837
|
+
current = path9.dirname(current);
|
|
5339
5838
|
}
|
|
5340
5839
|
return null;
|
|
5341
5840
|
}
|
|
@@ -5382,9 +5881,9 @@ function validateGitArgs(userArgs) {
|
|
|
5382
5881
|
}
|
|
5383
5882
|
if (arg === "--git-dir" || arg.startsWith("--git-dir=") || arg === "--work-tree" || arg.startsWith("--work-tree=") || arg === "-C") {
|
|
5384
5883
|
throw new Error(
|
|
5385
|
-
`Unsupported argument "${arg}". Use ${
|
|
5884
|
+
`Unsupported argument "${arg}". Use ${kleur9.cyan(
|
|
5386
5885
|
"cd"
|
|
5387
|
-
)} instead; ${
|
|
5886
|
+
)} instead; ${kleur9.cyan("instafy git")} manages --git-dir/--work-tree automatically.`
|
|
5388
5887
|
);
|
|
5389
5888
|
}
|
|
5390
5889
|
if (arg === "-c" || arg === "--config-env" || arg === "--exec-path" || arg === "--namespace") {
|
|
@@ -5496,7 +5995,7 @@ function collectDirtyPaths(context, options) {
|
|
|
5496
5995
|
return unique;
|
|
5497
5996
|
}
|
|
5498
5997
|
function findEmbeddedGitDirs(context, pathSpecs) {
|
|
5499
|
-
const instafyGitDir =
|
|
5998
|
+
const instafyGitDir = path9.resolve(context.gitDir);
|
|
5500
5999
|
const seen = /* @__PURE__ */ new Set();
|
|
5501
6000
|
for (const rawPath of pathSpecs) {
|
|
5502
6001
|
const normalized = normalizePathSpec(rawPath).replace(/\/+$/, "");
|
|
@@ -5505,11 +6004,11 @@ function findEmbeddedGitDirs(context, pathSpecs) {
|
|
|
5505
6004
|
}
|
|
5506
6005
|
let cursor = normalized;
|
|
5507
6006
|
while (cursor && cursor !== ".") {
|
|
5508
|
-
const candidate =
|
|
5509
|
-
if (pathExists(candidate) &&
|
|
5510
|
-
seen.add(
|
|
6007
|
+
const candidate = path9.join(context.workTree, ...cursor.split("/"), ".git");
|
|
6008
|
+
if (pathExists(candidate) && path9.resolve(candidate) !== instafyGitDir) {
|
|
6009
|
+
seen.add(path9.resolve(candidate));
|
|
5511
6010
|
}
|
|
5512
|
-
const next =
|
|
6011
|
+
const next = path9.posix.dirname(cursor);
|
|
5513
6012
|
if (next === "." || next === cursor) {
|
|
5514
6013
|
break;
|
|
5515
6014
|
}
|
|
@@ -5518,8 +6017,8 @@ function findEmbeddedGitDirs(context, pathSpecs) {
|
|
|
5518
6017
|
}
|
|
5519
6018
|
const candidates = Array.from(seen);
|
|
5520
6019
|
candidates.sort((a, b) => {
|
|
5521
|
-
const depthA = a.split(
|
|
5522
|
-
const depthB = b.split(
|
|
6020
|
+
const depthA = a.split(path9.sep).length;
|
|
6021
|
+
const depthB = b.split(path9.sep).length;
|
|
5523
6022
|
return depthB - depthA;
|
|
5524
6023
|
});
|
|
5525
6024
|
return candidates;
|
|
@@ -5529,17 +6028,17 @@ function hideEmbeddedGitDirs(context, pathSpecs) {
|
|
|
5529
6028
|
if (candidates.length === 0) {
|
|
5530
6029
|
return [];
|
|
5531
6030
|
}
|
|
5532
|
-
const stagingBase =
|
|
5533
|
-
|
|
6031
|
+
const stagingBase = path9.join(context.workTree, ".instafy", "origin-staging", "embedded-git");
|
|
6032
|
+
fs8.mkdirSync(stagingBase, { recursive: true });
|
|
5534
6033
|
const renames = [];
|
|
5535
6034
|
for (const candidate of candidates) {
|
|
5536
|
-
let hidden =
|
|
6035
|
+
let hidden = path9.join(stagingBase, randomUUID2());
|
|
5537
6036
|
for (let attempt = 0; attempt < 8; attempt += 1) {
|
|
5538
6037
|
if (!pathExists(hidden))
|
|
5539
6038
|
break;
|
|
5540
|
-
hidden =
|
|
6039
|
+
hidden = path9.join(stagingBase, randomUUID2());
|
|
5541
6040
|
}
|
|
5542
|
-
|
|
6041
|
+
fs8.renameSync(candidate, hidden);
|
|
5543
6042
|
renames.push({ original: candidate, hidden });
|
|
5544
6043
|
}
|
|
5545
6044
|
return renames;
|
|
@@ -5550,7 +6049,7 @@ function restoreEmbeddedGitDirs(renames) {
|
|
|
5550
6049
|
if (!rename)
|
|
5551
6050
|
continue;
|
|
5552
6051
|
try {
|
|
5553
|
-
|
|
6052
|
+
fs8.renameSync(rename.hidden, rename.original);
|
|
5554
6053
|
} catch {
|
|
5555
6054
|
}
|
|
5556
6055
|
}
|
|
@@ -5620,15 +6119,15 @@ function runInstafyGit(userArgs, options) {
|
|
|
5620
6119
|
console.log("instafy git <git-args...>");
|
|
5621
6120
|
console.log("");
|
|
5622
6121
|
console.log(
|
|
5623
|
-
`Runs ${
|
|
6122
|
+
`Runs ${kleur9.cyan("git")} against the Instafy canonical repo at ${kleur9.cyan(
|
|
5624
6123
|
".instafy/.git"
|
|
5625
6124
|
)} (auto-detected by walking up from cwd).`
|
|
5626
6125
|
);
|
|
5627
6126
|
console.log("");
|
|
5628
6127
|
console.log("Example:");
|
|
5629
|
-
console.log(` ${
|
|
5630
|
-
console.log(` ${
|
|
5631
|
-
console.log(` ${
|
|
6128
|
+
console.log(` ${kleur9.cyan("instafy git status")}`);
|
|
6129
|
+
console.log(` ${kleur9.cyan("instafy git add -A")}`);
|
|
6130
|
+
console.log(` ${kleur9.cyan('instafy git commit -am "instafy: checkpoint"')}`);
|
|
5632
6131
|
return 0;
|
|
5633
6132
|
}
|
|
5634
6133
|
const context = findInstafyGitContext(cwd);
|
|
@@ -5638,8 +6137,8 @@ function runInstafyGit(userArgs, options) {
|
|
|
5638
6137
|
"No Instafy canonical git checkout found (expected .instafy/.git).",
|
|
5639
6138
|
"",
|
|
5640
6139
|
"Tips:",
|
|
5641
|
-
`- Run this inside a git-canonical workspace (where ${
|
|
5642
|
-
`- If you're trying to operate on a user repo, use normal ${
|
|
6140
|
+
`- Run this inside a git-canonical workspace (where ${kleur9.cyan(".instafy/.git")} exists).`,
|
|
6141
|
+
`- If you're trying to operate on a user repo, use normal ${kleur9.cyan("git")} (it uses .git).`
|
|
5643
6142
|
].join("\n")
|
|
5644
6143
|
);
|
|
5645
6144
|
}
|
|
@@ -5904,7 +6403,7 @@ async function runInstafyGitSync(args, options) {
|
|
|
5904
6403
|
}
|
|
5905
6404
|
} catch (error) {
|
|
5906
6405
|
const message = error instanceof Error ? error.message : String(error);
|
|
5907
|
-
console.warn(
|
|
6406
|
+
console.warn(kleur9.yellow(`[instafy git sync] ${message}; falling back to environment token.`));
|
|
5908
6407
|
}
|
|
5909
6408
|
}
|
|
5910
6409
|
if (!originToken) {
|
|
@@ -5952,7 +6451,7 @@ async function runInstafyGitSync(args, options) {
|
|
|
5952
6451
|
} catch (error) {
|
|
5953
6452
|
const message = error instanceof Error ? error.message : String(error);
|
|
5954
6453
|
console.warn(
|
|
5955
|
-
|
|
6454
|
+
kleur9.yellow(
|
|
5956
6455
|
`[instafy git sync] failed to recover from invalid origin token: ${message}`
|
|
5957
6456
|
)
|
|
5958
6457
|
);
|
|
@@ -5960,13 +6459,13 @@ async function runInstafyGitSync(args, options) {
|
|
|
5960
6459
|
}
|
|
5961
6460
|
if (!response.ok) {
|
|
5962
6461
|
const suffix = text.trim() ? `: ${text.trim()}` : "";
|
|
5963
|
-
console.error(
|
|
6462
|
+
console.error(kleur9.red(`Origin git sync failed (${response.status} ${response.statusText})${suffix}`));
|
|
5964
6463
|
return 1;
|
|
5965
6464
|
}
|
|
5966
6465
|
const payload = text.trim() ? JSON.parse(text) : null;
|
|
5967
6466
|
const rev = typeof payload?.rev === "string" ? payload.rev.trim() : "";
|
|
5968
6467
|
if (!rev) {
|
|
5969
|
-
console.error(
|
|
6468
|
+
console.error(kleur9.red("Origin git sync response missing rev field."));
|
|
5970
6469
|
return 1;
|
|
5971
6470
|
}
|
|
5972
6471
|
if (parsed.json) {
|
|
@@ -5981,7 +6480,7 @@ async function runInstafyGitSync(args, options) {
|
|
|
5981
6480
|
init_config();
|
|
5982
6481
|
init_errors();
|
|
5983
6482
|
init_controller_fetch();
|
|
5984
|
-
import
|
|
6483
|
+
import fs9 from "node:fs";
|
|
5985
6484
|
function normalizeUrl5(raw) {
|
|
5986
6485
|
const value = (raw ?? "").trim();
|
|
5987
6486
|
if (!value)
|
|
@@ -6060,7 +6559,7 @@ function parseHeader(raw) {
|
|
|
6060
6559
|
}
|
|
6061
6560
|
function parseJsonBody(options) {
|
|
6062
6561
|
if (options.jsonFile) {
|
|
6063
|
-
const raw =
|
|
6562
|
+
const raw = fs9.readFileSync(options.jsonFile, "utf8");
|
|
6064
6563
|
const parsed = JSON.parse(raw);
|
|
6065
6564
|
return JSON.stringify(parsed);
|
|
6066
6565
|
}
|
|
@@ -6298,9 +6797,9 @@ async function historyConversations(options) {
|
|
|
6298
6797
|
|
|
6299
6798
|
// src/hardware-bindings.ts
|
|
6300
6799
|
init_project_manifest();
|
|
6301
|
-
import
|
|
6302
|
-
import
|
|
6303
|
-
import
|
|
6800
|
+
import fs10 from "node:fs";
|
|
6801
|
+
import path10 from "node:path";
|
|
6802
|
+
import kleur10 from "kleur";
|
|
6304
6803
|
var SERIAL_HARDWARE_PROVIDER_ID = "hardware.serial";
|
|
6305
6804
|
var DEFAULT_SERIAL_CAPABILITIES = [
|
|
6306
6805
|
"hardware_serial_list",
|
|
@@ -6310,7 +6809,7 @@ var SUPPORTED_HARDWARE_CAPABILITIES = new Set(
|
|
|
6310
6809
|
DEFAULT_SERIAL_CAPABILITIES
|
|
6311
6810
|
);
|
|
6312
6811
|
function resolveHardwareBindingContext(startDir) {
|
|
6313
|
-
const lookup = findProjectManifest(
|
|
6812
|
+
const lookup = findProjectManifest(path10.resolve(startDir));
|
|
6314
6813
|
if (!lookup.manifest || !lookup.path) {
|
|
6315
6814
|
throw new Error(
|
|
6316
6815
|
"Linked space manifest required. Run `instafy space init` in this folder or pass --path <dir>."
|
|
@@ -6320,17 +6819,17 @@ function resolveHardwareBindingContext(startDir) {
|
|
|
6320
6819
|
if (!projectId) {
|
|
6321
6820
|
throw new Error("Linked space manifest is missing a spaceId.");
|
|
6322
6821
|
}
|
|
6323
|
-
const instafyDir =
|
|
6822
|
+
const instafyDir = path10.dirname(lookup.path);
|
|
6324
6823
|
return {
|
|
6325
|
-
bindingsPath:
|
|
6824
|
+
bindingsPath: path10.join(instafyDir, "hardware-bindings.json"),
|
|
6326
6825
|
projectId
|
|
6327
6826
|
};
|
|
6328
6827
|
}
|
|
6329
6828
|
function readHardwareBindingStore(bindingsPath) {
|
|
6330
|
-
if (!
|
|
6829
|
+
if (!fs10.existsSync(bindingsPath)) {
|
|
6331
6830
|
return { version: 1, bindings: {} };
|
|
6332
6831
|
}
|
|
6333
|
-
const raw = JSON.parse(
|
|
6832
|
+
const raw = JSON.parse(fs10.readFileSync(bindingsPath, "utf8"));
|
|
6334
6833
|
const bindings = raw && typeof raw.bindings === "object" && raw.bindings !== null ? raw.bindings : {};
|
|
6335
6834
|
return {
|
|
6336
6835
|
version: 1,
|
|
@@ -6338,8 +6837,8 @@ function readHardwareBindingStore(bindingsPath) {
|
|
|
6338
6837
|
};
|
|
6339
6838
|
}
|
|
6340
6839
|
function writeHardwareBindingStore(bindingsPath, store) {
|
|
6341
|
-
|
|
6342
|
-
|
|
6840
|
+
fs10.mkdirSync(path10.dirname(bindingsPath), { recursive: true });
|
|
6841
|
+
fs10.writeFileSync(bindingsPath, JSON.stringify(store, null, 2), "utf8");
|
|
6343
6842
|
}
|
|
6344
6843
|
function normalizeCapabilities(providerId, values) {
|
|
6345
6844
|
const requested = Array.isArray(values) && values.length > 0 ? values : providerId === SERIAL_HARDWARE_PROVIDER_ID ? DEFAULT_SERIAL_CAPABILITIES : [];
|
|
@@ -6367,18 +6866,18 @@ function normalizeDevices(values) {
|
|
|
6367
6866
|
if (!trimmed) {
|
|
6368
6867
|
continue;
|
|
6369
6868
|
}
|
|
6370
|
-
const resolved =
|
|
6869
|
+
const resolved = path10.resolve(trimmed);
|
|
6371
6870
|
unique.set(resolved, {
|
|
6372
6871
|
kind: "serial_device",
|
|
6373
6872
|
id: resolved,
|
|
6374
6873
|
path: resolved,
|
|
6375
|
-
displayName:
|
|
6874
|
+
displayName: path10.basename(resolved)
|
|
6376
6875
|
});
|
|
6377
6876
|
}
|
|
6378
6877
|
return [...unique.values()];
|
|
6379
6878
|
}
|
|
6380
6879
|
function printHardwareBinding(record) {
|
|
6381
|
-
console.log(
|
|
6880
|
+
console.log(kleur10.cyan(`Hardware provider: ${record.providerId}`));
|
|
6382
6881
|
console.log(`Status: ${record.status}`);
|
|
6383
6882
|
console.log(`Project: ${record.projectId}`);
|
|
6384
6883
|
console.log(`Capabilities: ${record.grantedCapabilities.join(", ") || "(none)"}`);
|
|
@@ -6424,10 +6923,10 @@ function showHardwareBinding(options) {
|
|
|
6424
6923
|
return;
|
|
6425
6924
|
}
|
|
6426
6925
|
if (bindings.length === 0) {
|
|
6427
|
-
console.log(
|
|
6926
|
+
console.log(kleur10.yellow("No hardware bindings recorded for this space."));
|
|
6428
6927
|
return;
|
|
6429
6928
|
}
|
|
6430
|
-
console.log(
|
|
6929
|
+
console.log(kleur10.cyan(`Hardware bindings for ${context.projectId}:`));
|
|
6431
6930
|
for (const record of bindings) {
|
|
6432
6931
|
console.log(`- ${record.providerId} (${record.status})`);
|
|
6433
6932
|
}
|
|
@@ -6460,9 +6959,9 @@ function grantHardwareBinding(options) {
|
|
|
6460
6959
|
console.log(JSON.stringify(record));
|
|
6461
6960
|
return;
|
|
6462
6961
|
}
|
|
6463
|
-
console.log(
|
|
6962
|
+
console.log(kleur10.green(`Hardware binding granted: ${providerId}`));
|
|
6464
6963
|
printHardwareBinding(record);
|
|
6465
|
-
console.log(
|
|
6964
|
+
console.log(kleur10.cyan(`Stored at ${context.bindingsPath}`));
|
|
6466
6965
|
}
|
|
6467
6966
|
function revokeHardwareBinding(options) {
|
|
6468
6967
|
const providerId = options.providerId.trim();
|
|
@@ -6481,12 +6980,12 @@ function revokeHardwareBinding(options) {
|
|
|
6481
6980
|
console.log(JSON.stringify({ revoked: true, providerId }));
|
|
6482
6981
|
return;
|
|
6483
6982
|
}
|
|
6484
|
-
console.log(
|
|
6485
|
-
console.log(
|
|
6983
|
+
console.log(kleur10.green(`Hardware binding revoked: ${providerId}`));
|
|
6984
|
+
console.log(kleur10.cyan(`Updated ${context.bindingsPath}`));
|
|
6486
6985
|
}
|
|
6487
6986
|
|
|
6488
6987
|
// src/agents.ts
|
|
6489
|
-
import
|
|
6988
|
+
import kleur11 from "kleur";
|
|
6490
6989
|
init_project_manifest();
|
|
6491
6990
|
var DEFAULT_CONTEXT_LIMIT = 50;
|
|
6492
6991
|
var MAX_CONTEXT_LIMIT = 200;
|
|
@@ -6597,16 +7096,16 @@ async function agentsList(options) {
|
|
|
6597
7096
|
return;
|
|
6598
7097
|
}
|
|
6599
7098
|
if (!agents.length) {
|
|
6600
|
-
console.log(
|
|
7099
|
+
console.log(kleur11.yellow("No agents found."));
|
|
6601
7100
|
return;
|
|
6602
7101
|
}
|
|
6603
|
-
console.log(
|
|
7102
|
+
console.log(kleur11.bold("Agents"));
|
|
6604
7103
|
for (const agent of agents) {
|
|
6605
7104
|
const provider = trimOrNull(agent.provider);
|
|
6606
7105
|
const model = trimOrNull(agent.model);
|
|
6607
7106
|
const details = [provider, model].filter(Boolean).join(" \xB7 ");
|
|
6608
7107
|
console.log(
|
|
6609
|
-
`- ${
|
|
7108
|
+
`- ${kleur11.cyan(`@${agent.handle}`)} ${displayName(agent)}${details ? ` (${details})` : ""}`
|
|
6610
7109
|
);
|
|
6611
7110
|
console.log(` id: ${agent.id}`);
|
|
6612
7111
|
}
|
|
@@ -6626,15 +7125,15 @@ async function agentContextsList(options) {
|
|
|
6626
7125
|
return;
|
|
6627
7126
|
}
|
|
6628
7127
|
if (!contexts.length) {
|
|
6629
|
-
console.log(
|
|
7128
|
+
console.log(kleur11.yellow("No agent context cards found."));
|
|
6630
7129
|
return;
|
|
6631
7130
|
}
|
|
6632
|
-
console.log(
|
|
7131
|
+
console.log(kleur11.bold("Agent context"));
|
|
6633
7132
|
for (const card of contexts) {
|
|
6634
7133
|
const title = trimOrNull(card.title);
|
|
6635
7134
|
const updatedAt = trimOrNull(card.updatedAt) ?? trimOrNull(card.updated_at);
|
|
6636
7135
|
console.log(
|
|
6637
|
-
`- ${
|
|
7136
|
+
`- ${kleur11.cyan(contextAgentLabel(card))} ${kleur11.gray(`[${contextScope(card)}]`)}${title ? ` ${title}` : ""}`
|
|
6638
7137
|
);
|
|
6639
7138
|
console.log(` ${summarize(card.context)}`);
|
|
6640
7139
|
if (updatedAt) {
|
|
@@ -6671,7 +7170,7 @@ async function agentContextPut(options) {
|
|
|
6671
7170
|
return;
|
|
6672
7171
|
}
|
|
6673
7172
|
console.log(
|
|
6674
|
-
`${
|
|
7173
|
+
`${kleur11.green("Saved")} ${kleur11.cyan(contextAgentLabel(saved))} context for ${kleur11.gray(contextScope(saved))}.`
|
|
6675
7174
|
);
|
|
6676
7175
|
}
|
|
6677
7176
|
function workerLabel(worker) {
|
|
@@ -6697,7 +7196,7 @@ async function agentPlanGroupStatus(options) {
|
|
|
6697
7196
|
console.log(JSON.stringify(status, null, 2));
|
|
6698
7197
|
return;
|
|
6699
7198
|
}
|
|
6700
|
-
console.log(
|
|
7199
|
+
console.log(kleur11.bold(`Plan group ${trimOrNull(status.groupId) ?? groupId}`));
|
|
6701
7200
|
const conversationId = trimOrNull(status.conversationId);
|
|
6702
7201
|
if (conversationId) {
|
|
6703
7202
|
console.log(` conversation: ${conversationId}`);
|
|
@@ -6707,13 +7206,13 @@ async function agentPlanGroupStatus(options) {
|
|
|
6707
7206
|
);
|
|
6708
7207
|
const workers = status.workers ?? [];
|
|
6709
7208
|
if (!workers.length) {
|
|
6710
|
-
console.log(
|
|
7209
|
+
console.log(kleur11.yellow("No worker jobs found."));
|
|
6711
7210
|
return;
|
|
6712
7211
|
}
|
|
6713
7212
|
for (const worker of workers) {
|
|
6714
7213
|
const marker = worker.terminal ? "terminal" : "running";
|
|
6715
7214
|
const details = [trimOrNull(worker.status) ?? "unknown", marker, trimOrNull(worker.outcome)].filter(Boolean).join(" \xB7 ");
|
|
6716
|
-
console.log(`- ${
|
|
7215
|
+
console.log(`- ${kleur11.cyan(workerLabel(worker))} ${kleur11.gray(`[${details}]`)}`);
|
|
6717
7216
|
const scope = trimOrNull(worker.scopeSummary);
|
|
6718
7217
|
if (scope) {
|
|
6719
7218
|
console.log(` scope: ${scope}`);
|
|
@@ -6724,7 +7223,7 @@ async function agentPlanGroupStatus(options) {
|
|
|
6724
7223
|
}
|
|
6725
7224
|
const errorMessage = trimOrNull(worker.errorMessage);
|
|
6726
7225
|
if (errorMessage) {
|
|
6727
|
-
console.log(` ${
|
|
7226
|
+
console.log(` ${kleur11.red(`error: ${summarize(errorMessage)}`)}`);
|
|
6728
7227
|
}
|
|
6729
7228
|
}
|
|
6730
7229
|
}
|
|
@@ -6751,11 +7250,11 @@ async function agentJobsCancel(options) {
|
|
|
6751
7250
|
const canceledJobs = result.canceledJobIds?.length ?? 0;
|
|
6752
7251
|
const canceledRuns = result.canceledRunIds?.length ?? 0;
|
|
6753
7252
|
if (!canceledJobs && !canceledRuns) {
|
|
6754
|
-
console.log(
|
|
7253
|
+
console.log(kleur11.yellow(`Nothing to cancel for ${target} (no queued or leased jobs).`));
|
|
6755
7254
|
return;
|
|
6756
7255
|
}
|
|
6757
7256
|
console.log(
|
|
6758
|
-
`${
|
|
7257
|
+
`${kleur11.green("Canceled")} ${canceledJobs} job(s) and ${canceledRuns} run(s) for ${target}.`
|
|
6759
7258
|
);
|
|
6760
7259
|
}
|
|
6761
7260
|
|
|
@@ -6800,17 +7299,17 @@ function extractMentionedAgentHandles(prompt) {
|
|
|
6800
7299
|
}
|
|
6801
7300
|
return handles;
|
|
6802
7301
|
}
|
|
6803
|
-
function buildPromptMetadata(prompt) {
|
|
7302
|
+
function buildPromptMetadata(prompt, intent) {
|
|
6804
7303
|
const mentionedHandles = extractMentionedAgentHandles(prompt);
|
|
7304
|
+
const metadata = intent.toLowerCase() === "terminal_command" ? {} : { writeIntent: true };
|
|
6805
7305
|
if (mentionedHandles.length === 0) {
|
|
6806
|
-
return
|
|
7306
|
+
return metadata;
|
|
6807
7307
|
}
|
|
6808
|
-
|
|
6809
|
-
|
|
6810
|
-
|
|
6811
|
-
mentions: mentionedHandles
|
|
6812
|
-
}
|
|
7308
|
+
metadata.agentSelection = {
|
|
7309
|
+
active: mentionedHandles,
|
|
7310
|
+
mentions: mentionedHandles
|
|
6813
7311
|
};
|
|
7312
|
+
return metadata;
|
|
6814
7313
|
}
|
|
6815
7314
|
function normalizeBooleanEnv(value) {
|
|
6816
7315
|
const normalized = value?.trim().toLowerCase();
|
|
@@ -6920,10 +7419,11 @@ async function sleep(ms) {
|
|
|
6920
7419
|
}
|
|
6921
7420
|
async function dispatchPrompt(options) {
|
|
6922
7421
|
const prompt = normalizePrompt(options.prompt);
|
|
7422
|
+
const intent = options.intent?.trim() || "feature";
|
|
6923
7423
|
const payload = {
|
|
6924
7424
|
promptText: prompt,
|
|
6925
|
-
intent
|
|
6926
|
-
metadata: buildPromptMetadata(prompt)
|
|
7425
|
+
intent,
|
|
7426
|
+
metadata: buildPromptMetadata(prompt, intent)
|
|
6927
7427
|
};
|
|
6928
7428
|
if (options.conversation?.trim()) {
|
|
6929
7429
|
const conversationId2 = options.conversation.trim();
|
|
@@ -7071,7 +7571,7 @@ async function chatPrompt(options) {
|
|
|
7071
7571
|
|
|
7072
7572
|
// src/conversations.ts
|
|
7073
7573
|
init_project_manifest();
|
|
7074
|
-
import
|
|
7574
|
+
import kleur12 from "kleur";
|
|
7075
7575
|
var DEFAULT_CONVERSATION_LIMIT = 50;
|
|
7076
7576
|
var DEFAULT_MESSAGE_LIMIT = 80;
|
|
7077
7577
|
var MAX_LIMIT = 200;
|
|
@@ -7298,7 +7798,7 @@ async function buildSearchMatches(conversations, options) {
|
|
|
7298
7798
|
}));
|
|
7299
7799
|
}
|
|
7300
7800
|
function formatConversationMatch(match) {
|
|
7301
|
-
const lines = [`- ${
|
|
7801
|
+
const lines = [`- ${kleur12.green(match.title)} (${match.id})`];
|
|
7302
7802
|
const details = [];
|
|
7303
7803
|
if (match.matchedIn.length > 0) {
|
|
7304
7804
|
details.push(`match: ${match.matchedIn.join(", ")}`);
|
|
@@ -7310,7 +7810,7 @@ function formatConversationMatch(match) {
|
|
|
7310
7810
|
lines.push(` ${details.join(" \xB7 ")}`);
|
|
7311
7811
|
}
|
|
7312
7812
|
if (match.preview) {
|
|
7313
|
-
lines.push(` ${
|
|
7813
|
+
lines.push(` ${kleur12.gray(summarizeContent(match.preview))}`);
|
|
7314
7814
|
}
|
|
7315
7815
|
return lines.join("\n");
|
|
7316
7816
|
}
|
|
@@ -7369,16 +7869,16 @@ async function createConversation(options) {
|
|
|
7369
7869
|
console.log(JSON.stringify(payload, null, 2));
|
|
7370
7870
|
return;
|
|
7371
7871
|
}
|
|
7372
|
-
console.log(
|
|
7373
|
-
console.log(`${
|
|
7872
|
+
console.log(kleur12.green("Created conversation"));
|
|
7873
|
+
console.log(`${kleur12.gray("ID:")} ${conversationId}`);
|
|
7374
7874
|
if (title) {
|
|
7375
|
-
console.log(`${
|
|
7875
|
+
console.log(`${kleur12.gray("Title:")} ${title}`);
|
|
7376
7876
|
}
|
|
7377
7877
|
if (parentConversationId) {
|
|
7378
|
-
console.log(`${
|
|
7878
|
+
console.log(`${kleur12.gray("Parent:")} ${parentConversationId}`);
|
|
7379
7879
|
}
|
|
7380
7880
|
if (threadKind) {
|
|
7381
|
-
console.log(`${
|
|
7881
|
+
console.log(`${kleur12.gray("Thread kind:")} ${threadKind}`);
|
|
7382
7882
|
}
|
|
7383
7883
|
}
|
|
7384
7884
|
async function listConversations(options) {
|
|
@@ -7405,10 +7905,10 @@ async function listConversations(options) {
|
|
|
7405
7905
|
return;
|
|
7406
7906
|
}
|
|
7407
7907
|
if (items.length === 0) {
|
|
7408
|
-
console.log(
|
|
7908
|
+
console.log(kleur12.yellow("No conversations found for this space."));
|
|
7409
7909
|
return;
|
|
7410
7910
|
}
|
|
7411
|
-
console.log(
|
|
7911
|
+
console.log(kleur12.green(`Conversations (${items.length})`));
|
|
7412
7912
|
for (const item of items) {
|
|
7413
7913
|
console.log(formatConversationMatch({ ...item, score: 0, matchedIn: [] }));
|
|
7414
7914
|
}
|
|
@@ -7430,10 +7930,10 @@ async function searchConversations(options) {
|
|
|
7430
7930
|
return matches;
|
|
7431
7931
|
}
|
|
7432
7932
|
if (matches.length === 0) {
|
|
7433
|
-
console.log(
|
|
7933
|
+
console.log(kleur12.yellow(`No conversations matched "${options.query}".`));
|
|
7434
7934
|
return matches;
|
|
7435
7935
|
}
|
|
7436
|
-
console.log(
|
|
7936
|
+
console.log(kleur12.green(`Matches for "${options.query}"`));
|
|
7437
7937
|
for (const match of matches.slice(0, Math.min(limit, matches.length))) {
|
|
7438
7938
|
console.log(formatConversationMatch(match));
|
|
7439
7939
|
}
|
|
@@ -7517,35 +8017,35 @@ async function showConversation(options) {
|
|
|
7517
8017
|
);
|
|
7518
8018
|
return;
|
|
7519
8019
|
}
|
|
7520
|
-
console.log(
|
|
7521
|
-
console.log(`${
|
|
8020
|
+
console.log(kleur12.green(selected.title));
|
|
8021
|
+
console.log(`${kleur12.gray("ID:")} ${selected.id}`);
|
|
7522
8022
|
if (selected.updatedAt) {
|
|
7523
|
-
console.log(`${
|
|
8023
|
+
console.log(`${kleur12.gray("Updated:")} ${selected.updatedAt}`);
|
|
7524
8024
|
}
|
|
7525
8025
|
if (selected.preview) {
|
|
7526
|
-
console.log(`${
|
|
8026
|
+
console.log(`${kleur12.gray("Preview:")} ${summarizeContent(selected.preview, 240)}`);
|
|
7527
8027
|
}
|
|
7528
8028
|
console.log("");
|
|
7529
8029
|
if (messages.length === 0) {
|
|
7530
|
-
console.log(
|
|
8030
|
+
console.log(kleur12.yellow("No messages found in this conversation."));
|
|
7531
8031
|
return;
|
|
7532
8032
|
}
|
|
7533
8033
|
for (const message of messages.slice().reverse()) {
|
|
7534
8034
|
const role = (message.role ?? "unknown").trim().toLowerCase();
|
|
7535
8035
|
const createdAt = trimOrNull2(message.createdAt) ?? trimOrNull2(message.created_at);
|
|
7536
8036
|
const header = createdAt ? `${role} \xB7 ${createdAt}` : role;
|
|
7537
|
-
console.log(
|
|
8037
|
+
console.log(kleur12.cyan(`[${header}]`));
|
|
7538
8038
|
console.log(summarizeContent(message.content ?? "", 4e3));
|
|
7539
8039
|
console.log("");
|
|
7540
8040
|
}
|
|
7541
8041
|
}
|
|
7542
8042
|
|
|
7543
8043
|
// src/invitations.ts
|
|
7544
|
-
import
|
|
7545
|
-
import
|
|
8044
|
+
import kleur13 from "kleur";
|
|
8045
|
+
import path11 from "node:path";
|
|
7546
8046
|
init_project_manifest();
|
|
7547
8047
|
function resolveStartDir(rawPath) {
|
|
7548
|
-
return
|
|
8048
|
+
return path11.resolve(rawPath ?? process.cwd());
|
|
7549
8049
|
}
|
|
7550
8050
|
function trimOrNull3(value) {
|
|
7551
8051
|
const trimmed = value?.trim() ?? "";
|
|
@@ -7687,7 +8187,7 @@ async function inviteSpaceMember(options) {
|
|
|
7687
8187
|
return normalized;
|
|
7688
8188
|
}
|
|
7689
8189
|
const scopeLabel = orgName ? `${orgName}` : "this space";
|
|
7690
|
-
console.log(
|
|
8190
|
+
console.log(kleur13.green(`Invitation sent to ${normalized.email}`));
|
|
7691
8191
|
console.log(`Scope: ${scopeLabel}`);
|
|
7692
8192
|
console.log(`Role: ${normalized.role}`);
|
|
7693
8193
|
if (normalized.expiresAt) {
|
|
@@ -7747,7 +8247,7 @@ async function setSpaceMemberRole(options) {
|
|
|
7747
8247
|
return normalized;
|
|
7748
8248
|
}
|
|
7749
8249
|
console.log(
|
|
7750
|
-
|
|
8250
|
+
kleur13.green(
|
|
7751
8251
|
normalized.status === "updated" ? `Updated ${normalized.email} to ${normalized.role}` : `${normalized.email} already has role ${normalized.role}`
|
|
7752
8252
|
)
|
|
7753
8253
|
);
|
|
@@ -7786,7 +8286,7 @@ async function setSpaceMemberRole(options) {
|
|
|
7786
8286
|
return normalized;
|
|
7787
8287
|
}
|
|
7788
8288
|
console.log(
|
|
7789
|
-
|
|
8289
|
+
kleur13.green(
|
|
7790
8290
|
normalized.status === "updated" ? `Updated pending invite for ${normalized.email} to ${normalized.role}` : `Pending invite for ${normalized.email} already has role ${normalized.role}`
|
|
7791
8291
|
)
|
|
7792
8292
|
);
|
|
@@ -7832,14 +8332,446 @@ async function sendSpaceInvitation(options) {
|
|
|
7832
8332
|
};
|
|
7833
8333
|
}
|
|
7834
8334
|
|
|
8335
|
+
// src/team.ts
|
|
8336
|
+
init_config();
|
|
8337
|
+
init_controller_fetch();
|
|
8338
|
+
init_errors();
|
|
8339
|
+
import kleur14 from "kleur";
|
|
8340
|
+
var DEFAULT_STUDIO_URL = "https://instafy.dev";
|
|
8341
|
+
var ORG_ROLES = ["owner", "admin", "builder", "viewer"];
|
|
8342
|
+
var INVITE_LINK_ROLES = ["builder", "viewer"];
|
|
8343
|
+
var UUID_PATTERN3 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
8344
|
+
var ControllerRequestError = class extends Error {
|
|
8345
|
+
constructor(status, serverMessage, message) {
|
|
8346
|
+
super(message);
|
|
8347
|
+
this.name = "ControllerRequestError";
|
|
8348
|
+
this.status = status;
|
|
8349
|
+
this.serverMessage = serverMessage;
|
|
8350
|
+
}
|
|
8351
|
+
};
|
|
8352
|
+
function normalizeBaseUrl(value) {
|
|
8353
|
+
const trimmed = typeof value === "string" ? value.trim() : "";
|
|
8354
|
+
if (!trimmed)
|
|
8355
|
+
return null;
|
|
8356
|
+
return trimmed.replace(/\/$/, "");
|
|
8357
|
+
}
|
|
8358
|
+
function isUuid3(value) {
|
|
8359
|
+
return UUID_PATTERN3.test(value.trim());
|
|
8360
|
+
}
|
|
8361
|
+
function requireUuid(value, label) {
|
|
8362
|
+
const trimmed = value?.trim() ?? "";
|
|
8363
|
+
if (!trimmed) {
|
|
8364
|
+
throw new Error(`${label} is required.`);
|
|
8365
|
+
}
|
|
8366
|
+
if (!isUuid3(trimmed)) {
|
|
8367
|
+
throw new Error(`${label} must be a UUID.`);
|
|
8368
|
+
}
|
|
8369
|
+
return trimmed;
|
|
8370
|
+
}
|
|
8371
|
+
function normalizeRole2(value, allowed, label) {
|
|
8372
|
+
const resolved = (value ?? "").trim().toLowerCase();
|
|
8373
|
+
if (!resolved) {
|
|
8374
|
+
throw new Error(`${label} is required.`);
|
|
8375
|
+
}
|
|
8376
|
+
if (!allowed.includes(resolved)) {
|
|
8377
|
+
throw new Error(`${label} must be one of ${allowed.join(", ")}.`);
|
|
8378
|
+
}
|
|
8379
|
+
return resolved;
|
|
8380
|
+
}
|
|
8381
|
+
function resolveControllerAuth4(options, retryCommand) {
|
|
8382
|
+
const cwd = options.cwd ?? process.cwd();
|
|
8383
|
+
const controllerUrl = resolveControllerUrl({
|
|
8384
|
+
controllerUrl: options.controllerUrl ?? null,
|
|
8385
|
+
cwd
|
|
8386
|
+
});
|
|
8387
|
+
const resolved = resolveUserAccessTokenWithSource({
|
|
8388
|
+
accessToken: options.accessToken ?? null,
|
|
8389
|
+
cwd
|
|
8390
|
+
});
|
|
8391
|
+
if (!resolved.token) {
|
|
8392
|
+
throw formatAuthRequiredError({
|
|
8393
|
+
retryCommand,
|
|
8394
|
+
advancedHint: "pass --access-token, or set INSTAFY_ACCESS_TOKEN / SUPABASE_ACCESS_TOKEN"
|
|
8395
|
+
});
|
|
8396
|
+
}
|
|
8397
|
+
return {
|
|
8398
|
+
controllerUrl,
|
|
8399
|
+
accessToken: resolved.token,
|
|
8400
|
+
tokenSource: resolved.source,
|
|
8401
|
+
profile: resolved.profile,
|
|
8402
|
+
cwd
|
|
8403
|
+
};
|
|
8404
|
+
}
|
|
8405
|
+
async function controllerJson(auth, retryCommand, params) {
|
|
8406
|
+
const url = `${auth.controllerUrl.replace(/\/$/, "")}${params.path}`;
|
|
8407
|
+
const headers = new Headers();
|
|
8408
|
+
headers.set("accept", "application/json");
|
|
8409
|
+
let bodyText;
|
|
8410
|
+
if (params.body !== void 0) {
|
|
8411
|
+
headers.set("content-type", "application/json");
|
|
8412
|
+
bodyText = JSON.stringify(params.body);
|
|
8413
|
+
}
|
|
8414
|
+
const response = (await fetchWithControllerAuth({
|
|
8415
|
+
url,
|
|
8416
|
+
init: {
|
|
8417
|
+
method: params.method,
|
|
8418
|
+
headers,
|
|
8419
|
+
body: bodyText
|
|
8420
|
+
},
|
|
8421
|
+
accessToken: auth.accessToken,
|
|
8422
|
+
tokenSource: auth.tokenSource,
|
|
8423
|
+
profile: auth.profile,
|
|
8424
|
+
cwd: auth.cwd
|
|
8425
|
+
})).response;
|
|
8426
|
+
const text = await response.text().catch(() => "");
|
|
8427
|
+
if (response.status === 401 || response.status === 403) {
|
|
8428
|
+
throw formatAuthRejectedError({
|
|
8429
|
+
status: response.status,
|
|
8430
|
+
responseBody: text,
|
|
8431
|
+
retryCommand,
|
|
8432
|
+
advancedHint: "run `instafy login`, or pass --access-token"
|
|
8433
|
+
});
|
|
8434
|
+
}
|
|
8435
|
+
if (!response.ok) {
|
|
8436
|
+
const serverMessage = extractControllerErrorMessage(text);
|
|
8437
|
+
throw new ControllerRequestError(
|
|
8438
|
+
response.status,
|
|
8439
|
+
serverMessage,
|
|
8440
|
+
`Request failed (${response.status} ${response.statusText})${serverMessage ? `: ${serverMessage}` : ""}`
|
|
8441
|
+
);
|
|
8442
|
+
}
|
|
8443
|
+
return text ? JSON.parse(text) : null;
|
|
8444
|
+
}
|
|
8445
|
+
async function fetchOrgs(auth) {
|
|
8446
|
+
const payload = await controllerJson(auth, "instafy team list", {
|
|
8447
|
+
method: "GET",
|
|
8448
|
+
path: "/orgs"
|
|
8449
|
+
});
|
|
8450
|
+
return Array.isArray(payload?.orgs) ? payload.orgs : [];
|
|
8451
|
+
}
|
|
8452
|
+
async function resolveTeamId(auth, teamOpt) {
|
|
8453
|
+
const raw = teamOpt?.trim();
|
|
8454
|
+
if (raw && isUuid3(raw)) {
|
|
8455
|
+
return raw;
|
|
8456
|
+
}
|
|
8457
|
+
const orgs = await fetchOrgs(auth);
|
|
8458
|
+
if (raw) {
|
|
8459
|
+
const bySlug = orgs.find(
|
|
8460
|
+
(org) => (org.slug ?? "").toLowerCase() === raw.toLowerCase()
|
|
8461
|
+
);
|
|
8462
|
+
if (bySlug)
|
|
8463
|
+
return bySlug.id;
|
|
8464
|
+
const byId = orgs.find((org) => org.id === raw);
|
|
8465
|
+
if (byId)
|
|
8466
|
+
return byId.id;
|
|
8467
|
+
throw new Error(
|
|
8468
|
+
`No team matches "${raw}". Run \`instafy team list\` to see the teams you belong to.`
|
|
8469
|
+
);
|
|
8470
|
+
}
|
|
8471
|
+
if (orgs.length === 1) {
|
|
8472
|
+
return orgs[0].id;
|
|
8473
|
+
}
|
|
8474
|
+
if (orgs.length === 0) {
|
|
8475
|
+
throw new Error(
|
|
8476
|
+
"No teams found for this account. Run `instafy team list` to see your teams."
|
|
8477
|
+
);
|
|
8478
|
+
}
|
|
8479
|
+
throw new Error(
|
|
8480
|
+
"Multiple teams found. Pass --team-id <uuid|slug>. Run `instafy team list` to see the options."
|
|
8481
|
+
);
|
|
8482
|
+
}
|
|
8483
|
+
function resolveStudioBaseUrl(auth, studioUrlOption) {
|
|
8484
|
+
return normalizeBaseUrl(studioUrlOption ?? null) ?? normalizeBaseUrl(process.env["INSTAFY_STUDIO_URL"] ?? null) ?? normalizeBaseUrl(
|
|
8485
|
+
resolveConfiguredStudioUrl({ profile: auth.profile, cwd: auth.cwd })
|
|
8486
|
+
) ?? DEFAULT_STUDIO_URL;
|
|
8487
|
+
}
|
|
8488
|
+
function shortId(value) {
|
|
8489
|
+
const trimmed = value.trim();
|
|
8490
|
+
return trimmed.length > 8 ? trimmed.slice(0, 8) : trimmed;
|
|
8491
|
+
}
|
|
8492
|
+
function printTable(headers, rows) {
|
|
8493
|
+
const widths = headers.map(
|
|
8494
|
+
(header, index) => Math.max(header.length, ...rows.map((row) => (row[index] ?? "").length))
|
|
8495
|
+
);
|
|
8496
|
+
const format = (cells) => cells.map((cell, index) => (cell ?? "").padEnd(widths[index])).join(" ").trimEnd();
|
|
8497
|
+
console.log(kleur14.bold(format(headers)));
|
|
8498
|
+
for (const row of rows) {
|
|
8499
|
+
console.log(format(row));
|
|
8500
|
+
}
|
|
8501
|
+
}
|
|
8502
|
+
async function teamMembersList(options) {
|
|
8503
|
+
const auth = resolveControllerAuth4(options, "instafy team members");
|
|
8504
|
+
const orgId = await resolveTeamId(auth, options.teamId);
|
|
8505
|
+
const payload = await controllerJson(auth, "instafy team members", {
|
|
8506
|
+
method: "GET",
|
|
8507
|
+
path: `/orgs/${encodeURIComponent(orgId)}/members`
|
|
8508
|
+
});
|
|
8509
|
+
const members = Array.isArray(payload?.members) ? payload.members : [];
|
|
8510
|
+
if (options.json) {
|
|
8511
|
+
console.log(
|
|
8512
|
+
JSON.stringify(
|
|
8513
|
+
{
|
|
8514
|
+
members,
|
|
8515
|
+
nextCursor: payload?.nextCursor ?? null,
|
|
8516
|
+
hasMore: payload?.hasMore ?? false,
|
|
8517
|
+
total: payload?.total
|
|
8518
|
+
},
|
|
8519
|
+
null,
|
|
8520
|
+
2
|
|
8521
|
+
)
|
|
8522
|
+
);
|
|
8523
|
+
return;
|
|
8524
|
+
}
|
|
8525
|
+
if (members.length === 0) {
|
|
8526
|
+
console.log(kleur14.gray("No members."));
|
|
8527
|
+
return;
|
|
8528
|
+
}
|
|
8529
|
+
const rows = members.map((member) => [
|
|
8530
|
+
shortId(member.userId),
|
|
8531
|
+
(member.email ?? "").trim() || "-",
|
|
8532
|
+
(member.fullName ?? "").trim() || "-",
|
|
8533
|
+
member.role,
|
|
8534
|
+
(member.createdAt ?? "").trim() || "-"
|
|
8535
|
+
]);
|
|
8536
|
+
printTable(["ID", "EMAIL", "NAME", "ROLE", "JOINED"], rows);
|
|
8537
|
+
}
|
|
8538
|
+
async function teamInvite(options) {
|
|
8539
|
+
const auth = resolveControllerAuth4(options, "instafy team invite");
|
|
8540
|
+
const email = options.email?.trim() ?? "";
|
|
8541
|
+
if (!email) {
|
|
8542
|
+
throw new Error("An email address is required.");
|
|
8543
|
+
}
|
|
8544
|
+
const role = options.role !== void 0 ? normalizeRole2(options.role, ORG_ROLES, "--role") : void 0;
|
|
8545
|
+
const orgId = await resolveTeamId(auth, options.teamId);
|
|
8546
|
+
const body = { email };
|
|
8547
|
+
if (role)
|
|
8548
|
+
body.role = role;
|
|
8549
|
+
let payload;
|
|
8550
|
+
try {
|
|
8551
|
+
payload = await controllerJson(auth, "instafy team invite", {
|
|
8552
|
+
method: "POST",
|
|
8553
|
+
path: `/orgs/${encodeURIComponent(orgId)}/invitations`,
|
|
8554
|
+
body
|
|
8555
|
+
});
|
|
8556
|
+
} catch (error) {
|
|
8557
|
+
if (error instanceof ControllerRequestError && error.status >= 400 && error.status < 500 && /already a member|already exists|already has access/i.test(
|
|
8558
|
+
error.serverMessage ?? ""
|
|
8559
|
+
)) {
|
|
8560
|
+
throw new Error(
|
|
8561
|
+
`${error.serverMessage}
|
|
8562
|
+
|
|
8563
|
+
If they already have an Instafy account, add them directly with:
|
|
8564
|
+
instafy team add-member --user-id <uuid>${options.teamId ? ` --team-id ${options.teamId}` : ""}`
|
|
8565
|
+
);
|
|
8566
|
+
}
|
|
8567
|
+
throw error;
|
|
8568
|
+
}
|
|
8569
|
+
const invitation = payload?.invitation;
|
|
8570
|
+
if (!invitation?.id) {
|
|
8571
|
+
throw new Error("Invitation response missing invitation details.");
|
|
8572
|
+
}
|
|
8573
|
+
if (options.json) {
|
|
8574
|
+
console.log(
|
|
8575
|
+
JSON.stringify(
|
|
8576
|
+
{ invitation, acceptUrl: payload?.acceptUrl ?? null },
|
|
8577
|
+
null,
|
|
8578
|
+
2
|
|
8579
|
+
)
|
|
8580
|
+
);
|
|
8581
|
+
return;
|
|
8582
|
+
}
|
|
8583
|
+
console.log(kleur14.green(`Invitation sent to ${invitation.email}`));
|
|
8584
|
+
console.log(`Role: ${invitation.role}`);
|
|
8585
|
+
if (invitation.expiresAt) {
|
|
8586
|
+
console.log(`Expires: ${invitation.expiresAt}`);
|
|
8587
|
+
}
|
|
8588
|
+
console.log("");
|
|
8589
|
+
console.log(
|
|
8590
|
+
`${invitation.email} must sign in to Instafy with this email address to accept the invitation.`
|
|
8591
|
+
);
|
|
8592
|
+
}
|
|
8593
|
+
async function teamInviteLink(options) {
|
|
8594
|
+
const auth = resolveControllerAuth4(options, "instafy team invite-link");
|
|
8595
|
+
const role = options.role !== void 0 ? normalizeRole2(options.role, INVITE_LINK_ROLES, "--role") : void 0;
|
|
8596
|
+
const orgId = await resolveTeamId(auth, options.teamId);
|
|
8597
|
+
const body = {};
|
|
8598
|
+
if (role)
|
|
8599
|
+
body.role = role;
|
|
8600
|
+
const payload = await controllerJson(auth, "instafy team invite-link", {
|
|
8601
|
+
method: "POST",
|
|
8602
|
+
path: `/orgs/${encodeURIComponent(orgId)}/invite-links`,
|
|
8603
|
+
body
|
|
8604
|
+
});
|
|
8605
|
+
const inviteLink = payload?.inviteLink;
|
|
8606
|
+
if (!inviteLink?.token || !inviteLink.acceptPath) {
|
|
8607
|
+
throw new Error("Invite link response missing link details.");
|
|
8608
|
+
}
|
|
8609
|
+
const studioBase = resolveStudioBaseUrl(auth, options.studioUrl);
|
|
8610
|
+
const acceptUrl = typeof payload?.acceptUrl === "string" && payload.acceptUrl.trim() || `${studioBase}${inviteLink.acceptPath}`;
|
|
8611
|
+
if (options.json) {
|
|
8612
|
+
console.log(JSON.stringify({ inviteLink, acceptUrl }, null, 2));
|
|
8613
|
+
return;
|
|
8614
|
+
}
|
|
8615
|
+
console.log(kleur14.green("Shareable invite link created."));
|
|
8616
|
+
console.log(`Role: ${inviteLink.role}`);
|
|
8617
|
+
console.log(`Link: ${acceptUrl}`);
|
|
8618
|
+
console.log(`Token: ${inviteLink.token}`);
|
|
8619
|
+
if (inviteLink.expiresAt) {
|
|
8620
|
+
console.log(`Expires: ${inviteLink.expiresAt}`);
|
|
8621
|
+
}
|
|
8622
|
+
console.log("");
|
|
8623
|
+
console.log(
|
|
8624
|
+
"Anyone who opens this link and signs in (with any sign-in method) can join the team. Treat it like a shared secret."
|
|
8625
|
+
);
|
|
8626
|
+
}
|
|
8627
|
+
async function teamInvites(options) {
|
|
8628
|
+
const auth = resolveControllerAuth4(options, "instafy team invites");
|
|
8629
|
+
const orgId = await resolveTeamId(auth, options.teamId);
|
|
8630
|
+
const [invitationsPayload, linksPayload] = await Promise.all([
|
|
8631
|
+
controllerJson(auth, "instafy team invites", {
|
|
8632
|
+
method: "GET",
|
|
8633
|
+
path: `/orgs/${encodeURIComponent(orgId)}/invitations`
|
|
8634
|
+
}),
|
|
8635
|
+
controllerJson(auth, "instafy team invites", {
|
|
8636
|
+
method: "GET",
|
|
8637
|
+
path: `/orgs/${encodeURIComponent(orgId)}/invite-links`
|
|
8638
|
+
})
|
|
8639
|
+
]);
|
|
8640
|
+
const invitations = Array.isArray(invitationsPayload?.invitations) ? invitationsPayload.invitations : [];
|
|
8641
|
+
const inviteLinks = Array.isArray(linksPayload?.inviteLinks) ? linksPayload.inviteLinks : [];
|
|
8642
|
+
if (options.json) {
|
|
8643
|
+
console.log(JSON.stringify({ invitations, inviteLinks }, null, 2));
|
|
8644
|
+
return;
|
|
8645
|
+
}
|
|
8646
|
+
if (invitations.length === 0 && inviteLinks.length === 0) {
|
|
8647
|
+
console.log(kleur14.gray("No pending invitations or invite links."));
|
|
8648
|
+
return;
|
|
8649
|
+
}
|
|
8650
|
+
if (invitations.length > 0) {
|
|
8651
|
+
console.log(kleur14.bold("Email invitations"));
|
|
8652
|
+
const rows = invitations.map((invitation) => [
|
|
8653
|
+
shortId(invitation.id),
|
|
8654
|
+
invitation.email,
|
|
8655
|
+
invitation.role,
|
|
8656
|
+
(invitation.expiresAt ?? "").trim() || "-"
|
|
8657
|
+
]);
|
|
8658
|
+
printTable(["ID", "EMAIL", "ROLE", "EXPIRES"], rows);
|
|
8659
|
+
}
|
|
8660
|
+
if (inviteLinks.length > 0) {
|
|
8661
|
+
if (invitations.length > 0)
|
|
8662
|
+
console.log("");
|
|
8663
|
+
console.log(kleur14.bold("Invite links (shareable, grant join on sign-in)"));
|
|
8664
|
+
const rows = inviteLinks.map((link) => [
|
|
8665
|
+
shortId(link.id),
|
|
8666
|
+
link.role,
|
|
8667
|
+
(link.status ?? "").trim() || "-",
|
|
8668
|
+
(link.expiresAt ?? "").trim() || "-"
|
|
8669
|
+
]);
|
|
8670
|
+
printTable(["ID", "ROLE", "STATUS", "EXPIRES"], rows);
|
|
8671
|
+
}
|
|
8672
|
+
}
|
|
8673
|
+
async function teamAddMember(options) {
|
|
8674
|
+
const auth = resolveControllerAuth4(options, "instafy team add-member");
|
|
8675
|
+
const userId = requireUuid(options.userId, "--user-id");
|
|
8676
|
+
const role = options.role !== void 0 ? normalizeRole2(options.role, ORG_ROLES, "--role") : void 0;
|
|
8677
|
+
const orgId = await resolveTeamId(auth, options.teamId);
|
|
8678
|
+
const body = { userId };
|
|
8679
|
+
if (role)
|
|
8680
|
+
body.role = role;
|
|
8681
|
+
const payload = await controllerJson(auth, "instafy team add-member", {
|
|
8682
|
+
method: "POST",
|
|
8683
|
+
path: `/orgs/${encodeURIComponent(orgId)}/members`,
|
|
8684
|
+
body
|
|
8685
|
+
});
|
|
8686
|
+
const member = payload?.member;
|
|
8687
|
+
if (!member?.userId) {
|
|
8688
|
+
throw new Error("Add member response missing member details.");
|
|
8689
|
+
}
|
|
8690
|
+
if (options.json) {
|
|
8691
|
+
console.log(JSON.stringify({ member }, null, 2));
|
|
8692
|
+
return;
|
|
8693
|
+
}
|
|
8694
|
+
const label = (member.email ?? "").trim() || member.userId;
|
|
8695
|
+
console.log(kleur14.green(`Added ${label} as ${member.role}.`));
|
|
8696
|
+
}
|
|
8697
|
+
async function teamAccept(options) {
|
|
8698
|
+
const auth = resolveControllerAuth4(options, "instafy team accept");
|
|
8699
|
+
const token = requireUuid(options.token, "token");
|
|
8700
|
+
const payload = await controllerJson(auth, "instafy team accept", {
|
|
8701
|
+
method: "POST",
|
|
8702
|
+
path: "/org-invitations/accept",
|
|
8703
|
+
body: { token }
|
|
8704
|
+
});
|
|
8705
|
+
if (options.json) {
|
|
8706
|
+
console.log(JSON.stringify(payload ?? {}, null, 2));
|
|
8707
|
+
return;
|
|
8708
|
+
}
|
|
8709
|
+
const name = (payload?.orgName ?? "").trim() || payload?.orgSlug || payload?.orgId || "team";
|
|
8710
|
+
console.log(kleur14.green(`Joined ${name} as ${payload?.role ?? "member"}.`));
|
|
8711
|
+
}
|
|
8712
|
+
async function confirmDestructive(message, yes, json) {
|
|
8713
|
+
if (yes)
|
|
8714
|
+
return;
|
|
8715
|
+
const input3 = process.stdin;
|
|
8716
|
+
const interactive = Boolean(
|
|
8717
|
+
input3.isTTY && process.stdout.isTTY && json !== true && process.env["CI"] !== "true"
|
|
8718
|
+
);
|
|
8719
|
+
if (!interactive) {
|
|
8720
|
+
throw new Error("Refusing to continue without confirmation. Re-run with --yes.");
|
|
8721
|
+
}
|
|
8722
|
+
const { confirm, isCancel } = await import("@clack/prompts");
|
|
8723
|
+
const proceed = await confirm({ message, initialValue: false });
|
|
8724
|
+
if (isCancel(proceed) || !proceed) {
|
|
8725
|
+
throw new Error("Cancelled.");
|
|
8726
|
+
}
|
|
8727
|
+
}
|
|
8728
|
+
async function teamRevokeInvite(options) {
|
|
8729
|
+
const auth = resolveControllerAuth4(options, "instafy team revoke-invite");
|
|
8730
|
+
const invitationId = requireUuid(options.invitationId, "invitation id");
|
|
8731
|
+
const orgId = await resolveTeamId(auth, options.teamId);
|
|
8732
|
+
await confirmDestructive(
|
|
8733
|
+
`Revoke pending invitation ${shortId(invitationId)}?`,
|
|
8734
|
+
options.yes,
|
|
8735
|
+
options.json
|
|
8736
|
+
);
|
|
8737
|
+
await controllerJson(auth, "instafy team revoke-invite", {
|
|
8738
|
+
method: "DELETE",
|
|
8739
|
+
path: `/orgs/${encodeURIComponent(orgId)}/invitations/${encodeURIComponent(invitationId)}`
|
|
8740
|
+
});
|
|
8741
|
+
if (options.json) {
|
|
8742
|
+
console.log(JSON.stringify({ ok: true, invitationId }, null, 2));
|
|
8743
|
+
return;
|
|
8744
|
+
}
|
|
8745
|
+
console.log(kleur14.green(`Revoked invitation ${invitationId}.`));
|
|
8746
|
+
}
|
|
8747
|
+
async function teamRevokeLink(options) {
|
|
8748
|
+
const auth = resolveControllerAuth4(options, "instafy team revoke-link");
|
|
8749
|
+
const inviteLinkId = requireUuid(options.inviteLinkId, "invite link id");
|
|
8750
|
+
const orgId = await resolveTeamId(auth, options.teamId);
|
|
8751
|
+
await confirmDestructive(
|
|
8752
|
+
`Revoke invite link ${shortId(inviteLinkId)}?`,
|
|
8753
|
+
options.yes,
|
|
8754
|
+
options.json
|
|
8755
|
+
);
|
|
8756
|
+
await controllerJson(auth, "instafy team revoke-link", {
|
|
8757
|
+
method: "DELETE",
|
|
8758
|
+
path: `/orgs/${encodeURIComponent(orgId)}/invite-links/${encodeURIComponent(inviteLinkId)}`
|
|
8759
|
+
});
|
|
8760
|
+
if (options.json) {
|
|
8761
|
+
console.log(JSON.stringify({ ok: true, inviteLinkId }, null, 2));
|
|
8762
|
+
return;
|
|
8763
|
+
}
|
|
8764
|
+
console.log(kleur14.green(`Revoked invite link ${inviteLinkId}.`));
|
|
8765
|
+
}
|
|
8766
|
+
|
|
7835
8767
|
// src/provider-bindings.ts
|
|
7836
8768
|
init_project_manifest();
|
|
7837
|
-
import
|
|
7838
|
-
import
|
|
8769
|
+
import fs11 from "node:fs";
|
|
8770
|
+
import path12 from "node:path";
|
|
7839
8771
|
import { pathToFileURL } from "node:url";
|
|
7840
|
-
import
|
|
8772
|
+
import kleur15 from "kleur";
|
|
7841
8773
|
function resolveBindingContext(startDir) {
|
|
7842
|
-
const lookup = findProjectManifest(
|
|
8774
|
+
const lookup = findProjectManifest(path12.resolve(startDir));
|
|
7843
8775
|
if (!lookup.manifest || !lookup.path) {
|
|
7844
8776
|
throw new Error(
|
|
7845
8777
|
"Linked space manifest required. Run `instafy space init` in this folder or pass --path <dir>."
|
|
@@ -7849,19 +8781,19 @@ function resolveBindingContext(startDir) {
|
|
|
7849
8781
|
if (!projectId) {
|
|
7850
8782
|
throw new Error("Linked space manifest is missing a spaceId.");
|
|
7851
8783
|
}
|
|
7852
|
-
const instafyDir =
|
|
7853
|
-
const projectRoot =
|
|
8784
|
+
const instafyDir = path12.dirname(lookup.path);
|
|
8785
|
+
const projectRoot = path12.dirname(instafyDir);
|
|
7854
8786
|
return {
|
|
7855
|
-
bindingsPath:
|
|
8787
|
+
bindingsPath: path12.join(instafyDir, "provider-bindings.json"),
|
|
7856
8788
|
projectId,
|
|
7857
8789
|
projectRoot
|
|
7858
8790
|
};
|
|
7859
8791
|
}
|
|
7860
8792
|
function readBindingStore(bindingsPath) {
|
|
7861
|
-
if (!
|
|
8793
|
+
if (!fs11.existsSync(bindingsPath)) {
|
|
7862
8794
|
return { version: 1, bindings: {} };
|
|
7863
8795
|
}
|
|
7864
|
-
const raw = JSON.parse(
|
|
8796
|
+
const raw = JSON.parse(fs11.readFileSync(bindingsPath, "utf8"));
|
|
7865
8797
|
const bindings = raw && typeof raw.bindings === "object" && raw.bindings !== null ? raw.bindings : {};
|
|
7866
8798
|
return {
|
|
7867
8799
|
version: 1,
|
|
@@ -7869,8 +8801,8 @@ function readBindingStore(bindingsPath) {
|
|
|
7869
8801
|
};
|
|
7870
8802
|
}
|
|
7871
8803
|
function writeBindingStore(bindingsPath, store) {
|
|
7872
|
-
|
|
7873
|
-
|
|
8804
|
+
fs11.mkdirSync(path12.dirname(bindingsPath), { recursive: true });
|
|
8805
|
+
fs11.writeFileSync(bindingsPath, JSON.stringify(store, null, 2), "utf8");
|
|
7874
8806
|
}
|
|
7875
8807
|
function normalizeCapabilities2(values) {
|
|
7876
8808
|
const requested = Array.isArray(values) && values.length > 0 ? values : ["project_content_read", "project_content_write"];
|
|
@@ -7893,7 +8825,7 @@ function deriveStatus(capabilities) {
|
|
|
7893
8825
|
return "bound_read_only";
|
|
7894
8826
|
}
|
|
7895
8827
|
function printBinding(record) {
|
|
7896
|
-
console.log(
|
|
8828
|
+
console.log(kleur15.cyan(`Provider: ${record.providerId}`));
|
|
7897
8829
|
console.log(`Status: ${record.status}`);
|
|
7898
8830
|
console.log(`Project: ${record.projectId}`);
|
|
7899
8831
|
console.log(`Root URI: ${record.rootUri}`);
|
|
@@ -7935,10 +8867,10 @@ function showProviderBinding(options) {
|
|
|
7935
8867
|
return;
|
|
7936
8868
|
}
|
|
7937
8869
|
if (bindings.length === 0) {
|
|
7938
|
-
console.log(
|
|
8870
|
+
console.log(kleur15.yellow("No provider bindings recorded for this space."));
|
|
7939
8871
|
return;
|
|
7940
8872
|
}
|
|
7941
|
-
console.log(
|
|
8873
|
+
console.log(kleur15.cyan(`Bindings for ${context.projectId}:`));
|
|
7942
8874
|
for (const record of bindings) {
|
|
7943
8875
|
console.log(`- ${record.providerId} (${record.status})`);
|
|
7944
8876
|
}
|
|
@@ -7970,9 +8902,9 @@ function grantProviderBinding(options) {
|
|
|
7970
8902
|
console.log(JSON.stringify(record));
|
|
7971
8903
|
return;
|
|
7972
8904
|
}
|
|
7973
|
-
console.log(
|
|
8905
|
+
console.log(kleur15.green(`Provider binding granted: ${providerId}`));
|
|
7974
8906
|
printBinding(record);
|
|
7975
|
-
console.log(
|
|
8907
|
+
console.log(kleur15.cyan(`Stored at ${context.bindingsPath}`));
|
|
7976
8908
|
}
|
|
7977
8909
|
function revokeProviderBinding(options) {
|
|
7978
8910
|
const providerId = options.providerId.trim();
|
|
@@ -7991,12 +8923,12 @@ function revokeProviderBinding(options) {
|
|
|
7991
8923
|
console.log(JSON.stringify({ revoked: true, providerId }));
|
|
7992
8924
|
return;
|
|
7993
8925
|
}
|
|
7994
|
-
console.log(
|
|
7995
|
-
console.log(
|
|
8926
|
+
console.log(kleur15.green(`Provider binding revoked: ${providerId}`));
|
|
8927
|
+
console.log(kleur15.cyan(`Updated ${context.bindingsPath}`));
|
|
7996
8928
|
}
|
|
7997
8929
|
|
|
7998
8930
|
// src/providers.ts
|
|
7999
|
-
import
|
|
8931
|
+
import kleur16 from "kleur";
|
|
8000
8932
|
|
|
8001
8933
|
// ../provider-client/index.js
|
|
8002
8934
|
var DEFAULT_PROVIDER_HOST_BASE_URL = "http://127.0.0.1:8797";
|
|
@@ -8068,12 +9000,12 @@ function resolveFetchImplementation(fetchImpl) {
|
|
|
8068
9000
|
function createProviderHostClient(options = {}) {
|
|
8069
9001
|
const fetchImpl = resolveFetchImplementation(options.fetch);
|
|
8070
9002
|
const baseUrl = normalizeProviderHostBaseUrl(options.baseUrl);
|
|
8071
|
-
async function jsonRequest(
|
|
8072
|
-
const response = await fetchImpl(`${baseUrl}${
|
|
9003
|
+
async function jsonRequest(path15, init) {
|
|
9004
|
+
const response = await fetchImpl(`${baseUrl}${path15}`, init);
|
|
8073
9005
|
const json = await response.json();
|
|
8074
9006
|
if (!response.ok || json?.ok === false) {
|
|
8075
9007
|
throw new Error(
|
|
8076
|
-
json?.error || json?.stderr || `provider host request failed for ${
|
|
9008
|
+
json?.error || json?.stderr || `provider host request failed for ${path15}`
|
|
8077
9009
|
);
|
|
8078
9010
|
}
|
|
8079
9011
|
return json;
|
|
@@ -8166,7 +9098,7 @@ function formatProviderLabel(provider) {
|
|
|
8166
9098
|
return provider.title?.trim().length ? provider.title.trim() : provider.id;
|
|
8167
9099
|
}
|
|
8168
9100
|
function printProviderSummary(provider) {
|
|
8169
|
-
console.log(
|
|
9101
|
+
console.log(kleur16.green(formatProviderLabel(provider)));
|
|
8170
9102
|
console.log(` id: ${provider.id}`);
|
|
8171
9103
|
if (provider.description) {
|
|
8172
9104
|
console.log(` description: ${provider.description}`);
|
|
@@ -8178,7 +9110,7 @@ function printProviderSummary(provider) {
|
|
|
8178
9110
|
console.log(` type: ${provider.providerType}`);
|
|
8179
9111
|
}
|
|
8180
9112
|
console.log(
|
|
8181
|
-
` discoverable: ${provider.discoverable !== false ?
|
|
9113
|
+
` discoverable: ${provider.discoverable !== false ? kleur16.green("yes") : kleur16.yellow("no")}`
|
|
8182
9114
|
);
|
|
8183
9115
|
if (provider.capabilityIds?.length) {
|
|
8184
9116
|
console.log(` capabilities: ${provider.capabilityIds.join(", ")}`);
|
|
@@ -8190,7 +9122,7 @@ function printProviderSummary(provider) {
|
|
|
8190
9122
|
console.log(` resources: ${provider.resourceUris.join(", ")}`);
|
|
8191
9123
|
}
|
|
8192
9124
|
if (provider.error) {
|
|
8193
|
-
console.log(` error: ${
|
|
9125
|
+
console.log(` error: ${kleur16.yellow(provider.error)}`);
|
|
8194
9126
|
}
|
|
8195
9127
|
}
|
|
8196
9128
|
function parseCommandJson(commandJson) {
|
|
@@ -8210,10 +9142,10 @@ async function providersList(options = {}) {
|
|
|
8210
9142
|
});
|
|
8211
9143
|
return;
|
|
8212
9144
|
}
|
|
8213
|
-
console.log(
|
|
9145
|
+
console.log(kleur16.green("Local providers"));
|
|
8214
9146
|
console.log(`Host: ${providerHostUrl}`);
|
|
8215
9147
|
if (!result.providers.length) {
|
|
8216
|
-
console.log(
|
|
9148
|
+
console.log(kleur16.yellow("No providers discovered."));
|
|
8217
9149
|
return;
|
|
8218
9150
|
}
|
|
8219
9151
|
for (const provider of result.providers) {
|
|
@@ -8230,7 +9162,7 @@ async function providersDiscover(params) {
|
|
|
8230
9162
|
});
|
|
8231
9163
|
return;
|
|
8232
9164
|
}
|
|
8233
|
-
console.log(
|
|
9165
|
+
console.log(kleur16.green(`Provider discovery: ${params.providerId}`));
|
|
8234
9166
|
console.log(`Host: ${providerHostUrl}`);
|
|
8235
9167
|
console.log(JSON.stringify(result.provider ?? result, null, 2));
|
|
8236
9168
|
}
|
|
@@ -8244,10 +9176,10 @@ async function providersRead(params) {
|
|
|
8244
9176
|
});
|
|
8245
9177
|
return;
|
|
8246
9178
|
}
|
|
8247
|
-
console.log(
|
|
9179
|
+
console.log(kleur16.green(`Provider resource: ${params.uri}`));
|
|
8248
9180
|
console.log(`Host: ${providerHostUrl}`);
|
|
8249
9181
|
if (result.exists === false) {
|
|
8250
|
-
console.log(
|
|
9182
|
+
console.log(kleur16.yellow("Resource does not exist."));
|
|
8251
9183
|
return;
|
|
8252
9184
|
}
|
|
8253
9185
|
console.log(JSON.stringify(result.value ?? result, null, 2));
|
|
@@ -8273,7 +9205,7 @@ async function providersProbe(params) {
|
|
|
8273
9205
|
});
|
|
8274
9206
|
return;
|
|
8275
9207
|
}
|
|
8276
|
-
console.log(
|
|
9208
|
+
console.log(kleur16.green(`Provider transport probe: ${params.providerId}`));
|
|
8277
9209
|
console.log(`Host: ${providerHostUrl}`);
|
|
8278
9210
|
console.log(JSON.stringify(result, null, 2));
|
|
8279
9211
|
}
|
|
@@ -8479,8 +9411,8 @@ async function diagnosticsRunResult(options) {
|
|
|
8479
9411
|
}
|
|
8480
9412
|
|
|
8481
9413
|
// src/support.ts
|
|
8482
|
-
import
|
|
8483
|
-
import
|
|
9414
|
+
import fs12 from "node:fs";
|
|
9415
|
+
import path13 from "node:path";
|
|
8484
9416
|
init_project_manifest();
|
|
8485
9417
|
var MAX_SUMMARY_CHARS = 500;
|
|
8486
9418
|
var MAX_DETAILS_BYTES = 2e4;
|
|
@@ -8494,34 +9426,34 @@ function cleanText3(value) {
|
|
|
8494
9426
|
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
8495
9427
|
}
|
|
8496
9428
|
function readRegularFile(filePath, maxBytes, label) {
|
|
8497
|
-
const resolved =
|
|
9429
|
+
const resolved = path13.resolve(filePath);
|
|
8498
9430
|
const manifestPath = findProjectManifest(process.cwd()).path;
|
|
8499
|
-
const workspaceRoot = manifestPath ?
|
|
8500
|
-
const canonicalRoot =
|
|
8501
|
-
const canonicalParent =
|
|
8502
|
-
const canonicalTarget =
|
|
8503
|
-
const relativeTarget =
|
|
8504
|
-
if (relativeTarget === ".." || relativeTarget.startsWith(`..${
|
|
9431
|
+
const workspaceRoot = manifestPath ? path13.dirname(path13.dirname(manifestPath)) : process.cwd();
|
|
9432
|
+
const canonicalRoot = fs12.realpathSync(workspaceRoot);
|
|
9433
|
+
const canonicalParent = fs12.realpathSync(path13.dirname(resolved));
|
|
9434
|
+
const canonicalTarget = path13.join(canonicalParent, path13.basename(resolved));
|
|
9435
|
+
const relativeTarget = path13.relative(canonicalRoot, canonicalTarget);
|
|
9436
|
+
if (relativeTarget === ".." || relativeTarget.startsWith(`..${path13.sep}`) || path13.isAbsolute(relativeTarget)) {
|
|
8505
9437
|
throw new Error(`${label} must stay inside the active Instafy workspace.`);
|
|
8506
9438
|
}
|
|
8507
|
-
const initialStat =
|
|
9439
|
+
const initialStat = fs12.lstatSync(canonicalTarget);
|
|
8508
9440
|
if (initialStat.isSymbolicLink() || !initialStat.isFile()) {
|
|
8509
9441
|
throw new Error(`${label} must be a regular file, not a symlink.`);
|
|
8510
9442
|
}
|
|
8511
|
-
const noFollow = typeof
|
|
8512
|
-
const descriptor =
|
|
9443
|
+
const noFollow = typeof fs12.constants.O_NOFOLLOW === "number" ? fs12.constants.O_NOFOLLOW : 0;
|
|
9444
|
+
const descriptor = fs12.openSync(canonicalTarget, fs12.constants.O_RDONLY | noFollow);
|
|
8513
9445
|
try {
|
|
8514
|
-
const openedStat =
|
|
9446
|
+
const openedStat = fs12.fstatSync(descriptor);
|
|
8515
9447
|
if (!openedStat.isFile() || openedStat.dev !== initialStat.dev || openedStat.ino !== initialStat.ino || openedStat.size > maxBytes) {
|
|
8516
9448
|
throw new Error(`${label} must be a regular file no larger than ${maxBytes} bytes.`);
|
|
8517
9449
|
}
|
|
8518
|
-
const bytes =
|
|
9450
|
+
const bytes = fs12.readFileSync(descriptor);
|
|
8519
9451
|
if (bytes.length > maxBytes) {
|
|
8520
9452
|
throw new Error(`${label} must be ${maxBytes} bytes or smaller.`);
|
|
8521
9453
|
}
|
|
8522
9454
|
return bytes;
|
|
8523
9455
|
} finally {
|
|
8524
|
-
|
|
9456
|
+
fs12.closeSync(descriptor);
|
|
8525
9457
|
}
|
|
8526
9458
|
}
|
|
8527
9459
|
function readJsonFile(filePath, maxBytes, label) {
|
|
@@ -8597,7 +9529,7 @@ function resolveScreenshots(filePaths = []) {
|
|
|
8597
9529
|
);
|
|
8598
9530
|
}
|
|
8599
9531
|
return {
|
|
8600
|
-
fileName:
|
|
9532
|
+
fileName: path13.basename(filePath),
|
|
8601
9533
|
mediaType,
|
|
8602
9534
|
dataBase64: bytes.toString("base64"),
|
|
8603
9535
|
byteLength: bytes.length
|
|
@@ -8900,7 +9832,7 @@ program.command("login").description("Log in and save an access token for future
|
|
|
8900
9832
|
json: opts.json
|
|
8901
9833
|
});
|
|
8902
9834
|
} catch (error) {
|
|
8903
|
-
console.error(
|
|
9835
|
+
console.error(kleur19.red(String(error)));
|
|
8904
9836
|
process.exit(1);
|
|
8905
9837
|
}
|
|
8906
9838
|
});
|
|
@@ -8908,7 +9840,7 @@ program.command("logout").description("Clear the saved CLI access token").option
|
|
|
8908
9840
|
try {
|
|
8909
9841
|
await logout({ json: opts.json, profile: opts.profile });
|
|
8910
9842
|
} catch (error) {
|
|
8911
|
-
console.error(
|
|
9843
|
+
console.error(kleur19.red(String(error)));
|
|
8912
9844
|
process.exit(1);
|
|
8913
9845
|
}
|
|
8914
9846
|
});
|
|
@@ -8932,7 +9864,7 @@ chatCommand.option("--json", "Output JSON").action(async (promptParts, opts) =>
|
|
|
8932
9864
|
json: opts.json
|
|
8933
9865
|
});
|
|
8934
9866
|
} catch (error) {
|
|
8935
|
-
console.error(
|
|
9867
|
+
console.error(kleur19.red(String(error)));
|
|
8936
9868
|
process.exit(1);
|
|
8937
9869
|
}
|
|
8938
9870
|
});
|
|
@@ -8956,7 +9888,7 @@ function registerSpaceCommand(command) {
|
|
|
8956
9888
|
json: opts.json
|
|
8957
9889
|
});
|
|
8958
9890
|
} catch (error) {
|
|
8959
|
-
console.error(
|
|
9891
|
+
console.error(kleur19.red(String(error)));
|
|
8960
9892
|
process.exit(1);
|
|
8961
9893
|
}
|
|
8962
9894
|
});
|
|
@@ -8972,7 +9904,7 @@ function registerSpaceCommand(command) {
|
|
|
8972
9904
|
json: opts.json
|
|
8973
9905
|
});
|
|
8974
9906
|
} catch (error) {
|
|
8975
|
-
console.error(
|
|
9907
|
+
console.error(kleur19.red(String(error)));
|
|
8976
9908
|
process.exit(1);
|
|
8977
9909
|
}
|
|
8978
9910
|
});
|
|
@@ -8986,7 +9918,7 @@ function registerSpaceCommand(command) {
|
|
|
8986
9918
|
json: opts.json
|
|
8987
9919
|
});
|
|
8988
9920
|
} catch (error) {
|
|
8989
|
-
console.error(
|
|
9921
|
+
console.error(kleur19.red(String(error)));
|
|
8990
9922
|
process.exit(1);
|
|
8991
9923
|
}
|
|
8992
9924
|
});
|
|
@@ -9009,7 +9941,7 @@ function registerSpaceCommand(command) {
|
|
|
9009
9941
|
json: opts.json
|
|
9010
9942
|
});
|
|
9011
9943
|
} catch (error) {
|
|
9012
|
-
console.error(
|
|
9944
|
+
console.error(kleur19.red(String(error)));
|
|
9013
9945
|
process.exit(1);
|
|
9014
9946
|
}
|
|
9015
9947
|
});
|
|
@@ -9021,7 +9953,7 @@ function registerSpaceCommand(command) {
|
|
|
9021
9953
|
json: opts.json
|
|
9022
9954
|
});
|
|
9023
9955
|
} catch (error) {
|
|
9024
|
-
console.error(
|
|
9956
|
+
console.error(kleur19.red(String(error)));
|
|
9025
9957
|
process.exit(1);
|
|
9026
9958
|
}
|
|
9027
9959
|
});
|
|
@@ -9043,7 +9975,7 @@ function registerSpaceCommand(command) {
|
|
|
9043
9975
|
json: opts.json
|
|
9044
9976
|
});
|
|
9045
9977
|
} catch (error) {
|
|
9046
|
-
console.error(
|
|
9978
|
+
console.error(kleur19.red(String(error)));
|
|
9047
9979
|
process.exit(1);
|
|
9048
9980
|
}
|
|
9049
9981
|
});
|
|
@@ -9059,7 +9991,7 @@ function registerSpaceCommand(command) {
|
|
|
9059
9991
|
json: opts.json
|
|
9060
9992
|
});
|
|
9061
9993
|
} catch (error) {
|
|
9062
|
-
console.error(
|
|
9994
|
+
console.error(kleur19.red(String(error)));
|
|
9063
9995
|
process.exit(1);
|
|
9064
9996
|
}
|
|
9065
9997
|
});
|
|
@@ -9085,7 +10017,7 @@ function registerSpaceCommand(command) {
|
|
|
9085
10017
|
json: opts.json
|
|
9086
10018
|
});
|
|
9087
10019
|
} catch (error) {
|
|
9088
|
-
console.error(
|
|
10020
|
+
console.error(kleur19.red(String(error)));
|
|
9089
10021
|
process.exit(1);
|
|
9090
10022
|
}
|
|
9091
10023
|
});
|
|
@@ -9110,7 +10042,7 @@ function registerSpaceCommand(command) {
|
|
|
9110
10042
|
json: opts.json
|
|
9111
10043
|
});
|
|
9112
10044
|
} catch (error) {
|
|
9113
|
-
console.error(
|
|
10045
|
+
console.error(kleur19.red(String(error)));
|
|
9114
10046
|
process.exit(1);
|
|
9115
10047
|
}
|
|
9116
10048
|
});
|
|
@@ -9130,7 +10062,7 @@ hardwareBindingsCommand.command("show").description("Show hardware bindings for
|
|
|
9130
10062
|
json: opts.json
|
|
9131
10063
|
});
|
|
9132
10064
|
} catch (error) {
|
|
9133
|
-
console.error(
|
|
10065
|
+
console.error(kleur19.red(String(error)));
|
|
9134
10066
|
process.exit(1);
|
|
9135
10067
|
}
|
|
9136
10068
|
});
|
|
@@ -9150,7 +10082,7 @@ hardwareBindingsCommand.command("grant").description("Grant a local hardware pro
|
|
|
9150
10082
|
json: opts.json
|
|
9151
10083
|
});
|
|
9152
10084
|
} catch (error) {
|
|
9153
|
-
console.error(
|
|
10085
|
+
console.error(kleur19.red(String(error)));
|
|
9154
10086
|
process.exit(1);
|
|
9155
10087
|
}
|
|
9156
10088
|
});
|
|
@@ -9162,7 +10094,7 @@ hardwareBindingsCommand.command("revoke").description("Revoke a local hardware b
|
|
|
9162
10094
|
json: opts.json
|
|
9163
10095
|
});
|
|
9164
10096
|
} catch (error) {
|
|
9165
|
-
console.error(
|
|
10097
|
+
console.error(kleur19.red(String(error)));
|
|
9166
10098
|
process.exit(1);
|
|
9167
10099
|
}
|
|
9168
10100
|
});
|
|
@@ -9176,7 +10108,7 @@ hardwareSerialCommand.command("list").description("List local serial devices vis
|
|
|
9176
10108
|
scanDirs: opts.scanDir
|
|
9177
10109
|
});
|
|
9178
10110
|
} catch (error) {
|
|
9179
|
-
console.error(
|
|
10111
|
+
console.error(kleur19.red(String(error)));
|
|
9180
10112
|
process.exit(1);
|
|
9181
10113
|
}
|
|
9182
10114
|
});
|
|
@@ -9188,7 +10120,7 @@ hardwareSerialCommand.command("probe").description("Probe host permissions for o
|
|
|
9188
10120
|
json: opts.json
|
|
9189
10121
|
});
|
|
9190
10122
|
} catch (error) {
|
|
9191
|
-
console.error(
|
|
10123
|
+
console.error(kleur19.red(String(error)));
|
|
9192
10124
|
process.exit(1);
|
|
9193
10125
|
}
|
|
9194
10126
|
});
|
|
@@ -9200,7 +10132,7 @@ hardwareCommand.command("opportunities").description("List host-local IO opportu
|
|
|
9200
10132
|
scanDirs: opts.scanDir
|
|
9201
10133
|
});
|
|
9202
10134
|
} catch (error) {
|
|
9203
|
-
console.error(
|
|
10135
|
+
console.error(kleur19.red(String(error)));
|
|
9204
10136
|
process.exit(1);
|
|
9205
10137
|
}
|
|
9206
10138
|
});
|
|
@@ -9213,7 +10145,7 @@ hardwareCommand.command("run").description("Run one available host-local IO acti
|
|
|
9213
10145
|
json: opts.json
|
|
9214
10146
|
});
|
|
9215
10147
|
} catch (error) {
|
|
9216
|
-
console.error(
|
|
10148
|
+
console.error(kleur19.red(String(error)));
|
|
9217
10149
|
process.exit(1);
|
|
9218
10150
|
}
|
|
9219
10151
|
});
|
|
@@ -9228,7 +10160,7 @@ providersListCommand.option("--json", "Output JSON").action(async (opts) => {
|
|
|
9228
10160
|
json: opts.json
|
|
9229
10161
|
});
|
|
9230
10162
|
} catch (error) {
|
|
9231
|
-
console.error(
|
|
10163
|
+
console.error(kleur19.red(String(error)));
|
|
9232
10164
|
process.exit(1);
|
|
9233
10165
|
}
|
|
9234
10166
|
});
|
|
@@ -9242,7 +10174,7 @@ providersDiscoverCommand.option("--json", "Output JSON").action(async (providerI
|
|
|
9242
10174
|
json: opts.json
|
|
9243
10175
|
});
|
|
9244
10176
|
} catch (error) {
|
|
9245
|
-
console.error(
|
|
10177
|
+
console.error(kleur19.red(String(error)));
|
|
9246
10178
|
process.exit(1);
|
|
9247
10179
|
}
|
|
9248
10180
|
});
|
|
@@ -9257,7 +10189,7 @@ providersReadCommand.option("--json", "Output JSON").action(async (providerId, u
|
|
|
9257
10189
|
json: opts.json
|
|
9258
10190
|
});
|
|
9259
10191
|
} catch (error) {
|
|
9260
|
-
console.error(
|
|
10192
|
+
console.error(kleur19.red(String(error)));
|
|
9261
10193
|
process.exit(1);
|
|
9262
10194
|
}
|
|
9263
10195
|
});
|
|
@@ -9280,7 +10212,7 @@ providersProbeCommand.option("--json", "Output JSON").action(async (providerId,
|
|
|
9280
10212
|
json: opts.json
|
|
9281
10213
|
});
|
|
9282
10214
|
} catch (error) {
|
|
9283
|
-
console.error(
|
|
10215
|
+
console.error(kleur19.red(String(error)));
|
|
9284
10216
|
process.exit(1);
|
|
9285
10217
|
}
|
|
9286
10218
|
});
|
|
@@ -9302,7 +10234,7 @@ agentsListCommand.option("--json", "Output JSON").action(async (opts) => {
|
|
|
9302
10234
|
json: opts.json
|
|
9303
10235
|
});
|
|
9304
10236
|
} catch (error) {
|
|
9305
|
-
console.error(
|
|
10237
|
+
console.error(kleur19.red(String(error)));
|
|
9306
10238
|
process.exit(1);
|
|
9307
10239
|
}
|
|
9308
10240
|
});
|
|
@@ -9330,7 +10262,7 @@ agentsContextListCommand.option("--agent <handle>", "Filter by agent handle (for
|
|
|
9330
10262
|
json: opts.json
|
|
9331
10263
|
});
|
|
9332
10264
|
} catch (error) {
|
|
9333
|
-
console.error(
|
|
10265
|
+
console.error(kleur19.red(String(error)));
|
|
9334
10266
|
process.exit(1);
|
|
9335
10267
|
}
|
|
9336
10268
|
});
|
|
@@ -9356,7 +10288,7 @@ agentsContextPutCommand.action(async (contextParts, opts) => {
|
|
|
9356
10288
|
json: opts.json
|
|
9357
10289
|
});
|
|
9358
10290
|
} catch (error) {
|
|
9359
|
-
console.error(
|
|
10291
|
+
console.error(kleur19.red(String(error)));
|
|
9360
10292
|
process.exit(1);
|
|
9361
10293
|
}
|
|
9362
10294
|
});
|
|
@@ -9372,7 +10304,7 @@ agentsStatusCommand.option("--json", "Output JSON").action(async (groupId, opts)
|
|
|
9372
10304
|
json: opts.json
|
|
9373
10305
|
});
|
|
9374
10306
|
} catch (error) {
|
|
9375
|
-
console.error(
|
|
10307
|
+
console.error(kleur19.red(String(error)));
|
|
9376
10308
|
process.exit(1);
|
|
9377
10309
|
}
|
|
9378
10310
|
});
|
|
@@ -9390,7 +10322,7 @@ agentsCancelCommand.option("--json", "Output JSON").action(async (opts) => {
|
|
|
9390
10322
|
json: opts.json
|
|
9391
10323
|
});
|
|
9392
10324
|
} catch (error) {
|
|
9393
|
-
console.error(
|
|
10325
|
+
console.error(kleur19.red(String(error)));
|
|
9394
10326
|
process.exit(1);
|
|
9395
10327
|
}
|
|
9396
10328
|
});
|
|
@@ -9412,7 +10344,7 @@ secretsListCommand.option("--json", "Output JSON").action(async (opts) => {
|
|
|
9412
10344
|
json: opts.json
|
|
9413
10345
|
});
|
|
9414
10346
|
} catch (error) {
|
|
9415
|
-
console.error(
|
|
10347
|
+
console.error(kleur19.red(String(error)));
|
|
9416
10348
|
process.exit(1);
|
|
9417
10349
|
}
|
|
9418
10350
|
});
|
|
@@ -9433,7 +10365,7 @@ secretsGetCommand.option("--json", "Output JSON").action(async (nameOrId, opts)
|
|
|
9433
10365
|
json: opts.json
|
|
9434
10366
|
});
|
|
9435
10367
|
} catch (error) {
|
|
9436
|
-
console.error(
|
|
10368
|
+
console.error(kleur19.red(String(error)));
|
|
9437
10369
|
process.exit(1);
|
|
9438
10370
|
}
|
|
9439
10371
|
});
|
|
@@ -9458,7 +10390,7 @@ secretsPutCommand.option("--json", "Output JSON").action(async (name, opts) => {
|
|
|
9458
10390
|
json: opts.json
|
|
9459
10391
|
});
|
|
9460
10392
|
} catch (error) {
|
|
9461
|
-
console.error(
|
|
10393
|
+
console.error(kleur19.red(String(error)));
|
|
9462
10394
|
process.exit(1);
|
|
9463
10395
|
}
|
|
9464
10396
|
});
|
|
@@ -9479,10 +10411,24 @@ secretsRevokeCommand.option("--json", "Output JSON").action(async (nameOrId, opt
|
|
|
9479
10411
|
json: opts.json
|
|
9480
10412
|
});
|
|
9481
10413
|
} catch (error) {
|
|
9482
|
-
console.error(
|
|
10414
|
+
console.error(kleur19.red(String(error)));
|
|
9483
10415
|
process.exit(1);
|
|
9484
10416
|
}
|
|
9485
10417
|
});
|
|
10418
|
+
function resolveResultVisibilityFlag(opts) {
|
|
10419
|
+
if (opts.resultVisibility !== void 0) {
|
|
10420
|
+
const value = String(opts.resultVisibility).trim().toLowerCase();
|
|
10421
|
+
if (value !== "private" && value !== "team") {
|
|
10422
|
+
throw new Error("--result-visibility must be private or team");
|
|
10423
|
+
}
|
|
10424
|
+
return value;
|
|
10425
|
+
}
|
|
10426
|
+
if (opts.shareResults === true)
|
|
10427
|
+
return "team";
|
|
10428
|
+
if (opts.shareResults === false)
|
|
10429
|
+
return "private";
|
|
10430
|
+
return void 0;
|
|
10431
|
+
}
|
|
9486
10432
|
var automationsCommand = program.command("automations").description("Manage scheduled automations (run prompts on a schedule)");
|
|
9487
10433
|
failWithGroupHelp(automationsCommand);
|
|
9488
10434
|
var automationsListCommand = automationsCommand.command("list").description("List automations for this space");
|
|
@@ -9501,13 +10447,22 @@ automationsListCommand.option("--json", "Output JSON").action(async (opts) => {
|
|
|
9501
10447
|
json: opts.json
|
|
9502
10448
|
});
|
|
9503
10449
|
} catch (error) {
|
|
9504
|
-
console.error(
|
|
10450
|
+
console.error(kleur19.red(String(error)));
|
|
9505
10451
|
process.exit(1);
|
|
9506
10452
|
}
|
|
9507
10453
|
});
|
|
9508
10454
|
var automationsCreateCommand = automationsCommand.command("create").description("Create an automation").requiredOption("--name <name>", "Automation name").requiredOption("--prompt <text>", "Prompt to run on schedule").option("--schedule-kind <kind>", "weekly|hourly|once (default: weekly)").option("--run-at <datetime>", "Run time for once schedule (RFC3339 or YYYY-MM-DDTHH:MM[:SS])").option("--interval-hours <n>", "Interval hours (hourly schedule)", (value) => Number(value)).option("--days <list>", "Weekdays for weekly schedule (e.g. mo,tu,we,th,fr)").option("--time <hh:mm>", "Time for weekly schedule (24h, e.g. 09:00)").option("--timezone <tz>", "IANA timezone (e.g. America/New_York)").option("--runtime-mode <mode>", "auto|hosted|existing (default: auto)").option("--runtime-provider <id>", "Runtime provider id (optional)").option(
|
|
9509
10455
|
"--silent-when-nothing-to-report",
|
|
9510
10456
|
"Do not post a completion result or send a result notification when a successful run has no findings"
|
|
10457
|
+
).option(
|
|
10458
|
+
"--share-results",
|
|
10459
|
+
"Share this automation's result threads with your team (visible to anyone with space access)"
|
|
10460
|
+
).option(
|
|
10461
|
+
"--no-share-results",
|
|
10462
|
+
"Keep this automation's result threads private to you (default)"
|
|
10463
|
+
).option(
|
|
10464
|
+
"--result-visibility <private|team>",
|
|
10465
|
+
"Result-thread visibility (private|team); overrides --share-results"
|
|
9511
10466
|
).option("--paused", "Create paused");
|
|
9512
10467
|
addSpaceOption(
|
|
9513
10468
|
automationsCreateCommand,
|
|
@@ -9529,6 +10484,7 @@ automationsCreateCommand.option("--json", "Output JSON").action(async (opts) =>
|
|
|
9529
10484
|
runtimeMode: opts.runtimeMode,
|
|
9530
10485
|
runtimeProvider: opts.runtimeProvider,
|
|
9531
10486
|
silentWhenNothingToReport: Boolean(opts.silentWhenNothingToReport),
|
|
10487
|
+
resultVisibility: resolveResultVisibilityFlag(opts),
|
|
9532
10488
|
paused: Boolean(opts.paused),
|
|
9533
10489
|
project: resolveSpaceIdOption(opts),
|
|
9534
10490
|
controllerUrl: opts.serverUrl,
|
|
@@ -9536,7 +10492,53 @@ automationsCreateCommand.option("--json", "Output JSON").action(async (opts) =>
|
|
|
9536
10492
|
json: opts.json
|
|
9537
10493
|
});
|
|
9538
10494
|
} catch (error) {
|
|
9539
|
-
console.error(
|
|
10495
|
+
console.error(kleur19.red(String(error)));
|
|
10496
|
+
process.exit(1);
|
|
10497
|
+
}
|
|
10498
|
+
});
|
|
10499
|
+
var automationsUpdateCommand = automationsCommand.command("update").description(
|
|
10500
|
+
"Update an automation's name, prompt, schedule, runtime settings, or result-sharing visibility in place"
|
|
10501
|
+
).argument("<automation-id>", "Automation UUID").option("--name <name>", "New automation name").option("--prompt <text>", "New prompt to run on schedule").option("--prompt-file <path>", "Read the new prompt from a file").option("--schedule-kind <kind>", "weekly|hourly|once").option("--run-at <datetime>", "Run time for once schedule (RFC3339 or YYYY-MM-DDTHH:MM[:SS])").option("--interval-hours <n>", "Interval hours (hourly schedule)", (value) => Number(value)).option("--days <list>", "Weekdays for weekly schedule (e.g. mo,tu,we,th,fr)").option("--time <hh:mm>", "Time for weekly schedule (24h, e.g. 09:00)").option("--timezone <tz>", "IANA timezone (e.g. America/New_York)").option("--runtime-mode <mode>", "auto|hosted|existing").option("--runtime-provider <id>", "Runtime provider id").option(
|
|
10502
|
+
"--silent-when-nothing-to-report",
|
|
10503
|
+
"Do not post a completion result or send a result notification when a successful run has no findings"
|
|
10504
|
+
).option(
|
|
10505
|
+
"--no-silent-when-nothing-to-report",
|
|
10506
|
+
"Always post a completion result and send a result notification"
|
|
10507
|
+
).option(
|
|
10508
|
+
"--share-results",
|
|
10509
|
+
"Share this automation's result threads with your team (visible to anyone with space access)"
|
|
10510
|
+
).option(
|
|
10511
|
+
"--no-share-results",
|
|
10512
|
+
"Keep this automation's result threads private to you"
|
|
10513
|
+
).option(
|
|
10514
|
+
"--result-visibility <private|team>",
|
|
10515
|
+
"Result-thread visibility (private|team); overrides --share-results"
|
|
10516
|
+
);
|
|
10517
|
+
addServerUrlOptions(automationsUpdateCommand);
|
|
10518
|
+
addAccessTokenOptions(automationsUpdateCommand, "Instafy access token");
|
|
10519
|
+
automationsUpdateCommand.option("--json", "Output JSON").action(async (automationId, opts) => {
|
|
10520
|
+
try {
|
|
10521
|
+
await automationsUpdate({
|
|
10522
|
+
automationId,
|
|
10523
|
+
name: opts.name,
|
|
10524
|
+
prompt: opts.prompt,
|
|
10525
|
+
promptFile: opts.promptFile,
|
|
10526
|
+
scheduleKind: opts.scheduleKind,
|
|
10527
|
+
runAt: opts.runAt,
|
|
10528
|
+
intervalHours: opts.intervalHours,
|
|
10529
|
+
days: opts.days,
|
|
10530
|
+
time: opts.time,
|
|
10531
|
+
timezone: opts.timezone,
|
|
10532
|
+
runtimeMode: opts.runtimeMode,
|
|
10533
|
+
runtimeProvider: opts.runtimeProvider,
|
|
10534
|
+
silentWhenNothingToReport: opts.silentWhenNothingToReport,
|
|
10535
|
+
resultVisibility: resolveResultVisibilityFlag(opts),
|
|
10536
|
+
controllerUrl: opts.serverUrl,
|
|
10537
|
+
accessToken: opts.accessToken,
|
|
10538
|
+
json: opts.json
|
|
10539
|
+
});
|
|
10540
|
+
} catch (error) {
|
|
10541
|
+
console.error(kleur19.red(String(error)));
|
|
9540
10542
|
process.exit(1);
|
|
9541
10543
|
}
|
|
9542
10544
|
});
|
|
@@ -9553,7 +10555,7 @@ automationsPauseCommand.option("--json", "Output JSON").action(async (automation
|
|
|
9553
10555
|
json: opts.json
|
|
9554
10556
|
});
|
|
9555
10557
|
} catch (error) {
|
|
9556
|
-
console.error(
|
|
10558
|
+
console.error(kleur19.red(String(error)));
|
|
9557
10559
|
process.exit(1);
|
|
9558
10560
|
}
|
|
9559
10561
|
});
|
|
@@ -9570,7 +10572,7 @@ automationsResumeCommand.option("--json", "Output JSON").action(async (automatio
|
|
|
9570
10572
|
json: opts.json
|
|
9571
10573
|
});
|
|
9572
10574
|
} catch (error) {
|
|
9573
|
-
console.error(
|
|
10575
|
+
console.error(kleur19.red(String(error)));
|
|
9574
10576
|
process.exit(1);
|
|
9575
10577
|
}
|
|
9576
10578
|
});
|
|
@@ -9586,7 +10588,7 @@ automationsRunCommand.option("--json", "Output JSON").action(async (automationId
|
|
|
9586
10588
|
json: opts.json
|
|
9587
10589
|
});
|
|
9588
10590
|
} catch (error) {
|
|
9589
|
-
console.error(
|
|
10591
|
+
console.error(kleur19.red(String(error)));
|
|
9590
10592
|
process.exit(1);
|
|
9591
10593
|
}
|
|
9592
10594
|
});
|
|
@@ -9602,7 +10604,92 @@ automationsDeleteCommand.option("--json", "Output JSON").action(async (automatio
|
|
|
9602
10604
|
json: opts.json
|
|
9603
10605
|
});
|
|
9604
10606
|
} catch (error) {
|
|
9605
|
-
console.error(
|
|
10607
|
+
console.error(kleur19.red(String(error)));
|
|
10608
|
+
process.exit(1);
|
|
10609
|
+
}
|
|
10610
|
+
});
|
|
10611
|
+
var credentialsCommand = program.command("credentials").description("Inspect, verify and pick the AI provider credentials your jobs use");
|
|
10612
|
+
failWithGroupHelp(credentialsCommand);
|
|
10613
|
+
var credentialsListCommand = credentialsCommand.command("list").description("List your AI credentials (secret material is never shown)").option("--all", "Include revoked credentials");
|
|
10614
|
+
addServerUrlOptions(credentialsListCommand);
|
|
10615
|
+
addAccessTokenOptions(credentialsListCommand, "Instafy access token");
|
|
10616
|
+
credentialsListCommand.option("--json", "Output JSON").action(async (opts) => {
|
|
10617
|
+
try {
|
|
10618
|
+
await credentialsList({
|
|
10619
|
+
all: Boolean(opts.all),
|
|
10620
|
+
controllerUrl: opts.serverUrl,
|
|
10621
|
+
accessToken: opts.accessToken,
|
|
10622
|
+
json: opts.json
|
|
10623
|
+
});
|
|
10624
|
+
} catch (error) {
|
|
10625
|
+
console.error(kleur19.red(String(error)));
|
|
10626
|
+
process.exit(1);
|
|
10627
|
+
}
|
|
10628
|
+
});
|
|
10629
|
+
var credentialsTestCommand = credentialsCommand.command("test").description("Probe one credential through the proxy against its upstream provider (exit 1 on failure)").argument("<id-or-prefix>", "Credential UUID or unique id prefix");
|
|
10630
|
+
addServerUrlOptions(credentialsTestCommand);
|
|
10631
|
+
addAccessTokenOptions(credentialsTestCommand, "Instafy access token");
|
|
10632
|
+
credentialsTestCommand.option("--json", "Output JSON").action(async (idOrPrefix, opts) => {
|
|
10633
|
+
try {
|
|
10634
|
+
const result = await credentialsTest({
|
|
10635
|
+
idOrPrefix,
|
|
10636
|
+
controllerUrl: opts.serverUrl,
|
|
10637
|
+
accessToken: opts.accessToken,
|
|
10638
|
+
json: opts.json
|
|
10639
|
+
});
|
|
10640
|
+
if (!result.ok) {
|
|
10641
|
+
process.exitCode = 1;
|
|
10642
|
+
}
|
|
10643
|
+
} catch (error) {
|
|
10644
|
+
console.error(kleur19.red(String(error)));
|
|
10645
|
+
process.exit(1);
|
|
10646
|
+
}
|
|
10647
|
+
});
|
|
10648
|
+
var credentialsDefaultCommand = credentialsCommand.command("default").description("Set the default credential jobs use, or clear it with --clear").argument("[id-or-prefix]", "Credential UUID or unique id prefix").option("--clear", "Clear the default credential instead of setting one");
|
|
10649
|
+
addServerUrlOptions(credentialsDefaultCommand);
|
|
10650
|
+
addAccessTokenOptions(credentialsDefaultCommand, "Instafy access token");
|
|
10651
|
+
credentialsDefaultCommand.option("--json", "Output JSON").action(async (idOrPrefix, opts) => {
|
|
10652
|
+
try {
|
|
10653
|
+
const target = pickTrimmedString2(idOrPrefix);
|
|
10654
|
+
if (opts.clear && target) {
|
|
10655
|
+
throw new Error("Pass either a credential id or --clear, not both.");
|
|
10656
|
+
}
|
|
10657
|
+
if (!opts.clear && !target) {
|
|
10658
|
+
throw new Error("Provide a credential id (or unique prefix), or pass --clear.");
|
|
10659
|
+
}
|
|
10660
|
+
if (opts.clear) {
|
|
10661
|
+
await credentialsClearDefault({
|
|
10662
|
+
controllerUrl: opts.serverUrl,
|
|
10663
|
+
accessToken: opts.accessToken,
|
|
10664
|
+
json: opts.json
|
|
10665
|
+
});
|
|
10666
|
+
return;
|
|
10667
|
+
}
|
|
10668
|
+
await credentialsSetDefault({
|
|
10669
|
+
idOrPrefix: target,
|
|
10670
|
+
controllerUrl: opts.serverUrl,
|
|
10671
|
+
accessToken: opts.accessToken,
|
|
10672
|
+
json: opts.json
|
|
10673
|
+
});
|
|
10674
|
+
} catch (error) {
|
|
10675
|
+
console.error(kleur19.red(String(error)));
|
|
10676
|
+
process.exit(1);
|
|
10677
|
+
}
|
|
10678
|
+
});
|
|
10679
|
+
var credentialsRevokeCommand = credentialsCommand.command("revoke").description("Revoke a credential (asks for confirmation unless --yes)").argument("<id-or-prefix>", "Credential UUID or unique id prefix").option("--yes", "Skip the confirmation prompt (required when not running in a terminal)");
|
|
10680
|
+
addServerUrlOptions(credentialsRevokeCommand);
|
|
10681
|
+
addAccessTokenOptions(credentialsRevokeCommand, "Instafy access token");
|
|
10682
|
+
credentialsRevokeCommand.option("--json", "Output JSON").action(async (idOrPrefix, opts) => {
|
|
10683
|
+
try {
|
|
10684
|
+
await credentialsRevoke({
|
|
10685
|
+
idOrPrefix,
|
|
10686
|
+
yes: Boolean(opts.yes),
|
|
10687
|
+
controllerUrl: opts.serverUrl,
|
|
10688
|
+
accessToken: opts.accessToken,
|
|
10689
|
+
json: opts.json
|
|
10690
|
+
});
|
|
10691
|
+
} catch (error) {
|
|
10692
|
+
console.error(kleur19.red(String(error)));
|
|
9606
10693
|
process.exit(1);
|
|
9607
10694
|
}
|
|
9608
10695
|
});
|
|
@@ -9612,7 +10699,7 @@ configCommand.command("path").description("Print the config file path").option("
|
|
|
9612
10699
|
try {
|
|
9613
10700
|
configPath({ json: opts.json });
|
|
9614
10701
|
} catch (error) {
|
|
9615
|
-
console.error(
|
|
10702
|
+
console.error(kleur19.red(String(error)));
|
|
9616
10703
|
process.exit(1);
|
|
9617
10704
|
}
|
|
9618
10705
|
});
|
|
@@ -9620,7 +10707,7 @@ configCommand.command("list").description("List saved configuration").option("--
|
|
|
9620
10707
|
try {
|
|
9621
10708
|
configList({ json: opts.json });
|
|
9622
10709
|
} catch (error) {
|
|
9623
|
-
console.error(
|
|
10710
|
+
console.error(kleur19.red(String(error)));
|
|
9624
10711
|
process.exit(1);
|
|
9625
10712
|
}
|
|
9626
10713
|
});
|
|
@@ -9628,7 +10715,7 @@ configCommand.command("get").description("Get a config value (controller-url, st
|
|
|
9628
10715
|
try {
|
|
9629
10716
|
configGet({ key, json: opts.json });
|
|
9630
10717
|
} catch (error) {
|
|
9631
|
-
console.error(
|
|
10718
|
+
console.error(kleur19.red(String(error)));
|
|
9632
10719
|
process.exit(1);
|
|
9633
10720
|
}
|
|
9634
10721
|
});
|
|
@@ -9636,7 +10723,7 @@ configCommand.command("set").description("Set a config value (controller-url, st
|
|
|
9636
10723
|
try {
|
|
9637
10724
|
configSet({ key, value, json: opts.json });
|
|
9638
10725
|
} catch (error) {
|
|
9639
|
-
console.error(
|
|
10726
|
+
console.error(kleur19.red(String(error)));
|
|
9640
10727
|
process.exit(1);
|
|
9641
10728
|
}
|
|
9642
10729
|
});
|
|
@@ -9644,7 +10731,7 @@ configCommand.command("unset").description("Unset a config value (controller-url
|
|
|
9644
10731
|
try {
|
|
9645
10732
|
configUnset({ key, json: opts.json });
|
|
9646
10733
|
} catch (error) {
|
|
9647
|
-
console.error(
|
|
10734
|
+
console.error(kleur19.red(String(error)));
|
|
9648
10735
|
process.exit(1);
|
|
9649
10736
|
}
|
|
9650
10737
|
});
|
|
@@ -9664,7 +10751,7 @@ runtimeStartCommand.option("--supabase-access-token <token>", "Supabase session
|
|
|
9664
10751
|
controllerAccessToken: opts.accessToken
|
|
9665
10752
|
});
|
|
9666
10753
|
} catch (error) {
|
|
9667
|
-
console.error(
|
|
10754
|
+
console.error(kleur19.red(String(error)));
|
|
9668
10755
|
process.exit(1);
|
|
9669
10756
|
}
|
|
9670
10757
|
});
|
|
@@ -9672,7 +10759,7 @@ runtimeCommand.command("status").description("Show runtime health").option("--js
|
|
|
9672
10759
|
try {
|
|
9673
10760
|
await runtimeStatus({ json: opts.json });
|
|
9674
10761
|
} catch (error) {
|
|
9675
|
-
console.error(
|
|
10762
|
+
console.error(kleur19.red(String(error)));
|
|
9676
10763
|
process.exit(1);
|
|
9677
10764
|
}
|
|
9678
10765
|
});
|
|
@@ -9680,7 +10767,7 @@ runtimeCommand.command("stop").description("Stop the local Instafy runtime").opt
|
|
|
9680
10767
|
try {
|
|
9681
10768
|
await runtimeStop({ json: opts.json });
|
|
9682
10769
|
} catch (error) {
|
|
9683
|
-
console.error(
|
|
10770
|
+
console.error(kleur19.red(String(error)));
|
|
9684
10771
|
process.exit(1);
|
|
9685
10772
|
}
|
|
9686
10773
|
});
|
|
@@ -9706,7 +10793,7 @@ runtimeTokenCommand.option("--runtime-id <uuid>", "Runtime ID to bind token to")
|
|
|
9706
10793
|
json: opts.json
|
|
9707
10794
|
});
|
|
9708
10795
|
} catch (error) {
|
|
9709
|
-
console.error(
|
|
10796
|
+
console.error(kleur19.red(String(error)));
|
|
9710
10797
|
process.exit(1);
|
|
9711
10798
|
}
|
|
9712
10799
|
});
|
|
@@ -9728,7 +10815,7 @@ diagnosticsRuntimeEventsCommand.action(async (opts) => {
|
|
|
9728
10815
|
accessToken: opts.accessToken
|
|
9729
10816
|
});
|
|
9730
10817
|
} catch (error) {
|
|
9731
|
-
console.error(
|
|
10818
|
+
console.error(kleur19.red(String(error)));
|
|
9732
10819
|
process.exit(1);
|
|
9733
10820
|
}
|
|
9734
10821
|
});
|
|
@@ -9743,7 +10830,7 @@ diagnosticsRunResultCommand.action(async (runId, opts) => {
|
|
|
9743
10830
|
accessToken: opts.accessToken
|
|
9744
10831
|
});
|
|
9745
10832
|
} catch (error) {
|
|
9746
|
-
console.error(
|
|
10833
|
+
console.error(kleur19.red(String(error)));
|
|
9747
10834
|
process.exit(1);
|
|
9748
10835
|
}
|
|
9749
10836
|
});
|
|
@@ -9777,7 +10864,7 @@ supportReportCommand.action(async (summaryParts, opts) => {
|
|
|
9777
10864
|
json: opts.json
|
|
9778
10865
|
});
|
|
9779
10866
|
} catch (error) {
|
|
9780
|
-
console.error(
|
|
10867
|
+
console.error(kleur19.red(String(error)));
|
|
9781
10868
|
process.exit(1);
|
|
9782
10869
|
}
|
|
9783
10870
|
});
|
|
@@ -9796,7 +10883,7 @@ supportListCommand.action(async (opts) => {
|
|
|
9796
10883
|
json: opts.json
|
|
9797
10884
|
});
|
|
9798
10885
|
} catch (error) {
|
|
9799
|
-
console.error(
|
|
10886
|
+
console.error(kleur19.red(String(error)));
|
|
9800
10887
|
process.exit(1);
|
|
9801
10888
|
}
|
|
9802
10889
|
});
|
|
@@ -9812,7 +10899,7 @@ supportShowCommand.action(async (reportId, opts) => {
|
|
|
9812
10899
|
json: opts.json
|
|
9813
10900
|
});
|
|
9814
10901
|
} catch (error) {
|
|
9815
|
-
console.error(
|
|
10902
|
+
console.error(kleur19.red(String(error)));
|
|
9816
10903
|
process.exit(1);
|
|
9817
10904
|
}
|
|
9818
10905
|
});
|
|
@@ -9857,19 +10944,19 @@ tunnelStartCommand.option("--no-detach", "Run in foreground until interrupted").
|
|
|
9857
10944
|
console.log(JSON.stringify(started, null, 2));
|
|
9858
10945
|
return;
|
|
9859
10946
|
}
|
|
9860
|
-
console.log(
|
|
9861
|
-
console.log(
|
|
9862
|
-
console.log(
|
|
10947
|
+
console.log(kleur19.green(`Tunnel started: ${started.url} (tunnelId=${started.tunnelId})`));
|
|
10948
|
+
console.log(kleur19.gray(`pid=${started.pid} \xB7 port=${started.localPort}`));
|
|
10949
|
+
console.log(kleur19.gray(`log: ${started.logFile}`));
|
|
9863
10950
|
console.log("");
|
|
9864
10951
|
console.log("Next:");
|
|
9865
|
-
console.log(`- ${
|
|
9866
|
-
console.log(`- ${
|
|
9867
|
-
console.log(`- ${
|
|
10952
|
+
console.log(`- ${kleur19.cyan(`instafy tunnel list`)}`);
|
|
10953
|
+
console.log(`- ${kleur19.cyan(`instafy tunnel logs ${started.tunnelId} --follow`)}`);
|
|
10954
|
+
console.log(`- ${kleur19.cyan(`instafy tunnel stop ${started.tunnelId}`)}`);
|
|
9868
10955
|
if (process.platform !== "win32") {
|
|
9869
|
-
console.log(
|
|
10956
|
+
console.log(kleur19.gray(`(or) tail -n 200 -f ${started.logFile}`));
|
|
9870
10957
|
}
|
|
9871
10958
|
} catch (error) {
|
|
9872
|
-
console.error(
|
|
10959
|
+
console.error(kleur19.red(String(error)));
|
|
9873
10960
|
process.exit(1);
|
|
9874
10961
|
}
|
|
9875
10962
|
});
|
|
@@ -9881,14 +10968,14 @@ tunnelCommand.command("list").description("List local tunnel sessions started by
|
|
|
9881
10968
|
return;
|
|
9882
10969
|
}
|
|
9883
10970
|
if (tunnels.length === 0) {
|
|
9884
|
-
console.log(
|
|
10971
|
+
console.log(kleur19.yellow("No tunnels found."));
|
|
9885
10972
|
return;
|
|
9886
10973
|
}
|
|
9887
10974
|
for (const tunnel of tunnels) {
|
|
9888
10975
|
console.log(`${tunnel.tunnelId} \xB7 ${tunnel.url} \xB7 port=${tunnel.localPort} \xB7 pid=${tunnel.pid}`);
|
|
9889
10976
|
}
|
|
9890
10977
|
} catch (error) {
|
|
9891
|
-
console.error(
|
|
10978
|
+
console.error(kleur19.red(String(error)));
|
|
9892
10979
|
process.exit(1);
|
|
9893
10980
|
}
|
|
9894
10981
|
});
|
|
@@ -9904,9 +10991,9 @@ tunnelCommand.command("stop").description("Stop a local tunnel session and revok
|
|
|
9904
10991
|
console.log(JSON.stringify(result, null, 2));
|
|
9905
10992
|
return;
|
|
9906
10993
|
}
|
|
9907
|
-
console.log(
|
|
10994
|
+
console.log(kleur19.green(`Tunnel stopped: ${result.tunnelId}`));
|
|
9908
10995
|
} catch (error) {
|
|
9909
|
-
console.error(
|
|
10996
|
+
console.error(kleur19.red(String(error)));
|
|
9910
10997
|
process.exit(1);
|
|
9911
10998
|
}
|
|
9912
10999
|
});
|
|
@@ -9920,7 +11007,7 @@ tunnelCommand.command("logs").description("Show logs for a local tunnel session"
|
|
|
9920
11007
|
json: Boolean(opts.json)
|
|
9921
11008
|
});
|
|
9922
11009
|
} catch (error) {
|
|
9923
|
-
console.error(
|
|
11010
|
+
console.error(kleur19.red(String(error)));
|
|
9924
11011
|
process.exit(1);
|
|
9925
11012
|
}
|
|
9926
11013
|
});
|
|
@@ -9936,7 +11023,158 @@ orgListCommand.option("--access-token <token>", "Instafy or Supabase access toke
|
|
|
9936
11023
|
json: opts.json
|
|
9937
11024
|
});
|
|
9938
11025
|
} catch (error) {
|
|
9939
|
-
console.error(
|
|
11026
|
+
console.error(kleur19.red(String(error)));
|
|
11027
|
+
process.exit(1);
|
|
11028
|
+
}
|
|
11029
|
+
});
|
|
11030
|
+
function teamScopeCommandFactory(nameAndArgs, description) {
|
|
11031
|
+
const command = orgCommand.command(nameAndArgs).description(description);
|
|
11032
|
+
addServerUrlOptions(command);
|
|
11033
|
+
addAccessTokenOptions(command, "Instafy access token");
|
|
11034
|
+
command.option("--team-id <team>", "Team id (UUID) or slug (defaults to your only team)").option("--json", "Output JSON");
|
|
11035
|
+
return command;
|
|
11036
|
+
}
|
|
11037
|
+
var teamMembersCommand = teamScopeCommandFactory("members", "List members of a team");
|
|
11038
|
+
teamMembersCommand.action(async (opts) => {
|
|
11039
|
+
try {
|
|
11040
|
+
await teamMembersList({
|
|
11041
|
+
teamId: opts.teamId,
|
|
11042
|
+
controllerUrl: opts.serverUrl,
|
|
11043
|
+
accessToken: opts.accessToken,
|
|
11044
|
+
json: opts.json
|
|
11045
|
+
});
|
|
11046
|
+
} catch (error) {
|
|
11047
|
+
console.error(kleur19.red(String(error)));
|
|
11048
|
+
process.exit(1);
|
|
11049
|
+
}
|
|
11050
|
+
});
|
|
11051
|
+
var teamInviteCommand = teamScopeCommandFactory(
|
|
11052
|
+
"invite <email>",
|
|
11053
|
+
"Invite a teammate by email (they must sign in with that email to accept)"
|
|
11054
|
+
);
|
|
11055
|
+
teamInviteCommand.option("--role <role>", "owner, admin, builder, or viewer (default: builder)").action(async (email, opts) => {
|
|
11056
|
+
try {
|
|
11057
|
+
await teamInvite({
|
|
11058
|
+
email,
|
|
11059
|
+
role: opts.role,
|
|
11060
|
+
teamId: opts.teamId,
|
|
11061
|
+
controllerUrl: opts.serverUrl,
|
|
11062
|
+
accessToken: opts.accessToken,
|
|
11063
|
+
json: opts.json
|
|
11064
|
+
});
|
|
11065
|
+
} catch (error) {
|
|
11066
|
+
console.error(kleur19.red(String(error)));
|
|
11067
|
+
process.exit(1);
|
|
11068
|
+
}
|
|
11069
|
+
});
|
|
11070
|
+
var teamInviteLinkCommand = teamScopeCommandFactory(
|
|
11071
|
+
"invite-link",
|
|
11072
|
+
"Create a shareable invite link that works with any sign-in method"
|
|
11073
|
+
);
|
|
11074
|
+
teamInviteLinkCommand.option("--role <role>", "builder or viewer (default: builder)").option("--studio-url <url>", "Studio base URL for the accept link (default: https://instafy.dev)").action(async (opts) => {
|
|
11075
|
+
try {
|
|
11076
|
+
await teamInviteLink({
|
|
11077
|
+
role: opts.role,
|
|
11078
|
+
studioUrl: opts.studioUrl,
|
|
11079
|
+
teamId: opts.teamId,
|
|
11080
|
+
controllerUrl: opts.serverUrl,
|
|
11081
|
+
accessToken: opts.accessToken,
|
|
11082
|
+
json: opts.json
|
|
11083
|
+
});
|
|
11084
|
+
} catch (error) {
|
|
11085
|
+
console.error(kleur19.red(String(error)));
|
|
11086
|
+
process.exit(1);
|
|
11087
|
+
}
|
|
11088
|
+
});
|
|
11089
|
+
var teamInvitesCommand = teamScopeCommandFactory(
|
|
11090
|
+
"invites",
|
|
11091
|
+
"List pending email invitations and invite links"
|
|
11092
|
+
);
|
|
11093
|
+
teamInvitesCommand.action(async (opts) => {
|
|
11094
|
+
try {
|
|
11095
|
+
await teamInvites({
|
|
11096
|
+
teamId: opts.teamId,
|
|
11097
|
+
controllerUrl: opts.serverUrl,
|
|
11098
|
+
accessToken: opts.accessToken,
|
|
11099
|
+
json: opts.json
|
|
11100
|
+
});
|
|
11101
|
+
} catch (error) {
|
|
11102
|
+
console.error(kleur19.red(String(error)));
|
|
11103
|
+
process.exit(1);
|
|
11104
|
+
}
|
|
11105
|
+
});
|
|
11106
|
+
var teamAddMemberCommand = teamScopeCommandFactory(
|
|
11107
|
+
"add-member",
|
|
11108
|
+
"Add an existing Instafy account to a team by user id"
|
|
11109
|
+
);
|
|
11110
|
+
teamAddMemberCommand.requiredOption("--user-id <uuid>", "User id of an existing Instafy account").option("--role <role>", "owner, admin, builder, or viewer (default: builder)").action(async (opts) => {
|
|
11111
|
+
try {
|
|
11112
|
+
await teamAddMember({
|
|
11113
|
+
userId: opts.userId,
|
|
11114
|
+
role: opts.role,
|
|
11115
|
+
teamId: opts.teamId,
|
|
11116
|
+
controllerUrl: opts.serverUrl,
|
|
11117
|
+
accessToken: opts.accessToken,
|
|
11118
|
+
json: opts.json
|
|
11119
|
+
});
|
|
11120
|
+
} catch (error) {
|
|
11121
|
+
console.error(kleur19.red(String(error)));
|
|
11122
|
+
process.exit(1);
|
|
11123
|
+
}
|
|
11124
|
+
});
|
|
11125
|
+
var teamAcceptCommand = teamScopeCommandFactory(
|
|
11126
|
+
"accept <token>",
|
|
11127
|
+
"Accept a team invitation or invite link with the current account"
|
|
11128
|
+
);
|
|
11129
|
+
teamAcceptCommand.action(async (token, opts) => {
|
|
11130
|
+
try {
|
|
11131
|
+
await teamAccept({
|
|
11132
|
+
token,
|
|
11133
|
+
teamId: opts.teamId,
|
|
11134
|
+
controllerUrl: opts.serverUrl,
|
|
11135
|
+
accessToken: opts.accessToken,
|
|
11136
|
+
json: opts.json
|
|
11137
|
+
});
|
|
11138
|
+
} catch (error) {
|
|
11139
|
+
console.error(kleur19.red(String(error)));
|
|
11140
|
+
process.exit(1);
|
|
11141
|
+
}
|
|
11142
|
+
});
|
|
11143
|
+
var teamRevokeInviteCommand = teamScopeCommandFactory(
|
|
11144
|
+
"revoke-invite <invitation-id>",
|
|
11145
|
+
"Revoke a pending email invitation"
|
|
11146
|
+
);
|
|
11147
|
+
teamRevokeInviteCommand.option("--yes", "Skip the confirmation prompt").action(async (invitationId, opts) => {
|
|
11148
|
+
try {
|
|
11149
|
+
await teamRevokeInvite({
|
|
11150
|
+
invitationId,
|
|
11151
|
+
yes: opts.yes,
|
|
11152
|
+
teamId: opts.teamId,
|
|
11153
|
+
controllerUrl: opts.serverUrl,
|
|
11154
|
+
accessToken: opts.accessToken,
|
|
11155
|
+
json: opts.json
|
|
11156
|
+
});
|
|
11157
|
+
} catch (error) {
|
|
11158
|
+
console.error(kleur19.red(String(error)));
|
|
11159
|
+
process.exit(1);
|
|
11160
|
+
}
|
|
11161
|
+
});
|
|
11162
|
+
var teamRevokeLinkCommand = teamScopeCommandFactory(
|
|
11163
|
+
"revoke-link <invite-link-id>",
|
|
11164
|
+
"Revoke a shareable invite link"
|
|
11165
|
+
);
|
|
11166
|
+
teamRevokeLinkCommand.option("--yes", "Skip the confirmation prompt").action(async (inviteLinkId, opts) => {
|
|
11167
|
+
try {
|
|
11168
|
+
await teamRevokeLink({
|
|
11169
|
+
inviteLinkId,
|
|
11170
|
+
yes: opts.yes,
|
|
11171
|
+
teamId: opts.teamId,
|
|
11172
|
+
controllerUrl: opts.serverUrl,
|
|
11173
|
+
accessToken: opts.accessToken,
|
|
11174
|
+
json: opts.json
|
|
11175
|
+
});
|
|
11176
|
+
} catch (error) {
|
|
11177
|
+
console.error(kleur19.red(String(error)));
|
|
9940
11178
|
process.exit(1);
|
|
9941
11179
|
}
|
|
9942
11180
|
});
|
|
@@ -9961,17 +11199,17 @@ profileCommand.command("list").description("List saved CLI profiles").option("--
|
|
|
9961
11199
|
return;
|
|
9962
11200
|
}
|
|
9963
11201
|
if (profiles.length === 0) {
|
|
9964
|
-
console.log(
|
|
9965
|
-
console.log(`Create one with: ${
|
|
11202
|
+
console.log(kleur19.yellow("No profiles found."));
|
|
11203
|
+
console.log(`Create one with: ${kleur19.cyan("instafy login --profile <name>")}`);
|
|
9966
11204
|
return;
|
|
9967
11205
|
}
|
|
9968
|
-
console.log(
|
|
11206
|
+
console.log(kleur19.green("Instafy CLI profiles"));
|
|
9969
11207
|
for (const profile of profiles) {
|
|
9970
|
-
const token = profile.accessTokenSet ?
|
|
9971
|
-
console.log(`- ${
|
|
11208
|
+
const token = profile.accessTokenSet ? kleur19.green("token") : kleur19.yellow("no-token");
|
|
11209
|
+
console.log(`- ${kleur19.cyan(profile.name)} (${token})`);
|
|
9972
11210
|
}
|
|
9973
11211
|
} catch (error) {
|
|
9974
|
-
console.error(
|
|
11212
|
+
console.error(kleur19.red(String(error)));
|
|
9975
11213
|
process.exit(1);
|
|
9976
11214
|
}
|
|
9977
11215
|
});
|
|
@@ -9991,7 +11229,7 @@ historyMessagesCommand.option("--limit <n>", "Max messages to return (1-200, def
|
|
|
9991
11229
|
pretty: opts.pretty
|
|
9992
11230
|
});
|
|
9993
11231
|
} catch (error) {
|
|
9994
|
-
console.error(
|
|
11232
|
+
console.error(kleur19.red(String(error)));
|
|
9995
11233
|
process.exit(1);
|
|
9996
11234
|
}
|
|
9997
11235
|
});
|
|
@@ -10008,7 +11246,7 @@ historyRunsCommand.option("--limit <n>", "Max runs to return (1-200, default: 50
|
|
|
10008
11246
|
pretty: opts.pretty
|
|
10009
11247
|
});
|
|
10010
11248
|
} catch (error) {
|
|
10011
|
-
console.error(
|
|
11249
|
+
console.error(kleur19.red(String(error)));
|
|
10012
11250
|
process.exit(1);
|
|
10013
11251
|
}
|
|
10014
11252
|
});
|
|
@@ -10025,7 +11263,7 @@ historyConversationsCommand.option("--limit <n>", "Max conversations to return (
|
|
|
10025
11263
|
pretty: opts.pretty
|
|
10026
11264
|
});
|
|
10027
11265
|
} catch (error) {
|
|
10028
|
-
console.error(
|
|
11266
|
+
console.error(kleur19.red(String(error)));
|
|
10029
11267
|
process.exit(1);
|
|
10030
11268
|
}
|
|
10031
11269
|
});
|
|
@@ -10046,7 +11284,7 @@ conversationCreateCommand.action(async (opts) => {
|
|
|
10046
11284
|
json: opts.json
|
|
10047
11285
|
});
|
|
10048
11286
|
} catch (error) {
|
|
10049
|
-
console.error(
|
|
11287
|
+
console.error(kleur19.red(String(error)));
|
|
10050
11288
|
process.exit(1);
|
|
10051
11289
|
}
|
|
10052
11290
|
});
|
|
@@ -10064,7 +11302,7 @@ conversationListCommand.action(async (opts) => {
|
|
|
10064
11302
|
json: opts.json
|
|
10065
11303
|
});
|
|
10066
11304
|
} catch (error) {
|
|
10067
|
-
console.error(
|
|
11305
|
+
console.error(kleur19.red(String(error)));
|
|
10068
11306
|
process.exit(1);
|
|
10069
11307
|
}
|
|
10070
11308
|
});
|
|
@@ -10083,7 +11321,7 @@ conversationSearchCommand.action(async (queryParts, opts) => {
|
|
|
10083
11321
|
json: opts.json
|
|
10084
11322
|
});
|
|
10085
11323
|
} catch (error) {
|
|
10086
|
-
console.error(
|
|
11324
|
+
console.error(kleur19.red(String(error)));
|
|
10087
11325
|
process.exit(1);
|
|
10088
11326
|
}
|
|
10089
11327
|
});
|
|
@@ -10102,7 +11340,7 @@ conversationShowCommand.action(async (targetParts, opts) => {
|
|
|
10102
11340
|
json: opts.json
|
|
10103
11341
|
});
|
|
10104
11342
|
} catch (error) {
|
|
10105
|
-
console.error(
|
|
11343
|
+
console.error(kleur19.red(String(error)));
|
|
10106
11344
|
process.exit(1);
|
|
10107
11345
|
}
|
|
10108
11346
|
});
|