@brainervirus/workit-cursor 8.17.0 → 8.17.1

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.
@@ -2,7 +2,7 @@
2
2
  "name": "workit",
3
3
  "displayName": "Workit",
4
4
  "description": "Adaptive Workit workflow with shared MCP tools and native Cursor hooks",
5
- "version": "8.17.0",
5
+ "version": "8.17.1",
6
6
  "author": {
7
7
  "name": "Cristhofer Pincetti"
8
8
  },
@@ -22274,6 +22274,102 @@ var init_handle = __esm(() => {
22274
22274
  CLAUDE_WORKTREE = /[\\/]\.claude[\\/]worktrees[\\/]/;
22275
22275
  });
22276
22276
 
22277
+ // packages/workit-core/src/hooks/deadline.ts
22278
+ import { appendFileSync, mkdirSync as mkdirSync3 } from "node:fs";
22279
+ import path28 from "node:path";
22280
+ var HOOK_SKIP_TEXT = "workit context skipped: host under load", HOOK_DEADLINE_MS = 8000, HOST_DEADLINES, HOOK_SKIPS_FILE = "hook-skips.jsonl", override = (env) => {
22281
+ const value = Number(env.WORKIT_HOOK_DEADLINE_MS);
22282
+ return Number.isFinite(value) && value > 0 ? value : null;
22283
+ }, hookDeadlineMs = (env, host = "", native) => {
22284
+ const row = HOST_DEADLINES[host];
22285
+ return override(env) ?? (row ? native === undefined ? Math.min(...Object.values(row)) : row[native] ?? row[""] : HOOK_DEADLINE_MS);
22286
+ }, skipsFile = (stateDir) => path28.join(stateDir, HOOK_SKIPS_FILE), recordHookSkip = (skip, stateDir = resolveStateDir()) => {
22287
+ try {
22288
+ mkdirSync3(stateDir, { recursive: true });
22289
+ appendFileSync(skipsFile(stateDir), `${JSON.stringify(skip)}
22290
+ `);
22291
+ } catch {}
22292
+ }, QUIET, skipDecision = (event) => QUIET.has(event) ? { kind: "none" } : { kind: "context", text: HOOK_SKIP_TEXT }, TIMED_OUT, within = async (work, ms) => {
22293
+ let timer;
22294
+ const expired = new Promise((resolve) => {
22295
+ timer = setTimeout(() => resolve(TIMED_OUT), Math.max(0, ms));
22296
+ timer.unref?.();
22297
+ });
22298
+ try {
22299
+ return await Promise.race([work, expired]);
22300
+ } finally {
22301
+ clearTimeout(timer);
22302
+ }
22303
+ }, isTimedOut = (value) => value === TIMED_OUT, PROCESS_START, hookBudget = (env, options = {}, host = "") => {
22304
+ const now = options.now ?? Date.now;
22305
+ return {
22306
+ now,
22307
+ record: options.record ?? ((skip) => recordHookSkip(skip)),
22308
+ startedAt: options.startedAt ?? now(),
22309
+ deadlineMs: options.deadlineMs ?? hookDeadlineMs(env, host),
22310
+ host: options.deadlineMs === undefined ? host : null
22311
+ };
22312
+ }, readWithin = async (stdin, budget) => {
22313
+ const read = (async () => {
22314
+ let text = "";
22315
+ for await (const chunk of stdin)
22316
+ text += String(chunk);
22317
+ return text;
22318
+ })();
22319
+ const text = await within(read, budget.startedAt + budget.deadlineMs - budget.now());
22320
+ return isTimedOut(text) ? null : text;
22321
+ }, note = (adapter, raw, env, budget, outcome, stage) => {
22322
+ const parsed = raw === undefined ? null : adapter.parse(raw, env);
22323
+ const event = parsed ? parsed.ok ? parsed.input.event.kind : parsed.event : null;
22324
+ budget.record({
22325
+ at: new Date(budget.now()).toISOString(),
22326
+ host: adapter.descriptor.host,
22327
+ event,
22328
+ outcome,
22329
+ stage,
22330
+ elapsedMs: Math.round(budget.now() - budget.startedAt)
22331
+ });
22332
+ return { native: parsed?.native ?? null, event };
22333
+ }, skippedHook = (adapter, raw, env, budget, stage) => {
22334
+ const { native, event } = note(adapter, raw, env, budget, "skip", stage);
22335
+ return {
22336
+ ...adapter.render(skipDecision(event), native),
22337
+ error: `${HOOK_SKIP_TEXT} (past the ${budget.deadlineMs} ms hook deadline)`,
22338
+ skipped: true
22339
+ };
22340
+ }, dispatchWithin = async (adapter, raw, env, budget, dispatch = dispatchHook) => {
22341
+ const native = raw?.hook_event_name;
22342
+ if (budget.host !== null && typeof native === "string")
22343
+ budget.deadlineMs = hookDeadlineMs(env, budget.host, native);
22344
+ const remaining = () => budget.startedAt + budget.deadlineMs - budget.now();
22345
+ const result = remaining() > 0 ? await within(Promise.resolve().then(() => dispatch(adapter, raw, env)), remaining()) : TIMED_OUT;
22346
+ if (isTimedOut(result))
22347
+ return skippedHook(adapter, raw, env, budget, "dispatch");
22348
+ if (remaining() < 0)
22349
+ note(adapter, raw, env, budget, "late", "done");
22350
+ return { ...result, skipped: false };
22351
+ };
22352
+ var init_deadline = __esm(() => {
22353
+ init_logger();
22354
+ init_handle();
22355
+ HOST_DEADLINES = {
22356
+ claude_code: { "": 8000, SessionStart: 16000, Stop: 16000 },
22357
+ codex_cli: { "": 45000, Stop: 16000 },
22358
+ codex_desktop: { "": 45000, Stop: 16000 },
22359
+ cursor: { "": 45000 }
22360
+ };
22361
+ QUIET = new Set([
22362
+ "stop",
22363
+ "subagent.stop",
22364
+ "shell.post",
22365
+ "compact.pre",
22366
+ "prompt.submit",
22367
+ null
22368
+ ]);
22369
+ TIMED_OUT = Symbol("timed out");
22370
+ PROCESS_START = performance.timeOrigin;
22371
+ });
22372
+
22277
22373
  // packages/workit-core/src/hooks/hosts/claude-code.ts
22278
22374
  var CLAUDE_CODE_DESCRIPTOR, EVENTS, SOURCES, SHELL_TOOLS, dialectOf2 = (value) => value.tool_name === "PowerShell" ? "powershell" : "posix", toolCommand = (value) => isRecord6(value.tool_input) ? commandText(value.tool_input.command) : null, eventOf = (name, value) => {
22279
22375
  const toolUseId = optionalText(value.tool_use_id);
@@ -22832,7 +22928,7 @@ var init_codex = __esm(() => {
22832
22928
 
22833
22929
  // packages/workit-core/src/hooks/hosts/cursor.ts
22834
22930
  import fs21 from "node:fs";
22835
- import path28 from "node:path";
22931
+ import path29 from "node:path";
22836
22932
  var undocumented, none, CURSOR_DESCRIPTOR, EVENTS3, parseCursorHookInput = (value) => {
22837
22933
  if (!isRecord6(value) || !Object.hasOwn(EVENTS3, String(value.hook_event_name)))
22838
22934
  return { ok: false, error: "hook_event_name is required" };
@@ -22913,7 +23009,7 @@ var undocumented, none, CURSOR_DESCRIPTOR, EVENTS3, parseCursorHookInput = (valu
22913
23009
  };
22914
23010
  }
22915
23011
  }, TRANSCRIPT_TAIL_BYTES, lastAssistantText = (file) => {
22916
- if (!file || !path28.isAbsolute(file))
23012
+ if (!file || !path29.isAbsolute(file))
22917
23013
  return null;
22918
23014
  try {
22919
23015
  const size = fs21.statSync(file).size;
@@ -22949,14 +23045,14 @@ var undocumented, none, CURSOR_DESCRIPTOR, EVENTS3, parseCursorHookInput = (valu
22949
23045
  } catch {
22950
23046
  return null;
22951
23047
  }
22952
- }, within = (root, dir) => dir === root || dir.startsWith(root.endsWith(path28.sep) ? root : `${root}${path28.sep}`), hookCwd = (input) => {
23048
+ }, within2 = (root, dir) => dir === root || dir.startsWith(root.endsWith(path29.sep) ? root : `${root}${path29.sep}`), hookCwd = (input) => {
22953
23049
  const cwd = existingDirectory(input.cwd);
22954
23050
  if (cwd && input.hook_event_name === "beforeShellExecution")
22955
23051
  return cwd;
22956
23052
  return cursorWorkspaceRoot(input);
22957
23053
  }, cursorWorkspaceRoot = (input) => {
22958
23054
  const cwd = existingDirectory(input.cwd);
22959
- return cwd && input.workspace_roots.find((root) => within(root, cwd)) || input.workspace_roots[0];
23055
+ return cwd && input.workspace_roots.find((root) => within2(root, cwd)) || input.workspace_roots[0];
22960
23056
  }, cursorDeny = (reason) => ({
22961
23057
  permission: "deny",
22962
23058
  user_message: "Workit blocked this action",
@@ -23130,19 +23226,21 @@ var init_cursor = __esm(() => {
23130
23226
  });
23131
23227
 
23132
23228
  // packages/workit-core/src/hooks/run.ts
23133
- async function runHookProcess(host, stdin, stdout, stderr = process.stderr, env = process.env) {
23229
+ async function runHookProcess(host, stdin, stdout, stderr = process.stderr, env = process.env, deadline = {}) {
23134
23230
  const adapter = typeof host === "string" ? HOOK_ADAPTERS[host] : host;
23135
- let text = "";
23136
- for await (const chunk of stdin)
23137
- text += String(chunk);
23231
+ const budget = hookBudget(env, deadline, adapter.descriptor.host);
23232
+ const text = await readWithin(stdin, budget);
23138
23233
  let raw;
23139
23234
  try {
23140
- raw = JSON.parse(text || "{}");
23235
+ raw = text === null ? undefined : JSON.parse(text || "{}");
23141
23236
  } catch {
23142
23237
  raw = undefined;
23143
23238
  }
23144
- const result = dispatchHook(adapter, raw, env);
23145
- if (raw === undefined || result.error)
23239
+ const result = text === null ? skippedHook(adapter, undefined, env, budget, "input") : await dispatchWithin(adapter, raw, env, budget, deadline.dispatch);
23240
+ if (result.skipped)
23241
+ stderr.write(`[workit] ${result.error}
23242
+ `);
23243
+ else if (raw === undefined || result.error)
23146
23244
  stderr.write(`[workit] hook input rejected: ${raw === undefined ? "invalid JSON hook input" : result.error}
23147
23245
  `);
23148
23246
  stdout.write(`${JSON.stringify(result.json)}
@@ -23151,7 +23249,7 @@ async function runHookProcess(host, stdin, stdout, stderr = process.stderr, env
23151
23249
  }
23152
23250
  var HOOK_ADAPTERS;
23153
23251
  var init_run = __esm(async () => {
23154
- init_handle();
23252
+ init_deadline();
23155
23253
  init_claude_code();
23156
23254
  init_codex();
23157
23255
  init_cursor();
@@ -23309,6 +23407,14 @@ var hostRef = (handle) => ({ kind: "host", host: "cursor", handle }), cursorCapa
23309
23407
  return { json: {} };
23310
23408
  const note = `[workit: ${gap}; Workit checks are skipped for this action]`;
23311
23409
  return { json: { permission: "allow", user_message: note, agent_message: note } };
23410
+ }, subagentStartStep = (_adapter, raw) => {
23411
+ let json;
23412
+ try {
23413
+ json = handleSubagentStartHook(raw);
23414
+ } catch (error) {
23415
+ json = cursorDeny(`hook failure: ${String(error)}`);
23416
+ }
23417
+ return { json, exitCode: json.permission === "deny" ? 2 : 0, error: null };
23312
23418
  }, runCursorHook = async () => {
23313
23419
  let text = "";
23314
23420
  for await (const chunk of process.stdin)
@@ -23326,24 +23432,16 @@ var hostRef = (handle) => ({ kind: "host", host: "cursor", handle }), cursorCapa
23326
23432
  process.exitCode = 0;
23327
23433
  return;
23328
23434
  }
23329
- if (isSubagentStart(raw)) {
23330
- let output;
23331
- try {
23332
- output = handleSubagentStartHook(raw);
23333
- } catch (error) {
23334
- output = cursorDeny(`hook failure: ${String(error)}`);
23335
- }
23336
- process.stdout.write(`${JSON.stringify(output)}
23337
- `);
23338
- process.exitCode = output.permission === "deny" ? 2 : 0;
23339
- return;
23340
- }
23341
- process.exitCode = await runHookProcess(cursorAdapter, [text], process.stdout);
23435
+ process.exitCode = await runHookProcess(cursorAdapter, [text], process.stdout, process.stderr, process.env, {
23436
+ startedAt: PROCESS_START,
23437
+ ...isSubagentStart(raw) ? { dispatch: subagentStartStep } : {}
23438
+ });
23342
23439
  };
23343
23440
  var init_workit_hook = __esm(async () => {
23344
23441
  init_task_contract();
23345
23442
  init_task_engine();
23346
23443
  init_task_store();
23444
+ init_deadline();
23347
23445
  await __promiseAll([
23348
23446
  init_hooks(),
23349
23447
  init_hooks()
@@ -28828,6 +28828,18 @@ var WRITE_TOOLS = new Set([
28828
28828
  ]);
28829
28829
  // packages/workit-core/src/hooks/handle.ts
28830
28830
  var offered = new Set;
28831
+ // packages/workit-core/src/hooks/deadline.ts
28832
+ var QUIET = new Set([
28833
+ "stop",
28834
+ "subagent.stop",
28835
+ "shell.post",
28836
+ "compact.pre",
28837
+ "prompt.submit",
28838
+ null
28839
+ ]);
28840
+ var TIMED_OUT = Symbol("timed out");
28841
+ var PROCESS_START = performance.timeOrigin;
28842
+
28831
28843
  // packages/workit-core/src/hooks/hosts/claude-code.ts
28832
28844
  var SOURCES = new Set(["startup", "resume", "clear", "compact", "fork"]);
28833
28845
  var SHELL_TOOLS = new Set(["Bash", "PowerShell"]);
@@ -22498,6 +22498,112 @@ var dispatchHook = (adapter, raw, env = process.env) => {
22498
22498
  };
22499
22499
  }
22500
22500
  };
22501
+ // packages/workit-core/src/hooks/deadline.ts
22502
+ import { appendFileSync, mkdirSync as mkdirSync3 } from "node:fs";
22503
+ import path28 from "node:path";
22504
+ var HOOK_SKIP_TEXT = "workit context skipped: host under load";
22505
+ var HOOK_DEADLINE_MS = 8000;
22506
+ var HOST_DEADLINES = {
22507
+ claude_code: { "": 8000, SessionStart: 16000, Stop: 16000 },
22508
+ codex_cli: { "": 45000, Stop: 16000 },
22509
+ codex_desktop: { "": 45000, Stop: 16000 },
22510
+ cursor: { "": 45000 }
22511
+ };
22512
+ var HOOK_SKIPS_FILE = "hook-skips.jsonl";
22513
+ var override = (env) => {
22514
+ const value = Number(env.WORKIT_HOOK_DEADLINE_MS);
22515
+ return Number.isFinite(value) && value > 0 ? value : null;
22516
+ };
22517
+ var hookDeadlineMs = (env, host = "", native) => {
22518
+ const row = HOST_DEADLINES[host];
22519
+ return override(env) ?? (row ? native === undefined ? Math.min(...Object.values(row)) : row[native] ?? row[""] : HOOK_DEADLINE_MS);
22520
+ };
22521
+ var skipsFile = (stateDir) => path28.join(stateDir, HOOK_SKIPS_FILE);
22522
+ var recordHookSkip = (skip, stateDir = resolveStateDir()) => {
22523
+ try {
22524
+ mkdirSync3(stateDir, { recursive: true });
22525
+ appendFileSync(skipsFile(stateDir), `${JSON.stringify(skip)}
22526
+ `);
22527
+ } catch {}
22528
+ };
22529
+ var QUIET = new Set([
22530
+ "stop",
22531
+ "subagent.stop",
22532
+ "shell.post",
22533
+ "compact.pre",
22534
+ "prompt.submit",
22535
+ null
22536
+ ]);
22537
+ var skipDecision = (event) => QUIET.has(event) ? { kind: "none" } : { kind: "context", text: HOOK_SKIP_TEXT };
22538
+ var TIMED_OUT = Symbol("timed out");
22539
+ var within = async (work, ms) => {
22540
+ let timer;
22541
+ const expired = new Promise((resolve) => {
22542
+ timer = setTimeout(() => resolve(TIMED_OUT), Math.max(0, ms));
22543
+ timer.unref?.();
22544
+ });
22545
+ try {
22546
+ return await Promise.race([work, expired]);
22547
+ } finally {
22548
+ clearTimeout(timer);
22549
+ }
22550
+ };
22551
+ var isTimedOut = (value) => value === TIMED_OUT;
22552
+ var PROCESS_START = performance.timeOrigin;
22553
+ var hookBudget = (env, options = {}, host = "") => {
22554
+ const now = options.now ?? Date.now;
22555
+ return {
22556
+ now,
22557
+ record: options.record ?? ((skip) => recordHookSkip(skip)),
22558
+ startedAt: options.startedAt ?? now(),
22559
+ deadlineMs: options.deadlineMs ?? hookDeadlineMs(env, host),
22560
+ host: options.deadlineMs === undefined ? host : null
22561
+ };
22562
+ };
22563
+ var readWithin = async (stdin, budget) => {
22564
+ const read = (async () => {
22565
+ let text = "";
22566
+ for await (const chunk of stdin)
22567
+ text += String(chunk);
22568
+ return text;
22569
+ })();
22570
+ const text = await within(read, budget.startedAt + budget.deadlineMs - budget.now());
22571
+ return isTimedOut(text) ? null : text;
22572
+ };
22573
+ var note = (adapter, raw, env, budget, outcome, stage) => {
22574
+ const parsed = raw === undefined ? null : adapter.parse(raw, env);
22575
+ const event = parsed ? parsed.ok ? parsed.input.event.kind : parsed.event : null;
22576
+ budget.record({
22577
+ at: new Date(budget.now()).toISOString(),
22578
+ host: adapter.descriptor.host,
22579
+ event,
22580
+ outcome,
22581
+ stage,
22582
+ elapsedMs: Math.round(budget.now() - budget.startedAt)
22583
+ });
22584
+ return { native: parsed?.native ?? null, event };
22585
+ };
22586
+ var skippedHook = (adapter, raw, env, budget, stage) => {
22587
+ const { native, event } = note(adapter, raw, env, budget, "skip", stage);
22588
+ return {
22589
+ ...adapter.render(skipDecision(event), native),
22590
+ error: `${HOOK_SKIP_TEXT} (past the ${budget.deadlineMs} ms hook deadline)`,
22591
+ skipped: true
22592
+ };
22593
+ };
22594
+ var dispatchWithin = async (adapter, raw, env, budget, dispatch = dispatchHook) => {
22595
+ const native = raw?.hook_event_name;
22596
+ if (budget.host !== null && typeof native === "string")
22597
+ budget.deadlineMs = hookDeadlineMs(env, budget.host, native);
22598
+ const remaining = () => budget.startedAt + budget.deadlineMs - budget.now();
22599
+ const result = remaining() > 0 ? await within(Promise.resolve().then(() => dispatch(adapter, raw, env)), remaining()) : TIMED_OUT;
22600
+ if (isTimedOut(result))
22601
+ return skippedHook(adapter, raw, env, budget, "dispatch");
22602
+ if (remaining() < 0)
22603
+ note(adapter, raw, env, budget, "late", "done");
22604
+ return { ...result, skipped: false };
22605
+ };
22606
+
22501
22607
  // packages/workit-core/src/hooks/hosts/claude-code.ts
22502
22608
  var CLAUDE_CODE_DESCRIPTOR = {
22503
22609
  host: "claude_code",
@@ -23057,7 +23163,7 @@ var codexAdapter = {
23057
23163
 
23058
23164
  // packages/workit-core/src/hooks/hosts/cursor.ts
23059
23165
  import fs21 from "node:fs";
23060
- import path28 from "node:path";
23166
+ import path29 from "node:path";
23061
23167
  var undocumented = { support: "undocumented", native: null };
23062
23168
  var none = { support: "none", native: null };
23063
23169
  var CURSOR_DESCRIPTOR = {
@@ -23254,7 +23360,7 @@ var protocolEvent2 = (input) => {
23254
23360
  };
23255
23361
  var TRANSCRIPT_TAIL_BYTES = 256 * 1024;
23256
23362
  var lastAssistantText = (file) => {
23257
- if (!file || !path28.isAbsolute(file))
23363
+ if (!file || !path29.isAbsolute(file))
23258
23364
  return null;
23259
23365
  try {
23260
23366
  const size = fs21.statSync(file).size;
@@ -23291,7 +23397,7 @@ var lastAssistantText = (file) => {
23291
23397
  return null;
23292
23398
  }
23293
23399
  };
23294
- var within = (root, dir) => dir === root || dir.startsWith(root.endsWith(path28.sep) ? root : `${root}${path28.sep}`);
23400
+ var within2 = (root, dir) => dir === root || dir.startsWith(root.endsWith(path29.sep) ? root : `${root}${path29.sep}`);
23295
23401
  var hookCwd = (input) => {
23296
23402
  const cwd = existingDirectory(input.cwd);
23297
23403
  if (cwd && input.hook_event_name === "beforeShellExecution")
@@ -23300,7 +23406,7 @@ var hookCwd = (input) => {
23300
23406
  };
23301
23407
  var cursorWorkspaceRoot = (input) => {
23302
23408
  const cwd = existingDirectory(input.cwd);
23303
- return cwd && input.workspace_roots.find((root) => within(root, cwd)) || input.workspace_roots[0];
23409
+ return cwd && input.workspace_roots.find((root) => within2(root, cwd)) || input.workspace_roots[0];
23304
23410
  };
23305
23411
  var cursorDeny = (reason) => ({
23306
23412
  permission: "deny",
@@ -23365,19 +23471,21 @@ var HOOK_ADAPTERS = {
23365
23471
  codex_desktop: codexAdapter,
23366
23472
  cursor: cursorAdapter
23367
23473
  };
23368
- async function runHookProcess(host, stdin, stdout, stderr = process.stderr, env = process.env) {
23474
+ async function runHookProcess(host, stdin, stdout, stderr = process.stderr, env = process.env, deadline = {}) {
23369
23475
  const adapter = typeof host === "string" ? HOOK_ADAPTERS[host] : host;
23370
- let text = "";
23371
- for await (const chunk of stdin)
23372
- text += String(chunk);
23476
+ const budget = hookBudget(env, deadline, adapter.descriptor.host);
23477
+ const text = await readWithin(stdin, budget);
23373
23478
  let raw;
23374
23479
  try {
23375
- raw = JSON.parse(text || "{}");
23480
+ raw = text === null ? undefined : JSON.parse(text || "{}");
23376
23481
  } catch {
23377
23482
  raw = undefined;
23378
23483
  }
23379
- const result = dispatchHook(adapter, raw, env);
23380
- if (raw === undefined || result.error)
23484
+ const result = text === null ? skippedHook(adapter, undefined, env, budget, "input") : await dispatchWithin(adapter, raw, env, budget, deadline.dispatch);
23485
+ if (result.skipped)
23486
+ stderr.write(`[workit] ${result.error}
23487
+ `);
23488
+ else if (raw === undefined || result.error)
23381
23489
  stderr.write(`[workit] hook input rejected: ${raw === undefined ? "invalid JSON hook input" : result.error}
23382
23490
  `);
23383
23491
  stdout.write(`${JSON.stringify(result.json)}
@@ -23530,6 +23638,15 @@ var degradedCursorHook = (raw) => {
23530
23638
  return { json: { permission: "allow", user_message: note, agent_message: note } };
23531
23639
  };
23532
23640
  var handleCursorHook = (raw) => degradedCursorHook(raw)?.json ?? (isSubagentStart(raw) ? handleSubagentStartHook(raw) : dispatchHook(cursorAdapter, raw).json);
23641
+ var subagentStartStep = (_adapter, raw) => {
23642
+ let json;
23643
+ try {
23644
+ json = handleSubagentStartHook(raw);
23645
+ } catch (error) {
23646
+ json = cursorDeny(`hook failure: ${String(error)}`);
23647
+ }
23648
+ return { json, exitCode: json.permission === "deny" ? 2 : 0, error: null };
23649
+ };
23533
23650
  var runCursorHook = async () => {
23534
23651
  let text = "";
23535
23652
  for await (const chunk of process.stdin)
@@ -23547,19 +23664,10 @@ var runCursorHook = async () => {
23547
23664
  process.exitCode = 0;
23548
23665
  return;
23549
23666
  }
23550
- if (isSubagentStart(raw)) {
23551
- let output;
23552
- try {
23553
- output = handleSubagentStartHook(raw);
23554
- } catch (error) {
23555
- output = cursorDeny(`hook failure: ${String(error)}`);
23556
- }
23557
- process.stdout.write(`${JSON.stringify(output)}
23558
- `);
23559
- process.exitCode = output.permission === "deny" ? 2 : 0;
23560
- return;
23561
- }
23562
- process.exitCode = await runHookProcess(cursorAdapter, [text], process.stdout);
23667
+ process.exitCode = await runHookProcess(cursorAdapter, [text], process.stdout, process.stderr, process.env, {
23668
+ startedAt: PROCESS_START,
23669
+ ...isSubagentStart(raw) ? { dispatch: subagentStartStep } : {}
23670
+ });
23563
23671
  };
23564
23672
  if (__require.main == __require.module)
23565
23673
  await runCursorHook();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brainervirus/workit-cursor",
3
- "version": "8.17.0",
3
+ "version": "8.17.1",
4
4
  "private": false,
5
5
  "description": "Workit Cursor plugin — shared MCP transport, native hooks, and sixteen method skills",
6
6
  "keywords": [
@@ -46,8 +46,8 @@
46
46
  "build": "bun scripts/build.ts"
47
47
  },
48
48
  "devDependencies": {
49
- "@brainervirus/workit-core": "^8.17.0",
50
- "@brainervirus/workit-mcp": "^8.17.0"
49
+ "@brainervirus/workit-core": "^8.17.1",
50
+ "@brainervirus/workit-mcp": "^8.17.1"
51
51
  },
52
52
  "engines": {
53
53
  "node": ">=24"