@cmodjs/core 2.1.0 → 3.1.0

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 (72) hide show
  1. package/docs/commands.md +2 -2
  2. package/docs/mod.md +3 -1
  3. package/docs/permissions.md +3 -1
  4. package/docs/session.md +9 -1
  5. package/docs/testing.md +4 -2
  6. package/jobs/context.d.ts.map +1 -1
  7. package/jobs/context.js +2 -1
  8. package/jobs/permissions.d.ts.map +1 -1
  9. package/jobs/permissions.js +1 -1
  10. package/jobs/prompt.d.ts.map +1 -1
  11. package/jobs/prompt.js +2 -1
  12. package/jobs/slash-command.d.ts.map +1 -1
  13. package/jobs/slash-command.js +4 -3
  14. package/package.json +1 -1
  15. package/records.d.ts +2 -1
  16. package/records.d.ts.map +1 -1
  17. package/records.js +4 -1
  18. package/register.d.ts.map +1 -1
  19. package/register.js +58 -51
  20. package/runtime/before.d.ts +1 -1
  21. package/runtime/before.d.ts.map +1 -1
  22. package/runtime/before.js +6 -5
  23. package/runtime/conversations.d.ts.map +1 -1
  24. package/runtime/conversations.js +46 -19
  25. package/runtime/hooks.d.ts +2 -1
  26. package/runtime/hooks.d.ts.map +1 -1
  27. package/runtime/hooks.js +7 -0
  28. package/runtime/lifecycle.d.ts +2 -1
  29. package/runtime/lifecycle.d.ts.map +1 -1
  30. package/runtime/lifecycle.js +31 -9
  31. package/runtime/permission-check.d.ts +3 -0
  32. package/runtime/permission-check.d.ts.map +1 -1
  33. package/runtime/permission-check.js +31 -10
  34. package/runtime/router.d.ts +3 -1
  35. package/runtime/router.d.ts.map +1 -1
  36. package/runtime/router.js +19 -11
  37. package/runtime/sessions.d.ts +13 -4
  38. package/runtime/sessions.d.ts.map +1 -1
  39. package/runtime/sessions.js +67 -26
  40. package/runtime/toaster.d.ts.map +1 -1
  41. package/runtime/toaster.js +3 -0
  42. package/session/context/turn/message/message.d.ts.map +1 -1
  43. package/session/context/turn/message/message.js +30 -2
  44. package/session/context/turn/message/note.d.ts +7 -0
  45. package/session/context/turn/message/note.d.ts.map +1 -1
  46. package/session/context/turn/message/note.js +12 -0
  47. package/session/session.d.ts +3 -1
  48. package/session/session.d.ts.map +1 -1
  49. package/src/jobs/context.ts +2 -1
  50. package/src/jobs/permissions.ts +8 -4
  51. package/src/jobs/prompt.ts +2 -1
  52. package/src/jobs/slash-command.ts +4 -3
  53. package/src/records.ts +5 -1
  54. package/src/register.ts +63 -52
  55. package/src/runtime/before.ts +7 -6
  56. package/src/runtime/conversations.ts +54 -27
  57. package/src/runtime/hooks.ts +9 -1
  58. package/src/runtime/lifecycle.ts +37 -13
  59. package/src/runtime/permission-check.ts +51 -21
  60. package/src/runtime/router.ts +23 -13
  61. package/src/runtime/sessions.ts +91 -37
  62. package/src/runtime/toaster.ts +2 -0
  63. package/src/session/context/turn/message/message.ts +27 -2
  64. package/src/session/context/turn/message/note.ts +16 -0
  65. package/src/session/session.ts +1 -2
  66. package/src/testing/fake-claude.ts +4 -3
  67. package/src/testing.ts +6 -5
  68. package/testing/fake-claude.d.ts +1 -0
  69. package/testing/fake-claude.d.ts.map +1 -1
  70. package/testing/fake-claude.js +3 -2
  71. package/testing.d.ts.map +1 -1
  72. package/testing.js +5 -4
@@ -1,6 +1,6 @@
1
1
  import { consentPath, dataFolder, isObject, parseConsent } from '../records.js';
2
2
  import { Message, rowOfAppend } from '../session/context/turn/message/message.js';
3
- import { Note } from '../session/context/turn/message/note.js';
3
+ import { modNote, Note } from '../session/context/turn/message/note.js';
4
4
  import { Person } from '../session/context/turn/message/sender.js';
5
5
  import { createConversation, emptyConversation } from '../session/conversation.js';
6
6
  import { Session, UsageChange } from '../session/session.js';
@@ -8,12 +8,14 @@ import { GoalChange } from '../session/goal/goal.js';
8
8
  import { receivedMatcher } from '../utils/matcher.js';
9
9
  import { ifMissing } from '../utils/paths.js';
10
10
  import { formatExit, messageOf } from '../utils/text.js';
11
- import { foldBefore, installBefore, relayOf } from './before.js';
11
+ import { beforeAnswerKeys, foldBefore, installBefore, relayOf } from './before.js';
12
12
  import { cmodPluginName } from './dependencies.js';
13
13
  import { readLines, runCmod } from './programs.js';
14
- import { actPermission, conversationMethods, everySession, isAct, isHeardBy, resultOf, spawnTask, usageOf } from './sessions.js';
14
+ import { PassedTimeout } from './deadline.js';
15
+ import { actPermission, conversationMethods, everySession, isAct, isHeardBy, isInScope, resultOf, spawnTask, usageOf } from './sessions.js';
15
16
  const bufferedTaskRows = 200;
16
17
  const beforeDeadlineMs = 5000;
18
+ const awayFoldMs = 8000;
17
19
  const livenessMs = 5000;
18
20
  export function serveConversations({ claude, router, store, project, report }) {
19
21
  const folder = dataFolder(store, cmodPluginName);
@@ -161,7 +163,7 @@ export function serveConversations({ claude, router, store, project, report }) {
161
163
  reject(error);
162
164
  },
163
165
  };
164
- const timer = deadlineMs === undefined ? watchLife(settle, to) : claude.clock.after(deadlineMs, () => settle.reject(new Error(`session ${to} did not answer within ${deadlineMs / 1000} s`)));
166
+ const timer = deadlineMs === undefined ? watchLife(settle, to) : claude.clock.after(deadlineMs, () => settle.reject(new PassedTimeout(`session ${to} did not answer within ${deadlineMs / 1000} s`)));
165
167
  asked.set(id, settle);
166
168
  post(to, { ...relay, id, from: session }).catch((error) => settle.reject(error instanceof Error ? error : new Error(messageOf(error))));
167
169
  });
@@ -210,13 +212,26 @@ export function serveConversations({ claude, router, store, project, report }) {
210
212
  throw new Error(`${mod} needs the conversation permission to change what happens in another session. Turn it on in /mods ${mod}.`);
211
213
  return claude.cmod.call({ to: mod, method: conversationMethods.before, input: { session: from, event, change, isInProject } });
212
214
  };
213
- const askAway = async (watcher, event, change) => {
215
+ const isUnderHere = (task, ancestor) => {
216
+ for (let at = task, steps = 0; at !== undefined && steps < 64; at = conversation.state.tasks[at]?.parent, steps += 1)
217
+ if (at === ancestor)
218
+ return true;
219
+ return false;
220
+ };
221
+ const refuses = (watcher, event, change) => beforeAnswerKeys[event].includes('refuse') && (watcher.refusing ?? []).some(({ event: heard, matcher, scope }) => isInScope(scope ?? {}, session, change, isUnderHere) && isHeardBy(heard, matcher === undefined ? undefined : receivedMatcher(matcher), change));
222
+ const askAway = async (watcher, event, change, endsAt) => {
214
223
  try {
215
- return await ask(watcher.from, { kind: 'before', mod: watcher.mod, event, change, project: project() }, beforeDeadlineMs);
224
+ const leftMs = Math.min(beforeDeadlineMs, endsAt - (await claude.clock.now()));
225
+ if (leftMs <= 0)
226
+ throw new PassedTimeout(`the ${awayFoldMs / 1000} s cmod waits on other sessions ran out before session ${watcher.from} was asked`);
227
+ return await ask(watcher.from, { kind: 'before', mod: watcher.mod, event, change, project: project() }, leftMs);
216
228
  }
217
229
  catch (error) {
218
- if (await isRunning(watcher.from))
230
+ if (await isRunning(watcher.from)) {
231
+ if (error instanceof PassedTimeout && refuses(watcher, event, change))
232
+ return { refuse: `${watcher.mod}: ${error.message}` };
219
233
  throw error;
234
+ }
220
235
  watchers = watchers.filter((each) => each.from !== watcher.from);
221
236
  claude.ui.log(`cmod: session ${watcher.from} ended without clearing its before listeners, so they are cleared now`, { to: 'debug' });
222
237
  await claude.fs.write(`${watches}/${watcher.from}.json`, '[]');
@@ -235,7 +250,15 @@ export function serveConversations({ claude, router, store, project, report }) {
235
250
  await Promise.all([starting, watching]);
236
251
  return deciders(event).length > 0;
237
252
  },
238
- decide: (event, change) => foldBefore(event, change, deciders(event).map((watcher) => (latest) => (watcher.from === session ? askHere(watcher.mod, event, latest) : askAway(watcher, event, latest))), (error) => report(`before:${event}`, `Passed the ${event} on without a mod's answer`, error)),
253
+ fold: () => {
254
+ let endsAt;
255
+ return (event, change) => foldBefore(event, change, deciders(event).map((watcher) => async (latest) => {
256
+ if (watcher.from === session)
257
+ return askHere(watcher.mod, event, latest);
258
+ endsAt ??= claude.clock.now().then((now) => now + awayFoldMs);
259
+ return askAway(watcher, event, latest, await endsAt);
260
+ }), (error) => report(`before:${event}`, `Passed the ${event} on without a mod's answer`, error));
261
+ },
239
262
  },
240
263
  });
241
264
  const start = (id, source) => {
@@ -285,15 +308,16 @@ export function serveConversations({ claude, router, store, project, report }) {
285
308
  await publishWatches(true).catch((error) => report('before', 'Left its before listeners registered', error));
286
309
  return next(e);
287
310
  });
288
- router.add('session.append', async (e, next) => {
311
+ const recordAppend = async (e, next) => {
289
312
  const kept = await next(e);
290
313
  if (kept.deny !== undefined || session === '')
291
314
  return kept;
292
315
  const cwd = e.message.type === 'assistant' ? await claude.session.cwd() : '';
293
316
  void take(rowOfAppend({ uuid: kept.uuid, door: e.door, origin: e.origin, message: kept.message }, new Date().toISOString(), cwd), e.agentId).catch((error) => report('append', 'Missed a message', error));
294
317
  return kept;
295
- });
296
- router.add('session.compact', async (e, next) => {
318
+ };
319
+ router.add('session.append', recordAppend, (e, _error, next) => recordAppend(e, next));
320
+ const recordCompaction = async (e, next) => {
297
321
  const compacted = await next(e);
298
322
  if (e.trigger === 'precompute' || compacted.skip !== undefined || session === '')
299
323
  return compacted;
@@ -301,14 +325,15 @@ export function serveConversations({ claude, router, store, project, report }) {
301
325
  const boundary = { id: `compact:${e.agentId ?? session}:${at}`, at, type: 'system', name: 'compact_boundary', isMeta: false, isSummary: false, content: [] };
302
326
  void take(boundary, e.agentId).catch((error) => report('compact', 'Missed a compaction', error));
303
327
  return compacted;
304
- });
328
+ };
329
+ router.add('session.compact', recordCompaction, (e, _error, next) => recordCompaction(e, next));
305
330
  router.add('session.measure', async (e, next) => {
306
331
  const measured = await next(e);
307
332
  if (session !== '')
308
333
  dispatch(session, [{ type: UsageChange, usage: await usageOf(claude) }]);
309
334
  return measured;
310
335
  });
311
- router.add('agent.spawn', async (e, next) => {
336
+ const recordSpawn = async (e, next) => {
312
337
  const spawned = await next(e);
313
338
  if (spawned.deny !== undefined || spawned.agentId === undefined)
314
339
  return spawned;
@@ -321,7 +346,8 @@ export function serveConversations({ claude, router, store, project, report }) {
321
346
  for (const row of waiting)
322
347
  dispatch(session, conversation.add(row, id));
323
348
  return spawned;
324
- });
349
+ };
350
+ router.add('agent.spawn', recordSpawn, (e, _error, next) => recordSpawn(e, next));
325
351
  router.add('session.receive', async (e, next) => {
326
352
  const sent = relayOf(e);
327
353
  if (sent === undefined)
@@ -369,7 +395,7 @@ export function serveConversations({ claude, router, store, project, report }) {
369
395
  if (action === 'abort')
370
396
  return abortTurn(input, task);
371
397
  if (task !== undefined)
372
- return performInTask(action, input, task);
398
+ return performInTask(caller, action, input, task);
373
399
  if (action === 'usage')
374
400
  return usageOf(claude);
375
401
  if (action === 'surfaces')
@@ -378,7 +404,7 @@ export function serveConversations({ claude, router, store, project, report }) {
378
404
  const { type, text, as } = input;
379
405
  if (as === Session)
380
406
  throw new Error(`session ${session} cannot send as itself to itself.`);
381
- const delivered = type === Note ? await claude.session.append({ message: { type: 'user', content: [{ type: 'text', text }] } }) : await claude.prompt.submit({ text, ...(as === Person ? { asUser: true } : {}) });
407
+ const delivered = type === Note ? await claude.session.append({ message: { type: 'user', content: [{ type: 'text', text: modNote(caller, text) }] } }) : await claude.prompt.submit({ text, ...(as === Person ? { asUser: true } : {}) });
382
408
  if ('deny' in delivered && typeof delivered.deny === 'string')
383
409
  throw new Error(`Claude Code refused the note: ${delivered.deny}`);
384
410
  if ('drop' in delivered && typeof delivered.drop === 'string')
@@ -401,7 +427,7 @@ export function serveConversations({ claude, router, store, project, report }) {
401
427
  await claude.turn.abort({ turnId });
402
428
  return null;
403
429
  };
404
- const performInTask = async (action, input, task) => {
430
+ const performInTask = async (caller, action, input, task) => {
405
431
  const running = conversation.state.tasks[task];
406
432
  if (action === 'usage')
407
433
  return json(['history', 'usage', session, '--task', task]);
@@ -411,7 +437,8 @@ export function serveConversations({ claude, router, store, project, report }) {
411
437
  throw new Error(`cmod: ${action} runs only on a session's own main loop.`);
412
438
  if (running === undefined || running.closedAt !== undefined)
413
439
  throw ended(task);
414
- const sent = await claude.session.send({ to: { agentId: task }, text: input.text });
440
+ const { type, text } = input;
441
+ const sent = await claude.session.send({ to: { agentId: task }, text: type === Note ? modNote(caller, text) : text });
415
442
  if (sent.isDelivered !== true)
416
443
  throw ended(task);
417
444
  return null;
@@ -554,7 +581,7 @@ export function serveConversations({ claude, router, store, project, report }) {
554
581
  throw new Error('cmod hears no caller for this before listener.');
555
582
  const target = String(request['session']);
556
583
  const list = Array.isArray(request['subscriptions']) ? request['subscriptions'] : [];
557
- ownWatches.set(`${caller}\n${target}`, { mod: caller, target, project: project(), events: [...new Set(list.map(({ event }) => event))] });
584
+ ownWatches.set(`${caller}\n${target}`, { mod: caller, target, project: project(), events: [...new Set(list.map(({ event }) => event))], refusing: list.filter((each) => each.onFailure === 'refuse') });
558
585
  await publishWatches();
559
586
  return null;
560
587
  },
@@ -1,6 +1,6 @@
1
1
  import type { ClassicHookEvent, ClassicHookInputs } from 'claude-code';
2
2
  import type { Claude } from './claude.js';
3
- import type { RoutedHook } from './router.js';
3
+ import type { RoutedFailure, RoutedHook } from './router.js';
4
4
  import type { Failure } from './toaster.js';
5
5
  import { type CallBase } from '../utils/call-effects.js';
6
6
  export type Hook = Exclude<ClassicHookEvent, 'PreToolUse'>;
@@ -12,6 +12,7 @@ type CallFiles = {
12
12
  readonly changed: string[];
13
13
  };
14
14
  export declare function classicHook<H extends Hook>(event: H, hook: HookListener<H>, report: (failure: Failure) => void): RoutedHook<RoutedEvent>;
15
+ export declare function classicFailure<H extends Hook>(failed: (input: ClassicHookInputs[H], error: Error) => HookFields | undefined | Promise<HookFields | undefined>): RoutedFailure<RoutedEvent>;
15
16
  export declare function userSkillHook(claude: Claude): RoutedHook<'skill.prompt'>;
16
17
  export type HomeFolders = {
17
18
  readonly home: string | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../src/runtime/hooks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAEtE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAC7C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAC3C,OAAO,EAAe,KAAK,QAAQ,EAAmB,MAAM,0BAA0B,CAAA;AAKtF,MAAM,MAAM,IAAI,GAAG,OAAO,CAAC,gBAAgB,EAAE,YAAY,CAAC,CAAA;AAE1D,MAAM,MAAM,UAAU,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;AAE1D,MAAM,MAAM,YAAY,CAAC,CAAC,SAAS,IAAI,IAAI,CAAC,KAAK,EAAE,iBAAiB,CAAC,CAAC,CAAC,KAAK,UAAU,GAAG,SAAS,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAAA;AAEpI,MAAM,MAAM,WAAW,GACnB,WAAW,IAAI,EAAE,GACjB,YAAY,GACZ,WAAW,GACX,eAAe,GACf,gBAAgB,GAChB,mBAAmB,GACnB,aAAa,GACb,iBAAiB,GACjB,cAAc,GACd,WAAW,GACX,UAAU,GACV,WAAW,GACX,UAAU,GACV,WAAW,GACX,gBAAgB,GAChB,iBAAiB,GACjB,iBAAiB,GACjB,aAAa,GACb,YAAY,CAAA;AAEhB,KAAK,SAAS,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAAA;AAExE,wBAAgB,WAAW,CAAC,CAAC,SAAS,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,GAAG,UAAU,CAAC,WAAW,CAAC,CAYxI;AAMD,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,CAAC,cAAc,CAAC,CAexE;AAED,MAAM,MAAM,WAAW,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,CAAA;AAExG,wBAAsB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,WAAW,CAAC,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAgB3I"}
1
+ {"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../src/runtime/hooks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAEtE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAC5D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAC3C,OAAO,EAAe,KAAK,QAAQ,EAAmB,MAAM,0BAA0B,CAAA;AAKtF,MAAM,MAAM,IAAI,GAAG,OAAO,CAAC,gBAAgB,EAAE,YAAY,CAAC,CAAA;AAE1D,MAAM,MAAM,UAAU,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;AAE1D,MAAM,MAAM,YAAY,CAAC,CAAC,SAAS,IAAI,IAAI,CAAC,KAAK,EAAE,iBAAiB,CAAC,CAAC,CAAC,KAAK,UAAU,GAAG,SAAS,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAAA;AAEpI,MAAM,MAAM,WAAW,GACnB,WAAW,IAAI,EAAE,GACjB,YAAY,GACZ,WAAW,GACX,eAAe,GACf,gBAAgB,GAChB,mBAAmB,GACnB,aAAa,GACb,iBAAiB,GACjB,cAAc,GACd,WAAW,GACX,UAAU,GACV,WAAW,GACX,UAAU,GACV,WAAW,GACX,gBAAgB,GAChB,iBAAiB,GACjB,iBAAiB,GACjB,aAAa,GACb,YAAY,CAAA;AAEhB,KAAK,SAAS,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAAA;AAExE,wBAAgB,WAAW,CAAC,CAAC,SAAS,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,GAAG,UAAU,CAAC,WAAW,CAAC,CAYxI;AAED,wBAAgB,cAAc,CAAC,CAAC,SAAS,IAAI,EAAE,MAAM,EAAE,CAAC,KAAK,EAAE,iBAAiB,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,KAAK,UAAU,GAAG,SAAS,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,GAAG,aAAa,CAAC,WAAW,CAAC,CAM1L;AAMD,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,CAAC,cAAc,CAAC,CAexE;AAED,MAAM,MAAM,WAAW,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,CAAA;AAExG,wBAAsB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,WAAW,CAAC,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAgB3I"}
package/runtime/hooks.js CHANGED
@@ -17,6 +17,13 @@ export function classicHook(event, hook, report) {
17
17
  };
18
18
  return routed;
19
19
  }
20
+ export function classicFailure(failed) {
21
+ const routed = async (e, error, next) => {
22
+ const ours = await failed(e, error);
23
+ return ours === undefined ? undefined : mergeClassic((await next(e)), ours);
24
+ };
25
+ return routed;
26
+ }
20
27
  const frontmatter = /^---\r?\n[\s\S]*?\r?\n---[ \t]*(?:\r?\n|$)/;
21
28
  const baseDirectoryLine = /^Base directory for this skill: [^\n]*\n\n/;
22
29
  export function userSkillHook(claude) {
@@ -1,4 +1,4 @@
1
- import type { Args, EventResult, Frozen, PluginOptions } from 'claude-code';
1
+ import type { Args, EventResult, Frozen, HookFailure, PluginOptions } from 'claude-code';
2
2
  import type { Mod, ModDefinition } from '../mod.js';
3
3
  import type { Options } from '../options.js';
4
4
  import { type Steps } from '../records.js';
@@ -25,6 +25,7 @@ export type Lifecycle<State extends object> = {
25
25
  readonly toasts: readonly ShownToast[];
26
26
  start(claude: Claude, read: (claude: Claude) => Promise<Plugin>): Promise<void>;
27
27
  route<N extends RoutedEvent>(event: N, e: Frozen<Args<N>>, next: RouterNext<N>): Promise<EventResult<N>>;
28
+ caught<N extends RoutedEvent>(event: N, e: Frozen<Args<N>>, next: RouterNext<N>, failure: HookFailure): Promise<EventResult<N>>;
28
29
  raise(method: string, payload: Readonly<Record<string, unknown>>): Promise<unknown>;
29
30
  };
30
31
  export declare function readPlugin(claude: Claude): Promise<Plugin>;
@@ -1 +1 @@
1
- {"version":3,"file":"lifecycle.d.ts","sourceRoot":"","sources":["../src/runtime/lifecycle.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAc,aAAa,EAAwB,MAAM,aAAa,CAAA;AAE7G,OAAO,KAAK,EAA4C,GAAG,EAAE,aAAa,EAAmF,MAAM,WAAW,CAAA;AAC9K,OAAO,KAAK,EAAE,OAAO,EAAgB,MAAM,eAAe,CAAA;AAC1D,OAAO,EAA2T,KAAK,KAAK,EAAE,MAAM,eAAe,CAAA;AAGnW,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAOzC,OAAO,EAA4D,KAAK,WAAW,EAAE,MAAM,YAAY,CAAA;AACvG,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AAO7D,OAAO,EAA6B,KAAK,UAAU,EAAE,MAAM,aAAa,CAAA;AAMxE,OAAO,EAA+B,KAAK,UAAU,EAAgB,MAAM,cAAc,CAAA;AAMzF,MAAM,MAAM,MAAM,GAAG;IACnB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,CAAA;IACpC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAA;IAC7B,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAA;IAC9B,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAA;IACrB,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAA;CACpC,CAAA;AAED,MAAM,MAAM,KAAK,GAAG,UAAU,GAAG,YAAY,GAAG,SAAS,GAAG,UAAU,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,CAAA;AAEtG,MAAM,MAAM,SAAS,CAAC,KAAK,SAAS,MAAM,IAAI;IAC5C,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAA;IACrB,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC,KAAK,CAAC,GAAG,SAAS,CAAA;IACpC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE,CAAA;IACtC,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC/E,KAAK,CAAC,CAAC,SAAS,WAAW,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAA;IACxG,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;CACpF,CAAA;AA2CD,wBAAsB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAwBhE;AAkCD,wBAAgB,eAAe,CAAC,KAAK,SAAS,MAAM,EAAE,QAAQ,SAAS,OAAO,GAAG,OAAO,EACtF,UAAU,EAAE,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,EAClD,gBAAgB,GAAE,MAAM,gBAAgB,GAAG,SAA2B,EACtE,OAAO,GAAE,aAAkB,EAC3B,UAAU,UAAO,GAChB,SAAS,CAAC,KAAK,CAAC,CAsdlB"}
1
+ {"version":3,"file":"lifecycle.d.ts","sourceRoot":"","sources":["../src/runtime/lifecycle.ts"],"names":[],"mappings":"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"}
@@ -7,7 +7,7 @@ import { bind } from './bound.js';
7
7
  import { serveConversations } from './conversations.js';
8
8
  import { answerCall, answeringOwnCalls, cmodPluginName, dependencyCalls, withBareRefusals } from './dependencies.js';
9
9
  import { keepEngine } from './engine.js';
10
- import { classicHook, userSkillHook } from './hooks.js';
10
+ import { classicFailure, classicHook, userSkillHook } from './hooks.js';
11
11
  import { checkedAnswer, checkingGrants, checkSettings, checksAnswers, checkWrite, isCovered, itemOf, passedDown, programAddresses } from './grants.js';
12
12
  import { cmodError, lastLineOf, locatingPrograms, readLines } from './programs.js';
13
13
  import { createModFiles, resolvedPath } from './metadata.js';
@@ -29,7 +29,8 @@ const installRetrySeconds = [2, 4, 8, 16, 32, 64, 128];
29
29
  const cmodCheckMs = 1000;
30
30
  const cmodWaitMs = 60_000;
31
31
  const cmodSlowCheckMs = 10_000;
32
- const startHoldMs = 10_000 - 1_000;
32
+ const hookMs = 10_000;
33
+ const startHoldMs = hookMs - 1_000;
33
34
  const dependencyCallMs = 30_000;
34
35
  const cannotStart = /failed to start: /;
35
36
  const shellTools = ['Bash', 'PowerShell'];
@@ -582,6 +583,17 @@ export function createLifecycle(definition, permissionRoutes = () => undefined,
582
583
  return answer;
583
584
  return runtime.toaster.draw((await answer), runtime.claude.ui.resolve(render), render.props, render.requestId);
584
585
  },
586
+ async caught(event, e, next, { kind, message }) {
587
+ const call = e;
588
+ const isAsk = event === 'cmod.call' && call.to === definition.name && beforeAskOf(call) !== undefined;
589
+ const reasons = { timeout: `it ran past the ${hookMs / 1000} s Claude Code gives a hook`, throw: message ?? 'it threw' };
590
+ const reason = reasons[kind];
591
+ if (reason === undefined)
592
+ return isAsk ? { value: null } : next(e);
593
+ const error = new Error(reason);
594
+ toastFailure({ id: `stopped:${event}`, message: `Claude Code stopped its ${event.replace(/^classic\./, '')} hook`, error });
595
+ return router.dispatchFailure(event, e, error, next);
596
+ },
585
597
  };
586
598
  }
587
599
  async function createMod(definition, runtime) {
@@ -661,7 +673,7 @@ async function createMod(definition, runtime) {
661
673
  }));
662
674
  const modState = createState({ name: definition.name, initial: definition.state ?? {}, session, root, claude, report, changed: area.changed, forkParent });
663
675
  const modOptions = createOptions({ name: definition.name, declared: definition.options ?? {}, fromClaude: runtime.options, claude, report, changed: modState.changed });
664
- const hookOn = (hook, listener) => router.add(`classic.${hook}`, classicHook(hook, listener, report));
676
+ const hookOn = (hook, listener, failed) => router.add(`classic.${hook}`, classicHook(hook, listener, report), failed === undefined ? undefined : classicFailure(failed));
665
677
  const expand = (path) => (homePrefix.test(path) ? resolvedPath(path, places) : path);
666
678
  const settingsFile = (source) => ({
667
679
  read: () => checked.settings.read({ source }),
@@ -675,8 +687,8 @@ async function createMod(definition, runtime) {
675
687
  claude: checked,
676
688
  report: (id, message, error) => report({ id, message, error }),
677
689
  isGranted: (permission) => flag(permission),
678
- hookOn: (hook, listener) => hookOn(hook, listener),
679
- routeOn: (event, hook) => router.add(event, hook),
690
+ hookOn: (hook, listener, failed) => hookOn(hook, listener, failed),
691
+ routeOn: (event, hook, failed) => router.add(event, hook, failed),
680
692
  permissionRoutes: runtime.permissionRoutes,
681
693
  });
682
694
  let followed;
@@ -918,10 +930,9 @@ async function createMod(definition, runtime) {
918
930
  client.changed(changedSession, change, isInProject !== false);
919
931
  return { value: null };
920
932
  }
921
- if (e.method === conversationMethods.before && call.caller === cmodPluginName) {
922
- const { session: asking, event, change, isInProject } = e.input;
923
- return { value: (await client.answerBefore(asking, event, change, isInProject !== false)) ?? null };
924
- }
933
+ const ask = beforeAskOf(call);
934
+ if (ask !== undefined)
935
+ return { value: (await client.answerBefore(ask.session, ask.event, ask.change, ask.isInProject)) ?? null };
925
936
  if (e.method === settingsPagesMethod)
926
937
  return { value: [...pages].map(([id, { title }]) => ({ id, title })) };
927
938
  if (e.method === openPageMethod) {
@@ -930,6 +941,11 @@ async function createMod(definition, runtime) {
930
941
  }
931
942
  const served = await conversations?.answer(call);
932
943
  return served ?? answerCall(definition.name, api, e);
944
+ }, (e, error) => {
945
+ if (e.to !== definition.name)
946
+ return undefined;
947
+ const ask = beforeAskOf(e);
948
+ return ask === undefined ? { deny: `${definition.name}: ${error.message}` } : { value: client.failedBefore(ask.session, ask.event, ask.change, ask.isInProject, error) ?? null };
933
949
  });
934
950
  const agents = toolCalls(claude, router);
935
951
  keepEngine(mod, { claude: checked, router, toolCalls: agents, report, hasPermissionCheck: () => runtime.permissionRoutes() !== undefined });
@@ -972,6 +988,12 @@ function checkedMs(name, subject, ms) {
972
988
  throw new Error(`${name}: ${subject} is ${ms}. Give a whole number of milliseconds above 0 and at most ${longestTimerMs}.`);
973
989
  return ms;
974
990
  }
991
+ function beforeAskOf(call) {
992
+ if (call.method !== conversationMethods.before || call.caller !== cmodPluginName)
993
+ return undefined;
994
+ const { session, event, change, isInProject } = call.input;
995
+ return { session, event, change, isInProject: isInProject !== false };
996
+ }
975
997
  async function failsAs(subject, step) {
976
998
  try {
977
999
  await step();
@@ -3,6 +3,9 @@ import type { HookFields } from './hooks.js';
3
3
  import { type HookOn, type RouteOn } from './sessions.js';
4
4
  export type PermissionUse = {
5
5
  readonly raise: (method: string, payload: HookFields) => Promise<HookFields | undefined>;
6
+ readonly refusalFor: (method: string, payload: HookFields, error: Error) => {
7
+ readonly refuse: string;
8
+ } | undefined;
6
9
  readonly hookOn: HookOn;
7
10
  readonly routeOn: RouteOn;
8
11
  readonly current: () => {
@@ -1 +1 @@
1
- {"version":3,"file":"permission-check.d.ts","sourceRoot":"","sources":["../src/runtime/permission-check.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AAC3C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAC5C,OAAO,EAAuC,KAAK,MAAM,EAAE,KAAK,OAAO,EAAkB,MAAM,eAAe,CAAA;AAE9G,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,KAAK,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAAA;IACxF,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM;QAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAA;CACtE,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,aAAa,KAAK,UAAU,CAAA;AAMjF,eAAO,MAAM,gBAAgB,EAAE,gBA6B9B,CAAA"}
1
+ {"version":3,"file":"permission-check.d.ts","sourceRoot":"","sources":["../src/runtime/permission-check.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AAC3C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAC5C,OAAO,EAAuC,KAAK,MAAM,EAAE,KAAK,OAAO,EAAkB,MAAM,eAAe,CAAA;AAE9G,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,KAAK,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAAA;IACxF,QAAQ,CAAC,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK,KAAK;QAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAA;IACnH,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM;QAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAA;CACtE,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,aAAa,KAAK,UAAU,CAAA;AAQjF,eAAO,MAAM,gBAAgB,EAAE,gBAwD9B,CAAA"}
@@ -1,12 +1,19 @@
1
1
  import { defined, processPayloadOf, recordOf } from './sessions.js';
2
2
  const verdictName = (decision) => (decision === 'deny' ? 'refuse' : decision);
3
- export const permissionRoutes = (method, { raise, hookOn, routeOn, current }) => {
3
+ export const permissionRoutes = (method, { raise, refusalFor, hookOn, routeOn, current }) => {
4
4
  const isBefore = method.startsWith('before');
5
5
  if (method.endsWith('PermissionCheck')) {
6
+ const payloadOf = (e, below) => {
7
+ const { id, cwd } = current();
8
+ return { session: id, cwd, ...defined({ task: e.agentId, callId: e.tool_use_id, reason: below.reason, rule: below.rule, ceiling: e.ceiling === undefined ? undefined : verdictName(e.ceiling) }), name: e.tool, input: recordOf(e.input), decision: verdictName(below.decision) };
9
+ };
10
+ const failed = async (e, error, next) => {
11
+ const refusal = refusalFor(method, payloadOf(e, (await next(e))), error);
12
+ return refusal === undefined ? undefined : { decision: 'deny', reason: refusal.refuse };
13
+ };
6
14
  return routeOn('tool.check', async (e, next) => {
7
15
  const below = (await next(e));
8
- const { id, cwd } = current();
9
- const payload = { session: id, cwd, ...defined({ task: e.agentId, callId: e.tool_use_id, reason: below.reason, rule: below.rule, ceiling: e.ceiling === undefined ? undefined : verdictName(e.ceiling) }), name: e.tool, input: recordOf(e.input), decision: verdictName(below.decision) };
16
+ const payload = payloadOf(e, below);
10
17
  if (!isBefore) {
11
18
  void raise(method, payload);
12
19
  return below;
@@ -16,11 +23,16 @@ export const permissionRoutes = (method, { raise, hookOn, routeOn, current }) =>
16
23
  return below;
17
24
  if (typeof answer['refuse'] === 'string')
18
25
  return { decision: 'deny', reason: answer['refuse'] };
19
- if (typeof answer['ask'] === 'string')
20
- return { decision: 'ask', reason: answer['ask'] };
21
- return answer['allow'] === true ? { decision: 'allow' } : below;
22
- });
26
+ if (!globalThis.cmodWithoutApprove) {
27
+ if (typeof answer['ask'] === 'string')
28
+ return { decision: 'ask', reason: answer['ask'] };
29
+ if (answer['allow'] === true)
30
+ return { decision: 'allow' };
31
+ }
32
+ return below;
33
+ }, isBefore ? failed : undefined);
23
34
  }
35
+ const refused = (refuse, interrupt) => ({ decision: defined({ behavior: 'deny', message: refuse, interrupt }) });
24
36
  return hookOn('PermissionRequest', async (input) => {
25
37
  const payload = processPayloadOf('PermissionRequest', input);
26
38
  if (!isBefore) {
@@ -31,7 +43,16 @@ export const permissionRoutes = (method, { raise, hookOn, routeOn, current }) =>
31
43
  if (answer === undefined)
32
44
  return undefined;
33
45
  if (typeof answer['refuse'] === 'string')
34
- return { decision: defined({ behavior: 'deny', message: answer['refuse'], interrupt: answer['interrupt'] }) };
35
- return answer['allow'] === true ? { decision: defined({ behavior: 'allow', updatedInput: answer['input'], updatedPermissions: answer['updates'] }) } : undefined;
36
- });
46
+ return refused(answer['refuse'], answer['interrupt']);
47
+ if (!globalThis.cmodWithoutApprove) {
48
+ if (answer['allow'] === true)
49
+ return { decision: defined({ behavior: 'allow', updatedInput: answer['input'], updatedPermissions: answer['updates'] }) };
50
+ }
51
+ return undefined;
52
+ }, isBefore
53
+ ? (input, error) => {
54
+ const refusal = refusalFor(method, processPayloadOf('PermissionRequest', input), error);
55
+ return refusal === undefined ? undefined : refused(refusal.refuse);
56
+ }
57
+ : undefined);
37
58
  };
@@ -3,9 +3,11 @@ import type { Disposable } from '../mod.js';
3
3
  import type { RoutedEvent } from './hooks.js';
4
4
  export type RouterNext<N extends RoutedEvent> = (e: Frozen<Args<N>>) => Promise<EventResult<N>>;
5
5
  export type RoutedHook<N extends RoutedEvent> = (e: Frozen<Args<N>>, next: RouterNext<N>) => EventResult<N> | Promise<EventResult<N>>;
6
+ export type RoutedFailure<N extends RoutedEvent> = (e: Frozen<Args<N>>, error: Error, next: RouterNext<N>) => EventResult<N> | undefined | Promise<EventResult<N> | undefined>;
6
7
  export type Router = {
7
- add<N extends RoutedEvent>(event: N, hook: RoutedHook<N>): Disposable;
8
+ add<N extends RoutedEvent>(event: N, hook: RoutedHook<N>, failed?: RoutedFailure<N>): Disposable;
8
9
  dispatch<N extends RoutedEvent>(event: N, e: Frozen<Args<N>>, next: RouterNext<N>): Promise<EventResult<N>>;
10
+ dispatchFailure<N extends RoutedEvent>(event: N, e: Frozen<Args<N>>, error: Error, next: RouterNext<N>): Promise<EventResult<N>>;
9
11
  };
10
12
  export declare function createRouter(): Router;
11
13
  //# sourceMappingURL=router.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../src/runtime/router.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAC5D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AAC3C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAE7C,MAAM,MAAM,UAAU,CAAC,CAAC,SAAS,WAAW,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAA;AAE/F,MAAM,MAAM,UAAU,CAAC,CAAC,SAAS,WAAW,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,WAAW,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAA;AAErI,MAAM,MAAM,MAAM,GAAG;IACnB,GAAG,CAAC,CAAC,SAAS,WAAW,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,UAAU,CAAA;IACrE,QAAQ,CAAC,CAAC,SAAS,WAAW,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAA;CAC5G,CAAA;AAID,wBAAgB,YAAY,IAAI,MAAM,CAyBrC"}
1
+ {"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../src/runtime/router.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAC5D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AAC3C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAE7C,MAAM,MAAM,UAAU,CAAC,CAAC,SAAS,WAAW,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAA;AAE/F,MAAM,MAAM,UAAU,CAAC,CAAC,SAAS,WAAW,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,WAAW,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAA;AAErI,MAAM,MAAM,aAAa,CAAC,CAAC,SAAS,WAAW,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,WAAW,CAAC,CAAC,CAAC,GAAG,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,CAAA;AAE9K,MAAM,MAAM,MAAM,GAAG;IACnB,GAAG,CAAC,CAAC,SAAS,WAAW,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,UAAU,CAAA;IAChG,QAAQ,CAAC,CAAC,SAAS,WAAW,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAA;IAC3G,eAAe,CAAC,CAAC,SAAS,WAAW,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAA;CACjI,CAAA;AAID,wBAAgB,YAAY,IAAI,MAAM,CAgCrC"}
package/runtime/router.js CHANGED
@@ -1,28 +1,36 @@
1
1
  export function createRouter() {
2
- const hooks = new Map();
2
+ const routes = new Map();
3
3
  return {
4
- add(event, hook) {
5
- const erased = hook;
6
- hooks.set(event, [...(hooks.get(event) ?? []), erased]);
4
+ add(event, hook, failed) {
5
+ const route = { hook, ...(failed === undefined ? {} : { failed }) };
6
+ routes.set(event, [...(routes.get(event) ?? []), route]);
7
7
  return {
8
8
  dispose() {
9
- const chain = (hooks.get(event) ?? []).filter((each) => each !== erased);
9
+ const chain = (routes.get(event) ?? []).filter((each) => each !== route);
10
10
  if (chain.length === 0)
11
- hooks.delete(event);
11
+ routes.delete(event);
12
12
  else
13
- hooks.set(event, chain);
13
+ routes.set(event, chain);
14
14
  },
15
15
  };
16
16
  },
17
17
  dispatch(event, e, next) {
18
- const chain = hooks.get(event);
18
+ const chain = routes.get(event);
19
19
  const call = async (index, current) => {
20
- const hook = chain?.[index];
21
- if (hook === undefined)
20
+ const route = chain?.[index];
21
+ if (route === undefined)
22
22
  return next(current);
23
- return hook(current, (passed) => call(index + 1, passed));
23
+ return route.hook(current, (passed) => call(index + 1, passed));
24
24
  };
25
25
  return call(0, e);
26
26
  },
27
+ async dispatchFailure(event, e, error, next) {
28
+ for (const route of routes.get(event) ?? []) {
29
+ const answer = await route.failed?.(e, error, next);
30
+ if (answer !== undefined)
31
+ return answer;
32
+ }
33
+ return next(e);
34
+ },
27
35
  };
28
36
  }
@@ -1,4 +1,4 @@
1
- import type { Args, CommandRunResult } from 'claude-code';
1
+ import type { Args, CommandRunResult, SessionCompactResult } from 'claude-code';
2
2
  import type { Disposable } from '../mod.js';
3
3
  import { ToolResult } from '../session/context/turn/message/tool-result.js';
4
4
  import { type SessionChange, type SessionData, type TaskData } from '../session/conversation.js';
@@ -11,6 +11,8 @@ import type { PermissionRoutes } from './permission-check.js';
11
11
  export type Subscription = {
12
12
  readonly event: SessionEvent;
13
13
  readonly matcher: SentMatcher | undefined;
14
+ readonly onFailure?: 'refuse';
15
+ readonly scope?: Scope;
14
16
  };
15
17
  export declare const everySession = "*";
16
18
  export declare const conversationMethods: {
@@ -46,6 +48,9 @@ export type SessionsClient = {
46
48
  readonly sessions: Sessions;
47
49
  changed(session: string, change: SessionChange, isInProject: boolean): void;
48
50
  answerBefore(session: string, event: BeforeEvent, change: SessionChange, isInProject: boolean): Promise<unknown>;
51
+ failedBefore(session: string, event: BeforeEvent, change: SessionChange, isInProject: boolean, error: Error): {
52
+ readonly refuse: string;
53
+ } | undefined;
49
54
  raise(method: string, payload: Readonly<Record<string, unknown>>): Promise<unknown>;
50
55
  listen(method: string, args: readonly unknown[]): Disposable;
51
56
  /** An empty title keeps the title the session already has. */
@@ -56,7 +61,7 @@ export declare function payloadOf(change: SessionChange): unknown;
56
61
  export declare function isHeardBy(event: SessionEvent, matcher: unknown, change: SessionChange): boolean;
57
62
  export declare function isInScope(scope: Scope, session: string, change: SessionChange, isUnder: (task: string, ancestor: string) => boolean): boolean;
58
63
  export declare function withoutPermissionCheck(name: string, hearer: string): string;
59
- export type HookOn = (hook: string, listener: (input: unknown) => HookFields | undefined | Promise<HookFields | undefined>) => Disposable;
64
+ export type HookOn = (hook: string, listener: (input: unknown) => HookFields | undefined | Promise<HookFields | undefined>, failed?: (input: unknown, error: Error) => HookFields | undefined) => Disposable;
60
65
  export declare function createSessionsClient({ name, claude, report, isGranted, hookOn, routeOn, permissionRoutes }: {
61
66
  readonly name: string;
62
67
  readonly claude: Claude;
@@ -74,8 +79,12 @@ export type ToolCheck = {
74
79
  readonly ceiling?: 'allow' | 'ask' | 'deny';
75
80
  };
76
81
  export type RouteOn = {
77
- (event: 'tool.check', hook: (e: ToolCheck, next: (e: ToolCheck) => Promise<unknown>) => Promise<unknown>): Disposable;
78
- (event: 'command.run', hook: (e: Args<'command.run'>, next: (e: Args<'command.run'>) => Promise<CommandRunResult>) => Promise<CommandRunResult>): Disposable;
82
+ (event: 'tool.check', hook: (e: ToolCheck, next: (e: ToolCheck) => Promise<unknown>) => Promise<unknown>, failed?: (e: ToolCheck, error: Error, next: (e: ToolCheck) => Promise<unknown>) => Promise<{
83
+ readonly decision: 'deny';
84
+ readonly reason: string;
85
+ } | undefined>): Disposable;
86
+ (event: 'command.run', hook: (e: Args<'command.run'>, next: (e: Args<'command.run'>) => Promise<CommandRunResult>) => Promise<CommandRunResult>, failed?: (e: Args<'command.run'>, error: Error) => Promise<CommandRunResult | undefined>): Disposable;
87
+ (event: 'session.compact', hook: (e: Args<'session.compact'>, next: (e: Args<'session.compact'>) => Promise<SessionCompactResult>) => Promise<SessionCompactResult>): Disposable;
79
88
  };
80
89
  export declare const recordOf: (value: unknown) => Readonly<Record<string, unknown>>;
81
90
  export declare const defined: (fields: HookFields) => HookFields;
@@ -1 +1 @@
1
- {"version":3,"file":"sessions.d.ts","sourceRoot":"","sources":["../src/runtime/sessions.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sessions.d.ts","sourceRoot":"","sources":["../src/runtime/sessions.ts"],"names":[],"mappings":"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"}