@hasna/loops 0.3.29 → 0.3.31

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
@@ -5253,7 +5253,7 @@ function buildScriptInventoryReport(store, opts = {}) {
5253
5253
  // package.json
5254
5254
  var package_default = {
5255
5255
  name: "@hasna/loops",
5256
- version: "0.3.29",
5256
+ version: "0.3.31",
5257
5257
  description: "Persistent local loop and workflow runner for deterministic commands and headless AI coding agents",
5258
5258
  type: "module",
5259
5259
  main: "dist/index.js",
@@ -6211,7 +6211,7 @@ function runLocalCommand(command, args, opts = {}) {
6211
6211
  input: opts.input,
6212
6212
  encoding: "utf8",
6213
6213
  timeout: opts.timeoutMs ?? 30000,
6214
- maxBuffer: 8 * 1024 * 1024,
6214
+ maxBuffer: opts.maxBuffer ?? 8 * 1024 * 1024,
6215
6215
  env: process.env
6216
6216
  });
6217
6217
  return {
@@ -6636,6 +6636,10 @@ function routeThrottleDryRunPreview(args) {
6636
6636
  limits: args.limits
6637
6637
  };
6638
6638
  }
6639
+ function findLoopByTaskIdempotency(store, idempotencyKey) {
6640
+ const marker = `idempotency=${idempotencyKey}`;
6641
+ return store.listLoops({ includeArchived: true, limit: 1e5 }).find((loop) => loop.description?.includes(marker));
6642
+ }
6639
6643
  async function readEventEnvelopeFromStdin() {
6640
6644
  const raw = process.env.HASNA_EVENT_JSON || await Bun.stdin.text();
6641
6645
  const event = JSON.parse(raw);
@@ -6687,7 +6691,7 @@ function routeTodosTaskEvent(event, opts) {
6687
6691
  if (!opts.dryRun) {
6688
6692
  const store2 = new Store;
6689
6693
  try {
6690
- const existingLoop = store2.findLoopByName(loopName) ?? store2.findLoopByName(legacyLoopName);
6694
+ const existingLoop = store2.findLoopByName(loopName) ?? store2.findLoopByName(legacyLoopName) ?? findLoopByTaskIdempotency(store2, idempotencyKey);
6691
6695
  if (existingLoop) {
6692
6696
  const existingWorkflow = existingLoop.target.type === "workflow" ? store2.getWorkflow(existingLoop.target.workflowId) : undefined;
6693
6697
  return {
@@ -6775,7 +6779,7 @@ function routeTodosTaskEvent(event, opts) {
6775
6779
  event: event.id
6776
6780
  }, {}) : undefined;
6777
6781
  const outcome = store.writeTransaction(() => {
6778
- const existingLoop = store.findLoopByName(loopName) ?? store.findLoopByName(legacyLoopName);
6782
+ const existingLoop = store.findLoopByName(loopName) ?? store.findLoopByName(legacyLoopName) ?? findLoopByTaskIdempotency(store, idempotencyKey);
6779
6783
  if (existingLoop) {
6780
6784
  const existingWorkflow2 = existingLoop.target.type === "workflow" ? store.getWorkflow(existingLoop.target.workflowId) : undefined;
6781
6785
  return { kind: "deduped", existingLoop, existingWorkflow: existingWorkflow2 };
@@ -6897,10 +6901,16 @@ function taskDrainEvent(task) {
6897
6901
  function loadReadyTodosTasks(opts, scanLimit) {
6898
6902
  const todosProject = opts.todosProject ?? defaultLoopsProject();
6899
6903
  const args = ["--project", todosProject, "--json", "ready", "--limit", String(scanLimit)];
6900
- const result = runLocalCommand("todos", args, { timeoutMs: 60000 });
6904
+ const result = runLocalCommand("todos", args, { timeoutMs: 60000, maxBuffer: 64 * 1024 * 1024 });
6901
6905
  if (!result.ok)
6902
6906
  throw new Error(result.stderr || result.error || "todos ready failed");
6903
- const parsed = JSON.parse(result.stdout || "[]");
6907
+ let parsed;
6908
+ try {
6909
+ parsed = JSON.parse(result.stdout || "[]");
6910
+ } catch (error) {
6911
+ const message = error instanceof Error ? error.message : String(error);
6912
+ throw new Error(`failed to parse todos ready --json output (${result.stdout.length} bytes): ${message}`);
6913
+ }
6904
6914
  if (!Array.isArray(parsed))
6905
6915
  throw new Error("todos ready --json returned a non-array value");
6906
6916
  return parsed;
@@ -4574,7 +4574,7 @@ function enableStartup(result) {
4574
4574
  // package.json
4575
4575
  var package_default = {
4576
4576
  name: "@hasna/loops",
4577
- version: "0.3.29",
4577
+ version: "0.3.31",
4578
4578
  description: "Persistent local loop and workflow runner for deterministic commands and headless AI coding agents",
4579
4579
  type: "module",
4580
4580
  main: "dist/index.js",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/loops",
3
- "version": "0.3.29",
3
+ "version": "0.3.31",
4
4
  "description": "Persistent local loop and workflow runner for deterministic commands and headless AI coding agents",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",