pylot-cli 0.1.4 → 0.1.5
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.mjs +61 -43
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -14362,37 +14362,42 @@ async function resolveConfig(opts) {
|
|
|
14362
14362
|
pickToken(env2.PYLOT_API_TOKEN, "PYLOT_API_TOKEN");
|
|
14363
14363
|
pickToken(env2.PYLOT_SESSION_JWT, "PYLOT_SESSION_JWT");
|
|
14364
14364
|
pickToken(env2.PYLOT_BROKER_TOKEN, "PYLOT_BROKER_TOKEN");
|
|
14365
|
-
pickToken(env2.PYLOT_DISPATCH_TOKEN, "PYLOT_DISPATCH_TOKEN");
|
|
14366
14365
|
pickUrl(env2.PYLOT_DISPATCH_URL, "PYLOT_DISPATCH_URL");
|
|
14367
14366
|
pickUrl(env2.PYLOT_API_URL, "PYLOT_API_URL");
|
|
14368
14367
|
pickUrl(env2.PYLOT_GATEWAY_URL, "PYLOT_GATEWAY_URL");
|
|
14369
14368
|
pickUrl(env2.PYLOT_API, "PYLOT_API");
|
|
14370
|
-
pickToken(await confGet("token"), "config file");
|
|
14371
14369
|
pickUrl(await confGet("url"), "config file");
|
|
14372
|
-
|
|
14373
|
-
|
|
14374
|
-
|
|
14375
|
-
|
|
14376
|
-
|
|
14377
|
-
|
|
14378
|
-
|
|
14379
|
-
|
|
14380
|
-
|
|
14381
|
-
|
|
14382
|
-
|
|
14383
|
-
|
|
14384
|
-
|
|
14385
|
-
}
|
|
14386
|
-
entry = rotated;
|
|
14387
|
-
} else if (new Date(entry.expires_at).getTime() <= Date.now()) {
|
|
14388
|
-
throw new UsageError(`stored token for ${org} expired and refresh failed \u2014 run: pylot auth login`);
|
|
14370
|
+
const selectedOrg = opts.org ?? await confGet("org");
|
|
14371
|
+
if (selectedOrg && token === null) {
|
|
14372
|
+
let entry;
|
|
14373
|
+
try {
|
|
14374
|
+
const creds = readCredentials();
|
|
14375
|
+
entry = creds.orgs[selectedOrg];
|
|
14376
|
+
if (entry?.token && entry.refresh_token && baseUrl && isNearExpiry(entry.expires_at)) {
|
|
14377
|
+
const rotated = await refreshOrgCredential(baseUrl, selectedOrg, entry).catch(() => null);
|
|
14378
|
+
if (rotated) {
|
|
14379
|
+
creds.orgs[selectedOrg] = rotated;
|
|
14380
|
+
try {
|
|
14381
|
+
writeCredentials(creds);
|
|
14382
|
+
} catch {
|
|
14389
14383
|
}
|
|
14384
|
+
entry = rotated;
|
|
14385
|
+
} else if (new Date(entry.expires_at).getTime() <= Date.now()) {
|
|
14386
|
+
throw new UsageError(`stored token for ${selectedOrg} expired and refresh failed \u2014 run: pylot auth login`);
|
|
14390
14387
|
}
|
|
14391
|
-
if (entry?.token) pickToken(entry.token, "credentials file");
|
|
14392
|
-
} catch (err) {
|
|
14393
|
-
if (err instanceof UsageError) throw err;
|
|
14394
14388
|
}
|
|
14389
|
+
} catch (err) {
|
|
14390
|
+
if (err instanceof UsageError) throw err;
|
|
14395
14391
|
}
|
|
14392
|
+
if (!entry?.token) {
|
|
14393
|
+
throw new UsageError(
|
|
14394
|
+
`no credentials found for org '${selectedOrg}' \u2014 run: pylot auth login --org ${selectedOrg}`
|
|
14395
|
+
);
|
|
14396
|
+
}
|
|
14397
|
+
pickToken(entry.token, "credentials file");
|
|
14398
|
+
} else {
|
|
14399
|
+
pickToken(env2.PYLOT_DISPATCH_TOKEN, "PYLOT_DISPATCH_TOKEN");
|
|
14400
|
+
pickToken(await confGet("token"), "config file");
|
|
14396
14401
|
}
|
|
14397
14402
|
if (!baseUrl) {
|
|
14398
14403
|
throw new UsageError(
|
|
@@ -14918,9 +14923,11 @@ function registerAuth(program3) {
|
|
|
14918
14923
|
);
|
|
14919
14924
|
});
|
|
14920
14925
|
const tokens = auth.command("tokens").description("scoped API tokens (plt_*) \u2014 token plane #1884");
|
|
14921
|
-
tokens.command("create").description("mint a scoped API token (POST /auth/tokens \u2014 requires admin)").
|
|
14926
|
+
tokens.command("create").description("mint a scoped API token (POST /auth/tokens \u2014 requires admin)").option("--org <org>", "org the token is scoped to (or use global --org before the subcommand)").option("--label <label>", "human-readable label").option("--scopes <a,b,c>", "comma-separated scopes (e.g. dispatch,missions:read)").option("--expires-at <iso>", "expiry timestamp (ISO 8601)").action(async (flags, cmd) => {
|
|
14922
14927
|
const { opts, cfg } = await ctx(cmd);
|
|
14923
|
-
const
|
|
14928
|
+
const org = cmd.optsWithGlobals().org;
|
|
14929
|
+
if (!org) throw new UsageError("--org <org> is required");
|
|
14930
|
+
const body = { org, label: flags.label, expires_at: flags.expiresAt };
|
|
14924
14931
|
if (flags.scopes) body.scopes = String(flags.scopes).split(",").map((s) => s.trim()).filter(Boolean);
|
|
14925
14932
|
for (const key of Object.keys(body)) if (body[key] === void 0) delete body[key];
|
|
14926
14933
|
emit(opts, await request(cfg, "/auth/tokens", { method: "POST", body }));
|
|
@@ -15015,7 +15022,7 @@ Waiting for authorization\u2026
|
|
|
15015
15022
|
process.stdout.write(`Credentials written to ~/.pylot/credentials (mode 0600)
|
|
15016
15023
|
`);
|
|
15017
15024
|
if (flags.org) {
|
|
15018
|
-
process.stdout.write(`Active org: ${flags.org} \u2014 use
|
|
15025
|
+
process.stdout.write(`Active org: ${flags.org} \u2014 use --org ${flags.org} or: pylot config set org ${flags.org}
|
|
15019
15026
|
`);
|
|
15020
15027
|
}
|
|
15021
15028
|
return;
|
|
@@ -15069,7 +15076,7 @@ Waiting for authorization\u2026
|
|
|
15069
15076
|
process.stdout.write(`Credentials written to ~/.pylot/credentials (mode 0600)
|
|
15070
15077
|
`);
|
|
15071
15078
|
if (flags.org) {
|
|
15072
|
-
process.stdout.write(`Active org: ${flags.org} \u2014 use
|
|
15079
|
+
process.stdout.write(`Active org: ${flags.org} \u2014 use --org ${flags.org} or: pylot config set org ${flags.org}
|
|
15073
15080
|
`);
|
|
15074
15081
|
}
|
|
15075
15082
|
}
|
|
@@ -15078,7 +15085,7 @@ Waiting for authorization\u2026
|
|
|
15078
15085
|
}
|
|
15079
15086
|
|
|
15080
15087
|
// src/commands/config-cmd.mts
|
|
15081
|
-
var KEYS = ["url", "token", "staging-url", "staging-token"];
|
|
15088
|
+
var KEYS = ["url", "token", "org", "staging-url", "staging-token"];
|
|
15082
15089
|
function redact(key, value) {
|
|
15083
15090
|
if (!key.includes("token") || typeof value !== "string" || value.length === 0) return value;
|
|
15084
15091
|
return value.length > 8 ? `${value.slice(0, 4)}\u2026${value.slice(-4)}` : "****";
|
|
@@ -15332,14 +15339,16 @@ function convPath(id, sub = "") {
|
|
|
15332
15339
|
}
|
|
15333
15340
|
function registerConversations(program3) {
|
|
15334
15341
|
const conversations = program3.command("conversations").alias("convo").description("chat conversations: lifecycle, messages, wakes, resources");
|
|
15335
|
-
conversations.command("create").description("create a conversation (POST /conversations)").
|
|
15342
|
+
conversations.command("create").description("create a conversation (POST /conversations)").option("--org <org>", "owning org (required; or use global --org before the subcommand)").option("--title <title>", "conversation title").option("--team <team>", "team name (must belong to --org)").option("--repos <a,b>", "comma-separated repo list").option("--branch <branch>", "working branch").option("--user-handle <handle>", "user handle").action(async (flags, cmd) => {
|
|
15336
15343
|
const { opts, cfg } = await ctx(cmd);
|
|
15344
|
+
const org = cmd.optsWithGlobals().org;
|
|
15345
|
+
if (!org) throw new UsageError("--org <org> is required");
|
|
15337
15346
|
emit(
|
|
15338
15347
|
opts,
|
|
15339
15348
|
await request(cfg, "/conversations", {
|
|
15340
15349
|
method: "POST",
|
|
15341
15350
|
body: {
|
|
15342
|
-
org
|
|
15351
|
+
org,
|
|
15343
15352
|
title: flags.title,
|
|
15344
15353
|
team: flags.team,
|
|
15345
15354
|
repos: flags.repos ? String(flags.repos).split(",").map((r) => r.trim()).filter(Boolean) : void 0,
|
|
@@ -15700,7 +15709,7 @@ function withParentBuildOpts(flags, cmd) {
|
|
|
15700
15709
|
function registerDeploy(program3) {
|
|
15701
15710
|
const deploy = program3.command("deploy").description(
|
|
15702
15711
|
"trigger a cdk deploy via CodeBuild (POST /admin/deploy) \u2014 a 409 means a deploy is already running (deploy lock held: {stage, held_by, since, build_id}); wait for it or poll `pylot deploy status`"
|
|
15703
|
-
).option("--source-version <ref>", "git ref to deploy (default: gateway's stage branch)").option("--wait", "poll the build to a terminal state (exit 0 only on SUCCEEDED)").option("--timeout <seconds>", "max seconds to wait (default 1500 = 25min)", (v) => parseInt(v, 10), 1500).action(async (flags, cmd) => {
|
|
15712
|
+
).allowExcessArguments(false).showHelpAfterError("(run 'pylot deploy --help' to list valid subcommands)").option("--source-version <ref>", "git ref to deploy (default: gateway's stage branch)").option("--wait", "poll the build to a terminal state (exit 0 only on SUCCEEDED)").option("--timeout <seconds>", "max seconds to wait (default 1500 = 25min)", (v) => parseInt(v, 10), 1500).action(async (flags, cmd) => {
|
|
15704
15713
|
const { opts, cfg } = await ctx(cmd);
|
|
15705
15714
|
const body = {};
|
|
15706
15715
|
if (flags.sourceVersion) body.source_version = flags.sourceVersion;
|
|
@@ -15898,21 +15907,24 @@ function registerSkills(program3) {
|
|
|
15898
15907
|
const { opts, cfg } = await ctx(cmd);
|
|
15899
15908
|
emit(opts, await request(cfg, "/admin/skills/lock"));
|
|
15900
15909
|
});
|
|
15901
|
-
skills.command("staleness").description("SHA-mismatch report vs origin HEAD (GET /admin/skills/staleness?org=<org>)").
|
|
15910
|
+
skills.command("staleness").description("SHA-mismatch report vs origin HEAD (GET /admin/skills/staleness?org=<org>)").option("--org <org>", "GitHub org to check (staleness is per-org, #1919; or use global --org before the subcommand)").action(async (flags, cmd) => {
|
|
15902
15911
|
const { opts, cfg } = await ctx(cmd);
|
|
15903
|
-
|
|
15912
|
+
const org = cmd.optsWithGlobals().org;
|
|
15913
|
+
if (!org) throw new UsageError("--org <org> is required");
|
|
15914
|
+
emit(opts, await request(cfg, "/admin/skills/staleness", { query: { org } }));
|
|
15904
15915
|
});
|
|
15905
15916
|
skills.command("sync").description(
|
|
15906
15917
|
"trigger the CodeBuild skills-sync job for one org (POST /admin/skills/sync, body {org}) or every installed org (--all \u2192 POST /admin/skills/sync-all)"
|
|
15907
15918
|
).option("--all", "fan out one sync per installed org").option("--org <org>", "GitHub org to sync (required unless --all)").action(async (flags, cmd) => {
|
|
15908
15919
|
const { opts, cfg } = await ctx(cmd);
|
|
15920
|
+
const org = cmd.optsWithGlobals().org;
|
|
15909
15921
|
if (flags.all) {
|
|
15910
|
-
if (
|
|
15922
|
+
if (org) throw new UsageError("pass either --all or --org <org>, not both");
|
|
15911
15923
|
emit(opts, await request(cfg, "/admin/skills/sync-all", { method: "POST", body: {} }));
|
|
15912
15924
|
return;
|
|
15913
15925
|
}
|
|
15914
|
-
if (!
|
|
15915
|
-
emit(opts, await request(cfg, "/admin/skills/sync", { method: "POST", body: { org
|
|
15926
|
+
if (!org) throw new UsageError("--org <org> is required (or --all to sync every installed org)");
|
|
15927
|
+
emit(opts, await request(cfg, "/admin/skills/sync", { method: "POST", body: { org } }));
|
|
15916
15928
|
});
|
|
15917
15929
|
skills.command("sync-status").description("skills-sync build status + logs (GET /admin/skills/sync/:id)").argument("[build_id]", "CodeBuild build id (from `skills sync`)").action(async (buildId, _flags, cmd) => {
|
|
15918
15930
|
const { opts, cfg } = await ctx(cmd);
|
|
@@ -15924,26 +15936,30 @@ function registerSkills(program3) {
|
|
|
15924
15936
|
const body = await bodyFromArgs(fields, flags.file);
|
|
15925
15937
|
emit(opts, await request(cfg, "/admin/skills/reconcile-org", { method: "POST", body }));
|
|
15926
15938
|
});
|
|
15927
|
-
skills.command("update").description("update catalog metadata (PATCH /admin/skills/:name?org=<org> \u2014 tags, origin_repo, version, commit_sha, needs_worker)").argument("<name>").argument("[fields...]", "key=value pairs").
|
|
15939
|
+
skills.command("update").description("update catalog metadata (PATCH /admin/skills/:name?org=<org> \u2014 tags, origin_repo, version, commit_sha, needs_worker)").argument("<name>").argument("[fields...]", "key=value pairs").option("--org <org>", "owning org (catalog rows are keyed (org, name)); or use global --org before the subcommand)").option("--file <path>", "JSON body from file ('-' for stdin)").action(async (name, fields, flags, cmd) => {
|
|
15928
15940
|
const { opts, cfg } = await ctx(cmd);
|
|
15941
|
+
const org = cmd.optsWithGlobals().org;
|
|
15942
|
+
if (!org) throw new UsageError("--org <org> is required");
|
|
15929
15943
|
const body = await bodyFromArgs(fields, flags.file);
|
|
15930
15944
|
emit(
|
|
15931
15945
|
opts,
|
|
15932
15946
|
await request(cfg, `/admin/skills/${encodeURIComponent(name)}`, {
|
|
15933
15947
|
method: "PATCH",
|
|
15934
|
-
query: { org
|
|
15948
|
+
query: { org },
|
|
15935
15949
|
body
|
|
15936
15950
|
})
|
|
15937
15951
|
);
|
|
15938
15952
|
});
|
|
15939
|
-
skills.command("delete").description("remove a skill from the catalog (DELETE /admin/skills/:name?org=<org>)").argument("<name>").
|
|
15953
|
+
skills.command("delete").description("remove a skill from the catalog (DELETE /admin/skills/:name?org=<org>)").argument("<name>").option("--org <org>", "owning org (catalog rows are keyed (org, name)); or use global --org before the subcommand)").option("--force", "required to confirm deletion").action(async (name, flags, cmd) => {
|
|
15940
15954
|
const { opts, cfg } = await ctx(cmd);
|
|
15941
15955
|
if (!flags.force) throw new UsageError("deleting a catalog skill is destructive \u2014 re-run with --force");
|
|
15956
|
+
const org = cmd.optsWithGlobals().org;
|
|
15957
|
+
if (!org) throw new UsageError("--org <org> is required");
|
|
15942
15958
|
emit(
|
|
15943
15959
|
opts,
|
|
15944
15960
|
await request(cfg, `/admin/skills/${encodeURIComponent(name)}`, {
|
|
15945
15961
|
method: "DELETE",
|
|
15946
|
-
query: { org
|
|
15962
|
+
query: { org }
|
|
15947
15963
|
})
|
|
15948
15964
|
);
|
|
15949
15965
|
});
|
|
@@ -16004,9 +16020,11 @@ function registerAutomations(program3) {
|
|
|
16004
16020
|
init_http();
|
|
16005
16021
|
function registerProviders(program3) {
|
|
16006
16022
|
const providers = program3.command("providers").description("LLM provider instances and org purpose-chains");
|
|
16007
|
-
providers.command("list").description("provider instances for an org (GET /admin/providers?org=)").
|
|
16023
|
+
providers.command("list").description("provider instances for an org (GET /admin/providers?org=)").option("--org <org>", "org to list (required by the gateway; or use global --org before the subcommand)").action(async (flags, cmd) => {
|
|
16008
16024
|
const { opts, cfg } = await ctx(cmd);
|
|
16009
|
-
|
|
16025
|
+
const org = cmd.optsWithGlobals().org;
|
|
16026
|
+
if (!org) throw new UsageError("--org <org> is required");
|
|
16027
|
+
emit(opts, await request(cfg, "/admin/providers", { query: { org } }));
|
|
16010
16028
|
});
|
|
16011
16029
|
providers.command("create").description("create a provider instance (POST /admin/providers, body {org, type, model, label?, credentials?})").argument("[fields...]", "key=value pairs (e.g. org=my-org type=anthropic-api model=opus)").option("--file <path>", "JSON body from file ('-' for stdin)").action(async (fields, flags, cmd) => {
|
|
16012
16030
|
const { opts, cfg } = await ctx(cmd);
|
|
@@ -16113,12 +16131,12 @@ function registerAssets(program3) {
|
|
|
16113
16131
|
}
|
|
16114
16132
|
|
|
16115
16133
|
// src/index.mts
|
|
16116
|
-
var VERSION = true ? "0.1.
|
|
16134
|
+
var VERSION = true ? "0.1.5" : "0.0.0-dev";
|
|
16117
16135
|
installEpipeGuard();
|
|
16118
16136
|
var program2 = new Command();
|
|
16119
16137
|
program2.name("pylot").description(
|
|
16120
16138
|
"Pylot gateway CLI \u2014 dispatch missions, tail logs, manage teams/admin/secrets without curl.\nJSON on non-TTY stdout (pipe-friendly for agents and jq); tables on TTY."
|
|
16121
|
-
).allowExcessArguments(false).configureHelp({ sortSubcommands: true }).version(VERSION).option("--url <url>", "gateway base URL (default: PYLOT_DISPATCH_URL / PYLOT_API_URL / PYLOT_GATEWAY_URL)").option("--token <token>", "bearer token (default: PYLOT_API_TOKEN / PYLOT_SESSION_JWT / PYLOT_BROKER_TOKEN / PYLOT_DISPATCH_TOKEN)").option("--env <env>", "target environment: prod | staging (staging uses PYLOT_STAGING_URL + PYLOT_STAGING_DISPATCH_TOKEN)").option("--json", "force JSON output even on a TTY").option("-q, --quiet", "suppress progress notes on stderr");
|
|
16139
|
+
).allowExcessArguments(false).configureHelp({ sortSubcommands: true }).version(VERSION).option("--url <url>", "gateway base URL (default: PYLOT_DISPATCH_URL / PYLOT_API_URL / PYLOT_GATEWAY_URL)").option("--token <token>", "bearer token (default: PYLOT_API_TOKEN / PYLOT_SESSION_JWT / PYLOT_BROKER_TOKEN / PYLOT_DISPATCH_TOKEN)").option("--org <org>", "default org for credential resolution (selects ~/.pylot/credentials entry; overrides pylot config set org)").option("--env <env>", "target environment: prod | staging (staging uses PYLOT_STAGING_URL + PYLOT_STAGING_DISPATCH_TOKEN)").option("--json", "force JSON output even on a TTY").option("-q, --quiet", "suppress progress notes on stderr");
|
|
16122
16140
|
program2.exitOverride();
|
|
16123
16141
|
program2.configureOutput({ outputError: (str, write) => write(str) });
|
|
16124
16142
|
registerCore(program2);
|