@lesscap/baton-cli 0.3.2 → 0.3.3

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/baton.mjs +194 -19
  2. package/package.json +1 -1
package/dist/baton.mjs CHANGED
@@ -1137,6 +1137,17 @@ var fmtWorker = (w) => {
1137
1137
  const offline = w.connected === false ? " [offline]" : "";
1138
1138
  return `W-${w.id} ${w.name} ${w.hostname}${offline}`;
1139
1139
  };
1140
+ var fmtInterval = (sec) => {
1141
+ if (sec % 86400 === 0) return `${sec / 86400}d`;
1142
+ if (sec % 3600 === 0) return `${sec / 3600}h`;
1143
+ if (sec % 60 === 0) return `${sec / 60}m`;
1144
+ return `${sec}s`;
1145
+ };
1146
+ var fmtLoop = (l) => {
1147
+ const label = l.name ? `${l.name} ` : "";
1148
+ const last = l.lastStatus ? ` last:${l.lastStatus}` : "";
1149
+ return `${l.id} [${l.enabled ? "on" : "off"}] ${label}every ${fmtInterval(l.intervalSec)}${last} "${l.message}"`;
1150
+ };
1140
1151
  var renderOne = (item, fmt, json) => json ? toJson(item) : fmt(item);
1141
1152
  var renderList = (items, fmt, json) => {
1142
1153
  if (json) return toJson(items);
@@ -1193,6 +1204,20 @@ var primeLogin = (baseUrl) => {
1193
1204
  );
1194
1205
  };
1195
1206
 
1207
+ // src/client/loops.ts
1208
+ var loopsClient = (baseUrl) => {
1209
+ const u = (p) => `${baseUrl}${p}`;
1210
+ return {
1211
+ create: (sessionId, input) => request(u(`/sessions/${sessionId}/loops`), { method: "POST", body: input }),
1212
+ listBySession: (sessionId) => request(u(`/sessions/${sessionId}/loops`), { method: "GET" }),
1213
+ get: (id) => request(u(`/loops/${id}`), { method: "GET" }),
1214
+ update: (id, input) => request(u(`/loops/${id}`), { method: "PATCH", body: input }),
1215
+ remove: async (id) => {
1216
+ await request(u(`/loops/${id}`), { method: "DELETE" });
1217
+ }
1218
+ };
1219
+ };
1220
+
1196
1221
  // src/client/projects.ts
1197
1222
  var projectClient = (baseUrl) => {
1198
1223
  const u = (p) => `${baseUrl}${p}`;
@@ -1368,6 +1393,7 @@ var clientFromBase = (baseUrl) => ({
1368
1393
  requirements: requirementClient(baseUrl),
1369
1394
  tasks: taskClient(baseUrl),
1370
1395
  sessions: sessionsClient(baseUrl),
1396
+ loops: loopsClient(baseUrl),
1371
1397
  workers: workersClient(baseUrl)
1372
1398
  });
1373
1399
  var BOUNDARY_EVENTS = /* @__PURE__ */ new Set([
@@ -1441,6 +1467,13 @@ var parseWorkerHandle = (handle) => {
1441
1467
  return m ? Number(m[1]) : null;
1442
1468
  };
1443
1469
  var splitCsv = (s) => s ? s.split(",").map((x) => x.trim()).filter(Boolean) : void 0;
1470
+ var parseDuration = (s) => {
1471
+ const m = s.trim().match(/^(\d+)\s*([smhd]?)$/);
1472
+ if (!m) throw new Error(`bad interval "${s}" \u2014 use e.g. 90s, 30m, 2h, 1d`);
1473
+ const n = Number(m[1]);
1474
+ const mult = m[2] === "d" ? 86400 : m[2] === "h" ? 3600 : m[2] === "m" ? 60 : 1;
1475
+ return n * mult;
1476
+ };
1444
1477
 
1445
1478
  // src/commands/channel/close.ts
1446
1479
  var closeCommand = defineCommand({
@@ -1962,6 +1995,163 @@ var init = defineCommand({
1962
1995
  }
1963
1996
  });
1964
1997
 
1998
+ // src/commands/session/shared.ts
1999
+ import { homedir } from "node:os";
2000
+ import { join as join3 } from "node:path";
2001
+ var defaultWorktreeDir = (env = process.env) => env.BATON_WORKTREE_DIR ?? join3(env.XDG_DATA_HOME ?? join3(env.HOME ?? homedir(), ".local/share"), "baton", "worktrees");
2002
+ var slug = (s) => s.toLowerCase().replace(/[^a-z0-9_-]+/g, "-");
2003
+ var resolveSession = async (client, projectId, handle) => {
2004
+ const asInt = Number(handle);
2005
+ if (Number.isInteger(asInt) && asInt > 0) {
2006
+ const byId = await client.sessions.get(asInt).catch(() => null);
2007
+ if (byId) return { id: byId.id, name: byId.name };
2008
+ }
2009
+ const byName = await client.sessions.findByName(projectId, handle);
2010
+ if (byName) return { id: byName.id, name: byName.name };
2011
+ throw new Error(`session "${handle}" not found in project ${projectId}`);
2012
+ };
2013
+
2014
+ // src/commands/loop/create.ts
2015
+ var loopCreateCommand = defineCommand({
2016
+ meta: { name: "create", description: "create a recurring scheduled message on a session" },
2017
+ args: {
2018
+ session: { type: "positional", required: true, description: "session int id or name" },
2019
+ message: {
2020
+ type: "string",
2021
+ required: true,
2022
+ description: "message sent to the session each beat"
2023
+ },
2024
+ every: {
2025
+ type: "string",
2026
+ required: true,
2027
+ description: "interval: 90s / 30m / 2h / 1d (min 30s)"
2028
+ },
2029
+ name: { type: "string", description: "optional label" },
2030
+ off: { type: "boolean", description: "create paused (disabled)" },
2031
+ project: { type: "string", description: "project id (overrides .baton.json)" },
2032
+ ...common
2033
+ },
2034
+ run: async ({ args }) => {
2035
+ const c = clientFor(args);
2036
+ const session2 = await resolveSession(c, resolveProjectId(args), args.session);
2037
+ const loop2 = await c.loops.create(session2.id, {
2038
+ message: args.message,
2039
+ intervalSec: parseDuration(args.every),
2040
+ name: args.name,
2041
+ enabled: !args.off
2042
+ });
2043
+ console.log(renderOne(loop2, fmtLoop, Boolean(args.json)));
2044
+ }
2045
+ });
2046
+
2047
+ // src/commands/loop/disable.ts
2048
+ var loopDisableCommand = defineCommand({
2049
+ meta: { name: "disable", description: "disable (pause) a loop" },
2050
+ args: {
2051
+ loop: { type: "positional", required: true, description: "loop int id" },
2052
+ ...common
2053
+ },
2054
+ run: async ({ args }) => {
2055
+ const c = clientFor(args);
2056
+ const loop2 = await c.loops.update(Number(args.loop), { enabled: false });
2057
+ console.log(renderOne(loop2, fmtLoop, Boolean(args.json)));
2058
+ }
2059
+ });
2060
+
2061
+ // src/commands/loop/enable.ts
2062
+ var loopEnableCommand = defineCommand({
2063
+ meta: { name: "enable", description: "enable (resume) a loop" },
2064
+ args: {
2065
+ loop: { type: "positional", required: true, description: "loop int id" },
2066
+ ...common
2067
+ },
2068
+ run: async ({ args }) => {
2069
+ const c = clientFor(args);
2070
+ const loop2 = await c.loops.update(Number(args.loop), { enabled: true });
2071
+ console.log(renderOne(loop2, fmtLoop, Boolean(args.json)));
2072
+ }
2073
+ });
2074
+
2075
+ // src/commands/loop/get.ts
2076
+ var loopGetCommand = defineCommand({
2077
+ meta: { name: "get", description: "show one loop" },
2078
+ args: {
2079
+ loop: { type: "positional", required: true, description: "loop int id" },
2080
+ ...common
2081
+ },
2082
+ run: async ({ args }) => {
2083
+ const c = clientFor(args);
2084
+ const loop2 = await c.loops.get(Number(args.loop));
2085
+ console.log(renderOne(loop2, fmtLoop, Boolean(args.json)));
2086
+ }
2087
+ });
2088
+
2089
+ // src/commands/loop/ls.ts
2090
+ var loopLsCommand = defineCommand({
2091
+ meta: { name: "ls", description: "list a session's loops" },
2092
+ args: {
2093
+ session: { type: "positional", required: true, description: "session int id or name" },
2094
+ project: { type: "string", description: "project id (overrides .baton.json)" },
2095
+ ...common
2096
+ },
2097
+ run: async ({ args }) => {
2098
+ const c = clientFor(args);
2099
+ const session2 = await resolveSession(c, resolveProjectId(args), args.session);
2100
+ const loops = await c.loops.listBySession(session2.id);
2101
+ console.log(renderList(loops, fmtLoop, Boolean(args.json)));
2102
+ }
2103
+ });
2104
+
2105
+ // src/commands/loop/rm.ts
2106
+ var loopRmCommand = defineCommand({
2107
+ meta: { name: "rm", description: "delete a loop" },
2108
+ args: {
2109
+ loop: { type: "positional", required: true, description: "loop int id" },
2110
+ ...common
2111
+ },
2112
+ run: async ({ args }) => {
2113
+ const c = clientFor(args);
2114
+ const id = Number(args.loop);
2115
+ await c.loops.remove(id);
2116
+ console.log(removed("loop", id, Boolean(args.json)));
2117
+ }
2118
+ });
2119
+
2120
+ // src/commands/loop/set.ts
2121
+ var loopSetCommand = defineCommand({
2122
+ meta: { name: "set", description: "update a loop (message / interval / name)" },
2123
+ args: {
2124
+ loop: { type: "positional", required: true, description: "loop int id" },
2125
+ message: { type: "string", description: "new message" },
2126
+ every: { type: "string", description: "new interval: 90s / 30m / 2h / 1d" },
2127
+ name: { type: "string", description: "new label" },
2128
+ ...common
2129
+ },
2130
+ run: async ({ args }) => {
2131
+ const c = clientFor(args);
2132
+ const patch2 = {};
2133
+ if (args.message !== void 0) patch2.message = args.message;
2134
+ if (args.every !== void 0 && args.every !== "") patch2.intervalSec = parseDuration(args.every);
2135
+ if (args.name !== void 0) patch2.name = args.name;
2136
+ const loop2 = await c.loops.update(Number(args.loop), patch2);
2137
+ console.log(renderOne(loop2, fmtLoop, Boolean(args.json)));
2138
+ }
2139
+ });
2140
+
2141
+ // src/commands/loop.ts
2142
+ var loop = defineCommand({
2143
+ meta: { name: "loop", description: "recurring scheduled messages that wake a session" },
2144
+ subCommands: {
2145
+ create: loopCreateCommand,
2146
+ ls: loopLsCommand,
2147
+ get: loopGetCommand,
2148
+ set: loopSetCommand,
2149
+ enable: loopEnableCommand,
2150
+ disable: loopDisableCommand,
2151
+ rm: loopRmCommand
2152
+ }
2153
+ });
2154
+
1965
2155
  // src/commands/project.ts
1966
2156
  var createProject = (c, input, json) => c.projects.create(input).then((p) => renderOne(p, fmtProject, json));
1967
2157
  var listProjects = (c, workspaceId, json) => c.projects.listByWorkspace(workspaceId).then((ps) => renderList(ps, fmtProject, json));
@@ -2039,7 +2229,7 @@ var project = defineCommand({
2039
2229
  // src/commands/relay.ts
2040
2230
  import { mkdirSync as mkdirSync2, readFileSync as readFileSync3, writeFileSync as writeFileSync4 } from "node:fs";
2041
2231
  import { tmpdir as tmpdir2 } from "node:os";
2042
- import { join as join3 } from "node:path";
2232
+ import { join as join4 } from "node:path";
2043
2233
 
2044
2234
  // src/client/relay.ts
2045
2235
  var relayClient = (baseUrl) => {
@@ -2167,11 +2357,11 @@ var listenCommand2 = defineCommand({
2167
2357
  process.stdout.write(`${JSON.stringify(o)}
2168
2358
  `);
2169
2359
  };
2170
- const spillDir = join3(tmpdir2(), "hotline", args.channel);
2360
+ const spillDir = join4(tmpdir2(), "hotline", args.channel);
2171
2361
  mkdirSync2(spillDir, { recursive: true });
2172
2362
  const surface = (m) => {
2173
2363
  const text = typeof m.text === "string" ? m.text : "";
2174
- const file = join3(spillDir, `${m.seq}.txt`);
2364
+ const file = join4(spillDir, `${m.seq}.txt`);
2175
2365
  writeFileSync4(file, text);
2176
2366
  const truncated = text.length > PREVIEW2;
2177
2367
  emit({
@@ -2325,22 +2515,6 @@ var requirement = defineCommand({
2325
2515
  }
2326
2516
  });
2327
2517
 
2328
- // src/commands/session/shared.ts
2329
- import { homedir } from "node:os";
2330
- import { join as join4 } from "node:path";
2331
- var defaultWorktreeDir = (env = process.env) => env.BATON_WORKTREE_DIR ?? join4(env.XDG_DATA_HOME ?? join4(env.HOME ?? homedir(), ".local/share"), "baton", "worktrees");
2332
- var slug = (s) => s.toLowerCase().replace(/[^a-z0-9_-]+/g, "-");
2333
- var resolveSession = async (client, projectId, handle) => {
2334
- const asInt = Number(handle);
2335
- if (Number.isInteger(asInt) && asInt > 0) {
2336
- const byId = await client.sessions.get(asInt).catch(() => null);
2337
- if (byId) return { id: byId.id, name: byId.name };
2338
- }
2339
- const byName = await client.sessions.findByName(projectId, handle);
2340
- if (byName) return { id: byName.id, name: byName.name };
2341
- throw new Error(`session "${handle}" not found in project ${projectId}`);
2342
- };
2343
-
2344
2518
  // src/commands/session/abort.ts
2345
2519
  var sessionAbortCommand = defineCommand({
2346
2520
  meta: {
@@ -3866,6 +4040,7 @@ var main = defineCommand({
3866
4040
  init,
3867
4041
  worker,
3868
4042
  session,
4043
+ loop,
3869
4044
  relay,
3870
4045
  channel,
3871
4046
  workspace,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lesscap/baton-cli",
3
- "version": "0.3.2",
3
+ "version": "0.3.3",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "description": "baton CLI — register/run a worker, manage projects/requirements/tasks/sessions",