@khal-os/cli 1.0.27 → 1.0.39
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +143 -14
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -14262,17 +14262,17 @@ function detectArch() {
|
|
|
14262
14262
|
return "arm64";
|
|
14263
14263
|
return "x64";
|
|
14264
14264
|
}
|
|
14265
|
-
function getNatsUrl(version,
|
|
14266
|
-
const os2 =
|
|
14265
|
+
function getNatsUrl(version, platform2, arch) {
|
|
14266
|
+
const os2 = platform2 === "windows" ? "windows" : platform2;
|
|
14267
14267
|
const a = arch === "arm64" ? "arm64" : "amd64";
|
|
14268
|
-
const ext =
|
|
14268
|
+
const ext = platform2 === "windows" ? "zip" : "tar.gz";
|
|
14269
14269
|
return `https://github.com/nats-io/nats-server/releases/download/v${version}/nats-server-v${version}-${os2}-${a}.${ext}`;
|
|
14270
14270
|
}
|
|
14271
|
-
function getBunUrl(version,
|
|
14272
|
-
const os2 =
|
|
14271
|
+
function getBunUrl(version, platform2, arch) {
|
|
14272
|
+
const os2 = platform2 === "windows" ? "windows" : platform2;
|
|
14273
14273
|
const a = arch === "arm64" ? "aarch64" : "x64";
|
|
14274
14274
|
const profile = "baseline";
|
|
14275
|
-
const ext =
|
|
14275
|
+
const ext = platform2 === "windows" ? "zip" : "zip";
|
|
14276
14276
|
return `https://github.com/oven-sh/bun/releases/download/bun-v${version}/bun-${os2}-${a}-${profile}.${ext}`;
|
|
14277
14277
|
}
|
|
14278
14278
|
function followRedirects(url, maxRedirects = 5) {
|
|
@@ -14508,10 +14508,10 @@ var init_local = __esm(() => {
|
|
|
14508
14508
|
}
|
|
14509
14509
|
async ensureDeps() {
|
|
14510
14510
|
const binDir = join4(this.dataDir, "bin");
|
|
14511
|
-
const
|
|
14511
|
+
const platform2 = detectPlatform();
|
|
14512
14512
|
const arch = detectArch();
|
|
14513
14513
|
const emitter = (event) => this.emit(event);
|
|
14514
|
-
this.natsBin = await ensureBinary("nats-server", NATS_VERSION, binDir, getNatsUrl(NATS_VERSION,
|
|
14514
|
+
this.natsBin = await ensureBinary("nats-server", NATS_VERSION, binDir, getNatsUrl(NATS_VERSION, platform2, arch), emitter);
|
|
14515
14515
|
}
|
|
14516
14516
|
async depsReady() {
|
|
14517
14517
|
const binDir = join4(this.dataDir, "bin");
|
|
@@ -14892,9 +14892,9 @@ function isInCluster() {
|
|
|
14892
14892
|
_inClusterCached = existsSync5(IN_CLUSTER_TOKEN_PATH) && !!process.env.KUBERNETES_SERVICE_HOST;
|
|
14893
14893
|
return _inClusterCached;
|
|
14894
14894
|
}
|
|
14895
|
-
var
|
|
14895
|
+
var exec2, IN_CLUSTER_TOKEN_PATH = "/var/run/secrets/kubernetes.io/serviceaccount/token", _inClusterCached, DEFAULT_KUBECONFIG = "/etc/rancher/k3s/k3s.yaml", DEFAULT_NATS_URL = "nats://nats:4222", DEFAULT_RESOURCES, SANDBOX_RUNTIME_CLASS = "sysbox-runc", SANDBOX_PVC_SIZE = "20Gi", SANDBOX_STORAGE_CLASS = "local-path", SANDBOX_SSH_PORT = 22, SANDBOX_NAMESPACE = "khal-sandbox", SANDBOX_HELM_CHART, SANDBOX_RESOURCES, KubernetesRuntime;
|
|
14896
14896
|
var init_kubernetes = __esm(() => {
|
|
14897
|
-
|
|
14897
|
+
exec2 = promisify(execFile);
|
|
14898
14898
|
DEFAULT_RESOURCES = {
|
|
14899
14899
|
requests: { cpu: "100m", memory: "256Mi" },
|
|
14900
14900
|
limits: { cpu: "1", memory: "1Gi" }
|
|
@@ -14978,7 +14978,7 @@ var init_kubernetes = __esm(() => {
|
|
|
14978
14978
|
}
|
|
14979
14979
|
if (this.sandboxMode) {
|
|
14980
14980
|
try {
|
|
14981
|
-
await
|
|
14981
|
+
await exec2("helm", ["version", "--short"], { timeout: 1e4 });
|
|
14982
14982
|
this.emit({ type: "dep:ready", name: "helm", path: "helm" });
|
|
14983
14983
|
} catch {
|
|
14984
14984
|
throw new Error("helm not found. Required for sandbox deployment.");
|
|
@@ -15062,7 +15062,7 @@ var init_kubernetes = __esm(() => {
|
|
|
15062
15062
|
message: `helm ${helmArgs.join(" ")}`
|
|
15063
15063
|
});
|
|
15064
15064
|
try {
|
|
15065
|
-
await
|
|
15065
|
+
await exec2("helm", helmArgs, { timeout: 240000 });
|
|
15066
15066
|
} catch (err) {
|
|
15067
15067
|
const msg = err instanceof Error ? err.message : String(err);
|
|
15068
15068
|
throw new Error(`helm upgrade --install ${this.helmRelease} failed: ${msg}`);
|
|
@@ -15138,7 +15138,7 @@ var init_kubernetes = __esm(() => {
|
|
|
15138
15138
|
}
|
|
15139
15139
|
async stopSandbox() {
|
|
15140
15140
|
try {
|
|
15141
|
-
await
|
|
15141
|
+
await exec2("helm", [...this.kubeconfigArgs(), "uninstall", this.helmRelease, "--namespace", this.namespace, "--wait"], { timeout: 60000 });
|
|
15142
15142
|
this.emit({
|
|
15143
15143
|
type: "log",
|
|
15144
15144
|
source: "kubernetes",
|
|
@@ -15300,7 +15300,7 @@ var init_kubernetes = __esm(() => {
|
|
|
15300
15300
|
return this.kubeconfig ? ["--kubeconfig", this.kubeconfig] : [];
|
|
15301
15301
|
}
|
|
15302
15302
|
async kubectl(args) {
|
|
15303
|
-
const { stdout } = await
|
|
15303
|
+
const { stdout } = await exec2("kubectl", [...this.kubeconfigArgs(), ...args], {
|
|
15304
15304
|
timeout: 30000
|
|
15305
15305
|
});
|
|
15306
15306
|
return stdout;
|
|
@@ -20307,6 +20307,134 @@ ${source_default.bold("Leaderboard")}
|
|
|
20307
20307
|
console.log("");
|
|
20308
20308
|
});
|
|
20309
20309
|
|
|
20310
|
+
// src/commands/auth.ts
|
|
20311
|
+
import { exec } from "node:child_process";
|
|
20312
|
+
import { platform } from "node:os";
|
|
20313
|
+
import { setTimeout as wait } from "node:timers/promises";
|
|
20314
|
+
var PLATFORM_DEFAULT = process.env.KHAL_PLATFORM_URL ?? "https://platform.khal.ai";
|
|
20315
|
+
function openBrowser(url) {
|
|
20316
|
+
const cmd = platform() === "darwin" ? `open "${url}"` : platform() === "win32" ? `start "" "${url}"` : `xdg-open "${url}"`;
|
|
20317
|
+
exec(cmd, () => {});
|
|
20318
|
+
}
|
|
20319
|
+
async function fetchJson(url, init) {
|
|
20320
|
+
const resp = await fetch(url, init);
|
|
20321
|
+
const body = await resp.json().catch(() => ({}));
|
|
20322
|
+
if (!resp.ok || body.error) {
|
|
20323
|
+
throw new Error(body.error ?? `HTTP ${resp.status}`);
|
|
20324
|
+
}
|
|
20325
|
+
return body;
|
|
20326
|
+
}
|
|
20327
|
+
async function pollForConnection(platformUrl, userId, provider, timeoutMs) {
|
|
20328
|
+
const start = Date.now();
|
|
20329
|
+
while (Date.now() - start < timeoutMs) {
|
|
20330
|
+
try {
|
|
20331
|
+
const list = await fetchJson(`${platformUrl}/v1/integrations/list?userId=${encodeURIComponent(userId)}`);
|
|
20332
|
+
const match = (list.integrations ?? []).find((i) => i.provider === provider && !i.revoked);
|
|
20333
|
+
if (match)
|
|
20334
|
+
return match;
|
|
20335
|
+
} catch {}
|
|
20336
|
+
await wait(2000);
|
|
20337
|
+
}
|
|
20338
|
+
return null;
|
|
20339
|
+
}
|
|
20340
|
+
var authCommand = new Command("auth").description("Connect third-party accounts (GitHub for private pack installs)");
|
|
20341
|
+
authCommand.command("github").description("Authorize Khal OS to read your GitHub repos for pack installs").option("-u, --user-id <id>", "User ID (defaults to KHAL_USER_ID env)").option("-p, --platform <url>", `Platform URL (default: ${PLATFORM_DEFAULT})`).option("--no-open", "Don't auto-open the browser; print the URL only").option("--timeout <seconds>", "Polling timeout in seconds", "180").action(async (opts) => {
|
|
20342
|
+
const userId = opts.userId ?? process.env.KHAL_USER_ID;
|
|
20343
|
+
if (!userId) {
|
|
20344
|
+
console.error(source_default.red("User ID required. Pass --user-id <id> or set KHAL_USER_ID. Use the same id you'll pass to install workflows."));
|
|
20345
|
+
process.exit(1);
|
|
20346
|
+
}
|
|
20347
|
+
const platformUrl = opts.platform ?? PLATFORM_DEFAULT;
|
|
20348
|
+
const timeoutSec = Number.parseInt(opts.timeout ?? "180", 10);
|
|
20349
|
+
console.log(`${source_default.dim("platform:")} ${platformUrl}`);
|
|
20350
|
+
console.log(`${source_default.dim("user-id:")} ${userId}`);
|
|
20351
|
+
console.log();
|
|
20352
|
+
console.log(source_default.yellow("Requesting authorize URL..."));
|
|
20353
|
+
let authResp;
|
|
20354
|
+
try {
|
|
20355
|
+
authResp = await fetchJson(`${platformUrl}/v1/integrations/github/authorize`, {
|
|
20356
|
+
method: "POST",
|
|
20357
|
+
headers: { "Content-Type": "application/json" },
|
|
20358
|
+
body: JSON.stringify({ userId })
|
|
20359
|
+
});
|
|
20360
|
+
} catch (err) {
|
|
20361
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
20362
|
+
console.error(source_default.red(`Authorize request failed: ${msg}`));
|
|
20363
|
+
console.error(source_default.dim("Is the platform deployed with GITHUB_OAUTH_CLIENT_ID set?"));
|
|
20364
|
+
process.exit(1);
|
|
20365
|
+
return;
|
|
20366
|
+
}
|
|
20367
|
+
if (!authResp.authorizeUrl) {
|
|
20368
|
+
console.error(source_default.red("Platform did not return an authorize URL."));
|
|
20369
|
+
process.exit(1);
|
|
20370
|
+
return;
|
|
20371
|
+
}
|
|
20372
|
+
console.log();
|
|
20373
|
+
console.log(source_default.bold("Open this URL in your browser to authorize:"));
|
|
20374
|
+
console.log(` ${source_default.cyan(authResp.authorizeUrl)}`);
|
|
20375
|
+
console.log();
|
|
20376
|
+
if (opts.open !== false) {
|
|
20377
|
+
openBrowser(authResp.authorizeUrl);
|
|
20378
|
+
console.log(source_default.dim("(opening in your default browser)"));
|
|
20379
|
+
console.log();
|
|
20380
|
+
}
|
|
20381
|
+
console.log(`${source_default.yellow("Waiting for callback...")} (timeout ${timeoutSec}s)`);
|
|
20382
|
+
const result = await pollForConnection(platformUrl, userId, "github", timeoutSec * 1000);
|
|
20383
|
+
if (!result) {
|
|
20384
|
+
console.error();
|
|
20385
|
+
console.error(source_default.red("Timed out waiting for OAuth callback to complete."));
|
|
20386
|
+
console.error(source_default.dim("You can re-run `khal-os auth github` if you ran out of time, or if approval failed."));
|
|
20387
|
+
process.exit(1);
|
|
20388
|
+
return;
|
|
20389
|
+
}
|
|
20390
|
+
console.log();
|
|
20391
|
+
console.log(`${source_default.green("✓")} GitHub connected as ${source_default.bold(result.providerAccountLogin ?? "?")}`);
|
|
20392
|
+
console.log(`${source_default.dim(" scopes:")} ${result.scopes ?? "(none)"}`);
|
|
20393
|
+
console.log(`${source_default.dim(" connected:")} ${result.connectedAt}`);
|
|
20394
|
+
console.log();
|
|
20395
|
+
console.log(source_default.dim("Token is encrypted at rest on the platform; CLI never sees it."));
|
|
20396
|
+
});
|
|
20397
|
+
authCommand.command("list").description("List your connected provider integrations").option("-u, --user-id <id>", "User ID (defaults to KHAL_USER_ID env)").option("-p, --platform <url>", `Platform URL (default: ${PLATFORM_DEFAULT})`).action(async (opts) => {
|
|
20398
|
+
const userId = opts.userId ?? process.env.KHAL_USER_ID;
|
|
20399
|
+
if (!userId) {
|
|
20400
|
+
console.error(source_default.red("User ID required."));
|
|
20401
|
+
process.exit(1);
|
|
20402
|
+
}
|
|
20403
|
+
const platformUrl = opts.platform ?? PLATFORM_DEFAULT;
|
|
20404
|
+
try {
|
|
20405
|
+
const list = await fetchJson(`${platformUrl}/v1/integrations/list?userId=${encodeURIComponent(userId)}`);
|
|
20406
|
+
const items = list.integrations ?? [];
|
|
20407
|
+
if (items.length === 0) {
|
|
20408
|
+
console.log(source_default.dim("No integrations connected."));
|
|
20409
|
+
return;
|
|
20410
|
+
}
|
|
20411
|
+
for (const it of items) {
|
|
20412
|
+
const status = it.revoked ? source_default.red("revoked") : source_default.green("active");
|
|
20413
|
+
console.log(` ${it.provider} ${source_default.bold(it.providerAccountLogin ?? "?")} ${status} ${source_default.dim(it.scopes ?? "")}`);
|
|
20414
|
+
}
|
|
20415
|
+
} catch (err) {
|
|
20416
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
20417
|
+
console.error(source_default.red(`Failed to list integrations: ${msg}`));
|
|
20418
|
+
process.exit(1);
|
|
20419
|
+
}
|
|
20420
|
+
});
|
|
20421
|
+
authCommand.command("disconnect <provider>").description("Disconnect a provider (soft-revoke; token row stays for audit)").option("-u, --user-id <id>", "User ID (defaults to KHAL_USER_ID env)").option("-p, --platform <url>", `Platform URL (default: ${PLATFORM_DEFAULT})`).action(async (provider, opts) => {
|
|
20422
|
+
const userId = opts.userId ?? process.env.KHAL_USER_ID;
|
|
20423
|
+
if (!userId) {
|
|
20424
|
+
console.error(source_default.red("User ID required."));
|
|
20425
|
+
process.exit(1);
|
|
20426
|
+
}
|
|
20427
|
+
const platformUrl = opts.platform ?? PLATFORM_DEFAULT;
|
|
20428
|
+
try {
|
|
20429
|
+
await fetchJson(`${platformUrl}/v1/integrations/${encodeURIComponent(provider)}?userId=${encodeURIComponent(userId)}`, { method: "DELETE" });
|
|
20430
|
+
console.log(`${source_default.green("✓")} Disconnected ${provider}`);
|
|
20431
|
+
} catch (err) {
|
|
20432
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
20433
|
+
console.error(source_default.red(`Disconnect failed: ${msg}`));
|
|
20434
|
+
process.exit(1);
|
|
20435
|
+
}
|
|
20436
|
+
});
|
|
20437
|
+
|
|
20310
20438
|
// src/commands/deploy.ts
|
|
20311
20439
|
import { readFileSync as readFileSync3 } from "node:fs";
|
|
20312
20440
|
import { resolve } from "node:path";
|
|
@@ -23915,6 +24043,7 @@ ${source_default.bold("◆ Khal OS")}
|
|
|
23915
24043
|
// src/index.ts
|
|
23916
24044
|
var program2 = new Command().name("khal-os").description("Khal OS — develop, deploy, and observe").version(KHALOS_VERSION).option("-i, --instance <url>", "KhalOS instance URL (overrides KHAL_INSTANCE env and config)");
|
|
23917
24045
|
program2.addCommand(appCommand);
|
|
24046
|
+
program2.addCommand(authCommand);
|
|
23918
24047
|
program2.addCommand(devCommand);
|
|
23919
24048
|
program2.addCommand(startCommand);
|
|
23920
24049
|
program2.addCommand(stopCommand);
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@khal-os/cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.39",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
7
|
"module": "./dist/index.js",
|
|
8
8
|
"types": "./dist/index.d.ts",
|
|
9
9
|
"bin": {
|
|
10
|
-
"khal-os": "./dist/
|
|
10
|
+
"khal-os": "./dist/index.js"
|
|
11
11
|
},
|
|
12
12
|
"files": [
|
|
13
13
|
"dist",
|