@cmodjs/core 2.0.0 → 2.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 (58) hide show
  1. package/docs/commands.md +4 -4
  2. package/docs/dependencies.md +1 -1
  3. package/docs/jobs.md +1 -1
  4. package/docs/mod.md +2 -3
  5. package/docs/permissions.md +1 -1
  6. package/docs/session.md +3 -1
  7. package/docs/testing.md +2 -1
  8. package/jobs/permissions.d.ts.map +1 -1
  9. package/jobs/permissions.js +4 -1
  10. package/package.json +1 -1
  11. package/records.d.ts +1 -1
  12. package/records.js +1 -1
  13. package/register.d.ts.map +1 -1
  14. package/register.js +5 -4
  15. package/runtime/before.d.ts +8 -4
  16. package/runtime/before.d.ts.map +1 -1
  17. package/runtime/before.js +63 -39
  18. package/runtime/conversations.d.ts.map +1 -1
  19. package/runtime/conversations.js +38 -13
  20. package/runtime/engine.d.ts +1 -0
  21. package/runtime/engine.d.ts.map +1 -1
  22. package/runtime/hooks.d.ts +9 -23
  23. package/runtime/hooks.d.ts.map +1 -1
  24. package/runtime/hooks.js +4 -59
  25. package/runtime/lifecycle.d.ts +2 -1
  26. package/runtime/lifecycle.d.ts.map +1 -1
  27. package/runtime/lifecycle.js +36 -23
  28. package/runtime/permission-check.d.ts +15 -0
  29. package/runtime/permission-check.d.ts.map +1 -0
  30. package/runtime/permission-check.js +37 -0
  31. package/runtime/router.d.ts +0 -1
  32. package/runtime/router.d.ts.map +1 -1
  33. package/runtime/router.js +0 -1
  34. package/runtime/sessions.d.ts +13 -8
  35. package/runtime/sessions.d.ts.map +1 -1
  36. package/runtime/sessions.js +44 -80
  37. package/runtime/state.d.ts.map +1 -1
  38. package/runtime/state.js +14 -11
  39. package/session/context/turn/message/message.d.ts +1 -0
  40. package/session/context/turn/message/message.d.ts.map +1 -1
  41. package/session/context/turn/message/message.js +5 -2
  42. package/src/jobs/permissions.ts +3 -1
  43. package/src/records.ts +1 -1
  44. package/src/register.ts +5 -4
  45. package/src/runtime/before.ts +66 -42
  46. package/src/runtime/conversations.ts +35 -13
  47. package/src/runtime/engine.ts +1 -0
  48. package/src/runtime/hooks.ts +13 -86
  49. package/src/runtime/lifecycle.ts +51 -37
  50. package/src/runtime/permission-check.ts +47 -0
  51. package/src/runtime/router.ts +0 -2
  52. package/src/runtime/sessions.ts +55 -84
  53. package/src/runtime/state.ts +15 -8
  54. package/src/session/context/turn/message/message.ts +6 -2
  55. package/src/testing.ts +17 -10
  56. package/testing.d.ts +7 -2
  57. package/testing.d.ts.map +1 -1
  58. package/testing.js +13 -7
@@ -1,36 +1,22 @@
1
- import type { ClassicHookEvent, ClassicHookInputs, PermissionRequestDecision } from 'claude-code';
1
+ import type { ClassicHookEvent, ClassicHookInputs } from 'claude-code';
2
2
  import type { Claude } from './claude.js';
3
3
  import type { 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'>;
7
- export type HookAnswer = {
8
- decision?: 'block';
9
- reason?: string;
10
- hookSpecificOutput?: {
11
- hookEventName?: Hook;
12
- additionalContext?: string;
13
- permissionDecision?: 'deny' | 'ask';
14
- permissionDecisionReason?: string;
15
- sessionTitle?: string;
16
- initialUserMessage?: string;
17
- watchPaths?: string[];
18
- reloadSkills?: boolean;
19
- decision?: PermissionRequestDecision;
20
- retry?: boolean;
21
- displayContent?: string;
22
- worktreePath?: string;
23
- };
24
- };
25
- export type HookListener<H extends Hook> = (input: ClassicHookInputs[H]) => HookAnswer | void | Promise<HookAnswer | void>;
7
+ export type HookFields = Readonly<Record<string, unknown>>;
8
+ export type HookListener<H extends Hook> = (input: ClassicHookInputs[H]) => HookFields | undefined | Promise<HookFields | undefined>;
26
9
  export type RoutedEvent = `classic.${Hook}` | 'tool.check' | 'tool.call' | 'prompt.submit' | 'prompt.context' | 'prompt.attachment' | 'command.run' | 'session.measure' | 'skill.prompt' | 'ui.render' | 'ui.press' | 'ui.scroll' | 'ui.close' | 'cmod.call' | 'session.append' | 'session.compact' | 'session.receive' | 'agent.spawn' | 'turn.start';
27
- export declare const permissionEvents: readonly RoutedEvent[];
28
10
  type CallFiles = {
29
11
  readonly read: string[];
30
12
  readonly changed: string[];
31
13
  };
32
- export declare function classicHook<H extends Hook>(name: string, event: H, hook: HookListener<H>, report: (failure: Failure) => void): RoutedHook<RoutedEvent>;
14
+ export declare function classicHook<H extends Hook>(event: H, hook: HookListener<H>, report: (failure: Failure) => void): RoutedHook<RoutedEvent>;
33
15
  export declare function userSkillHook(claude: Claude): RoutedHook<'skill.prompt'>;
34
- export declare function callFiles(name: string, claude: Claude, use: CallBase, cwd: string): Promise<CallFiles>;
16
+ export type HomeFolders = {
17
+ readonly home: string | undefined;
18
+ readonly configRoot: string | undefined;
19
+ };
20
+ export declare function callFiles(name: string, claude: Claude, folders: Promise<HomeFolders>, use: CallBase, cwd: string): Promise<CallFiles>;
35
21
  export {};
36
22
  //# sourceMappingURL=hooks.d.ts.map
@@ -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,yBAAyB,EAAE,MAAM,aAAa,CAAA;AAEjG,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;IACvB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,kBAAkB,CAAC,EAAE;QACnB,aAAa,CAAC,EAAE,IAAI,CAAA;QACpB,iBAAiB,CAAC,EAAE,MAAM,CAAA;QAC1B,kBAAkB,CAAC,EAAE,MAAM,GAAG,KAAK,CAAA;QACnC,wBAAwB,CAAC,EAAE,MAAM,CAAA;QACjC,YAAY,CAAC,EAAE,MAAM,CAAA;QACrB,kBAAkB,CAAC,EAAE,MAAM,CAAA;QAC3B,UAAU,CAAC,EAAE,MAAM,EAAE,CAAA;QACrB,YAAY,CAAC,EAAE,OAAO,CAAA;QACtB,QAAQ,CAAC,EAAE,yBAAyB,CAAA;QACpC,KAAK,CAAC,EAAE,OAAO,CAAA;QACf,cAAc,CAAC,EAAE,MAAM,CAAA;QACvB,YAAY,CAAC,EAAE,MAAM,CAAA;KACtB,CAAA;CACF,CAAA;AAED,MAAM,MAAM,YAAY,CAAC,CAAC,SAAS,IAAI,IAAI,CAAC,KAAK,EAAE,iBAAiB,CAAC,CAAC,CAAC,KAAK,UAAU,GAAG,IAAI,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAAA;AAE1H,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,eAAO,MAAM,gBAAgB,EAAE,SAAS,WAAW,EAAgD,CAAA;AAInG,KAAK,SAAS,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAAA;AAuCxE,wBAAgB,WAAW,CAAC,CAAC,SAAS,IAAI,EAAE,IAAI,EAAE,MAAM,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,CAgBtJ;AAMD,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,CAAC,cAAc,CAAC,CAexE;AAED,wBAAsB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAgB5G"}
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"}
package/runtime/hooks.js CHANGED
@@ -3,52 +3,11 @@ import { callEffects } from '../utils/call-effects.js';
3
3
  import { dynamicPattern } from '../utils/parse-shell.js';
4
4
  import { isMissing } from '../utils/paths.js';
5
5
  import { messageOf } from '../utils/text.js';
6
- export const permissionEvents = ['tool.check', 'classic.PermissionRequest'];
7
- const flags = ['reloadSkills', 'retry'];
8
- const readFields = {
9
- Setup: ['additionalContext'],
10
- SessionStart: ['additionalContext', 'initialUserMessage', 'sessionTitle', 'watchPaths', 'reloadSkills'],
11
- SessionEnd: [],
12
- UserPromptSubmit: ['additionalContext', 'sessionTitle'],
13
- UserPromptExpansion: ['additionalContext'],
14
- InstructionsLoaded: [],
15
- ConfigChange: [],
16
- DirectoryAdded: [],
17
- PreModelSwitch: ['permissionDecision', 'permissionDecisionReason'],
18
- PostModelSwitch: ['additionalContext'],
19
- PermissionRequest: ['decision'],
20
- PermissionDenied: ['retry'],
21
- PostToolUse: ['additionalContext'],
22
- PostToolUseFailure: ['additionalContext'],
23
- PostToolBatch: ['additionalContext'],
24
- MessageDisplay: ['displayContent'],
25
- SubagentStart: ['additionalContext'],
26
- SubagentStop: ['additionalContext'],
27
- TaskCreated: [],
28
- TaskCompleted: [],
29
- TeammateIdle: [],
30
- Elicitation: [],
31
- ElicitationResult: [],
32
- Notification: [],
33
- PreCompact: [],
34
- PostCompact: [],
35
- Stop: ['additionalContext'],
36
- StopFailure: [],
37
- CwdChanged: [],
38
- FileChanged: [],
39
- WorktreeCreate: ['worktreePath'],
40
- WorktreeRemove: [],
41
- };
42
- export function classicHook(name, event, hook, report) {
6
+ export function classicHook(event, hook, report) {
43
7
  const routed = async (e, next) => {
44
8
  const ours = await Promise.resolve()
45
- .then(async () => {
46
- const answer = await hook(e);
47
- return answer === undefined ? undefined : classicResult(event, answer);
48
- })
9
+ .then(() => hook(e))
49
10
  .catch((error) => {
50
- if (event === 'PermissionRequest')
51
- return { decision: { behavior: 'deny', message: `${name}: the ${event} listener failed: ${messageOf(error)}` } };
52
11
  report({ id: `hook:${event}`, message: `The ${event} listener failed`, error });
53
12
  return undefined;
54
13
  });
@@ -80,9 +39,9 @@ export function userSkillHook(claude) {
80
39
  return next(e);
81
40
  };
82
41
  }
83
- export async function callFiles(name, claude, use, cwd) {
42
+ export async function callFiles(name, claude, folders, use, cwd) {
84
43
  try {
85
- const [home, configRoot] = await Promise.all([claude.env.home(), claude.env.configHome()]);
44
+ const { home, configRoot } = await folders;
86
45
  if (home === undefined)
87
46
  throw new Error('HOME is not set, so ~ in a path has no meaning.');
88
47
  const { shell, reads, writes } = callEffects(use, { cwd, home, ...(configRoot === undefined ? {} : { configRoot }), fs: claude.fs });
@@ -100,20 +59,6 @@ export async function callFiles(name, claude, use, cwd) {
100
59
  return { read: [], changed: [] };
101
60
  }
102
61
  }
103
- function classicResult(event, answer) {
104
- const result = {};
105
- if (answer.decision === 'block')
106
- result['block'] = answer.reason ?? '';
107
- const specific = answer.hookSpecificOutput ?? {};
108
- for (const [field, value] of Object.entries(specific)) {
109
- if (field === 'hookEventName' || (value === false && flags.includes(field)))
110
- continue;
111
- if (!readFields[event].includes(field))
112
- throw new Error(`it answered ${field}, which ${event} does not read.`);
113
- result[field] = field === 'additionalContext' ? [value] : value;
114
- }
115
- return result;
116
- }
117
62
  function mergeClassic(below, ours) {
118
63
  const merged = { ...below, ...ours };
119
64
  const context = [...(below['additionalContext'] ?? []), ...(ours['additionalContext'] ?? [])];
@@ -4,6 +4,7 @@ import type { Options } from '../options.js';
4
4
  import { type Steps } from '../records.js';
5
5
  import type { Claude } from './claude.js';
6
6
  import { type RoutedEvent } from './hooks.js';
7
+ import type { PermissionRoutes } from './permission-check.js';
7
8
  import { type RouterNext } from './router.js';
8
9
  import { type ShownToast } from './toaster.js';
9
10
  export type Plugin = {
@@ -27,5 +28,5 @@ export type Lifecycle<State extends object> = {
27
28
  raise(method: string, payload: Readonly<Record<string, unknown>>): Promise<unknown>;
28
29
  };
29
30
  export declare function readPlugin(claude: Claude): Promise<Plugin>;
30
- export declare function createLifecycle<State extends object, Declared extends Options = Options>(definition: ModDefinition<State, string, Declared>, checksPermissions?: () => boolean, options?: PluginOptions, asksPerson?: boolean): Lifecycle<State>;
31
+ export declare function createLifecycle<State extends object, Declared extends Options = Options>(definition: ModDefinition<State, string, Declared>, permissionRoutes?: () => PermissionRoutes | undefined, options?: PluginOptions, asksPerson?: boolean): Lifecycle<State>;
31
32
  //# sourceMappingURL=lifecycle.d.ts.map
@@ -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,EAA8E,KAAK,WAAW,EAAE,MAAM,YAAY,CAAA;AAOzH,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;AAyCD,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,iBAAiB,GAAE,MAAM,OAAoB,EAC7C,OAAO,GAAE,aAAkB,EAC3B,UAAU,UAAO,GAChB,SAAS,CAAC,KAAK,CAAC,CAyclB"}
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,13 +1,13 @@
1
1
  import { changelogPage, consentPath, dataFolder, finishStepsMethod, isAtLeast, marketplaceOf, oldestCmodFor, openPageMethod, parseConsent, pendingStepsMethod, parseEvent, permissionWords, readRecord, readSteps, recordPath, scriptsSha256, settingsPagesMethod, storeFolder, updatesToTurnOn } from '../records.js';
2
2
  import { homePrefix, ifMissing, relativePath } from '../utils/paths.js';
3
- import { firstLine, formatExit, listed, messageOf } from '../utils/text.js';
3
+ import { firstLine, formatExit, messageOf } from '../utils/text.js';
4
4
  import { beforeDeadline } from './deadline.js';
5
5
  import { announcedOf, announcementMs, announcementOf } from './announce.js';
6
6
  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, permissionEvents, userSkillHook } from './hooks.js';
10
+ import { 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';
@@ -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) };
@@ -915,7 +932,7 @@ async function createMod(definition, runtime) {
915
932
  return served ?? answerCall(definition.name, api, e);
916
933
  });
917
934
  const agents = toolCalls(claude, router);
918
- keepEngine(mod, { claude: checked, router, toolCalls: agents, report });
935
+ keepEngine(mod, { claude: checked, router, toolCalls: agents, report, hasPermissionCheck: () => runtime.permissionRoutes() !== undefined });
919
936
  const names = new Set();
920
937
  const reserveName = (type, name, taken) => {
921
938
  const key = `${type}:${name}`;
@@ -932,10 +949,6 @@ async function createMod(definition, runtime) {
932
949
  await failsAs('the details of its session did not load', () => followCurrent(undefined));
933
950
  await failsAs('its setup function threw', () => definition.setup(mod));
934
951
  isSetUp = true;
935
- const permissionHooks = permissionEvents.filter((event) => router.has(event));
936
- if (permissionHooks.length > 0 && !runtime.checksPermissions()) {
937
- throw new Error(`it decides permissions on ${listed(permissionHooks)}, so hooks/register.ts must call registerPermissionCheck(addHook) after registerMod`);
938
- }
939
952
  await failsAs('its open panes did not load', () => area.restorePanes());
940
953
  return { mod, added, imports, raise: client.raise };
941
954
  }
@@ -943,7 +956,7 @@ function checkingKeys(claude, toast, keys) {
943
956
  const bound = Object.entries(keys);
944
957
  if (bound.length === 0)
945
958
  return claude;
946
- const register = (command) => {
959
+ const addCommand = (command) => {
947
960
  for (const [key, commandName] of bound) {
948
961
  if (commandName === command.name && command.immediate !== true) {
949
962
  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 +964,7 @@ function checkingKeys(claude, toast, keys) {
951
964
  }
952
965
  return claude.command.register(command);
953
966
  };
954
- return { ...claude, command: { ...claude.command, register } };
967
+ return { ...claude, command: { ...claude.command, register: addCommand } };
955
968
  }
956
969
  const longestTimerMs = 2_147_483_647;
957
970
  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
+ };
@@ -5,7 +5,6 @@ export type RouterNext<N extends RoutedEvent> = (e: Frozen<Args<N>>) => Promise<
5
5
  export type RoutedHook<N extends RoutedEvent> = (e: Frozen<Args<N>>, next: RouterNext<N>) => EventResult<N> | Promise<EventResult<N>>;
6
6
  export type Router = {
7
7
  add<N extends RoutedEvent>(event: N, hook: RoutedHook<N>): Disposable;
8
- has(event: RoutedEvent): boolean;
9
8
  dispatch<N extends RoutedEvent>(event: N, e: Frozen<Args<N>>, next: RouterNext<N>): Promise<EventResult<N>>;
10
9
  };
11
10
  export declare function createRouter(): Router;
@@ -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,GAAG,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAA;IAChC,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,CA0BrC"}
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"}
package/runtime/router.js CHANGED
@@ -14,7 +14,6 @@ export function createRouter() {
14
14
  },
15
15
  };
16
16
  },
17
- has: (event) => hooks.has(event),
18
17
  dispatch(event, e, next) {
19
18
  const chain = hooks.get(event);
20
19
  const call = async (index, current) => {
@@ -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,18 @@ 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 declare function withoutPermissionCheck(name: string, hearer: string): string;
59
+ export type HookOn = (hook: string, listener: (input: unknown) => HookFields | undefined | Promise<HookFields | undefined>) => Disposable;
60
+ export declare function createSessionsClient({ name, claude, report, isGranted, hookOn, routeOn, permissionRoutes }: {
58
61
  readonly name: string;
59
62
  readonly claude: Claude;
60
63
  readonly report: (id: string, message: string, error: unknown) => void;
61
64
  readonly isGranted: (permission: string) => boolean;
62
- readonly hookOn?: (hook: string, listener: (input: unknown) => unknown) => Disposable;
65
+ readonly hookOn?: HookOn;
63
66
  readonly routeOn?: RouteOn;
67
+ readonly permissionRoutes?: () => PermissionRoutes | undefined;
64
68
  }): SessionsClient;
65
- type HookFields = Readonly<Record<string, unknown>>;
66
- type ToolCheck = {
69
+ export type ToolCheck = {
67
70
  readonly tool: string;
68
71
  readonly input: unknown;
69
72
  readonly tool_use_id?: string;
@@ -74,9 +77,11 @@ export type RouteOn = {
74
77
  (event: 'tool.check', hook: (e: ToolCheck, next: (e: ToolCheck) => Promise<unknown>) => Promise<unknown>): Disposable;
75
78
  (event: 'command.run', hook: (e: Args<'command.run'>, next: (e: Args<'command.run'>) => Promise<CommandRunResult>) => Promise<CommandRunResult>): Disposable;
76
79
  };
80
+ export declare const recordOf: (value: unknown) => Readonly<Record<string, unknown>>;
81
+ export declare const defined: (fields: HookFields) => HookFields;
82
+ type ProcessFieldsName = Exclude<ProcessName, 'PermissionCheck'>;
77
83
  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;
84
+ export declare function processPayloadOf(named: ProcessFieldsName, input: unknown): HookFields;
80
85
  export declare function resultOf(where: Pick<Place, 'session' | 'context' | 'turn'>, call: ToolCallArgs & {
81
86
  readonly cwd: string;
82
87
  }, answered: Awaited<ReturnType<Claude['tool']['call']>>): ToolResult;
@@ -1 +1 @@
1
- {"version":3,"file":"sessions.d.ts","sourceRoot":"","sources":["../src/runtime/sessions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AACzD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AAM3C,OAAO,EAAE,UAAU,EAAE,MAAM,gDAAgD,CAAA;AAE3E,OAAO,EAAgD,KAAK,aAAa,EAAE,KAAK,WAAW,EAAE,KAAK,QAAQ,EAAiB,MAAM,4BAA4B,CAAA;AAG7J,OAAO,EAAgB,aAAa,EAA0B,KAAK,WAAW,EAA6K,KAAK,YAAY,EAAuC,KAAK,QAAQ,EAAkB,KAAK,aAAa,EAAE,KAAK,YAAY,EAAE,KAAK,KAAK,EAAE,MAAM,uBAAuB,CAAA;AACla,OAAO,EAAsC,KAAK,WAAW,EAAE,MAAM,qBAAqB,CAAA;AAC1F,OAAO,EAA6B,KAAK,KAAK,EAAE,MAAM,aAAa,CAAA;AACnE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAIzC,OAAO,EAAwB,KAAK,UAAU,EAAE,MAAM,YAAY,CAAA;AAElE,MAAM,MAAM,YAAY,GAAG;IAAE,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,WAAW,GAAG,SAAS,CAAA;CAAE,CAAA;AAEtG,eAAO,MAAM,YAAY,MAAM,CAAA;AAE/B,eAAO,MAAM,mBAAmB;aAC9B,QAAQ,EAAE,eAAe;aACzB,MAAM,EAAE,aAAa;aACrB,QAAQ,EAAE,eAAe;aACzB,KAAK,EAAE,YAAY;aACnB,QAAQ,EAAE,eAAe;aACzB,KAAK,EAAE,YAAY;aACnB,IAAI,EAAE,WAAW;aACjB,UAAU,EAAE,iBAAiB;aAC7B,KAAK,EAAE,YAAY;aACnB,SAAS,EAAE,gBAAgB;aAC3B,WAAW,EAAE,kBAAkB;aAC/B,GAAG,EAAE,UAAU;aACf,OAAO,EAAE,cAAc;aACvB,MAAM,EAAE,aAAa;CACb,CAAA;AAEV,MAAM,MAAM,GAAG,GAAG,MAAM,GAAG,WAAW,GAAG,UAAU,GAAG,OAAO,GAAG,UAAU,GAAG,OAAO,CAAA;AAQpF,eAAO,MAAM,gBAAgB,UAAW,WAAW,KAAG,MAAqF,CAAA;AAI3I,eAAO,MAAM,KAAK,WAAY,MAAM,KAAG,MAAM,IAAI,GAAwD,CAAA;AAEzG,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAE/D;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAE7E;AAED,MAAM,MAAM,KAAK,GAAG;IAAE,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,IAAI,CAAA;CAAE,CAAA;AAE7K,MAAM,MAAM,cAAc,GAAG;IAC3B,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAA;IAC3B,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,WAAW,EAAE,OAAO,GAAG,IAAI,CAAA;IAC3E,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,aAAa,EAAE,WAAW,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IAChH,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IACnF,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,OAAO,EAAE,GAAG,UAAU,CAAA;IAC5D,8DAA8D;IAC9D,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,WAAW,EAAE,WAAW,GAAG,QAAQ,CAAC,GAAG,IAAI,CAAA;CACjE,CAAA;AAMD,wBAAsB,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,CAI7E;AAED,wBAAgB,SAAS,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAUxD;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,aAAa,GAAG,OAAO,CAG/F;AAwBD,wBAAgB,SAAS,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,GAAG,OAAO,CAS7I;AAED,wBAAgB,oBAAoB,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC;IAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,KAAK,UAAU,CAAC;IAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,cAAc,CA+b7Y;AAED,KAAK,UAAU,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;AAEnD,KAAK,SAAS,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,GAAG,KAAK,GAAG,MAAM,CAAA;CAAE,CAAA;AAI1K,MAAM,MAAM,OAAO,GAAG;IACpB,CAAC,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,SAAS,KAAK,OAAO,CAAC,OAAO,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,UAAU,CAAA;IACrH,CAAC,KAAK,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,IAAI,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,IAAI,CAAC,aAAa,CAAC,KAAK,OAAO,CAAC,gBAAgB,CAAC,KAAK,OAAO,CAAC,gBAAgB,CAAC,GAAG,UAAU,CAAA;CAC7J,CAAA;AA4ED,wBAAsB,SAAS,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,QAAQ,CAAC,CAarG;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,CAAC,MAAM,OAAO,aAAa,EAAE,iBAAiB,CAAC,EAAE,KAAK,EAAE,OAAO,GAAG,UAAU,CAG1H;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,UAAU,GAAG,SAAS,CAiBpG;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,SAAS,GAAG,SAAS,GAAG,MAAM,CAAC,EAAE,IAAI,EAAE,YAAY,GAAG;IAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CAAE,EAAE,QAAQ,EAAE,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,UAAU,CAI7L"}
1
+ {"version":3,"file":"sessions.d.ts","sourceRoot":"","sources":["../src/runtime/sessions.ts"],"names":[],"mappings":"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"}