tines 0.0.285 → 0.0.287
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 +307 -21
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3598,6 +3598,136 @@ var RUN_OUTCOME_BUCKETS = [
|
|
|
3598
3598
|
];
|
|
3599
3599
|
var LIBRARY_MAX_BYTES = 5 * 1024 * 1024;
|
|
3600
3600
|
|
|
3601
|
+
// ../shared/src/permissions.ts
|
|
3602
|
+
var ACCESS_LEVELS = ["none", "read", "write", "delete"];
|
|
3603
|
+
var MAX_PERMISSION_PROJECTS = 1e4;
|
|
3604
|
+
var MAX_PERMISSION_PROJECT_ID_LENGTH = 100;
|
|
3605
|
+
var FULL_API_KEY_PERMISSIONS = Object.freeze({
|
|
3606
|
+
version: 1,
|
|
3607
|
+
projects: Object.freeze({ access: "delete", scope: "all" }),
|
|
3608
|
+
workspace: "delete",
|
|
3609
|
+
control_plane: "delete"
|
|
3610
|
+
});
|
|
3611
|
+
var READ_ONLY_API_KEY_PERMISSIONS = Object.freeze({
|
|
3612
|
+
version: 1,
|
|
3613
|
+
projects: Object.freeze({ access: "read", scope: "all" }),
|
|
3614
|
+
workspace: "read",
|
|
3615
|
+
control_plane: "read"
|
|
3616
|
+
});
|
|
3617
|
+
var PROJECT_AUTOMATION_API_KEY_PERMISSIONS = Object.freeze({
|
|
3618
|
+
version: 1,
|
|
3619
|
+
projects: Object.freeze({ access: "write", scope: Object.freeze([]) }),
|
|
3620
|
+
workspace: "read",
|
|
3621
|
+
control_plane: "none"
|
|
3622
|
+
});
|
|
3623
|
+
var RUNNER_SETUP_API_KEY_PERMISSIONS = Object.freeze({
|
|
3624
|
+
version: 1,
|
|
3625
|
+
projects: Object.freeze({ access: "write", scope: "all" }),
|
|
3626
|
+
workspace: "write",
|
|
3627
|
+
control_plane: "write"
|
|
3628
|
+
});
|
|
3629
|
+
var ApiKeyPermissionsValidationError = class extends Error {
|
|
3630
|
+
constructor(message3, field = "permissions") {
|
|
3631
|
+
super(message3);
|
|
3632
|
+
this.field = field;
|
|
3633
|
+
this.name = "ApiKeyPermissionsValidationError";
|
|
3634
|
+
}
|
|
3635
|
+
field;
|
|
3636
|
+
};
|
|
3637
|
+
function objectAt(value, field) {
|
|
3638
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
3639
|
+
throw new ApiKeyPermissionsValidationError(`"${field}" must be an object`, field);
|
|
3640
|
+
}
|
|
3641
|
+
return value;
|
|
3642
|
+
}
|
|
3643
|
+
function rejectUnknownKeys(value, allowed, field) {
|
|
3644
|
+
const unknown = Object.keys(value).find((key) => !allowed.includes(key));
|
|
3645
|
+
if (unknown !== void 0) {
|
|
3646
|
+
throw new ApiKeyPermissionsValidationError(
|
|
3647
|
+
`"${field}.${unknown}" is not a supported permission field`,
|
|
3648
|
+
`${field}.${unknown}`
|
|
3649
|
+
);
|
|
3650
|
+
}
|
|
3651
|
+
}
|
|
3652
|
+
function accessAt(value, field, allowNone) {
|
|
3653
|
+
if (typeof value !== "string" || !ACCESS_LEVELS.includes(value) || !allowNone && value === "none") {
|
|
3654
|
+
const levels = allowNone ? ACCESS_LEVELS : ACCESS_LEVELS.slice(1);
|
|
3655
|
+
throw new ApiKeyPermissionsValidationError(
|
|
3656
|
+
`"${field}" must be one of ${levels.join(", ")}`,
|
|
3657
|
+
field
|
|
3658
|
+
);
|
|
3659
|
+
}
|
|
3660
|
+
return value;
|
|
3661
|
+
}
|
|
3662
|
+
function projectScopeAt(value) {
|
|
3663
|
+
if (value === "all") return "all";
|
|
3664
|
+
if (!Array.isArray(value)) {
|
|
3665
|
+
throw new ApiKeyPermissionsValidationError(
|
|
3666
|
+
'"permissions.projects.scope" must be "all" or an array of project IDs',
|
|
3667
|
+
"permissions.projects.scope"
|
|
3668
|
+
);
|
|
3669
|
+
}
|
|
3670
|
+
if (value.length > MAX_PERMISSION_PROJECTS) {
|
|
3671
|
+
throw new ApiKeyPermissionsValidationError(
|
|
3672
|
+
`"permissions.projects.scope" must contain at most ${MAX_PERMISSION_PROJECTS} project IDs`,
|
|
3673
|
+
"permissions.projects.scope"
|
|
3674
|
+
);
|
|
3675
|
+
}
|
|
3676
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3677
|
+
for (const id2 of value) {
|
|
3678
|
+
if (typeof id2 !== "string" || id2.length > MAX_PERMISSION_PROJECT_ID_LENGTH || !/^prj_[A-Za-z0-9_-]+$/.test(id2)) {
|
|
3679
|
+
throw new ApiKeyPermissionsValidationError(
|
|
3680
|
+
'"permissions.projects.scope" entries must be valid project IDs',
|
|
3681
|
+
"permissions.projects.scope"
|
|
3682
|
+
);
|
|
3683
|
+
}
|
|
3684
|
+
if (seen.has(id2)) {
|
|
3685
|
+
throw new ApiKeyPermissionsValidationError(
|
|
3686
|
+
`"permissions.projects.scope" contains duplicate project ID "${id2}"`,
|
|
3687
|
+
"permissions.projects.scope"
|
|
3688
|
+
);
|
|
3689
|
+
}
|
|
3690
|
+
seen.add(id2);
|
|
3691
|
+
}
|
|
3692
|
+
return [...seen].sort();
|
|
3693
|
+
}
|
|
3694
|
+
function parseApiKeyPermissions(value) {
|
|
3695
|
+
const policy = objectAt(value, "permissions");
|
|
3696
|
+
rejectUnknownKeys(policy, ["version", "projects", "workspace", "control_plane"], "permissions");
|
|
3697
|
+
if (policy.version !== void 0 && policy.version !== 1) {
|
|
3698
|
+
throw new ApiKeyPermissionsValidationError(
|
|
3699
|
+
'"permissions.version" must be 1',
|
|
3700
|
+
"permissions.version"
|
|
3701
|
+
);
|
|
3702
|
+
}
|
|
3703
|
+
for (const field of ["projects", "workspace", "control_plane"]) {
|
|
3704
|
+
if (!(field in policy)) {
|
|
3705
|
+
throw new ApiKeyPermissionsValidationError(
|
|
3706
|
+
`"permissions.${field}" is required`,
|
|
3707
|
+
`permissions.${field}`
|
|
3708
|
+
);
|
|
3709
|
+
}
|
|
3710
|
+
}
|
|
3711
|
+
const projects = objectAt(policy.projects, "permissions.projects");
|
|
3712
|
+
rejectUnknownKeys(projects, ["access", "scope"], "permissions.projects");
|
|
3713
|
+
if (!("access" in projects) || !("scope" in projects)) {
|
|
3714
|
+
const missing = !("access" in projects) ? "access" : "scope";
|
|
3715
|
+
throw new ApiKeyPermissionsValidationError(
|
|
3716
|
+
`"permissions.projects.${missing}" is required`,
|
|
3717
|
+
`permissions.projects.${missing}`
|
|
3718
|
+
);
|
|
3719
|
+
}
|
|
3720
|
+
return {
|
|
3721
|
+
version: 1,
|
|
3722
|
+
projects: {
|
|
3723
|
+
access: accessAt(projects.access, "permissions.projects.access", false),
|
|
3724
|
+
scope: projectScopeAt(projects.scope)
|
|
3725
|
+
},
|
|
3726
|
+
workspace: accessAt(policy.workspace, "permissions.workspace", true),
|
|
3727
|
+
control_plane: accessAt(policy.control_plane, "permissions.control_plane", true)
|
|
3728
|
+
};
|
|
3729
|
+
}
|
|
3730
|
+
|
|
3601
3731
|
// ../shared/src/events.ts
|
|
3602
3732
|
var text = (t) => ({ kind: "text", text: t });
|
|
3603
3733
|
var name = (t) => ({ kind: "name", text: str(t) });
|
|
@@ -3690,6 +3820,10 @@ var DESCRIBERS = {
|
|
|
3690
3820
|
"workflow.updated": (ev, p) => [text(`${action(ev.type)} workflow`), name(p.name)],
|
|
3691
3821
|
"workflow.deleted": (ev, p) => [text(`${action(ev.type)} workflow`), name(p.name)],
|
|
3692
3822
|
"api_key.created": (_ev, p) => [text("created API key"), name(p.name)],
|
|
3823
|
+
"api_key.permissions_updated": (_ev, p) => [
|
|
3824
|
+
text("updated permissions for API key"),
|
|
3825
|
+
name(p.name)
|
|
3826
|
+
],
|
|
3693
3827
|
"api_key.revoked": (_ev, p) => [text("revoked API key"), name(p.name)],
|
|
3694
3828
|
"scheduled_task.created": (ev, p) => [text(`${action(ev.type)} schedule`), name(p.name)],
|
|
3695
3829
|
"scheduled_task.updated": (ev, p) => [text(`${action(ev.type)} schedule`), name(p.name)],
|
|
@@ -4229,9 +4363,14 @@ function createApiClient(options) {
|
|
|
4229
4363
|
createSupervisorRate: (body) => request("POST", "/api/v1/supervisor/rates", body),
|
|
4230
4364
|
repriceSupervisorRate: (model, cursor = null) => request("POST", "/api/v1/supervisor/rates/reprice", { model, cursor }),
|
|
4231
4365
|
deleteSupervisorRate: (id2) => request("DELETE", `/api/v1/supervisor/rates/${id2}`),
|
|
4232
|
-
// API keys
|
|
4366
|
+
// API keys
|
|
4233
4367
|
listApiKeys: (filters = {}) => get(`/api/v1/api-keys${query(filters)}`),
|
|
4368
|
+
getApiKey: (id2) => get(`/api/v1/api-keys/${id2}`),
|
|
4369
|
+
getCurrentApiKeyAuthority: () => get(
|
|
4370
|
+
"/api/v1/api-keys/current"
|
|
4371
|
+
),
|
|
4234
4372
|
createApiKey: (body) => request("POST", "/api/v1/api-keys", body),
|
|
4373
|
+
updateApiKey: (id2, body) => request("PATCH", `/api/v1/api-keys/${id2}`, body),
|
|
4235
4374
|
revokeApiKey: (id2) => request("DELETE", `/api/v1/api-keys/${id2}`),
|
|
4236
4375
|
exportWorkflowPackage: (id2, opts = {}) => {
|
|
4237
4376
|
const params = new URLSearchParams();
|
|
@@ -6536,6 +6675,142 @@ function register(program3) {
|
|
|
6536
6675
|
});
|
|
6537
6676
|
}
|
|
6538
6677
|
|
|
6678
|
+
// src/commands/api-keys.ts
|
|
6679
|
+
var PRESETS = {
|
|
6680
|
+
full: FULL_API_KEY_PERMISSIONS,
|
|
6681
|
+
"read-only": READ_ONLY_API_KEY_PERMISSIONS,
|
|
6682
|
+
"project-automation": PROJECT_AUTOMATION_API_KEY_PERMISSIONS,
|
|
6683
|
+
"runner-setup": RUNNER_SETUP_API_KEY_PERMISSIONS
|
|
6684
|
+
};
|
|
6685
|
+
function clonePolicy(policy) {
|
|
6686
|
+
return parseApiKeyPermissions(JSON.parse(JSON.stringify(policy)));
|
|
6687
|
+
}
|
|
6688
|
+
function policyFromOptions(opts) {
|
|
6689
|
+
if (Boolean(opts.permissions) === Boolean(opts.preset)) {
|
|
6690
|
+
die("pass exactly one of --permissions or --preset");
|
|
6691
|
+
}
|
|
6692
|
+
if (opts.permissions) {
|
|
6693
|
+
if (opts.projects || opts.allProjects) die("--projects/--all-projects require --preset");
|
|
6694
|
+
try {
|
|
6695
|
+
return parseApiKeyPermissions(JSON.parse(readBodyValue(opts.permissions)));
|
|
6696
|
+
} catch (error) {
|
|
6697
|
+
die(error instanceof Error ? error.message : "invalid permission JSON");
|
|
6698
|
+
}
|
|
6699
|
+
}
|
|
6700
|
+
const preset2 = opts.preset;
|
|
6701
|
+
const policy = clonePolicy(PRESETS[preset2]);
|
|
6702
|
+
if (opts.projects && opts.allProjects) die("pass only one of --projects or --all-projects");
|
|
6703
|
+
if (opts.projects) {
|
|
6704
|
+
policy.projects.scope = opts.projects.split(",").map((id2) => id2.trim()).filter(Boolean);
|
|
6705
|
+
return parseApiKeyPermissions(policy);
|
|
6706
|
+
}
|
|
6707
|
+
if (opts.allProjects) policy.projects.scope = "all";
|
|
6708
|
+
if (preset2 === "project-automation" && policy.projects.scope.length === 0) {
|
|
6709
|
+
die("project-automation requires --projects <id,...> or --all-projects");
|
|
6710
|
+
}
|
|
6711
|
+
return policy;
|
|
6712
|
+
}
|
|
6713
|
+
function scopeLabel(policy) {
|
|
6714
|
+
return policy.projects.scope === "all" ? "all" : policy.projects.scope.length === 0 ? "none" : policy.projects.scope.join(",");
|
|
6715
|
+
}
|
|
6716
|
+
function printKey(key) {
|
|
6717
|
+
table([
|
|
6718
|
+
["ID", "NAME", "PROJECTS", "WORKSPACE", "CONTROL", "USABLE"],
|
|
6719
|
+
[
|
|
6720
|
+
key.id,
|
|
6721
|
+
key.name,
|
|
6722
|
+
`${key.permissions.projects.access}:${scopeLabel(key.permissions)}`,
|
|
6723
|
+
key.permissions.workspace,
|
|
6724
|
+
key.permissions.control_plane,
|
|
6725
|
+
key.usable === false ? "no" : "yes"
|
|
6726
|
+
]
|
|
6727
|
+
]);
|
|
6728
|
+
if (key.run_restrictions) {
|
|
6729
|
+
console.log(
|
|
6730
|
+
`also restricted to run ${key.run_restrictions.run_id}, issue ${key.run_restrictions.issue_id}, project ${key.run_restrictions.project_id}`
|
|
6731
|
+
);
|
|
6732
|
+
}
|
|
6733
|
+
}
|
|
6734
|
+
function addPolicyOptions(command, includePreset) {
|
|
6735
|
+
command.option(
|
|
6736
|
+
"--permissions <json|@file|->",
|
|
6737
|
+
"complete permission policy as JSON, @file, or stdin"
|
|
6738
|
+
);
|
|
6739
|
+
if (includePreset) {
|
|
6740
|
+
command.addOption(
|
|
6741
|
+
new Option("--preset <name>", "permission preset").choices([
|
|
6742
|
+
"full",
|
|
6743
|
+
"read-only",
|
|
6744
|
+
"project-automation",
|
|
6745
|
+
"runner-setup"
|
|
6746
|
+
])
|
|
6747
|
+
);
|
|
6748
|
+
command.option("--projects <ids>", "comma-separated explicit project IDs");
|
|
6749
|
+
command.option("--all-projects", "explicitly use all projects");
|
|
6750
|
+
}
|
|
6751
|
+
return command;
|
|
6752
|
+
}
|
|
6753
|
+
function register2(program3) {
|
|
6754
|
+
const keys = program3.command("api-keys").description("Manage scoped API keys");
|
|
6755
|
+
withCommon(
|
|
6756
|
+
keys.command("list").addOption(
|
|
6757
|
+
new Option("--run-keys <mode>", "run keys to include").choices(["none", "active", "all"])
|
|
6758
|
+
)
|
|
6759
|
+
).action(async (opts) => {
|
|
6760
|
+
const response = await client(opts).listApiKeys({ run_keys: opts.runKeys });
|
|
6761
|
+
if (opts.json) return printJson(response);
|
|
6762
|
+
if (response.items.length === 0) return console.log("no API keys");
|
|
6763
|
+
for (const key of response.items) printKey(key);
|
|
6764
|
+
});
|
|
6765
|
+
withCommon(keys.command("show <id>").description("Show stored and effective authority")).action(
|
|
6766
|
+
async (id2, opts) => {
|
|
6767
|
+
const key = await client(opts).getApiKey(id2);
|
|
6768
|
+
if (opts.json) return printJson(key);
|
|
6769
|
+
printKey(key);
|
|
6770
|
+
}
|
|
6771
|
+
);
|
|
6772
|
+
withCommon(keys.command("current").description("Inspect the acting credential authority")).action(
|
|
6773
|
+
async (opts) => {
|
|
6774
|
+
const current = await client(opts).getCurrentApiKeyAuthority();
|
|
6775
|
+
if (opts.json) return printJson(current);
|
|
6776
|
+
console.log(current.key ? `${current.key.name} (${current.key.id})` : "browser session");
|
|
6777
|
+
const policy = current.authority.effective_permissions;
|
|
6778
|
+
console.log(
|
|
6779
|
+
`projects ${policy.projects.access}:${scopeLabel(policy)}; workspace ${policy.workspace}; control ${policy.control_plane}`
|
|
6780
|
+
);
|
|
6781
|
+
}
|
|
6782
|
+
);
|
|
6783
|
+
withCommon(
|
|
6784
|
+
addPolicyOptions(keys.command("create <name>").description("Create a scoped key"), true)
|
|
6785
|
+
).action(async (name2, opts) => {
|
|
6786
|
+
const created = await client(opts).createApiKey({ name: name2, permissions: policyFromOptions(opts) });
|
|
6787
|
+
if (opts.json) return printJson(created);
|
|
6788
|
+
console.log(created.key);
|
|
6789
|
+
printKey(created);
|
|
6790
|
+
});
|
|
6791
|
+
withCommon(
|
|
6792
|
+
addPolicyOptions(keys.command("update <id>").description("Replace key permissions"), false)
|
|
6793
|
+
).action(async (id2, opts) => {
|
|
6794
|
+
if (!opts.permissions) die("--permissions is required");
|
|
6795
|
+
const api = client(opts);
|
|
6796
|
+
const current = await api.getApiKey(id2);
|
|
6797
|
+
const permissions = policyFromOptions(opts);
|
|
6798
|
+
const updated = await api.updateApiKey(id2, {
|
|
6799
|
+
permissions,
|
|
6800
|
+
expected_permissions: current.permissions
|
|
6801
|
+
});
|
|
6802
|
+
if (opts.json) return printJson(updated);
|
|
6803
|
+
printKey(updated);
|
|
6804
|
+
});
|
|
6805
|
+
withCommon(keys.command("revoke <id>").description("Revoke a key")).action(
|
|
6806
|
+
async (id2, opts) => {
|
|
6807
|
+
await client(opts).revokeApiKey(id2);
|
|
6808
|
+
if (opts.json) return printJson({ revoked: id2 });
|
|
6809
|
+
console.log(`revoked ${id2}`);
|
|
6810
|
+
}
|
|
6811
|
+
);
|
|
6812
|
+
}
|
|
6813
|
+
|
|
6539
6814
|
// src/commands/issues.ts
|
|
6540
6815
|
import { existsSync as existsSync4, mkdirSync as mkdirSync3, readdirSync, readFileSync as readFileSync5, statSync as statSync2, writeFileSync as writeFileSync3 } from "node:fs";
|
|
6541
6816
|
import { basename, dirname as dirname2, join as join3 } from "node:path";
|
|
@@ -7286,7 +7561,7 @@ function printIssueDetail(issue) {
|
|
|
7286
7561
|
console.log(`${issue.project_name}/#${issue.number} ${issue.title}`);
|
|
7287
7562
|
const dup = issue.duplicate_of;
|
|
7288
7563
|
console.log(
|
|
7289
|
-
`state: ${issue.effective_state.name} (${issue.effective_state.category})${dup ? ` (via ${issueRef(dup)} \u2014 duplicate)` : ""} workflow: ${issue.workflow
|
|
7564
|
+
`state: ${issue.effective_state.name} (${issue.effective_state.category})${dup ? ` (via ${issueRef(dup)} \u2014 duplicate)` : ""} workflow: ${issue.workflow?.name ?? "restricted"} updated: ${timestamp(issue.updated_at)}`
|
|
7290
7565
|
);
|
|
7291
7566
|
if (dup) {
|
|
7292
7567
|
console.log(
|
|
@@ -7419,7 +7694,7 @@ matched rule: ${ex.matched_rule.scope_label}`);
|
|
|
7419
7694
|
);
|
|
7420
7695
|
}
|
|
7421
7696
|
}
|
|
7422
|
-
function
|
|
7697
|
+
function register3(program3) {
|
|
7423
7698
|
const issues = program3.command("issues").description("Work with issues");
|
|
7424
7699
|
withList(
|
|
7425
7700
|
issues.command("list").description("List issues across projects (hides done and duplicate issues unless included)").option("-p, --project <name>", "filter by project name or id").option("-s, --state <name>", "filter by state name or id").option("-c, --category <cat>", "filter by state category").option("-w, --workflow <id-or-name>", "filter by workflow").option("-a, --all", "include issues in done states").option("--show-duplicates", "include issues marked as duplicates").option(
|
|
@@ -7584,7 +7859,8 @@ function register2(program3) {
|
|
|
7584
7859
|
const notes = [];
|
|
7585
7860
|
if (body.title !== void 0) notes.push(`title "${updated.title}"`);
|
|
7586
7861
|
if (body.description !== void 0) notes.push("description");
|
|
7587
|
-
if (body.workflow_id !== void 0)
|
|
7862
|
+
if (body.workflow_id !== void 0)
|
|
7863
|
+
notes.push(`workflow "${updated.workflow?.name ?? body.workflow_id}"`);
|
|
7588
7864
|
if (updated.state.id !== issue.state.id) {
|
|
7589
7865
|
notes.push(`state ${issue.state.name} \u2192 ${updated.state.name}`);
|
|
7590
7866
|
}
|
|
@@ -8282,6 +8558,15 @@ async function resolveJournal(api, ref, stateRef2) {
|
|
|
8282
8558
|
return { issue, scope, note, item };
|
|
8283
8559
|
} catch (err) {
|
|
8284
8560
|
if (!(err instanceof ApiError) || err.status !== 404) throw err;
|
|
8561
|
+
if (!issue.workflow)
|
|
8562
|
+
throw new ApiError(
|
|
8563
|
+
403,
|
|
8564
|
+
{
|
|
8565
|
+
code: "insufficient_permissions",
|
|
8566
|
+
message: "Journal fallback requires workspace read access"
|
|
8567
|
+
},
|
|
8568
|
+
"Journal fallback requires workspace read access"
|
|
8569
|
+
);
|
|
8285
8570
|
const scope = stateScope(issue, issue.state, issue.workflow);
|
|
8286
8571
|
return { issue, scope, note: null, item: await journalItemAt(api, scope) };
|
|
8287
8572
|
}
|
|
@@ -8289,7 +8574,7 @@ async function resolveJournal(api, ref, stateRef2) {
|
|
|
8289
8574
|
function printNote(note) {
|
|
8290
8575
|
if (note) console.error(`note: ${note}`);
|
|
8291
8576
|
}
|
|
8292
|
-
function
|
|
8577
|
+
function register4(program3) {
|
|
8293
8578
|
const journal = program3.command("journal").description(
|
|
8294
8579
|
"An issue's stage journal: shared notes for its project + the stage your run was launched in"
|
|
8295
8580
|
);
|
|
@@ -8376,7 +8661,7 @@ function parseLabelColor(value) {
|
|
|
8376
8661
|
}
|
|
8377
8662
|
return value;
|
|
8378
8663
|
}
|
|
8379
|
-
function
|
|
8664
|
+
function register5(program3) {
|
|
8380
8665
|
const labels = program3.command("labels").description("Manage the label library");
|
|
8381
8666
|
withCommon(
|
|
8382
8667
|
labels.command("list").description("List labels with how many issues carry each")
|
|
@@ -8473,7 +8758,7 @@ function readKeyArg(value) {
|
|
|
8473
8758
|
if (!key) die("no API key on stdin");
|
|
8474
8759
|
return key;
|
|
8475
8760
|
}
|
|
8476
|
-
function
|
|
8761
|
+
function register6(program3) {
|
|
8477
8762
|
program3.command("login").description("Store the API URL and key for this machine, so commands need no env vars").option("-u, --url <url>", `base URL of the Tines API to store (default ${DEFAULT_URL})`).option("--api-key <key>", 'API key from Settings \u2192 API keys ("-" reads it from stdin)').option("--no-verify", "store without checking the key against the API").action(async (opts) => {
|
|
8478
8763
|
if (!opts.url && !opts.apiKey) die("pass --url and/or --api-key");
|
|
8479
8764
|
const dir = defaultConfigDir();
|
|
@@ -8570,7 +8855,7 @@ function registerEvents(program3) {
|
|
|
8570
8855
|
}
|
|
8571
8856
|
|
|
8572
8857
|
// src/commands/projects.ts
|
|
8573
|
-
function
|
|
8858
|
+
function register7(program3) {
|
|
8574
8859
|
const projects = program3.command("projects").description("Manage projects");
|
|
8575
8860
|
withCommon(
|
|
8576
8861
|
projects.command("starters").description("List built-in project starters and their inputs")
|
|
@@ -8821,7 +9106,7 @@ async function resolveRoutingScope(api, opts) {
|
|
|
8821
9106
|
if (opts.label) parts.push(`label ${opts.label}`);
|
|
8822
9107
|
return { projectId, stateId, labelId, label: parts.length > 0 ? parts.join(" \xB7 ") : "global" };
|
|
8823
9108
|
}
|
|
8824
|
-
function
|
|
9109
|
+
function register8(program3) {
|
|
8825
9110
|
const routing = program3.command("routing").description(
|
|
8826
9111
|
"Scoped routing rules: which runner takes which issues (most specific scope wins)"
|
|
8827
9112
|
);
|
|
@@ -11910,7 +12195,7 @@ function printTierTable(runner) {
|
|
|
11910
12195
|
);
|
|
11911
12196
|
}
|
|
11912
12197
|
}
|
|
11913
|
-
function
|
|
12198
|
+
function register9(program3) {
|
|
11914
12199
|
const runners = program3.command("runners").description("Manage the runner registry");
|
|
11915
12200
|
withCommon(runners.command("list").description("List runners")).action(
|
|
11916
12201
|
async (opts) => {
|
|
@@ -12458,7 +12743,7 @@ title template: ${s.title_template}`);
|
|
|
12458
12743
|
for (const line of s.description_template.split("\n")) console.log(` ${line}`);
|
|
12459
12744
|
}
|
|
12460
12745
|
}
|
|
12461
|
-
function
|
|
12746
|
+
function register10(program3) {
|
|
12462
12747
|
const schedules = program3.command("schedules").description("Manage scheduled tasks (addressed as <project>/<name>)");
|
|
12463
12748
|
withList(
|
|
12464
12749
|
schedules.command("list").description("List scheduled tasks (hides paused schedules unless --all)").option("-p, --project <name>", "filter by project name or id").option("-a, --all", "include paused schedules")
|
|
@@ -12712,7 +12997,7 @@ function statsLevers() {
|
|
|
12712
12997
|
" sent back tines context show <wf>/<state> instructions"
|
|
12713
12998
|
];
|
|
12714
12999
|
}
|
|
12715
|
-
function
|
|
13000
|
+
function register11(program3) {
|
|
12716
13001
|
const supervisor = program3.command("supervisor").description("The automation kill switch, quota policy, and attempt limit");
|
|
12717
13002
|
withCommon(
|
|
12718
13003
|
supervisor.command("status").description("One-screen overview: kill switch, quota, utilization, runners").option("--project <name-or-id>", "filter waiting work to one project")
|
|
@@ -13729,7 +14014,7 @@ function printWorkflowDetail(wf, lib) {
|
|
|
13729
14014
|
for (const w of wf.warnings ?? []) console.log(`
|
|
13730
14015
|
warning: ${w}`);
|
|
13731
14016
|
}
|
|
13732
|
-
function
|
|
14017
|
+
function register12(program3) {
|
|
13733
14018
|
const workflows = program3.command("workflows").description("Manage the workflow library");
|
|
13734
14019
|
registerPackageCommands(workflows);
|
|
13735
14020
|
withList(workflows.command("list").description("List the workflow library")).action(
|
|
@@ -14351,7 +14636,7 @@ function printReport(report) {
|
|
|
14351
14636
|
for (const line of usageAggregateLines("Scope", scope)) console.log(line);
|
|
14352
14637
|
for (const line of usageAggregateLines("Matching", total)) console.log(line);
|
|
14353
14638
|
}
|
|
14354
|
-
function
|
|
14639
|
+
function register13(program3) {
|
|
14355
14640
|
withCommon(
|
|
14356
14641
|
program3.command("usage").description("Compare finalized run spend for a period").addOption(
|
|
14357
14642
|
new Option("--window <window>", "today, 7d, or 30d").choices(["today", "7d", "30d"])
|
|
@@ -14543,18 +14828,19 @@ function register12(program3) {
|
|
|
14543
14828
|
var program2 = new Command();
|
|
14544
14829
|
program2.name("tines").description("CLI for Tines").version(cliVersion()).enablePositionalOptions();
|
|
14545
14830
|
registerTime(program2);
|
|
14546
|
-
register5(program2);
|
|
14547
14831
|
register6(program2);
|
|
14548
|
-
register11(program2);
|
|
14549
14832
|
register2(program2);
|
|
14550
|
-
|
|
14551
|
-
|
|
14833
|
+
register7(program2);
|
|
14834
|
+
register12(program2);
|
|
14552
14835
|
register3(program2);
|
|
14836
|
+
register5(program2);
|
|
14837
|
+
register(program2);
|
|
14838
|
+
register4(program2);
|
|
14839
|
+
register10(program2);
|
|
14553
14840
|
register9(program2);
|
|
14554
14841
|
register8(program2);
|
|
14555
|
-
|
|
14556
|
-
|
|
14557
|
-
register12(program2);
|
|
14842
|
+
register11(program2);
|
|
14843
|
+
register13(program2);
|
|
14558
14844
|
registerEvents(program2);
|
|
14559
14845
|
|
|
14560
14846
|
// src/index.ts
|