@cmodjs/core 2.0.0 → 2.0.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.
Files changed (42) hide show
  1. package/docs/commands.md +3 -3
  2. package/docs/dependencies.md +1 -1
  3. package/package.json +1 -1
  4. package/records.d.ts +1 -1
  5. package/records.js +1 -1
  6. package/register.d.ts.map +1 -1
  7. package/register.js +5 -4
  8. package/runtime/before.d.ts +6 -3
  9. package/runtime/before.d.ts.map +1 -1
  10. package/runtime/before.js +59 -37
  11. package/runtime/conversations.d.ts.map +1 -1
  12. package/runtime/conversations.js +38 -13
  13. package/runtime/hooks.d.ts +9 -22
  14. package/runtime/hooks.d.ts.map +1 -1
  15. package/runtime/hooks.js +4 -58
  16. package/runtime/lifecycle.d.ts +2 -1
  17. package/runtime/lifecycle.d.ts.map +1 -1
  18. package/runtime/lifecycle.js +34 -17
  19. package/runtime/permission-check.d.ts +15 -0
  20. package/runtime/permission-check.d.ts.map +1 -0
  21. package/runtime/permission-check.js +37 -0
  22. package/runtime/sessions.d.ts +12 -8
  23. package/runtime/sessions.d.ts.map +1 -1
  24. package/runtime/sessions.js +41 -80
  25. package/runtime/state.d.ts.map +1 -1
  26. package/runtime/state.js +14 -11
  27. package/session/context/turn/message/message.d.ts +1 -0
  28. package/session/context/turn/message/message.d.ts.map +1 -1
  29. package/session/context/turn/message/message.js +5 -2
  30. package/src/records.ts +1 -1
  31. package/src/register.ts +5 -4
  32. package/src/runtime/before.ts +60 -39
  33. package/src/runtime/conversations.ts +35 -13
  34. package/src/runtime/hooks.ts +13 -84
  35. package/src/runtime/lifecycle.ts +49 -31
  36. package/src/runtime/permission-check.ts +47 -0
  37. package/src/runtime/sessions.ts +51 -84
  38. package/src/runtime/state.ts +15 -8
  39. package/src/session/context/turn/message/message.ts +6 -2
  40. package/src/testing.ts +4 -3
  41. package/testing.d.ts.map +1 -1
  42. package/testing.js +4 -3
@@ -28,6 +28,7 @@ const installId = 'cmod:install';
28
28
  const installRetrySeconds = [2, 4, 8, 16, 32, 64, 128];
29
29
  const cmodCheckMs = 1000;
30
30
  const cmodWaitMs = 60_000;
31
+ const cmodSlowCheckMs = 10_000;
31
32
  const startHoldMs = 10_000 - 1_000;
32
33
  const dependencyCallMs = 30_000;
33
34
  const cannotStart = /failed to start: /;
@@ -92,7 +93,7 @@ async function cmodVersion(claude) {
92
93
  throw new Error(`cmod --version ${formatExit(result.exitCode, lastLineOf(result.stderr) ?? '')}`);
93
94
  return result.stdout.trim().split(/\s+/).at(-1);
94
95
  }
95
- export function createLifecycle(definition, checksPermissions = () => true, options = {}, asksPerson = true) {
96
+ export function createLifecycle(definition, permissionRoutes = () => undefined, options = {}, asksPerson = true) {
96
97
  let router = createRouter();
97
98
  let phase = 'starting';
98
99
  let runtime;
@@ -250,7 +251,7 @@ export function createLifecycle(definition, checksPermissions = () => true, opti
250
251
  if (runtime === undefined || plugin === undefined)
251
252
  return;
252
253
  const activeRouter = createRouter();
253
- const active = await createMod(definition, { ...runtime, router: activeRouter, dataFolder: dataFolder(plugin.store, plugin.name), store: plugin.store, steps: plugin.steps, granted, refreshGrants, checksPermissions, options: pluginOptions }).catch(async (error) => {
254
+ const active = await createMod(definition, { ...runtime, router: activeRouter, dataFolder: dataFolder(plugin.store, plugin.name), store: plugin.store, steps: plugin.steps, granted, refreshGrants, permissionRoutes, options: pluginOptions }).catch(async (error) => {
254
255
  if (error instanceof MissingOptions && (await askOptions(error)))
255
256
  return undefined;
256
257
  fail(messageOf(error), error instanceof MissingOptions ? `Set ${error.keys.length === 1 ? 'it' : 'them'} in /config.` : undefined, begin);
@@ -268,12 +269,19 @@ export function createLifecycle(definition, checksPermissions = () => true, opti
268
269
  void runSteps(active.mod).catch((error) => toastFailure({ id: 'cmod:steps', message: 'Its installer stopped', error }));
269
270
  const missed = missedSessionStart;
270
271
  missedSessionStart = undefined;
271
- const lateAnswer = missed === undefined ? {} : await activeRouter.dispatch('classic.SessionStart', missed, async () => ({})).catch((error) => {
272
+ const replay = (e) => (definition.name === cmodPluginName ? activeRouter.dispatch('classic.SessionStart', e, async () => ({})) : checkedRoute('classic.SessionStart', e, async () => ({})));
273
+ const lateAnswer = missed === undefined ? {} : await replay(missed).catch((error) => {
272
274
  toastFailure({ id: 'classic.SessionStart', message: 'The SessionStart hook failed', error });
273
275
  return {};
274
276
  });
275
- if (Object.keys(lateAnswer).length > 0) {
276
- runtime.claude.ui.log(`${definition.name} started after Claude Code's SessionStart, so Claude Code did not read the answer of its SessionStart hooks.`, { to: 'debug' });
277
+ const { additionalContext, ...unread } = lateAnswer;
278
+ for (const text of additionalContext ?? []) {
279
+ const added = await runtime.claude.session.append({ message: { type: 'user', content: [{ type: 'text', text }] } });
280
+ if (added.deny !== undefined)
281
+ runtime.claude.ui.log(`${definition.name}: Claude Code refused its SessionStart note: ${added.deny}`, { to: 'debug' });
282
+ }
283
+ if (Object.keys(unread).length > 0) {
284
+ runtime.claude.ui.log(`${definition.name} started after Claude Code's SessionStart, so Claude Code did not read ${Object.keys(unread).join(', ')} from its SessionStart hooks.`, { to: 'debug' });
277
285
  }
278
286
  const version = plugin.version ?? '';
279
287
  const announced = announcedOf(await runtime.claude.store.get(announcedKey));
@@ -359,7 +367,7 @@ export function createLifecycle(definition, checksPermissions = () => true, opti
359
367
  timer.cancel();
360
368
  longWait.cancel();
361
369
  };
362
- const timer = claude().clock.every(cmodCheckMs, () => {
370
+ const poll = (ms) => claude().clock.every(ms, () => {
363
371
  check ??= cmodVersion(claude())
364
372
  .then((version) => {
365
373
  check = undefined;
@@ -374,9 +382,14 @@ export function createLifecycle(definition, checksPermissions = () => true, opti
374
382
  report(error);
375
383
  });
376
384
  });
377
- const longWait = claude().clock.after(cmodWaitMs, () => installing(latest === undefined
378
- ? "Still waiting for cmod to download cmod. See cmod's own line."
379
- : `PATH finds cmod ${latest}, and ${definition.name} needs cmod ${oldestCmodFor(plugin?.steps ?? {})} or later. Run npm i -g @cmodjs/cli, or put ~/.local/bin ahead of the old cmod on PATH.`));
385
+ let timer = poll(cmodCheckMs);
386
+ const longWait = claude().clock.after(cmodWaitMs, () => {
387
+ timer.cancel();
388
+ timer = poll(cmodSlowCheckMs);
389
+ installing(latest === undefined
390
+ ? "Still waiting for cmod to download cmod. See cmod's own line."
391
+ : `PATH finds cmod ${latest}, and ${definition.name} needs cmod ${oldestCmodFor(plugin?.steps ?? {})} or later. Run npm i -g @cmodjs/cli, or put ~/.local/bin ahead of the old cmod on PATH.`);
392
+ });
380
393
  };
381
394
  const bootstrap = async (root) => {
382
395
  installing();
@@ -544,8 +557,10 @@ export function createLifecycle(definition, checksPermissions = () => true, opti
544
557
  if (event === 'cmod.call' && !isCallToThisMod)
545
558
  return next(e);
546
559
  await (event === 'classic.SessionStart' || isCallToThisMod ? holdUntilStarted() : whenActive());
547
- if (event === 'classic.SessionStart' && phase !== 'active')
560
+ if (event === 'classic.SessionStart' && phase !== 'active') {
548
561
  missedSessionStart = e;
562
+ return next(e);
563
+ }
549
564
  if (isCallToThisMod && phase !== 'active') {
550
565
  const isStopped = phase === 'declined' || phase === 'failed';
551
566
  return { deny: isStopped ? `${definition.name} is not set up. Its toast says why.` : `${definition.name} is installing. Try again when it's ready.` };
@@ -646,7 +661,7 @@ async function createMod(definition, runtime) {
646
661
  }));
647
662
  const modState = createState({ name: definition.name, initial: definition.state ?? {}, session, root, claude, report, changed: area.changed, forkParent });
648
663
  const modOptions = createOptions({ name: definition.name, declared: definition.options ?? {}, fromClaude: runtime.options, claude, report, changed: modState.changed });
649
- const hookOn = (hook, listener) => router.add(`classic.${hook}`, classicHook(definition.name, hook, listener, report));
664
+ const hookOn = (hook, listener) => router.add(`classic.${hook}`, classicHook(hook, listener, report));
650
665
  const expand = (path) => (homePrefix.test(path) ? resolvedPath(path, places) : path);
651
666
  const settingsFile = (source) => ({
652
667
  read: () => checked.settings.read({ source }),
@@ -662,6 +677,7 @@ async function createMod(definition, runtime) {
662
677
  isGranted: (permission) => flag(permission),
663
678
  hookOn: (hook, listener) => hookOn(hook, listener),
664
679
  routeOn: (event, hook) => router.add(event, hook),
680
+ permissionRoutes: runtime.permissionRoutes,
665
681
  });
666
682
  let followed;
667
683
  let isSetUp = false;
@@ -706,8 +722,8 @@ async function createMod(definition, runtime) {
706
722
  const change = { source: source === 'skills' ? 'skills' : source.replace('_settings', ''), ...(file_path === undefined ? {} : { path: file_path }) };
707
723
  if (matcher !== undefined && !matches(change, matcher))
708
724
  return undefined;
709
- const answer = await listener(change);
710
- return answer === undefined ? undefined : { decision: 'block', reason: answer.refuse };
725
+ const refuse = (await listener(change))?.refuse;
726
+ return typeof refuse === 'string' ? { block: refuse } : undefined;
711
727
  });
712
728
  },
713
729
  },
@@ -729,11 +745,12 @@ async function createMod(definition, runtime) {
729
745
  const watch = { paths, listener };
730
746
  watches.add(watch);
731
747
  if (watches.size === 1) {
732
- hookOn('SessionStart', () => ({ hookSpecificOutput: { watchPaths: [...new Set([...watches].flatMap((each) => each.paths))] } }));
748
+ hookOn('SessionStart', () => ({ watchPaths: [...new Set([...watches].flatMap((each) => each.paths))] }));
733
749
  hookOn('FileChanged', ({ file_path, event }) => {
734
750
  for (const each of watches)
735
751
  if (each.paths.some((watched) => relativePath(watched, file_path) !== undefined))
736
752
  void Promise.resolve(each.listener({ path: file_path, type: event })).catch((error) => report({ id: 'fs:onChange', message: 'The fs.onChange listener failed', error }));
753
+ return undefined;
737
754
  });
738
755
  }
739
756
  return { dispose: () => void watches.delete(watch) };
@@ -933,7 +950,7 @@ async function createMod(definition, runtime) {
933
950
  await failsAs('its setup function threw', () => definition.setup(mod));
934
951
  isSetUp = true;
935
952
  const permissionHooks = permissionEvents.filter((event) => router.has(event));
936
- if (permissionHooks.length > 0 && !runtime.checksPermissions()) {
953
+ if (permissionHooks.length > 0 && runtime.permissionRoutes() === undefined) {
937
954
  throw new Error(`it decides permissions on ${listed(permissionHooks)}, so hooks/register.ts must call registerPermissionCheck(addHook) after registerMod`);
938
955
  }
939
956
  await failsAs('its open panes did not load', () => area.restorePanes());
@@ -943,7 +960,7 @@ function checkingKeys(claude, toast, keys) {
943
960
  const bound = Object.entries(keys);
944
961
  if (bound.length === 0)
945
962
  return claude;
946
- const register = (command) => {
963
+ const addCommand = (command) => {
947
964
  for (const [key, commandName] of bound) {
948
965
  if (commandName === command.name && command.immediate !== true) {
949
966
  toast.warning(`${key} runs /${command.name}, which waits for Claude's turn to end`, { id: `key:${key}`, description: `It adds a row to the conversation. Give /${command.name} immediate: true.`, duration: Infinity });
@@ -951,7 +968,7 @@ function checkingKeys(claude, toast, keys) {
951
968
  }
952
969
  return claude.command.register(command);
953
970
  };
954
- return { ...claude, command: { ...claude.command, register } };
971
+ return { ...claude, command: { ...claude.command, register: addCommand } };
955
972
  }
956
973
  const longestTimerMs = 2_147_483_647;
957
974
  function checkedMs(name, subject, ms) {
@@ -0,0 +1,15 @@
1
+ import type { Disposable } from '../mod.js';
2
+ import type { HookFields } from './hooks.js';
3
+ import { type HookOn, type RouteOn } from './sessions.js';
4
+ export type PermissionUse = {
5
+ readonly raise: (method: string, payload: HookFields) => Promise<HookFields | undefined>;
6
+ readonly hookOn: HookOn;
7
+ readonly routeOn: RouteOn;
8
+ readonly current: () => {
9
+ readonly id: string;
10
+ readonly cwd: string;
11
+ };
12
+ };
13
+ export type PermissionRoutes = (method: string, use: PermissionUse) => Disposable;
14
+ export declare const permissionRoutes: PermissionRoutes;
15
+ //# sourceMappingURL=permission-check.d.ts.map
@@ -0,0 +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"}
@@ -0,0 +1,37 @@
1
+ import { defined, processPayloadOf, recordOf } from './sessions.js';
2
+ const verdictName = (decision) => (decision === 'deny' ? 'refuse' : decision);
3
+ export const permissionRoutes = (method, { raise, hookOn, routeOn, current }) => {
4
+ const isBefore = method.startsWith('before');
5
+ if (method.endsWith('PermissionCheck')) {
6
+ return routeOn('tool.check', async (e, next) => {
7
+ 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) };
10
+ if (!isBefore) {
11
+ void raise(method, payload);
12
+ return below;
13
+ }
14
+ const answer = await raise(method, payload);
15
+ if (answer === undefined || below.decision === 'deny')
16
+ return below;
17
+ if (typeof answer['refuse'] === 'string')
18
+ 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
+ });
23
+ }
24
+ return hookOn('PermissionRequest', async (input) => {
25
+ const payload = processPayloadOf('PermissionRequest', input);
26
+ if (!isBefore) {
27
+ void raise(method, payload);
28
+ return undefined;
29
+ }
30
+ const answer = await raise(method, payload);
31
+ if (answer === undefined)
32
+ return undefined;
33
+ 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
+ });
37
+ };
@@ -2,11 +2,12 @@ import type { Args, CommandRunResult } 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';
5
- import { processEvents, type BeforeEvent, type SessionEvent, type Sessions, type TaskStartArgs, type ToolCallArgs, type Usage } from '../session/session.js';
5
+ import { type BeforeEvent, type ProcessName, type SessionEvent, type Sessions, type TaskStartArgs, type ToolCallArgs, type Usage } from '../session/session.js';
6
6
  import { type SentMatcher } from '../utils/matcher.js';
7
7
  import { type Place } from './before.js';
8
8
  import type { Claude } from './claude.js';
9
- import { type HookAnswer } from './hooks.js';
9
+ import { type HookFields } from './hooks.js';
10
+ import type { PermissionRoutes } from './permission-check.js';
10
11
  export type Subscription = {
11
12
  readonly event: SessionEvent;
12
13
  readonly matcher: SentMatcher | undefined;
@@ -54,16 +55,17 @@ export declare function usageOf(claude: Pick<Claude, 'session'>): Promise<Usage>
54
55
  export declare function payloadOf(change: SessionChange): unknown;
55
56
  export declare function isHeardBy(event: SessionEvent, matcher: unknown, change: SessionChange): boolean;
56
57
  export declare function isInScope(scope: Scope, session: string, change: SessionChange, isUnder: (task: string, ancestor: string) => boolean): boolean;
57
- export declare function createSessionsClient({ name, claude, report, isGranted, hookOn, routeOn }: {
58
+ export type HookOn = (hook: string, listener: (input: unknown) => HookFields | undefined | Promise<HookFields | undefined>) => Disposable;
59
+ export declare function createSessionsClient({ name, claude, report, isGranted, hookOn, routeOn, permissionRoutes }: {
58
60
  readonly name: string;
59
61
  readonly claude: Claude;
60
62
  readonly report: (id: string, message: string, error: unknown) => void;
61
63
  readonly isGranted: (permission: string) => boolean;
62
- readonly hookOn?: (hook: string, listener: (input: unknown) => unknown) => Disposable;
64
+ readonly hookOn?: HookOn;
63
65
  readonly routeOn?: RouteOn;
66
+ readonly permissionRoutes?: () => PermissionRoutes | undefined;
64
67
  }): SessionsClient;
65
- type HookFields = Readonly<Record<string, unknown>>;
66
- type ToolCheck = {
68
+ export type ToolCheck = {
67
69
  readonly tool: string;
68
70
  readonly input: unknown;
69
71
  readonly tool_use_id?: string;
@@ -74,9 +76,11 @@ export type RouteOn = {
74
76
  (event: 'tool.check', hook: (e: ToolCheck, next: (e: ToolCheck) => Promise<unknown>) => Promise<unknown>): Disposable;
75
77
  (event: 'command.run', hook: (e: Args<'command.run'>, next: (e: Args<'command.run'>) => Promise<CommandRunResult>) => Promise<CommandRunResult>): Disposable;
76
78
  };
79
+ export declare const recordOf: (value: unknown) => Readonly<Record<string, unknown>>;
80
+ export declare const defined: (fields: HookFields) => HookFields;
81
+ type ProcessFieldsName = Exclude<ProcessName, 'PermissionCheck'>;
77
82
  export declare function spawnTask(claude: Pick<Claude, 'agent'>, task: TaskStartArgs): Promise<TaskData>;
78
- export declare function processPayloadOf(named: Exclude<keyof typeof processEvents, 'PermissionCheck'>, input: unknown): HookFields;
79
- export declare function hookAnswerOf(named: string, hook: string, answer: HookFields): HookAnswer | undefined;
83
+ export declare function processPayloadOf(named: ProcessFieldsName, input: unknown): HookFields;
80
84
  export declare function resultOf(where: Pick<Place, 'session' | 'context' | 'turn'>, call: ToolCallArgs & {
81
85
  readonly cwd: string;
82
86
  }, answered: Awaited<ReturnType<Claude['tool']['call']>>): ToolResult;
@@ -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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"}
@@ -10,7 +10,7 @@ import { GoalChange } from '../session/goal/goal.js';
10
10
  import { TaskEnd, TaskStart } from '../session/goal/task.js';
11
11
  import { beforeEvents, processEvents, Session, sessionEvents } from '../session/session.js';
12
12
  import { matches, sentMatcher } from '../utils/matcher.js';
13
- import { foldAnswers } from './before.js';
13
+ import { beforeAnswerKeys, foldAnswers, foldBefore, methodOf, takenAnswer } from './before.js';
14
14
  import { cmodPluginName } from './dependencies.js';
15
15
  import { messageOf } from '../utils/text.js';
16
16
  import { listenerOf, PassedTimeout, withinTime } from './deadline.js';
@@ -36,7 +36,6 @@ const actPermissions = { send: 'prompt', startTask: 'tasks', usage: 'conversatio
36
36
  const startsTurns = ['CronCreate'];
37
37
  const ownSchedule = ['CronDelete', 'CronList'];
38
38
  export const beforePermission = (event) => (event === 'toolCall' ? 'tools' : event === TaskStart ? 'tasks' : 'prompt');
39
- const methodOf = (prefix, event) => `${prefix}${Object.entries(sessionEvents).find(([, each]) => each === event)?.[0] ?? event}`;
40
39
  export const isAct = (action) => action === 'callTool' || action in actPermissions;
41
40
  export function toolPermission(tool) {
42
41
  return startsTurns.includes(tool) ? 'prompt' : ownSchedule.includes(tool) ? undefined : 'tools';
@@ -113,7 +112,7 @@ export function isInScope(scope, session, change, isUnder) {
113
112
  return change.message.turn === scope.turn;
114
113
  return (change.type === TurnStart || change.type === TurnEnd) && change.turn.prompt.id === scope.turn;
115
114
  }
116
- export function createSessionsClient({ name, claude, report, isGranted, hookOn, routeOn }) {
115
+ export function createSessionsClient({ name, claude, report, isGranted, hookOn, routeOn, permissionRoutes }) {
117
116
  const call = (method, input) => claude.cmod.call({ to: cmodPluginName, method, input });
118
117
  const listening = new Map();
119
118
  const deciding = new Map();
@@ -176,6 +175,12 @@ export function createSessionsClient({ name, claude, report, isGranted, hookOn,
176
175
  },
177
176
  };
178
177
  };
178
+ const invoke = (method, options, run, takes = []) => withinTime(claude.clock, method, options, run).catch((error) => {
179
+ if (error instanceof PassedTimeout && !method.startsWith('before'))
180
+ return undefined;
181
+ report(`session:${method}`, `The ${method} listener failed`, error);
182
+ return options.onFailure === 'refuse' && takes.includes('refuse') ? { refuse: `${name}: ${messageOf(error)}` } : undefined;
183
+ });
179
184
  const combined = async (session, event, change, isInProject) => {
180
185
  const askers = [...(deciding.get(session) ?? []), ...(isInProject ? (deciding.get(everySession) ?? []) : [])]
181
186
  .filter((entry) => entry.event === event)
@@ -185,17 +190,12 @@ export function createSessionsClient({ name, claude, report, isGranted, hookOn,
185
190
  if (entry.matcher !== undefined && !matches(payloadOf(latest), entry.matcher))
186
191
  return undefined;
187
192
  const payload = await payloadFor(session, latest);
188
- const answer = await withinTime(claude.clock, entry.method, entry.options, (time) => entry.listener(payload, time)).catch((error) => {
189
- if (entry.options.onFailure !== 'refuse')
190
- throw error;
191
- report(`session:${entry.method}`, `The ${entry.method} listener failed`, error);
192
- return { refuse: `${name}: ${messageOf(error)}` };
193
- });
193
+ const answer = await invoke(entry.method, entry.options, async (time) => takenAnswer(entry.method, beforeAnswerKeys[event], await entry.listener(payload, time)), beforeAnswerKeys[event]);
194
194
  if (answer === undefined || answer === null || (typeof answer === 'object' && 'refuse' in answer) || isGranted(beforePermission(event)))
195
195
  return answer;
196
196
  throw new Error(`Its ${entry.method} answer changes nothing until ${beforePermission(event)} is turned on for ${name} in /mods.`);
197
197
  });
198
- return foldAnswers(event, change, askers, (error) => report(`session:${methodOf('before', event)}`, `The ${methodOf('before', event)} listener failed`, error));
198
+ return foldBefore(event, change, askers, (error) => report(`session:${methodOf('before', event)}`, `The ${methodOf('before', event)} listener failed`, error));
199
199
  };
200
200
  const eventMethods = (scopeOf, hasBefore, ended) => {
201
201
  const method = (into, named, event) => (...args) => {
@@ -208,10 +208,12 @@ export function createSessionsClient({ name, claude, report, isGranted, hookOn,
208
208
  ...(hasBefore ? beforeEvents.map((named) => [`before${named}`, method(deciding, `before${named}`, sessionEvents[named])]) : []),
209
209
  ]);
210
210
  };
211
+ let folders;
211
212
  const withFiles = async (message) => {
212
213
  if (message.type !== ToolCall && message.type !== ToolResult)
213
214
  return message;
214
- return { ...message, files: await callFiles(name, claude, { tool: message.name, input: message.input }, message.cwd) };
215
+ folders ??= Promise.all([claude.env.home(), claude.env.configHome()]).then(([home, configRoot]) => ({ home, configRoot }));
216
+ return { ...message, files: await callFiles(name, claude, folders, { tool: message.name, input: message.input }, message.cwd) };
215
217
  };
216
218
  const messagesFrom = async (method, input) => Promise.all((await call(method, input)).map(withFiles));
217
219
  const searched = (request, matcher) => ({
@@ -405,39 +407,16 @@ export function createSessionsClient({ name, claude, report, isGranted, hookOn,
405
407
  };
406
408
  const processListeners = new Map();
407
409
  const raise = async (method, payload) => {
408
- const isBefore = method.startsWith('before');
409
410
  const heard = [...(processListeners.get(method) ?? [])].filter(({ matcher }) => payload['task'] === undefined && (matcher === undefined || matches(payload, matcher)));
410
- if (!isBefore) {
411
- await Promise.all(heard.map(({ listener, options }) => withinTime(claude.clock, method, options, (time) => listener(payload, time)).catch((error) => {
412
- if (!(error instanceof PassedTimeout))
413
- report(`session:${method}`, `The ${method} listener failed`, error);
414
- })));
411
+ if (!method.startsWith('before')) {
412
+ await Promise.all(heard.map(({ listener, options }) => invoke(method, options, (time) => listener(payload, time))));
415
413
  return undefined;
416
414
  }
415
+ const failing = method === 'beforePermissionRequest' ? { onFailure: 'refuse' } : {};
417
416
  const takes = answerKeys[method.slice('before'.length)] ?? [];
418
- let merged;
419
- for (const { listener, options } of heard) {
420
- try {
421
- const answer = (await withinTime(claude.clock, method, options, (time) => listener(payload, time)));
422
- if (answer === undefined || answer === null)
423
- continue;
424
- const unread = Object.keys(answer).filter((key) => !takes.includes(key));
425
- if (unread.length > 0)
426
- throw new Error(`it answered ${unread.join(' and ')}, which ${method} does not take. It takes ${takes.map((key) => `{ ${key} }`).join(', ') || 'no answer'}.`);
427
- const notes = [merged?.['note'], answer['note']].filter((note) => typeof note === 'string');
428
- merged = { ...merged, ...answer, ...(notes.length === 0 ? {} : { note: notes.join('\n\n') }) };
429
- if (typeof answer['refuse'] === 'string')
430
- return merged;
431
- }
432
- catch (error) {
433
- report(`session:${method}`, `The ${method} listener failed`, error);
434
- if (options.onFailure === 'refuse' || method === 'beforePermissionRequest')
435
- return { refuse: `${name}: ${messageOf(error)}` };
436
- }
437
- }
438
- return merged;
417
+ const askers = heard.map(({ listener, options }) => () => invoke(method, { ...options, ...failing }, async (time) => takenAnswer(method, takes, await listener(payload, time)), takes));
418
+ return foldAnswers(method, takes, ['refuse'], undefined, askers, (error) => report(`session:${method}`, `The ${method} listener failed`, error));
439
419
  };
440
- const permissionCheck = (e, below) => ({ session: current.id, cwd: current.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) });
441
420
  const commandRun = async (e) => {
442
421
  const source = (await claude.command.list()).find((command) => command.name === e.command)?.source;
443
422
  return { session: current.id, cwd: current.cwd, name: e.command, args: e.args, ...defined({ source }), from: senderOf(e.origin, false) };
@@ -466,22 +445,11 @@ export function createSessionsClient({ name, claude, report, isGranted, hookOn,
466
445
  if (hookOn === undefined || routeOn === undefined)
467
446
  throw new Error(`${name}: ${method} works only in a mod's own session.`);
468
447
  const isBefore = method.startsWith('before');
469
- if (named === 'PermissionCheck') {
470
- return routeOn('tool.check', async (e, next) => {
471
- const below = (await next(e));
472
- if (!isBefore) {
473
- void raise(method, permissionCheck(e, below));
474
- return below;
475
- }
476
- const answer = await raise(method, permissionCheck(e, below));
477
- if (answer === undefined || below.decision === 'deny')
478
- return below;
479
- if (typeof answer['refuse'] === 'string')
480
- return { decision: 'deny', reason: answer['refuse'] };
481
- if (typeof answer['ask'] === 'string')
482
- return { decision: 'ask', reason: answer['ask'] };
483
- return answer['allow'] === true ? { decision: 'allow' } : below;
484
- });
448
+ if (named === 'PermissionCheck' || named === 'PermissionRequest') {
449
+ const routes = permissionRoutes?.();
450
+ if (routes !== undefined)
451
+ return routes(method, { raise, hookOn, routeOn, current: () => current });
452
+ return named === 'PermissionCheck' ? routeOn('tool.check', (e, next) => next(e)) : hookOn('PermissionRequest', () => undefined);
485
453
  }
486
454
  const event = processEvents[named];
487
455
  const hook = (isBefore ? event.before : undefined) ?? event.on;
@@ -493,7 +461,7 @@ export function createSessionsClient({ name, claude, report, isGranted, hookOn,
493
461
  return undefined;
494
462
  }
495
463
  const answer = await raise(method, payload);
496
- return answer === undefined ? undefined : hookAnswerOf(named, hook, answer);
464
+ return answer === undefined ? undefined : hookAnswerOf(named, answer);
497
465
  });
498
466
  };
499
467
  const listen = (method, args) => {
@@ -529,16 +497,15 @@ export function createSessionsClient({ name, claude, report, isGranted, hookOn,
529
497
  },
530
498
  changed(session, change, isInProject) {
531
499
  remember(session, change);
500
+ let payload;
532
501
  for (const key of isInProject ? [session, everySession] : [session]) {
533
502
  for (const { scope, event, method, matcher, listener, options } of listening.get(key) ?? []) {
534
503
  if (!isHeardBy(event, matcher, change) || !isInScope(scope, session, change, isUnderIn(session)))
535
504
  continue;
536
- void payloadFor(session, change)
537
- .then((payload) => withinTime(claude.clock, method, options, (time) => listener(payload, time)))
538
- .catch((error) => {
539
- if (!(error instanceof PassedTimeout))
540
- report(`session:${method}`, `The ${method} listener failed`, error);
541
- });
505
+ payload ??= payloadFor(session, change);
506
+ void payload
507
+ .then((heard) => invoke(method, options, (time) => listener(heard, time)))
508
+ .catch((error) => report(`session:${method}`, `The ${method} listener failed`, error));
542
509
  }
543
510
  }
544
511
  },
@@ -567,9 +534,8 @@ export function createSessionsClient({ name, claude, report, isGranted, hookOn,
567
534
  },
568
535
  };
569
536
  }
570
- const verdictName = (decision) => (decision === 'deny' ? 'refuse' : decision);
571
- const recordOf = (value) => (typeof value === 'object' && value !== null && !Array.isArray(value) ? value : {});
572
- const defined = (fields) => Object.fromEntries(Object.entries(fields).filter(([, value]) => value !== undefined));
537
+ export const recordOf = (value) => (typeof value === 'object' && value !== null && !Array.isArray(value) ? value : {});
538
+ export const defined = (fields) => Object.fromEntries(Object.entries(fields).filter(([, value]) => value !== undefined));
573
539
  const placementOf = (input) => defined({ session: input['session_id'], task: input['agent_id'], agentType: input['agent_type'], cwd: input['cwd'], permissionMode: input['permission_mode'] });
574
540
  const mcpServerOf = (server) => (server === undefined ? undefined : { name: String(recordOf(server)['name']), source: String(recordOf(server)['source']) });
575
541
  const modelChangeOf = (input) => ({
@@ -653,30 +619,25 @@ export function processPayloadOf(named, input) {
653
619
  const fields = recordOf(input);
654
620
  return { ...placementOf(fields), ...defined(processFields[named](fields)) };
655
621
  }
656
- export function hookAnswerOf(named, hook, answer) {
657
- const output = (fields) => ({ hookSpecificOutput: { hookEventName: hook, ...defined(fields) } });
622
+ function hookAnswerOf(named, answer) {
658
623
  const refuse = typeof answer['refuse'] === 'string' ? answer['refuse'] : undefined;
624
+ const note = typeof answer['note'] === 'string' ? [answer['note']] : undefined;
659
625
  if (named === 'SessionStart')
660
- return output({ additionalContext: answer['note'], sessionTitle: answer['title'], reloadSkills: answer['reloadSkills'], initialUserMessage: answer['firstPrompt'] });
626
+ return defined({ additionalContext: note, sessionTitle: answer['title'], reloadSkills: answer['reloadSkills'] === true ? true : undefined, initialUserMessage: answer['firstPrompt'] });
661
627
  if (named === 'ModelChange') {
662
628
  if (refuse !== undefined)
663
- return output({ permissionDecision: 'deny', permissionDecisionReason: refuse });
664
- return typeof answer['ask'] === 'string' ? output({ permissionDecision: 'ask', permissionDecisionReason: answer['ask'] }) : undefined;
629
+ return { permissionDecision: 'deny', permissionDecisionReason: refuse };
630
+ return typeof answer['ask'] === 'string' ? { permissionDecision: 'ask', permissionDecisionReason: answer['ask'] } : undefined;
665
631
  }
666
632
  if (named === 'WorktreeCreate')
667
- return output({ worktreePath: answer['result'] });
668
- if (named === 'PermissionRequest') {
669
- if (refuse !== undefined)
670
- return output({ decision: defined({ behavior: 'deny', message: refuse, interrupt: answer['interrupt'] }) });
671
- return answer['allow'] === true ? output({ decision: defined({ behavior: 'allow', updatedInput: answer['input'], updatedPermissions: answer['updates'] }) }) : undefined;
672
- }
633
+ return defined({ worktreePath: answer['result'] });
673
634
  if (named === 'PermissionDenial')
674
- return output({ retry: answer['retry'] });
635
+ return answer['retry'] === true ? { retry: true } : undefined;
675
636
  if (named === 'ToolBatch')
676
- return output({ additionalContext: answer['note'] });
637
+ return defined({ additionalContext: note });
677
638
  if (named === 'ReplyDisplay')
678
- return output({ displayContent: answer['text'] });
679
- return refuse === undefined ? undefined : { decision: 'block', reason: refuse };
639
+ return defined({ displayContent: answer['text'] });
640
+ return refuse === undefined ? undefined : { block: refuse };
680
641
  }
681
642
  export function resultOf(where, call, answered) {
682
643
  const base = { id: '', type: ToolResult, at: new Date().toISOString(), session: where.session, context: where.context, ...(where.turn === undefined ? {} : { turn: where.turn.prompt.id }), callId: '', name: call.name, input: call.input, cwd: call.cwd, files: noFiles };
@@ -1 +1 @@
1
- {"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../src/runtime/state.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AACpD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAQ3C,MAAM,MAAM,YAAY,GAAG;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAA;IAC3C,QAAQ,CAAC,OAAO,EAAE,MAAM,IAAI,CAAA;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAA;CACvD,CAAA;AAED,MAAM,MAAM,QAAQ,CAAC,KAAK,SAAS,MAAM,IAAI;IAC3C,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAA;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,OAAO,IAAI,IAAI,CAAA;IACf,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IACrB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACnC,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,iBAAiB,CAAC,cAAc,CAAC,CAAC,QAAQ,CAAC,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CACvH,CAAA;AAQD,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI,CAIvE;AAED,wBAAsB,YAAY,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAO9H;AAED,wBAAgB,WAAW,CAAC,KAAK,SAAS,MAAM,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,EAAE,YAAY,GAAG,QAAQ,CAAC,KAAK,CAAC,CA6G9J"}
1
+ {"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../src/runtime/state.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AACpD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAQ3C,MAAM,MAAM,YAAY,GAAG;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAA;IAC3C,QAAQ,CAAC,OAAO,EAAE,MAAM,IAAI,CAAA;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAA;CACvD,CAAA;AAED,MAAM,MAAM,QAAQ,CAAC,KAAK,SAAS,MAAM,IAAI;IAC3C,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAA;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,OAAO,IAAI,IAAI,CAAA;IACf,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IACrB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACnC,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,iBAAiB,CAAC,cAAc,CAAC,CAAC,QAAQ,CAAC,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CACvH,CAAA;AAQD,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI,CAIvE;AAED,wBAAsB,YAAY,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAO9H;AAED,wBAAgB,WAAW,CAAC,KAAK,SAAS,MAAM,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,EAAE,YAAY,GAAG,QAAQ,CAAC,KAAK,CAAC,CAoH9J"}
package/runtime/state.js CHANGED
@@ -46,17 +46,18 @@ export function createState({ name, initial, session, root, claude, report, chan
46
46
  const transcriptsKey = `${name}.$transcripts.`;
47
47
  const forgetEndedSessions = async (current) => {
48
48
  const stored = await claude.store.keys();
49
- for (const recorded of stored.filter((key) => key.startsWith(transcriptsKey))) {
50
- const owner = recorded.slice(transcriptsKey.length);
51
- if (owner === current)
52
- continue;
49
+ const ended = async (recorded) => {
53
50
  const transcript = await claude.store.get(recorded);
54
- if (typeof transcript === 'string' && (await claude.fs.exists(transcript)))
55
- continue;
56
- for (const value of stored.filter((key) => key.startsWith(`${name}.`) && key.endsWith(`.sessions.${owner}`)))
57
- await claude.store.delete(value);
51
+ return typeof transcript !== 'string' || !(await claude.fs.exists(transcript));
52
+ };
53
+ const owners = stored.filter((key) => key.startsWith(transcriptsKey) && key !== `${transcriptsKey}${current}`);
54
+ await Promise.all(owners.map(async (recorded) => {
55
+ if (!(await ended(recorded)))
56
+ return;
57
+ const owner = recorded.slice(transcriptsKey.length);
58
+ await Promise.all(stored.filter((key) => key.startsWith(`${name}.`) && key.endsWith(`.sessions.${owner}`)).map((value) => claude.store.delete(value)));
58
59
  await claude.store.delete(recorded);
59
- }
60
+ }));
60
61
  };
61
62
  const loadGroups = async (only, next) => {
62
63
  const loaded = [];
@@ -114,8 +115,10 @@ export function createState({ name, initial, session, root, claude, report, chan
114
115
  }),
115
116
  moveTo: (nextRoot) => inTurn(async () => (nextRoot === projectRoot ? undefined : loadGroups(['project'], { root: nextRoot, session: sessionId }))),
116
117
  switchSession: (nextSession, source, transcript) => inTurn(async () => {
117
- await claude.store.set(`${transcriptsKey}${nextSession}`, transcript);
118
- await forgetEndedSessions(nextSession);
118
+ if (Object.keys(declared.session).length > 0) {
119
+ await claude.store.set(`${transcriptsKey}${nextSession}`, transcript);
120
+ void forgetEndedSessions(nextSession).catch((error) => report({ id: 'state:sessions', message: 'Could not forget the session values of ended sessions', error }));
121
+ }
119
122
  if (nextSession === sessionId)
120
123
  return;
121
124
  if (source === 'fork')
@@ -35,6 +35,7 @@ export type Row = {
35
35
  };
36
36
  export declare const messageTypes: readonly MessageType[];
37
37
  export declare const skillPrefix = "Base directory for this skill:";
38
+ export declare function instructionPathOf(text: string): string;
38
39
  export declare function rowOfLine(row: Readonly<Record<string, unknown>>): Row | undefined;
39
40
  export declare function rowOfAppend(append: {
40
41
  readonly uuid: string;
@@ -1 +1 @@
1
- {"version":3,"file":"message.d.ts","sourceRoot":"","sources":["../../../../src/session/context/turn/message/message.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"message.d.ts","sourceRoot":"","sources":["../../../../src/session/context/turn/message/message.ts"],"names":[],"mappings":"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"}