@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.
- package/.cursor-plugin/plugin.json +1 -1
- package/dist/cursor-session-start.js +123 -25
- package/dist/mcp-server.js +12 -0
- package/dist/workit-hook.js +132 -24
- package/package.json +3 -3
|
@@ -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
|
|
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 || !
|
|
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
|
-
},
|
|
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) =>
|
|
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
|
-
|
|
23136
|
-
|
|
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 =
|
|
23145
|
-
if (
|
|
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
|
-
|
|
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
|
-
|
|
23330
|
-
|
|
23331
|
-
|
|
23332
|
-
|
|
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()
|
package/dist/mcp-server.js
CHANGED
|
@@ -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"]);
|
package/dist/workit-hook.js
CHANGED
|
@@ -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
|
|
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 || !
|
|
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
|
|
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) =>
|
|
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
|
-
|
|
23371
|
-
|
|
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 =
|
|
23380
|
-
if (
|
|
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
|
-
|
|
23551
|
-
|
|
23552
|
-
|
|
23553
|
-
|
|
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.
|
|
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.
|
|
50
|
-
"@brainervirus/workit-mcp": "^8.17.
|
|
49
|
+
"@brainervirus/workit-core": "^8.17.1",
|
|
50
|
+
"@brainervirus/workit-mcp": "^8.17.1"
|
|
51
51
|
},
|
|
52
52
|
"engines": {
|
|
53
53
|
"node": ">=24"
|