tines 0.0.127 → 0.0.129

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 +54 -7
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -3617,6 +3617,8 @@ var DESCRIBERS = {
3617
3617
  "project.created": (ev, p) => projectSegments(ev, p),
3618
3618
  "project.updated": (ev, p) => projectSegments(ev, p),
3619
3619
  "project.deleted": (ev, p) => projectSegments(ev, p),
3620
+ "project.archived": (ev, p) => projectSegments(ev, p),
3621
+ "project.unarchived": (ev, p) => projectSegments(ev, p),
3620
3622
  "workflow.created": (ev, p) => [text(`${action(ev.type)} workflow`), name(p.name)],
3621
3623
  "workflow.updated": (ev, p) => [text(`${action(ev.type)} workflow`), name(p.name)],
3622
3624
  "workflow.deleted": (ev, p) => [text(`${action(ev.type)} workflow`), name(p.name)],
@@ -3824,11 +3826,13 @@ function createApiClient(options) {
3824
3826
  return {
3825
3827
  getTime: () => get("/api/time"),
3826
3828
  // Projects
3827
- listProjects: (page = {}) => get(`/api/v1/projects${query(page)}`),
3829
+ listProjects: (params = {}) => get(`/api/v1/projects${query(params)}`),
3828
3830
  createProject: (body) => request("POST", "/api/v1/projects", body),
3829
3831
  getProject: (id) => get(`/api/v1/projects/${id}`),
3830
3832
  updateProject: (id, body) => request("PATCH", `/api/v1/projects/${id}`, body),
3831
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`),
3832
3836
  // Workflows
3833
3837
  listWorkflows: (page = {}) => get(`/api/v1/workflows${query(page)}`),
3834
3838
  createWorkflow: (body) => request("POST", "/api/v1/workflows", body),
@@ -4449,7 +4453,7 @@ function table(rows) {
4449
4453
  console.log(formatTable(rows));
4450
4454
  }
4451
4455
  async function resolveProject(api, ref) {
4452
- const { items } = await api.listProjects();
4456
+ const { items } = await api.listProjects({ archived: "all" });
4453
4457
  const byId = items.find((p) => p.id === ref);
4454
4458
  if (byId) return byId;
4455
4459
  const byName = items.filter((p) => p.name === ref);
@@ -4457,7 +4461,8 @@ async function resolveProject(api, ref) {
4457
4461
  if (byName.length > 1) {
4458
4462
  die(`project name "${ref}" is ambiguous; use an id: ${byName.map((p) => p.id).join(", ")}`);
4459
4463
  }
4460
- 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"})`);
4461
4466
  }
4462
4467
  async function resolveWorkflow(api, ref) {
4463
4468
  const { items } = await api.listWorkflows();
@@ -4852,6 +4857,11 @@ function printIssueDetail(issue) {
4852
4857
  `own state: ${issue.state.name} (${issue.state.category}) \u2014 dormant while this is a duplicate`
4853
4858
  );
4854
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
+ }
4855
4865
  if (issue.labels.length > 0) {
4856
4866
  console.log(`labels: ${issue.labels.map((l) => l.name).join(", ")}`);
4857
4867
  }
@@ -5893,14 +5903,25 @@ function registerEvents(program3) {
5893
5903
  // src/commands/projects.ts
5894
5904
  function register6(program3) {
5895
5905
  const projects = program3.command("projects").description("Manage projects");
5896
- 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) => {
5897
5909
  const api = client(opts);
5898
- 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
+ );
5899
5914
  printList(res, opts, (items) => {
5900
5915
  if (items.length === 0) return console.log("no projects");
5901
5916
  table([
5902
- ["NAME", "ISSUES", "ID", "CREATED"],
5903
- ...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
+ ])
5904
5925
  ]);
5905
5926
  });
5906
5927
  });
@@ -5943,6 +5964,7 @@ default workflow: ${defaultWorkflow}`);
5943
5964
  console.log(
5944
5965
  `issues: ${project.issue_count} created: ${timestamp(project.created_at)} updated: ${timestamp(project.updated_at)}`
5945
5966
  );
5967
+ if (project.archived_at !== null) console.log(`archived: ${timestamp(project.archived_at)}`);
5946
5968
  }
5947
5969
  );
5948
5970
  withCommon(
@@ -5966,6 +5988,31 @@ default workflow: ${defaultWorkflow}`);
5966
5988
  console.log(`updated project "${updated.name}" (${updated.id})`);
5967
5989
  }
5968
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
+ });
5969
6016
  withCommon(
5970
6017
  projects.command("delete <id-or-name>").description("Delete a project (refused while it still contains issues)")
5971
6018
  ).action(async (ref, opts) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tines",
3
- "version": "0.0.127",
3
+ "version": "0.0.129",
4
4
  "description": "CLI for Tines, an orchestration layer for AI agents",
5
5
  "repository": {
6
6
  "type": "git",