tines 0.0.126 → 0.0.128

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.
Files changed (2) hide show
  1. package/dist/index.js +59 -10
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -3401,10 +3401,12 @@ function readBodyValue(value, stdin = processStdin) {
3401
3401
  }
3402
3402
 
3403
3403
  // ../shared/src/types.ts
3404
+ function runRefLabel(run) {
3405
+ return run.issue_ref ? `run on ${run.issue_ref.project_name}/${run.issue_ref.number}` : `run ${run.run_id}`;
3406
+ }
3404
3407
  function actorLabel(actor) {
3405
3408
  if (actor.run) {
3406
- const ref = actor.run.issue_ref ? `run on ${actor.run.issue_ref.project_name}/${actor.run.issue_ref.number}` : `run ${actor.run.run_id}`;
3407
- return `${actor.user_name} via ${actor.run.runner_name} \xB7 ${ref}`;
3409
+ return `${actor.user_name} via ${actor.run.runner_name} \xB7 ${runRefLabel(actor.run)}`;
3408
3410
  }
3409
3411
  return actor.api_key_name ? `${actor.user_name} via ${actor.api_key_name}` : actor.user_name;
3410
3412
  }
@@ -3615,6 +3617,8 @@ var DESCRIBERS = {
3615
3617
  "project.created": (ev, p) => projectSegments(ev, p),
3616
3618
  "project.updated": (ev, p) => projectSegments(ev, p),
3617
3619
  "project.deleted": (ev, p) => projectSegments(ev, p),
3620
+ "project.archived": (ev, p) => projectSegments(ev, p),
3621
+ "project.unarchived": (ev, p) => projectSegments(ev, p),
3618
3622
  "workflow.created": (ev, p) => [text(`${action(ev.type)} workflow`), name(p.name)],
3619
3623
  "workflow.updated": (ev, p) => [text(`${action(ev.type)} workflow`), name(p.name)],
3620
3624
  "workflow.deleted": (ev, p) => [text(`${action(ev.type)} workflow`), name(p.name)],
@@ -3822,11 +3826,13 @@ function createApiClient(options) {
3822
3826
  return {
3823
3827
  getTime: () => get("/api/time"),
3824
3828
  // Projects
3825
- listProjects: (page = {}) => get(`/api/v1/projects${query(page)}`),
3829
+ listProjects: (params = {}) => get(`/api/v1/projects${query(params)}`),
3826
3830
  createProject: (body) => request("POST", "/api/v1/projects", body),
3827
3831
  getProject: (id) => get(`/api/v1/projects/${id}`),
3828
3832
  updateProject: (id, body) => request("PATCH", `/api/v1/projects/${id}`, body),
3829
3833
  deleteProject: (id, body) => request("DELETE", `/api/v1/projects/${id}`, body),
3834
+ archiveProject: (id) => request("POST", `/api/v1/projects/${id}/archive`),
3835
+ unarchiveProject: (id) => request("POST", `/api/v1/projects/${id}/unarchive`),
3830
3836
  // Workflows
3831
3837
  listWorkflows: (page = {}) => get(`/api/v1/workflows${query(page)}`),
3832
3838
  createWorkflow: (body) => request("POST", "/api/v1/workflows", body),
@@ -3986,7 +3992,7 @@ function createApiClient(options) {
3986
3992
  getSupervisorSettings: () => get("/api/v1/supervisor/settings"),
3987
3993
  updateSupervisorSettings: (body) => request("PUT", "/api/v1/supervisor/settings", body),
3988
3994
  // API keys (create/revoke require a browser session, not a key)
3989
- listApiKeys: () => get("/api/v1/api-keys"),
3995
+ listApiKeys: (filters = {}) => get(`/api/v1/api-keys${query(filters)}`),
3990
3996
  createApiKey: (body) => request("POST", "/api/v1/api-keys", body),
3991
3997
  revokeApiKey: (id) => request("DELETE", `/api/v1/api-keys/${id}`),
3992
3998
  // Library export / import (workflows + context; no tracker data, no secrets)
@@ -4447,7 +4453,7 @@ function table(rows) {
4447
4453
  console.log(formatTable(rows));
4448
4454
  }
4449
4455
  async function resolveProject(api, ref) {
4450
- const { items } = await api.listProjects();
4456
+ const { items } = await api.listProjects({ archived: "all" });
4451
4457
  const byId = items.find((p) => p.id === ref);
4452
4458
  if (byId) return byId;
4453
4459
  const byName = items.filter((p) => p.name === ref);
@@ -4455,7 +4461,8 @@ async function resolveProject(api, ref) {
4455
4461
  if (byName.length > 1) {
4456
4462
  die(`project name "${ref}" is ambiguous; use an id: ${byName.map((p) => p.id).join(", ")}`);
4457
4463
  }
4458
- die(`no project named "${ref}" (have: ${items.map((p) => p.name).join(", ") || "none"})`);
4464
+ const have = items.map((p) => p.archived_at ? `${p.name} (archived)` : p.name).join(", ");
4465
+ die(`no project named "${ref}" (have: ${have || "none"})`);
4459
4466
  }
4460
4467
  async function resolveWorkflow(api, ref) {
4461
4468
  const { items } = await api.listWorkflows();
@@ -4850,6 +4857,11 @@ function printIssueDetail(issue) {
4850
4857
  `own state: ${issue.state.name} (${issue.state.category}) \u2014 dormant while this is a duplicate`
4851
4858
  );
4852
4859
  }
4860
+ if (issue.project_archived_at !== null) {
4861
+ console.log(
4862
+ `project archived: ${timestamp(issue.project_archived_at)} \u2014 this issue is read-only`
4863
+ );
4864
+ }
4853
4865
  if (issue.labels.length > 0) {
4854
4866
  console.log(`labels: ${issue.labels.map((l) => l.name).join(", ")}`);
4855
4867
  }
@@ -5891,14 +5903,25 @@ function registerEvents(program3) {
5891
5903
  // src/commands/projects.ts
5892
5904
  function register6(program3) {
5893
5905
  const projects = program3.command("projects").description("Manage projects");
5894
- withList(projects.command("list").description("List projects")).action(async (opts) => {
5906
+ withList(
5907
+ projects.command("list").description("List projects").option("--archived", "include archived projects (hidden by default)")
5908
+ ).action(async (opts) => {
5895
5909
  const api = client(opts);
5896
- const res = await fetchList(opts, (page) => api.listProjects(page));
5910
+ const res = await fetchList(
5911
+ opts,
5912
+ (page) => api.listProjects({ ...page, ...opts.archived ? { archived: "all" } : {} })
5913
+ );
5897
5914
  printList(res, opts, (items) => {
5898
5915
  if (items.length === 0) return console.log("no projects");
5899
5916
  table([
5900
- ["NAME", "ISSUES", "ID", "CREATED"],
5901
- ...items.map((p) => [p.name, String(p.issue_count), p.id, timestamp(p.created_at)])
5917
+ ["NAME", "ISSUES", "ID", "CREATED", ...opts.archived ? ["ARCHIVED"] : []],
5918
+ ...items.map((p) => [
5919
+ p.name,
5920
+ String(p.issue_count),
5921
+ p.id,
5922
+ timestamp(p.created_at),
5923
+ ...opts.archived ? [p.archived_at ? timestamp(p.archived_at) : "-"] : []
5924
+ ])
5902
5925
  ]);
5903
5926
  });
5904
5927
  });
@@ -5941,6 +5964,7 @@ default workflow: ${defaultWorkflow}`);
5941
5964
  console.log(
5942
5965
  `issues: ${project.issue_count} created: ${timestamp(project.created_at)} updated: ${timestamp(project.updated_at)}`
5943
5966
  );
5967
+ if (project.archived_at !== null) console.log(`archived: ${timestamp(project.archived_at)}`);
5944
5968
  }
5945
5969
  );
5946
5970
  withCommon(
@@ -5964,6 +5988,31 @@ default workflow: ${defaultWorkflow}`);
5964
5988
  console.log(`updated project "${updated.name}" (${updated.id})`);
5965
5989
  }
5966
5990
  );
5991
+ withCommon(
5992
+ projects.command("archive <id-or-name>").description(
5993
+ "Archive a project: pause its schedules, stop dispatch, make its issues read-only"
5994
+ )
5995
+ ).action(async (ref, opts) => {
5996
+ const api = client(opts);
5997
+ const project = await resolveProject(api, ref);
5998
+ const res = await api.archiveProject(project.id);
5999
+ if (opts.json) return printJson(res);
6000
+ const draining = res.draining_runs.length ? `${res.draining_runs.length} run${res.draining_runs.length === 1 ? "" : "s"} draining (` + res.draining_runs.map((r) => `${r.runner_name} on ${res.project.name}/${r.issue_number}`).join(", ") + ")" : "0 runs draining";
6001
+ console.log(
6002
+ `archived project "${res.project.name}" (${res.project.id}): ${res.schedules_paused} schedule${res.schedules_paused === 1 ? "" : "s"} paused, ${draining}, ${res.issues_read_only} issue${res.issues_read_only === 1 ? "" : "s"} read-only`
6003
+ );
6004
+ });
6005
+ withCommon(
6006
+ projects.command("unarchive <id-or-name>").description("Unarchive a project: schedules resume from their next occurrence")
6007
+ ).action(async (ref, opts) => {
6008
+ const api = client(opts);
6009
+ const project = await resolveProject(api, ref);
6010
+ const res = await api.unarchiveProject(project.id);
6011
+ if (opts.json) return printJson(res);
6012
+ console.log(
6013
+ `unarchived project "${res.project.name}" (${res.project.id}): ${res.schedules_resumed} schedule${res.schedules_resumed === 1 ? "" : "s"} resumed`
6014
+ );
6015
+ });
5967
6016
  withCommon(
5968
6017
  projects.command("delete <id-or-name>").description("Delete a project (refused while it still contains issues)")
5969
6018
  ).action(async (ref, opts) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tines",
3
- "version": "0.0.126",
3
+ "version": "0.0.128",
4
4
  "description": "CLI for Tines, an orchestration layer for AI agents",
5
5
  "repository": {
6
6
  "type": "git",