@hasna/todos 0.11.54 → 0.11.55

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/cli/index.js CHANGED
@@ -50336,7 +50336,7 @@ import { join as join21 } from "path";
50336
50336
  function getOrCreateLocalMachineName() {
50337
50337
  return process.env["TODOS_MACHINE_NAME"] || __require("os").hostname() || "unknown";
50338
50338
  }
50339
- function wantsJson(program2, opts) {
50339
+ function wantsJson2(program2, opts) {
50340
50340
  return Boolean(opts["json"] || program2.opts().json);
50341
50341
  }
50342
50342
  function metadataString(machine, key) {
@@ -50450,7 +50450,7 @@ function registerMachineCommands(program2) {
50450
50450
  git_root: opts.gitRoot,
50451
50451
  primary: opts.primary
50452
50452
  }, db);
50453
- if (wantsJson(program2, opts)) {
50453
+ if (wantsJson2(program2, opts)) {
50454
50454
  console.log(JSON.stringify(machine));
50455
50455
  return;
50456
50456
  }
@@ -50482,7 +50482,7 @@ function registerMachineCommands(program2) {
50482
50482
  workspace_path: opts.workspace,
50483
50483
  git_root: opts.gitRoot
50484
50484
  }, db);
50485
- if (wantsJson(program2, opts)) {
50485
+ if (wantsJson2(program2, opts)) {
50486
50486
  console.log(JSON.stringify(machine));
50487
50487
  return;
50488
50488
  }
@@ -50592,7 +50592,7 @@ Warning: No primary machine set.`));
50592
50592
  stale_minutes: staleMinutes,
50593
50593
  include_archived: opts.includeArchived
50594
50594
  }, getDatabase());
50595
- if (wantsJson(program2, opts)) {
50595
+ if (wantsJson2(program2, opts)) {
50596
50596
  console.log(JSON.stringify(diagnostics));
50597
50597
  return;
50598
50598
  }
@@ -50635,7 +50635,7 @@ Path diagnostics (${diagnostics.path_issues.length})`));
50635
50635
  }
50636
50636
  }
50637
50637
  if (targets.length === 0) {
50638
- if (wantsJson(program2, opts)) {
50638
+ if (wantsJson2(program2, opts)) {
50639
50639
  console.log(JSON.stringify({
50640
50640
  dry_run: Boolean(opts.dryRun),
50641
50641
  pushed: Boolean(opts.push),
@@ -50656,14 +50656,14 @@ Path diagnostics (${diagnostics.path_issues.length})`));
50656
50656
  conflictStrategy: "safe_merge"
50657
50657
  }, db);
50658
50658
  const record = { machine: target.name, pull };
50659
- if (!wantsJson(program2, opts)) {
50659
+ if (!wantsJson2(program2, opts)) {
50660
50660
  const mode = opts.dryRun ? "would pull" : "pulled";
50661
50661
  console.log(chalk10.green(` ${target.name}: ${mode} ${formatBridgeImportSummary(pull)}`));
50662
50662
  }
50663
50663
  if (opts.push) {
50664
50664
  const push = pushLocalBridgeBundle(ssh, Boolean(opts.dryRun));
50665
50665
  record.push = push;
50666
- if (!wantsJson(program2, opts)) {
50666
+ if (!wantsJson2(program2, opts)) {
50667
50667
  const mode = opts.dryRun ? "would push" : "pushed";
50668
50668
  console.log(chalk10.green(` ${target.name}: ${mode} ${formatBridgeImportSummary(push)}`));
50669
50669
  }
@@ -50672,11 +50672,11 @@ Path diagnostics (${diagnostics.path_issues.length})`));
50672
50672
  } catch (error) {
50673
50673
  const message = error instanceof Error ? error.message : String(error);
50674
50674
  results.push({ machine: target.name, error: message });
50675
- if (!wantsJson(program2, opts))
50675
+ if (!wantsJson2(program2, opts))
50676
50676
  console.log(chalk10.yellow(` ${target.name}: sync failed: ${message}`));
50677
50677
  }
50678
50678
  }
50679
- if (wantsJson(program2, opts)) {
50679
+ if (wantsJson2(program2, opts)) {
50680
50680
  console.log(JSON.stringify({
50681
50681
  dry_run: Boolean(opts.dryRun),
50682
50682
  pushed: Boolean(opts.push),
@@ -58676,7 +58676,7 @@ var init_help_commands = __esm(() => {
58676
58676
  // src/cli/index.tsx
58677
58677
  init_esm();
58678
58678
 
58679
- // node_modules/.bun/@hasna+events@0.1.3/node_modules/@hasna/events/dist/commander.js
58679
+ // node_modules/.bun/@hasna+events@0.1.7/node_modules/@hasna/events/dist/commander.js
58680
58680
  import { chmod, mkdir, readFile, rename, writeFile } from "fs/promises";
58681
58681
  import { existsSync } from "fs";
58682
58682
  import { homedir } from "os";
@@ -59239,9 +59239,15 @@ function print(value, json, text) {
59239
59239
  else
59240
59240
  console.log(text);
59241
59241
  }
59242
+ function hasJsonOption(options) {
59243
+ return Boolean(options?.json || options?.opts?.().json || options?.optsWithGlobals?.().json || options?.parent?.opts?.().json || options?.parent?.optsWithGlobals?.().json);
59244
+ }
59245
+ function wantsJson(actionOptions, command) {
59246
+ return hasJsonOption(actionOptions) || hasJsonOption(command);
59247
+ }
59242
59248
  function registerWebhookCommands(program2, options) {
59243
59249
  const webhooks = program2.command(options.webhooksCommandName ?? "webhooks").description("Manage Hasna event webhook subscriptions");
59244
- webhooks.command("add").description("Add or replace a webhook or command subscription").argument("<target>", "Webhook URL or command binary").requiredOption("--id <id>", "Subscription/channel identifier").option("--transport <kind>", "Transport kind: webhook or command", "webhook").option("--name <name>", "Display name").option("--type <pattern>", "Event type filter, e.g. todos.task.*").option("--source <pattern>", "Event source filter").option("--subject <pattern>", "Event subject filter").option("--severity <pattern>", "Event severity filter").option("--secret <secret>", "Webhook HMAC secret").option("--header <name=value...>", "Webhook header", collectValues, []).option("--arg <arg...>", "Command argument", collectValues, []).option("--timeout-ms <ms>", "Transport timeout in milliseconds", parseNumber).option("--retry-attempts <n>", "Maximum delivery attempts", parseNumber).option("--retry-backoff-ms <ms>", "Initial retry backoff in milliseconds", parseNumber).option("--redact <path...>", "Event field path to redact before delivery", collectValues, []).option("--disabled", "Create channel disabled", false).option("-j, --json", "Print JSON output", false).action(async (target, actionOptions) => {
59250
+ webhooks.command("add").description("Add or replace a webhook or command subscription").argument("<target>", "Webhook URL or command binary").requiredOption("--id <id>", "Subscription/channel identifier").option("--transport <kind>", "Transport kind: webhook or command", "webhook").option("--name <name>", "Display name").option("--type <pattern>", "Event type filter, e.g. todos.task.*").option("--source <pattern>", "Event source filter").option("--subject <pattern>", "Event subject filter").option("--severity <pattern>", "Event severity filter").option("--secret <secret>", "Webhook HMAC secret").option("--header <name=value...>", "Webhook header", collectValues, []).option("--arg <arg...>", "Command argument", collectValues, []).option("--timeout-ms <ms>", "Transport timeout in milliseconds", parseNumber).option("--retry-attempts <n>", "Maximum delivery attempts", parseNumber).option("--retry-backoff-ms <ms>", "Initial retry backoff in milliseconds", parseNumber).option("--redact <path...>", "Event field path to redact before delivery", collectValues, []).option("--disabled", "Create channel disabled", false).option("-j, --json", "Print JSON output", false).action(async (target, actionOptions, command) => {
59245
59251
  const timestamp = new Date().toISOString();
59246
59252
  const channel = {
59247
59253
  id: actionOptions.id,
@@ -59262,11 +59268,11 @@ function registerWebhookCommands(program2, options) {
59262
59268
  throw new Error(`Transport ${actionOptions.transport} is reserved for future use and cannot be added yet`);
59263
59269
  }
59264
59270
  const saved = await createClient(options).addChannel(channel);
59265
- print(sanitizeChannelForOutput(saved), Boolean(actionOptions.json), `Added ${saved.transport} channel ${saved.id}`);
59271
+ print(sanitizeChannelForOutput(saved), wantsJson(actionOptions, command), `Added ${saved.transport} channel ${saved.id}`);
59266
59272
  });
59267
- webhooks.command("list").description("List configured subscriptions").option("-j, --json", "Print JSON output", false).action(async (actionOptions) => {
59273
+ webhooks.command("list").description("List configured subscriptions").option("-j, --json", "Print JSON output", false).action(async (actionOptions, command) => {
59268
59274
  const channels = await createClient(options).listChannels();
59269
- if (actionOptions.json) {
59275
+ if (wantsJson(actionOptions, command)) {
59270
59276
  console.log(JSON.stringify(sanitizeChannelsForOutput(channels), null, 2));
59271
59277
  return;
59272
59278
  }
@@ -59278,11 +59284,11 @@ function registerWebhookCommands(program2, options) {
59278
59284
  console.log(`${channel.id} ${channel.enabled ? "enabled" : "disabled"} ${channel.transport} ${channel.webhook?.url ?? channel.command?.command ?? channel.transport}`);
59279
59285
  }
59280
59286
  });
59281
- webhooks.command("remove").description("Remove a subscription").argument("<id>", "Subscription/channel identifier").option("-j, --json", "Print JSON output", false).action(async (id, actionOptions) => {
59287
+ webhooks.command("remove").description("Remove a subscription").argument("<id>", "Subscription/channel identifier").option("-j, --json", "Print JSON output", false).action(async (id, actionOptions, command) => {
59282
59288
  const removed = await createClient(options).removeChannel(id);
59283
- print({ removed }, Boolean(actionOptions.json), removed ? `Removed ${id}` : `Channel not found: ${id}`);
59289
+ print({ removed }, wantsJson(actionOptions, command), removed ? `Removed ${id}` : `Channel not found: ${id}`);
59284
59290
  });
59285
- webhooks.command("test").description("Send a test event to one subscription").argument("<id>", "Subscription/channel identifier").option("--type <type>", "Event type", "events.test").option("--subject <subject>", "Event subject").option("--message <message>", "Event message", "Hasna events test delivery").option("--data <json>", "Event data JSON object").option("-j, --json", "Print JSON output", false).action(async (id, actionOptions) => {
59291
+ webhooks.command("test").description("Send a test event to one subscription").argument("<id>", "Subscription/channel identifier").option("--type <type>", "Event type", "events.test").option("--subject <subject>", "Event subject").option("--message <message>", "Event message", "Hasna events test delivery").option("--data <json>", "Event data JSON object").option("-j, --json", "Print JSON output", false).action(async (id, actionOptions, command) => {
59286
59292
  const result = await createClient(options).testChannel(id, {
59287
59293
  source: options.source,
59288
59294
  type: actionOptions.type,
@@ -59290,13 +59296,13 @@ function registerWebhookCommands(program2, options) {
59290
59296
  message: actionOptions.message,
59291
59297
  data: parseJsonObject(actionOptions.data, { test: true })
59292
59298
  });
59293
- print(result, Boolean(actionOptions.json), `${result.status}: ${result.channelId}`);
59299
+ print(result, wantsJson(actionOptions, command), `${result.status}: ${result.channelId}`);
59294
59300
  });
59295
59301
  return webhooks;
59296
59302
  }
59297
59303
  function registerEventCommands(program2, options) {
59298
59304
  const events = program2.command(options.eventsCommandName ?? "events").description("Emit, list, and replay Hasna events");
59299
- events.command("emit").description("Emit an event from this app").argument("<type>", "Event type").option("--source <source>", "Event source override").option("--subject <subject>", "Event subject").option("--severity <severity>", "Event severity", "info").option("--message <message>", "Event message").option("--dedupe-key <key>", "Dedupe key").option("--data <json>", "Event data JSON object").option("--metadata <json>", "Event metadata JSON object").option("--no-deliver", "Record without delivering").option("--no-dedupe", "Allow duplicate id/dedupeKey events").option("-j, --json", "Print JSON output", false).action(async (type, actionOptions) => {
59305
+ events.command("emit").description("Emit an event from this app").argument("<type>", "Event type").option("--source <source>", "Event source override").option("--subject <subject>", "Event subject").option("--severity <severity>", "Event severity", "info").option("--message <message>", "Event message").option("--dedupe-key <key>", "Dedupe key").option("--data <json>", "Event data JSON object").option("--metadata <json>", "Event metadata JSON object").option("--no-deliver", "Record without delivering").option("--no-dedupe", "Allow duplicate id/dedupeKey events").option("-j, --json", "Print JSON output", false).action(async (type, actionOptions, command) => {
59300
59306
  const result = await createClient(options).emit({
59301
59307
  source: actionOptions.source ?? options.source,
59302
59308
  type,
@@ -59307,9 +59313,9 @@ function registerEventCommands(program2, options) {
59307
59313
  data: parseJsonObject(actionOptions.data, {}),
59308
59314
  metadata: parseJsonObject(actionOptions.metadata, {})
59309
59315
  }, { deliver: actionOptions.deliver, dedupe: actionOptions.dedupe });
59310
- print(result, Boolean(actionOptions.json), `${result.deduped ? "Deduped" : "Emitted"} ${result.event.id} to ${result.deliveries.length} channel(s)`);
59316
+ print(result, wantsJson(actionOptions, command), `${result.deduped ? "Deduped" : "Emitted"} ${result.event.id} to ${result.deliveries.length} channel(s)`);
59311
59317
  });
59312
- events.command("list").description("List recorded events").option("--source <source>", "Filter by source").option("--type <type>", "Filter by type").option("--limit <n>", "Limit results", parseNumber).option("-j, --json", "Print JSON output", false).action(async (actionOptions) => {
59318
+ events.command("list").description("List recorded events").option("--source <source>", "Filter by source").option("--type <type>", "Filter by type").option("--limit <n>", "Limit results", parseNumber).option("-j, --json", "Print JSON output", false).action(async (actionOptions, command) => {
59313
59319
  let rows = await createClient(options).listEvents();
59314
59320
  if (actionOptions.source)
59315
59321
  rows = rows.filter((event) => event.source === actionOptions.source);
@@ -59317,7 +59323,7 @@ function registerEventCommands(program2, options) {
59317
59323
  rows = rows.filter((event) => event.type === actionOptions.type);
59318
59324
  if (actionOptions.limit)
59319
59325
  rows = rows.slice(-actionOptions.limit);
59320
- if (actionOptions.json) {
59326
+ if (wantsJson(actionOptions, command)) {
59321
59327
  console.log(JSON.stringify(rows, null, 2));
59322
59328
  return;
59323
59329
  }
@@ -59328,14 +59334,14 @@ function registerEventCommands(program2, options) {
59328
59334
  for (const event of rows)
59329
59335
  console.log(`${event.time} ${event.id} ${event.source} ${event.type} ${event.severity}`);
59330
59336
  });
59331
- events.command("replay").description("Replay recorded events").option("--id <id>", "Replay one event id").option("--source <source>", "Filter by source").option("--type <type>", "Filter by type").option("--dry-run", "Preview without delivery", false).option("-j, --json", "Print JSON output", false).action(async (actionOptions) => {
59337
+ events.command("replay").description("Replay recorded events").option("--id <id>", "Replay one event id").option("--source <source>", "Filter by source").option("--type <type>", "Filter by type").option("--dry-run", "Preview without delivery", false).option("-j, --json", "Print JSON output", false).action(async (actionOptions, command) => {
59332
59338
  const result = await createClient(options).replay({
59333
59339
  eventId: actionOptions.id,
59334
59340
  source: actionOptions.source,
59335
59341
  type: actionOptions.type,
59336
59342
  dryRun: actionOptions.dryRun
59337
59343
  });
59338
- print(result, Boolean(actionOptions.json), `Replayed ${result.events.length} event(s), ${result.deliveries.length} delivery result(s)`);
59344
+ print(result, wantsJson(actionOptions, command), `Replayed ${result.events.length} event(s), ${result.deliveries.length} delivery result(s)`);
59339
59345
  });
59340
59346
  return events;
59341
59347
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "packageName": "@hasna/todos",
3
- "packageVersion": "0.11.54",
3
+ "packageVersion": "0.11.55",
4
4
  "repository": "https://github.com/hasna/todos.git",
5
- "gitCommit": "4801843ff5762614a95ac92a223082505aa8961e",
6
- "generatedAt": "2026-06-16T08:40:13.483Z"
5
+ "gitCommit": "00b566276db208cd222e9232ce2ff9fa20f9cba2",
6
+ "generatedAt": "2026-06-16T11:14:19.914Z"
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/todos",
3
- "version": "0.11.54",
3
+ "version": "0.11.55",
4
4
  "description": "Universal task management for AI coding agents - CLI + MCP server + interactive TUI",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -89,7 +89,7 @@
89
89
  "author": "Andrei Hasna <andrei@hasna.com>",
90
90
  "license": "Apache-2.0",
91
91
  "dependencies": {
92
- "@hasna/events": "^0.1.3",
92
+ "@hasna/events": "^0.1.7",
93
93
  "@modelcontextprotocol/sdk": "^1.12.1",
94
94
  "chalk": "^5.4.1",
95
95
  "commander": "^13.1.0",