@cmodjs/core 1.6.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 (136) hide show
  1. package/docs/commands.md +7 -7
  2. package/docs/dependencies.md +1 -1
  3. package/docs/index.md +12 -11
  4. package/docs/jobs.md +12 -16
  5. package/docs/mod.md +111 -36
  6. package/docs/permissions.md +14 -18
  7. package/docs/session.md +171 -82
  8. package/docs/state.md +5 -5
  9. package/docs/testing.md +57 -41
  10. package/docs/ui.md +9 -9
  11. package/jobs/permissions/decide-permission.d.ts.map +1 -1
  12. package/jobs/permissions/decide-permission.js +1 -1
  13. package/jobs/prompt.d.ts +1 -3
  14. package/jobs/prompt.d.ts.map +1 -1
  15. package/jobs/prompt.js +2 -21
  16. package/jobs/slash-command.d.ts +1 -1
  17. package/jobs/slash-command.d.ts.map +1 -1
  18. package/jobs/slash-command.js +1 -1
  19. package/jobs/status-line.d.ts +0 -1
  20. package/jobs/status-line.d.ts.map +1 -1
  21. package/jobs/status-line.js +3 -4
  22. package/mod.d.ts +53 -105
  23. package/mod.d.ts.map +1 -1
  24. package/mod.js +18 -80
  25. package/package.json +1 -1
  26. package/records.d.ts +1 -1
  27. package/records.js +1 -1
  28. package/register.d.ts.map +1 -1
  29. package/register.js +8 -5
  30. package/runtime/before.d.ts +11 -4
  31. package/runtime/before.d.ts.map +1 -1
  32. package/runtime/before.js +131 -67
  33. package/runtime/claude.d.ts +6 -1
  34. package/runtime/claude.d.ts.map +1 -1
  35. package/runtime/conversations.d.ts.map +1 -1
  36. package/runtime/conversations.js +82 -38
  37. package/runtime/deadline.d.ts +17 -0
  38. package/runtime/deadline.d.ts.map +1 -1
  39. package/runtime/deadline.js +34 -0
  40. package/runtime/dependencies.d.ts +2 -0
  41. package/runtime/dependencies.d.ts.map +1 -1
  42. package/runtime/dependencies.js +12 -0
  43. package/runtime/grants.d.ts.map +1 -1
  44. package/runtime/grants.js +13 -8
  45. package/runtime/hooks.d.ts +15 -11
  46. package/runtime/hooks.d.ts.map +1 -1
  47. package/runtime/hooks.js +8 -165
  48. package/runtime/lifecycle.d.ts +4 -2
  49. package/runtime/lifecycle.d.ts.map +1 -1
  50. package/runtime/lifecycle.js +96 -62
  51. package/runtime/permission-check.d.ts +15 -0
  52. package/runtime/permission-check.d.ts.map +1 -0
  53. package/runtime/permission-check.js +37 -0
  54. package/runtime/sessions.d.ts +35 -5
  55. package/runtime/sessions.d.ts.map +1 -1
  56. package/runtime/sessions.js +304 -82
  57. package/runtime/state.d.ts.map +1 -1
  58. package/runtime/state.js +14 -11
  59. package/runtime/tool-calls.d.ts +0 -1
  60. package/runtime/tool-calls.d.ts.map +1 -1
  61. package/runtime/tool-calls.js +0 -19
  62. package/session/context/turn/message/instruction-file.d.ts +9 -0
  63. package/session/context/turn/message/instruction-file.d.ts.map +1 -0
  64. package/session/context/turn/message/instruction-file.js +4 -0
  65. package/session/context/turn/message/message.d.ts +6 -4
  66. package/session/context/turn/message/message.d.ts.map +1 -1
  67. package/session/context/turn/message/message.js +12 -8
  68. package/session/context/turn/message/sender.d.ts +2 -1
  69. package/session/context/turn/message/sender.d.ts.map +1 -1
  70. package/session/context/turn/message/sender.js +4 -1
  71. package/session/context/turn/message/tool-call.d.ts +5 -0
  72. package/session/context/turn/message/tool-call.d.ts.map +1 -1
  73. package/session/context/turn/message/tool-result.d.ts +6 -1
  74. package/session/context/turn/message/tool-result.d.ts.map +1 -1
  75. package/session/context/turn/turn.d.ts +7 -0
  76. package/session/context/turn/turn.d.ts.map +1 -1
  77. package/session/conversation.d.ts +10 -3
  78. package/session/conversation.d.ts.map +1 -1
  79. package/session/conversation.js +14 -5
  80. package/session/goal/goal.d.ts +1 -1
  81. package/session/goal/goal.d.ts.map +1 -1
  82. package/session/goal/task.d.ts +2 -2
  83. package/session/goal/task.d.ts.map +1 -1
  84. package/session/session.d.ts +361 -26
  85. package/session/session.d.ts.map +1 -1
  86. package/session/session.js +40 -0
  87. package/src/jobs/permissions/decide-permission.ts +2 -1
  88. package/src/jobs/prompt.ts +3 -20
  89. package/src/jobs/slash-command.ts +2 -2
  90. package/src/jobs/status-line.ts +4 -7
  91. package/src/mod.ts +52 -147
  92. package/src/records.ts +1 -1
  93. package/src/register.ts +8 -5
  94. package/src/runtime/before.ts +140 -66
  95. package/src/runtime/claude.ts +5 -1
  96. package/src/runtime/conversations.ts +75 -37
  97. package/src/runtime/deadline.ts +38 -0
  98. package/src/runtime/dependencies.ts +12 -0
  99. package/src/runtime/grants.ts +11 -7
  100. package/src/runtime/hooks.ts +24 -163
  101. package/src/runtime/lifecycle.ts +110 -77
  102. package/src/runtime/permission-check.ts +47 -0
  103. package/src/runtime/sessions.ts +334 -91
  104. package/src/runtime/state.ts +15 -8
  105. package/src/runtime/tool-calls.ts +0 -19
  106. package/src/session/context/turn/message/instruction-file.ts +13 -0
  107. package/src/session/context/turn/message/message.ts +17 -11
  108. package/src/session/context/turn/message/sender.ts +5 -2
  109. package/src/session/context/turn/message/tool-call.ts +3 -0
  110. package/src/session/context/turn/message/tool-result.ts +6 -1
  111. package/src/session/context/turn/turn.ts +4 -0
  112. package/src/session/conversation.ts +21 -8
  113. package/src/session/goal/goal.ts +1 -1
  114. package/src/session/goal/task.ts +2 -2
  115. package/src/session/session.ts +227 -24
  116. package/src/testing/claude-code.ts +23 -0
  117. package/src/testing/fake-claude.ts +5 -1
  118. package/src/testing/fake-sessions.ts +38 -24
  119. package/src/testing.ts +88 -19
  120. package/testing/claude-code.d.ts +12 -0
  121. package/testing/claude-code.d.ts.map +1 -0
  122. package/testing/claude-code.js +10 -0
  123. package/testing/fake-claude.d.ts +4 -0
  124. package/testing/fake-claude.d.ts.map +1 -1
  125. package/testing/fake-claude.js +4 -1
  126. package/testing/fake-sessions.d.ts +8 -6
  127. package/testing/fake-sessions.d.ts.map +1 -1
  128. package/testing/fake-sessions.js +35 -20
  129. package/testing.d.ts +38 -9
  130. package/testing.d.ts.map +1 -1
  131. package/testing.js +58 -8
  132. package/docs/hooks.md +0 -259
  133. package/session/context/turn/message/document.d.ts +0 -7
  134. package/session/context/turn/message/document.d.ts.map +0 -1
  135. package/session/context/turn/message/document.js +0 -1
  136. package/src/session/context/turn/message/document.ts +0 -8
@@ -2,21 +2,18 @@ import type { Job, Mod } from '../mod.js'
2
2
  import type { Deadline } from '../runtime/deadline.js'
3
3
  import { engineOf } from '../runtime/engine.js'
4
4
  import { usageOf } from '../runtime/sessions.js'
5
+ import { onStateChange } from '../runtime/state.js'
5
6
  import type { Usage } from '../session/session.js'
6
7
  import { messageOf } from '../utils/text.js'
7
8
  import { withinDeadline } from './context.js'
8
9
 
9
10
  const deadline: Deadline = { ms: 2000, job: 'statusLine' }
10
11
 
11
- export function statusLine<State extends object = Record<never, never>>(options: {
12
- readonly text: (usage: Usage, mod: Mod<State>) => string | undefined | Promise<string | undefined>
13
- readonly interval?: number
14
- }): Job<void, State> {
15
- const { text, interval = 10000 } = options
12
+ export function statusLine<State extends object = Record<never, never>>(options: { readonly text: (usage: Usage, mod: Mod<State>) => string | undefined | Promise<string | undefined> }): Job<void, State> {
13
+ const { text } = options
16
14
  return (job) => {
17
15
  const { mod, announce, reserveName } = job
18
16
  const { claude, router } = engineOf(mod)
19
- if (!(interval >= 1)) throw new Error(`${mod.name}: the status line interval is ${interval}. Give it in milliseconds, 1 or more.`)
20
17
  reserveName('statusLine', '', `${mod.name}: a status line is already added. A mod has one status line: join the texts in one statusLine.`)
21
18
 
22
19
  let shown: string | undefined
@@ -41,7 +38,7 @@ export function statusLine<State extends object = Record<never, never>>(options:
41
38
  refresh()
42
39
  return next(e)
43
40
  })
44
- claude.clock.every(interval, refresh)
41
+ onStateChange(mod.state, refresh)
45
42
  refresh()
46
43
  }
47
44
  }
package/src/mod.ts CHANGED
@@ -1,8 +1,7 @@
1
1
  import type {
2
2
  AskOptions,
3
- ClassicHookInputs,
4
3
  CmodDependencies,
5
- ConfigRow,
4
+ ConfigRow as ClaudeConfigRow,
6
5
  FsStatOptions,
7
6
  HookStream,
8
7
  HttpInit,
@@ -11,7 +10,6 @@ import type {
11
10
  ModelCompleteRequest,
12
11
  ModelCompleteResult,
13
12
  PaneOpenArgs,
14
- PermissionRequestDecision,
15
13
  ProcessRunInit,
16
14
  ProcessRunResult,
17
15
  ProcessSpawnChunk,
@@ -26,7 +24,7 @@ import type { Step } from './installer.js'
26
24
  import { checkOptions, type Option, type Options, type OptionValues } from './options.js'
27
25
  import { bound } from './runtime/bound.js'
28
26
  import { Mod as modSender } from './session/context/turn/message/sender.js'
29
- import type { Sessions } from './session/session.js'
27
+ import { sessionEvents, type BeforeMethod, type CommandRun, type CommandRunAnswer, type OnMethod, type OnMethods, type Sessions } from './session/session.js'
30
28
  import type { Pane } from './ui/define-pane.js'
31
29
  import type { Place, PlaceProps } from './ui/places.js'
32
30
  import type { Disposable } from './utils/disposable.js'
@@ -67,132 +65,6 @@ export type PaneHandle = {
67
65
  readonly isFocused: boolean
68
66
  }
69
67
 
70
- export const SessionStart = 'SessionStart'
71
- export const SessionEnd = 'SessionEnd'
72
- export const UserPromptSubmit = 'UserPromptSubmit'
73
- export const InstructionsLoaded = 'InstructionsLoaded'
74
- export const PreToolUse = 'PreToolUse'
75
- export const PermissionRequest = 'PermissionRequest'
76
- export const PermissionDenied = 'PermissionDenied'
77
- export const PostToolUse = 'PostToolUse'
78
- export const PostToolUseFailure = 'PostToolUseFailure'
79
- export const PostToolBatch = 'PostToolBatch'
80
- export const SubagentStart = 'SubagentStart'
81
- export const SubagentStop = 'SubagentStop'
82
- export const Notification = 'Notification'
83
- export const PreCompact = 'PreCompact'
84
- export const Stop = 'Stop'
85
- export const StopFailure = 'StopFailure'
86
- export const CwdChanged = 'CwdChanged'
87
- export const FileChanged = 'FileChanged'
88
- export const UserPromptExpansion = 'UserPromptExpansion'
89
- export const Setup = 'Setup'
90
- export const ConfigChange = 'ConfigChange'
91
- export const DirectoryAdded = 'DirectoryAdded'
92
- export const PreModelSwitch = 'PreModelSwitch'
93
- export const PostModelSwitch = 'PostModelSwitch'
94
- export const PostCompact = 'PostCompact'
95
- export const MessageDisplay = 'MessageDisplay'
96
- export const TodoCreated = 'TaskCreated'
97
- export const TodoCompleted = 'TaskCompleted'
98
- export const TeammateIdle = 'TeammateIdle'
99
- export const Elicitation = 'Elicitation'
100
- export const ElicitationResult = 'ElicitationResult'
101
- export const WorktreeCreate = 'WorktreeCreate'
102
- export const WorktreeRemove = 'WorktreeRemove'
103
-
104
- export const hooks = [
105
- Setup,
106
- SessionStart,
107
- SessionEnd,
108
- UserPromptSubmit,
109
- UserPromptExpansion,
110
- InstructionsLoaded,
111
- ConfigChange,
112
- DirectoryAdded,
113
- PreModelSwitch,
114
- PostModelSwitch,
115
- PreToolUse,
116
- PermissionRequest,
117
- PermissionDenied,
118
- PostToolUse,
119
- PostToolUseFailure,
120
- PostToolBatch,
121
- MessageDisplay,
122
- SubagentStart,
123
- SubagentStop,
124
- TodoCreated,
125
- TodoCompleted,
126
- TeammateIdle,
127
- Elicitation,
128
- ElicitationResult,
129
- Notification,
130
- PreCompact,
131
- PostCompact,
132
- Stop,
133
- StopFailure,
134
- CwdChanged,
135
- FileChanged,
136
- WorktreeCreate,
137
- WorktreeRemove,
138
- ] as const
139
-
140
- export type Hook = (typeof hooks)[number]
141
-
142
- export type HookAnswer = {
143
- continue?: boolean
144
- stopReason?: string
145
- suppressOutput?: boolean
146
- systemMessage?: string
147
- decision?: 'block'
148
- reason?: string
149
- hookSpecificOutput?: {
150
- hookEventName?: Hook
151
- additionalContext?: string
152
- permissionDecision?: 'allow' | 'deny' | 'ask'
153
- permissionDecisionReason?: string
154
- updatedInput?: Record<string, unknown>
155
- sessionTitle?: string
156
- suppressOriginalPrompt?: boolean
157
- initialUserMessage?: string
158
- watchPaths?: string[]
159
- reloadSkills?: boolean
160
- decision?: PermissionRequestDecision
161
- updatedToolOutput?: unknown
162
- updatedMCPToolOutput?: unknown
163
- retry?: boolean
164
- displayContent?: string
165
- worktreePath?: string
166
- }
167
- }
168
-
169
- type CallFiles = { read: string[]; changed: string[] }
170
-
171
- type HookInputs = Omit<ClassicHookInputs, 'PreToolUse' | 'PostToolUse' | 'PostToolUseFailure' | 'CwdChanged'> & {
172
- PreToolUse: {
173
- session_id: string
174
- cwd: string
175
- hook_event_name: 'PreToolUse'
176
- tool_name: string
177
- tool_input: Record<string, unknown>
178
- tool_use_id: string
179
- agent_id?: string
180
- agent_type?: string
181
- files: CallFiles
182
- }
183
- PostToolUse: ClassicHookInputs['PostToolUse'] & { files: CallFiles }
184
- PostToolUseFailure: ClassicHookInputs['PostToolUseFailure'] & { files: CallFiles }
185
- CwdChanged: Omit<ClassicHookInputs['CwdChanged'], 'transcript_path'>
186
- }
187
-
188
- export type HookInput<H extends Hook> = HookInputs[H]
189
-
190
- export type HookListener<H extends Hook> = (input: HookInput<H>) => HookAnswer | void | Promise<HookAnswer | void>
191
-
192
- export type HookOptions = {
193
- readonly timeoutMs?: number
194
- }
195
-
196
68
  export type Metadata = Readonly<Record<string, string>>
197
69
 
198
70
  export type FileMatch = {
@@ -215,6 +87,8 @@ export type Stat = Omit<Entry, 'name'> & {
215
87
  readonly realPath?: string
216
88
  }
217
89
 
90
+ export type FileChange = { readonly path: string; readonly type: 'change' | 'add' | 'unlink' }
91
+
218
92
  export type Allowed = {
219
93
  allows(value: string): boolean
220
94
  }
@@ -237,15 +111,36 @@ export type SettingsFile = {
237
111
  update(values: Readonly<Record<string, unknown>>): Promise<void>
238
112
  }
239
113
 
240
- export type Setting = Pick<ConfigRow, 'key' | 'label' | 'kind' | 'value' | 'isLocked'> & {
114
+ export type SettingsFileChange = { readonly source: 'user' | 'project' | 'local' | 'policy' | 'skills'; readonly path?: string }
115
+
116
+ export type SettingsFileChangeListener = (change: SettingsFileChange) => { readonly refuse: string } | void | Promise<{ readonly refuse: string } | void>
117
+
118
+ export type ConfigRow = Pick<ClaudeConfigRow, 'key' | 'label' | 'kind' | 'value' | 'isLocked'> & {
241
119
  readonly description?: string
242
120
  readonly options?: readonly string[]
243
121
  readonly plugin?: string
244
122
  }
245
123
 
124
+ export type CommandInfo = { readonly name: string; readonly description: string; readonly source: 'builtin' | 'plugin' | 'user' | 'mcp'; readonly plugin?: string }
125
+
126
+ export type CommandRunResult = { readonly text?: string; readonly note?: string }
127
+
246
128
  export type Imports = {
247
129
  readonly sessions: Sessions
248
- readonly settings: { list(): Promise<Setting[]>; readonly user: SettingsFile; readonly project: SettingsFile; readonly local: SettingsFile }
130
+ readonly commands: {
131
+ list(): Promise<CommandInfo[]>
132
+ run(name: string, args?: string): Promise<CommandRunResult>
133
+ readonly beforeRun: BeforeMethod<CommandRun, CommandRunAnswer>
134
+ readonly onRun: OnMethod<CommandRun>
135
+ }
136
+ readonly config: { list(): Promise<ConfigRow[]> }
137
+ readonly settings: {
138
+ readonly user: SettingsFile
139
+ readonly project: SettingsFile
140
+ readonly local: SettingsFile
141
+ beforeFileChange(listener: SettingsFileChangeListener): Disposable
142
+ beforeFileChange(matcher: Matcher<SettingsFileChange>, listener: SettingsFileChangeListener): Disposable
143
+ }
249
144
  readonly model: { complete(request: ModelCompleteRequest, options?: ModelCompleteOptions): Promise<ModelCompleteResult> }
250
145
  readonly fs: {
251
146
  read(path: string): Promise<string>
@@ -254,6 +149,7 @@ export type Imports = {
254
149
  find(glob: string | readonly string[]): Promise<readonly FileMatch[]>
255
150
  list(path?: string): Promise<Entry[]>
256
151
  stat(path: string, options?: FsStatOptions): Promise<Stat>
152
+ onChange(matcher: { readonly path: string | readonly string[] }, listener: (change: FileChange) => unknown): Disposable
257
153
  }
258
154
  readonly metadata: {
259
155
  read(path: string): Promise<Metadata>
@@ -271,16 +167,26 @@ export const sessions: Imports['sessions'] = {
271
167
  return bound().sessions.current
272
168
  },
273
169
  list: (options) => bound().sessions.list(options),
274
- search: (text, options) => bound().sessions.search(text, options),
275
- on: ((...args: Parameters<Imports['sessions']['on']>) => bound().sessions.on(...args)) as Imports['sessions']['on'],
276
- before: ((...args: Parameters<Imports['sessions']['before']>) => bound().sessions.before(...args)) as Imports['sessions']['before'],
170
+ search: (text, matcher, options) => bound().sessions.search(text, matcher, options),
171
+ ...(Object.fromEntries(Object.keys(sessionEvents).map((named) => [`on${named}`, (...args: unknown[]) => (bound().sessions[`on${named}` as keyof OnMethods] as (...each: unknown[]) => Disposable)(...args)])) as OnMethods),
277
172
  }
278
173
 
279
174
  export const settings: Imports['settings'] = {
280
- list: () => bound().settings.list(),
281
175
  user: { read: () => bound().settings.user.read(), update: (values) => bound().settings.user.update(values) },
282
176
  project: { read: () => bound().settings.project.read(), update: (values) => bound().settings.project.update(values) },
283
177
  local: { read: () => bound().settings.local.read(), update: (values) => bound().settings.local.update(values) },
178
+ beforeFileChange: ((matcherOrListener: never, listener?: never) => bound().settings.beforeFileChange(matcherOrListener, listener as never)) as Imports['settings']['beforeFileChange'],
179
+ }
180
+
181
+ export const commands: Imports['commands'] = {
182
+ list: () => bound().commands.list(),
183
+ run: (name, args) => bound().commands.run(name, args),
184
+ beforeRun: ((...args: never[]) => (bound().commands.beforeRun as (...each: never[]) => Disposable)(...args)) as Imports['commands']['beforeRun'],
185
+ onRun: ((...args: never[]) => (bound().commands.onRun as (...each: never[]) => Disposable)(...args)) as Imports['commands']['onRun'],
186
+ }
187
+
188
+ export const config: Imports['config'] = {
189
+ list: () => bound().config.list(),
284
190
  }
285
191
 
286
192
  export const model: Imports['model'] = {
@@ -294,6 +200,7 @@ export const fs: Imports['fs'] = {
294
200
  find: (glob) => bound().fs.find(glob),
295
201
  list: (path) => bound().fs.list(path),
296
202
  stat: (path, options) => bound().fs.stat(path, options),
203
+ onChange: (matcher, listener) => bound().fs.onChange(matcher, listener),
297
204
  }
298
205
 
299
206
  export const metadata: Imports['metadata'] = {
@@ -317,12 +224,10 @@ export type Mod<State extends object = Record<never, never>, Declared extends Op
317
224
  readonly state: Readonly<State>
318
225
  readonly options: OptionValues<Declared>
319
226
  readonly permissions: Permissions
320
- on<H extends Hook>(hook: H, listener: HookListener<H>, options?: HookOptions): Disposable
321
- on<H extends Hook>(hook: H, matcher: Matcher<HookInput<H>>, listener: HookListener<H>, options?: HookOptions): Disposable
322
227
  every(ms: number, listener: () => unknown): Disposable
323
228
  after(ms: number, listener: () => unknown): Disposable
324
229
  use<Handle>(job: Job<Handle, State>): Handle
325
- log(text: string): void
230
+ log(text: string, options?: { readonly to?: 'debug' | 'transcript' }): void
326
231
  readonly ui: {
327
232
  pane(pane: Pane<State>): PaneHandle
328
233
  render<P extends Place>(place: P, Component: (props: PlaceProps<P>) => RenderElement): Disposable
@@ -378,21 +283,21 @@ export function defineMod<State extends StateGroups = Record<never, never>, Name
378
283
  export type { Matcher } from './utils/matcher.js'
379
284
  export type { Place, PlaceProps } from './ui/places.js'
380
285
  export { AbovePrompt, AskUserQuestion, CommandOutput, PromptHint, SessionMode, Spinner, ToolGroup, ToolProgress, TurnDuration } from './ui/places.js'
381
- export { Session, UsageChange, type BeforeAnswer, type BeforeEvent, type BeforeListener, type Client, type Listener, type RecordPart, type Refusal, type SearchOptions, type SessionEvent, type SessionPayload, type SessionScope, type SessionSend, type Sessions, type TaskStartArgs, type ToolCallArgs, type Usage } from './session/session.js'
382
- export { ContextEnd, ContextStart, type Context } from './session/context/context.js'
383
- export { TurnEnd, TurnStart, type Turn } from './session/context/turn/turn.js'
384
- export { Message, type MessageType } from './session/context/turn/message/message.js'
286
+ export { Session, type AnswerOptions, type BeforeMethods, type Surface, type Listener, type ListenerTime, type OnMethods, type ReadOptions, type RecordPart, type Refusal, type SearchOptions, type SessionScope, type SessionSend, type Sessions, type CurrentSession, type Placement, type ProjectSetup, type SessionStartAsked, type SessionStarted, type SessionEnded, type ModelChange, type CwdChange, type DirectoryAdd, type Worktree, type Notification, type Elicitation, type ElicitationResponse, type McpServer, type PermissionUpdate, type PermissionCheck, type PermissionRequest, type PermissionDenial, type BatchedCall, type ToolBatch, type Todo, type ReplyDisplay, type TaskOwner, type TaskStartArgs, type ToolCallArgs, type Usage, type CommandRun, type CommandRunAnswer } from './session/session.js'
287
+ export type { Context } from './session/context/context.js'
288
+ export type { Turn } from './session/context/turn/turn.js'
289
+ export type { Message, MessageType } from './session/context/turn/message/message.js'
385
290
  export { Prompt } from './session/context/turn/message/prompt.js'
386
291
  export { Note } from './session/context/turn/message/note.js'
387
292
  export { Reply } from './session/context/turn/message/reply.js'
388
293
  export { ToolCall } from './session/context/turn/message/tool-call.js'
389
294
  export { ToolResult } from './session/context/turn/message/tool-result.js'
390
295
  export { Skill } from './session/context/turn/message/skill.js'
391
- export { Document } from './session/context/turn/message/document.js'
296
+ export { InstructionFile } from './session/context/turn/message/instruction-file.js'
392
297
  export { Notice } from './session/context/turn/message/notice.js'
393
- export { Channel, Person, Schedule, Sdk, type Sender, type SenderType } from './session/context/turn/message/sender.js'
394
- export { GoalChange, type Goal } from './session/goal/goal.js'
395
- export { Task, TaskEnd, TaskStart } from './session/goal/task.js'
298
+ export { Channel, Engine, Person, Schedule, Sdk, type Sender, type SenderType } from './session/context/turn/message/sender.js'
299
+ export type { Goal } from './session/goal/goal.js'
300
+ export { Task } from './session/goal/task.js'
396
301
  export { longestMs } from './runtime/deadline.js'
397
302
  export { notInstalled } from './runtime/dependencies.js'
398
303
  export { messageOf } from './utils/text.js'
package/src/records.ts CHANGED
@@ -259,7 +259,7 @@ function readKeys(keys: unknown): Steps {
259
259
  return { keys: commands }
260
260
  }
261
261
 
262
- export const coreVersion = '1.6.0'
262
+ export const coreVersion = '2.0.1'
263
263
 
264
264
  export function oldestCmodFor(steps: Steps): string {
265
265
  if (steps.permissions?.some((item) => item.startsWith('config:')) === true) return '1.6.0'
package/src/register.ts CHANGED
@@ -5,10 +5,11 @@ import type { Claude } from './runtime/claude.js'
5
5
  import type { RoutedEvent } from './runtime/hooks.js'
6
6
  import { cmodPluginName } from './runtime/dependencies.js'
7
7
  import { createLifecycle, readPlugin, type Lifecycle } from './runtime/lifecycle.js'
8
+ import { permissionRoutes, type PermissionRoutes } from './runtime/permission-check.js'
8
9
 
9
10
  let lifecycle: Lifecycle<object>
10
11
 
11
- let checksPermissions = false
12
+ let permissionCheck: PermissionRoutes | undefined
12
13
 
13
14
  let registered: ModDefinition<object> | undefined
14
15
 
@@ -70,8 +71,9 @@ async function startMod($: EngineInterface, eventInput: Frozen<Args<'session.sta
70
71
  send: (args) => $.session.send(args),
71
72
  },
72
73
  prompt: { submit: (args) => $.prompt.submit(args) },
74
+ turn: { abort: (args) => $.turn.abort(args) },
73
75
  model: { complete: (request, options) => $.model.complete(request, options) },
74
- command: { register: (command) => $.command.register(command) },
76
+ command: { register: (command) => $.command.register(command), list: () => $.command.list(), run: (args) => $.command.run(args) },
75
77
  tool: { register: (tool) => $.tool.register(tool), call: (input: ToolCallArgs) => $.tool.call(input) },
76
78
  agent: {
77
79
  list: () => $.agent.list(),
@@ -98,9 +100,9 @@ function routeCallToMod(_$: EngineInterface, eventInput: Frozen<Args<'cmod.call'
98
100
  }
99
101
 
100
102
  export function registerMod<State extends object, Declared extends Options>(addHook: On, definition: ModDefinition<State, string, Declared>, options: PluginOptions): void {
101
- checksPermissions = false
103
+ permissionCheck = undefined
102
104
  registered = definition as ModDefinition<object>
103
- lifecycle = createLifecycle(definition, () => checksPermissions, options)
105
+ lifecycle = createLifecycle(definition, () => permissionCheck, options)
104
106
  addHook('session.start', startMod)
105
107
  addHook('classic.Setup', routeToMod)
106
108
  addHook('classic.SessionStart', routeToMod)
@@ -149,10 +151,11 @@ export function registerMod<State extends object, Declared extends Options>(addH
149
151
  addHook('session.receive', routeToMod)
150
152
  addHook('agent.spawn', routeToMod)
151
153
  addHook('prompt.attachment', routeToMod)
154
+ addHook('turn.start', routeToMod)
152
155
  }
153
156
 
154
157
  export function registerPermissionCheck(addHook: On): void {
155
- checksPermissions = true
158
+ permissionCheck = permissionRoutes
156
159
  addHook('tool.check', routeToMod)
157
160
  addHook('classic.PermissionRequest', routeToMod)
158
161
  }