@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
package/src/testing.ts CHANGED
@@ -18,25 +18,30 @@ import type {
18
18
  UiSelectArgument,
19
19
  } from 'claude-code'
20
20
  import type { CommandReply } from './jobs/slash-command.js'
21
- import type { Hook, ModDefinition } from './mod.js'
21
+ import type { ModDefinition } from './mod.js'
22
22
  import type { Options, OptionValues } from './options.js'
23
23
  import { readSteps, storeFolder, type Steps } from './records.js'
24
24
  import type { Claude } from './runtime/claude.js'
25
25
  import { answerCall, cmodPluginName, notInstalled } from './runtime/dependencies.js'
26
- import { foldAnswers, installBefore } from './runtime/before.js'
26
+ import { foldBefore, installBefore } from './runtime/before.js'
27
+ import { permissionRoutes } from './runtime/permission-check.js'
27
28
  import type { RoutedEvent } from './runtime/hooks.js'
29
+ import { keepClaudeCode, type ClaudeCode } from './testing/claude-code.js'
28
30
  import { createRouter } from './runtime/router.js'
29
31
  import { toolInputOf } from './runtime/tool-calls.js'
30
32
  import { createLifecycle } from './runtime/lifecycle.js'
31
33
  import { MissingOptions } from './runtime/options.js'
32
34
  import { conversationMethods } from './runtime/sessions.js'
33
35
  import type { ShownToast } from './runtime/toaster.js'
34
- import type { Message } from './session/context/turn/message/message.js'
36
+ import { Message } from './session/context/turn/message/message.js'
35
37
  import { Note } from './session/context/turn/message/note.js'
36
38
  import { Prompt } from './session/context/turn/message/prompt.js'
37
39
  import { Mod, Person } from './session/context/turn/message/sender.js'
38
40
  import type { SessionChange } from './session/conversation.js'
39
- import type { BeforeEvent } from './session/session.js'
41
+ import { TurnEnd, type Turn } from './session/context/turn/turn.js'
42
+ import { beforeEvents, processEvents, sessionEvents, type AnswerOf, type BeforeEvent, type BeforeName, type CommandRun, type CommandRunAnswer, type Placement, type ProcessAnswer, type ProcessAsked, type ProcessName, type ProcessPayload } from './session/session.js'
43
+ import { ContextEnd } from './session/context/context.js'
44
+ import { TaskStart } from './session/goal/task.js'
40
45
  import { calledAnswer, fakeClaude, type Fakes, type Shown as ShownByClaude, type TestCall } from './testing/fake-claude.js'
41
46
  import { elements, findElement, rowsOf } from './testing/fake-elements.js'
42
47
  import { fakeFiles } from './testing/fake-files.js'
@@ -64,18 +69,38 @@ export type TestOptions<State extends object, Declared extends Options = Options
64
69
  readonly sessions?: readonly FakeSession[]
65
70
  }
66
71
 
67
- type FilledField = 'session_id' | 'transcript_path' | 'cwd' | 'hook_event_name' | 'tool_use_id'
72
+ type Placed<Payload> = Omit<Payload, keyof Placement> & Partial<Placement>
68
73
 
69
- export type TestInput<H extends Hook> = Omit<ClassicHookInputs[H], FilledField> & Partial<Pick<ClassicHookInputs[H], FilledField & keyof ClassicHookInputs[H]>>
74
+ type MessageBefore = Exclude<BeforeName, 'TaskStart' | 'TurnEnd' | 'ContextEnd'>
75
+
76
+ type DraftOf<Name extends MessageBefore> = Omit<Extract<MessageDraft, { readonly type: (typeof sessionEvents)[Name] }>, 'type'>
77
+
78
+ export type Raise = {
79
+ readonly [Name in MessageBefore as `before${Name}`]: (message: DraftOf<Name>, options?: { readonly task?: string }) => Promise<AnswerOf<Name> | undefined>
80
+ } & {
81
+ beforeTaskStart(task: { readonly title: string; readonly agentType?: string; readonly model?: string }): Promise<AnswerOf<'TaskStart'> | undefined>
82
+ beforeTurnEnd(ending?: Pick<Turn, 'answer' | 'failure'>): Promise<AnswerOf<'TurnEnd'> | undefined>
83
+ beforeContextEnd(): Promise<AnswerOf<'ContextEnd'> | undefined>
84
+ } & {
85
+ readonly [Name in ProcessName as `on${Name}`]: (payload: Placed<ProcessPayload[Name]>) => Promise<void>
86
+ } & {
87
+ readonly [Name in keyof ProcessAnswer as `before${Name}`]: (payload: Placed<ProcessAsked[Name]>) => Promise<ProcessAnswer[Name] | undefined>
88
+ } & {
89
+ onRun(run: Placed<CommandRun>): Promise<void>
90
+ beforeRun(run: Placed<CommandRun>): Promise<CommandRunAnswer | undefined>
91
+ }
92
+
93
+ type FiredEvent = 'ui.render' | 'ui.scroll' | 'ui.close' | 'cmod.call' | 'tool.check' | 'prompt.context'
70
94
 
71
95
  export type TestedMod<State extends object> = {
72
96
  start(): Promise<void>
73
- fire<H extends Hook>(hook: H, input: TestInput<H>, below?: EventResult<`classic.${H}`>): Promise<EventResult<`classic.${H}`>>
74
- fire<N extends RoutedEvent>(event: N, input: Args<N>, below?: EventResult<N>): Promise<EventResult<N>>
97
+ readonly raise: Raise
98
+ fire<N extends FiredEvent>(event: N, input: Args<N>, below?: EventResult<N>): Promise<EventResult<N>>
75
99
  settle(): Promise<void>
76
100
  add(message: MessageDraft, options?: { readonly task?: string }): Promise<Message[]>
77
- endTurn(): Promise<void>
101
+ endTurn(ending?: Pick<Turn, 'answer' | 'failure'>): Promise<void>
78
102
  compact(): Promise<void>
103
+ startSession(start: { readonly source: 'startup' | 'resume' | 'clear' | 'fork'; readonly id?: string }): Promise<void>
79
104
  startTask(task: { readonly title: string; readonly agentType?: string; readonly model?: string; readonly openedBy?: string; readonly parent?: string }): Promise<string>
80
105
  lines(paneId: string): Promise<string[]>
81
106
  lines<P extends ComponentPlace>(place: P, props: Omit<PlaceProps<P>, 'Default'>, requestId?: string): Promise<string[]>
@@ -97,7 +122,7 @@ const defaultRows = 24
97
122
 
98
123
  const presentation: CommandPresentation = { isFullscreen: false, columns: defaultColumns }
99
124
 
100
- const toolUseEvents: readonly string[] = ['PreToolUse', 'PostToolUse', 'PostToolUseFailure', 'PermissionDenied'] satisfies readonly Hook[]
125
+ const toolUseEvents: readonly string[] = ['PreToolUse', 'PostToolUse', 'PostToolUseFailure', 'PermissionDenied']
101
126
 
102
127
  export function testMod<State extends object, Declared extends Options = Options>(definition: ModDefinition<State, string, Declared>, options: TestOptions<State, Declared> = {}): TestedMod<State> {
103
128
  installJsx()
@@ -117,6 +142,7 @@ export function testMod<State extends object, Declared extends Options = Options
117
142
  const conversations = fakeSessions({
118
143
  callTool: (args: Parameters<Claude["tool"]["call"]>[0]) => fake.claude.tool.call(args),
119
144
  project: () => projectRoot,
145
+ cwd: () => cwd,
120
146
  given: options.sessions ?? [],
121
147
  push: (mod, session, change) => {
122
148
  if (mod !== name) return
@@ -149,7 +175,7 @@ export function testMod<State extends object, Declared extends Options = Options
149
175
  const starting = options.state as Record<string, object> | undefined
150
176
  const declared = Object.entries(definition.state ?? {}) as [string, object][]
151
177
  const state = Object.fromEntries(declared.map(([lifetime, values]) => [lifetime, { ...values, ...starting?.[lifetime] }])) as State
152
- const lifecycle = createLifecycle<State, Declared>({ ...definition, state }, () => true, (options.options ?? {}) as PluginOptions, false)
178
+ const lifecycle = createLifecycle<State, Declared>({ ...definition, state }, () => permissionRoutes,(options.options ?? {}) as PluginOptions, false)
153
179
  let started: Promise<void> | undefined
154
180
 
155
181
  const start = async () => {
@@ -187,7 +213,7 @@ export function testMod<State extends object, Declared extends Options = Options
187
213
  hooks: {
188
214
  place: async () => conversations.place(),
189
215
  wants: async (event) => conversations.wants(name, event),
190
- decide: (event, change) => foldAnswers(event, change, [(latest) => askMod(event, latest)], (error) => fake.claude.ui.log(`cmod: passed the ${event} on without ${name}'s answer: ${messageOf(error)}`, { to: 'debug' })),
216
+ decide: (event, change) => foldBefore(event, change, [(latest) => askMod(event, latest)], (error) => fake.claude.ui.log(`cmod: passed the ${event} on without ${name}'s answer: ${messageOf(error)}`, { to: 'debug' })),
191
217
  },
192
218
  })
193
219
 
@@ -239,9 +265,44 @@ export function testMod<State extends object, Declared extends Options = Options
239
265
  const transcript = `/test/transcripts/${sessionId}.jsonl`
240
266
  const filled = { session_id: sessionId, transcript_path: transcript, cwd, hook_event_name: event, ...toolUse, ...input }
241
267
  if (event === 'SessionStart' && !('transcript_path' in input)) return files.write(transcript, '').then(() => route('classic.SessionStart', filled, below))
242
- if (event !== 'PreToolUse') return route(`classic.${event as Exclude<Hook, 'PreToolUse'>}`, filled, below)
268
+ if (event !== 'PreToolUse') return route(`classic.${event}` as RoutedEvent, filled, below)
243
269
  return firePreToolUse(filled as ClassicHookInputs['PreToolUse'], below as { deny?: string } | undefined)
244
- }) as TestedMod<State>['fire']
270
+ }) as ClaudeCode['fire']
271
+
272
+ const asked = async (event: BeforeEvent, change: SessionChange) => {
273
+ await start()
274
+ return (await askMod(event, change)) ?? undefined
275
+ }
276
+
277
+ const raise = Object.fromEntries([
278
+ ...beforeEvents
279
+ .filter((named) => named !== 'TaskStart' && named !== 'TurnEnd' && named !== 'ContextEnd')
280
+ .map((named) => [`before${named}`, async (draft: object, placed?: { readonly task?: string }) => {
281
+ await start()
282
+ return asked(sessionEvents[named], { type: Message, message: conversations.draft({ ...draft, type: sessionEvents[named] } as MessageDraft, placed?.task) })
283
+ }]),
284
+ ['beforeTaskStart', async ({ title, agentType = 'general-purpose', model }: { readonly title: string; readonly agentType?: string; readonly model?: string }) => {
285
+ await start()
286
+ return asked(TaskStart, { type: TaskStart, task: { id: '', title, agentType, openedBy: '', openedAt: new Date().toISOString(), context: conversations.place().context, ...(model === undefined ? {} : { model }) } })
287
+ }],
288
+ ['beforeTurnEnd', async (ending: Pick<Turn, 'answer' | 'failure'> = {}) => {
289
+ await start()
290
+ const { turn } = conversations.place()
291
+ if (turn === undefined) throw new Error(`${name} has no turn open to end. Open one with tested.add({ type: Prompt, text: '…' }).`)
292
+ return asked(TurnEnd, { type: TurnEnd, turn: { ...turn, ...ending, closedAt: new Date().toISOString() } })
293
+ }],
294
+ ['beforeContextEnd', async () => {
295
+ await start()
296
+ const { context, contextOpenedAt } = conversations.place()
297
+ return asked(ContextEnd, { type: ContextEnd, context: { number: context, openedAt: contextOpenedAt, closedAt: new Date().toISOString() } })
298
+ }],
299
+ ...[...Object.entries(processEvents).flatMap(([named, event]) => [`on${named}`, ...('before' in event ? [`before${named}`] : [])]), 'onRun', 'beforeRun'].map((method) => [method, async (payload: object) => {
300
+ await start()
301
+ const answer = await lifecycle.raise(method, { session: sessionId, cwd, ...payload })
302
+ await fake.settle()
303
+ return answer
304
+ }]),
305
+ ]) as Raise
245
306
 
246
307
  const firePreToolUse = async ({ tool_name, tool_input, tool_use_id, agent_id, agent_type }: ClassicHookInputs['PreToolUse'], below: { deny?: string } | undefined) => {
247
308
  await start()
@@ -269,22 +330,28 @@ export function testMod<State extends object, Declared extends Options = Options
269
330
  return value
270
331
  }
271
332
 
272
- return {
333
+ const tested: TestedMod<State> = {
273
334
  start,
335
+ raise,
274
336
  fire,
275
337
  settle: fake.settle,
276
338
  add: async (message, added) => {
277
339
  await start()
278
340
  return settled(conversations.add(message, added?.task))
279
341
  },
280
- endTurn: async () => {
342
+ endTurn: async (ending) => {
281
343
  await start()
282
- await settled(conversations.endTurn())
344
+ await settled(conversations.endTurn(ending === undefined ? undefined : { ...ending, ...(ending.failure === undefined ? {} : { reason: 'error' as const }) }))
283
345
  },
284
346
  compact: async () => {
285
347
  await start()
286
348
  await settled(conversations.compact())
287
349
  },
350
+ startSession: async ({ source, id }) => {
351
+ await start()
352
+ await fire('SessionStart', { source, ...(id === undefined ? {} : { session_id: id }) })
353
+ await fake.settle()
354
+ },
288
355
  startTask: async (task) => {
289
356
  await start()
290
357
  return settled(conversations.startTask(task))
@@ -353,7 +420,7 @@ export function testMod<State extends object, Declared extends Options = Options
353
420
  },
354
421
  get state() {
355
422
  const mod = lifecycle.mod
356
- if (mod === undefined) throw new Error(`${name} has not started. Await tested.start() or tested.fire(…) first.`)
423
+ if (mod === undefined) throw new Error(`${name} has not started. Await tested.start() first.`)
357
424
  return mod.state
358
425
  },
359
426
  calls: fake.calls,
@@ -366,6 +433,8 @@ export function testMod<State extends object, Declared extends Options = Options
366
433
  sent: conversations.sent,
367
434
  },
368
435
  }
436
+ keepClaudeCode(tested, { fire })
437
+ return tested
369
438
  }
370
439
 
371
440
  function fakeDependencies(caller: string, dependencies: NonNullable<TestOptions<object>['dependencies']>, conversations: FakeSessions): Claude['cmod']['call'] {
@@ -395,7 +464,7 @@ function plainOutput({ component, props }: Args<'ui.render'>): RenderElement {
395
464
  }
396
465
 
397
466
  function replyOf({ text, context }: CommandRunResult): CommandReply {
398
- return { ...(text === undefined ? {} : { text }), ...(context === undefined ? {} : { context: context.join('\n') }) }
467
+ return { ...(text === undefined ? {} : { text }), ...(context === undefined ? {} : { note: context.join('\n') }) }
399
468
  }
400
469
 
401
470
  async function modSteps(): Promise<Steps> {
@@ -0,0 +1,12 @@
1
+ import type { Args, ClassicHookInputs, EventResult } from 'claude-code';
2
+ import type { Hook, RoutedEvent } from '../runtime/hooks.js';
3
+ type FilledField = 'session_id' | 'transcript_path' | 'cwd' | 'hook_event_name' | 'tool_use_id';
4
+ export type HookInputOf<H extends Hook | 'PreToolUse'> = Omit<ClassicHookInputs[H], FilledField> & Partial<Pick<ClassicHookInputs[H], FilledField & keyof ClassicHookInputs[H]>>;
5
+ export type ClaudeCode = {
6
+ fire<H extends Hook | 'PreToolUse'>(hook: H, input: HookInputOf<H>, below?: EventResult<`classic.${H}`>): Promise<EventResult<`classic.${H}`>>;
7
+ fire<N extends RoutedEvent>(event: N, input: Args<N>, below?: EventResult<N>): Promise<EventResult<N>>;
8
+ };
9
+ export declare function keepClaudeCode(tested: object, driver: ClaudeCode): void;
10
+ export declare function claudeCodeOf(tested: object): ClaudeCode;
11
+ export {};
12
+ //# sourceMappingURL=claude-code.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-code.d.ts","sourceRoot":"","sources":["../src/testing/claude-code.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AACvE,OAAO,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AAE5D,KAAK,WAAW,GAAG,YAAY,GAAG,iBAAiB,GAAG,KAAK,GAAG,iBAAiB,GAAG,aAAa,CAAA;AAE/F,MAAM,MAAM,WAAW,CAAC,CAAC,SAAS,IAAI,GAAG,YAAY,IAAI,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE,WAAW,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE,WAAW,GAAG,MAAM,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;AAEhL,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,CAAC,CAAC,SAAS,IAAI,GAAG,YAAY,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,WAAW,CAAC,WAAW,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAA;IAC9I,IAAI,CAAC,CAAC,SAAS,WAAW,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAA;CACvG,CAAA;AAID,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI,CAEvE;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,CAIvD"}
@@ -0,0 +1,10 @@
1
+ const drivers = new WeakMap();
2
+ export function keepClaudeCode(tested, driver) {
3
+ drivers.set(tested, driver);
4
+ }
5
+ export function claudeCodeOf(tested) {
6
+ const driver = drivers.get(tested);
7
+ if (driver === undefined)
8
+ throw new Error('claudeCodeOf takes a mod testMod returned.');
9
+ return driver;
10
+ }
@@ -25,6 +25,10 @@ export type Fakes = {
25
25
  config: {
26
26
  list?: Claude['config']['list'];
27
27
  };
28
+ command: {
29
+ list?: Claude['command']['list'];
30
+ run?: Claude['command']['run'];
31
+ };
28
32
  ui: {
29
33
  ask?: Claude['ui']['ask'];
30
34
  open?: Claude['ui']['open'];
@@ -1 +1 @@
1
- {"version":3,"file":"fake-claude.d.ts","sourceRoot":"","sources":["../src/testing/fake-claude.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"fake-claude.d.ts","sourceRoot":"","sources":["../src/testing/fake-claude.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAS,MAAM,aAAa,CAAA;AAErD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAA;AAIlD,MAAM,MAAM,QAAQ,GAAG;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,IAAI,EAAE,SAAS,OAAO,EAAE,CAAA;CAClC,CAAA;AAED,MAAM,MAAM,KAAK,GAAG;IAClB,OAAO,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC,KAAK,CAAC,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,CAAA;KAAE,CAAA;IAC/E,EAAE,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAA;KAAE,CAAA;IAC7J,IAAI,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAA;KAAE,CAAA;IACzC,QAAQ,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,CAAA;KAAE,CAAA;IAC/C,MAAM,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAA;KAAE,CAAA;IAC3C,OAAO,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC,KAAK,CAAC,CAAA;KAAE,CAAA;IAC7E,EAAE,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,CAAA;KAAE,CAAA;IAC3J,OAAO,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC,UAAU,CAAC,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC,QAAQ,CAAC,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAA;KAAE,CAAA;IAC7H,MAAM,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,QAAQ,CAAC,CAAA;KAAE,CAAA;IAC/C,KAAK,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC,UAAU,CAAC,CAAA;KAAE,CAAA;IACjD,KAAK,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAA;KAAE,CAAA;IAC3E,KAAK,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAA;KAAE,CAAA;IAC7E,IAAI,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAA;KAAE,CAAA;IACvC,IAAI,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAA;KAAE,CAAA;CACxC,CAAA;AAED,MAAM,MAAM,aAAa,GAAG;IAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAA;AAEnG,MAAM,MAAM,KAAK,GAAG;IAClB,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,CAAA;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,CAAA;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAA;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,CAAA;IACxB,QAAQ,CAAC,QAAQ,EAAE,CAAC,MAAM,GAAG,SAAS,CAAC,EAAE,CAAA;IACzC,QAAQ,CAAC,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IAC/B,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;IAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,CAAA;IACxB,QAAQ,CAAC,SAAS,EAAE,aAAa,EAAE,CAAA;CACpC,CAAA;AAED,MAAM,MAAM,UAAU,GAAG;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,KAAK,EAAE,QAAQ,EAAE,CAAA;IAC1B,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAA;IACrB,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAA;IACrB,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACpC,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACxB,CAAA;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,CAAC,WAAW,CAAC,GAAG,OAAO,CAGtF;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,UAAU,CA2K/F"}
@@ -8,7 +8,7 @@ export function calledAnswer(caller, answer) {
8
8
  }
9
9
  export function fakeClaude(plugin) {
10
10
  const calls = [];
11
- const fakes = { process: {}, fs: {}, http: {}, settings: {}, config: {}, ui: {}, session: {}, prompt: {}, model: {}, agent: {}, clock: {}, cmod: {}, tool: {} };
11
+ const fakes = { process: {}, fs: {}, http: {}, settings: {}, config: {}, command: {}, ui: {}, session: {}, prompt: {}, model: {}, agent: {}, clock: {}, cmod: {}, tool: {} };
12
12
  const emptyDisk = fakeFiles({});
13
13
  const shown = { notes: [], prompts: [], logs: [], debug: [], statuses: [], openPanes: new Set(), commands: [], tools: [], schedules: [] };
14
14
  const unplacedPanes = new Set();
@@ -145,12 +145,15 @@ export function fakeClaude(plugin) {
145
145
  send: rejected('session.send', () => fakes.session.send ?? (async () => ({ isDelivered: true }))),
146
146
  },
147
147
  prompt: { submit: rejected('prompt.submit', () => fakes.prompt.submit ?? submitPrompt) },
148
+ turn: { abort: rejected('turn.abort', () => async () => undefined) },
148
149
  model: { complete: rejected('model.complete', () => fakes.model.complete) },
149
150
  command: {
150
151
  register: async (command) => {
151
152
  shown.commands.push(command.name);
152
153
  return { command: command.name };
153
154
  },
155
+ list: rejected('command.list', () => fakes.command.list ?? (async () => shown.commands.map((name) => ({ name, description: '', source: 'plugin', plugin: plugin.name })))),
156
+ run: rejected('command.run', () => fakes.command.run ?? (async () => ({}))),
154
157
  },
155
158
  tool: {
156
159
  register: async (tool) => {
@@ -1,4 +1,4 @@
1
- import { Document } from '../session/context/turn/message/document.js';
1
+ import { InstructionFile } from '../session/context/turn/message/instruction-file.js';
2
2
  import { Message } from '../session/context/turn/message/message.js';
3
3
  import { Note } from '../session/context/turn/message/note.js';
4
4
  import { Notice } from '../session/context/turn/message/notice.js';
@@ -8,7 +8,7 @@ import { type Sender } from '../session/context/turn/message/sender.js';
8
8
  import { Skill } from '../session/context/turn/message/skill.js';
9
9
  import { ToolCall } from '../session/context/turn/message/tool-call.js';
10
10
  import { ToolResult } from '../session/context/turn/message/tool-result.js';
11
- import { type SessionChange, type SessionData } from '../session/conversation.js';
11
+ import { type SessionChange, type SessionData, type TurnEnding } from '../session/conversation.js';
12
12
  import type { Place } from '../runtime/before.js';
13
13
  import type { Claude } from '../runtime/claude.js';
14
14
  export type MessageDraft = {
@@ -30,14 +30,14 @@ export type MessageDraft = {
30
30
  } | {
31
31
  readonly type: typeof ToolResult;
32
32
  readonly callId: string;
33
- readonly text: string;
33
+ readonly output: string;
34
34
  readonly isError?: boolean;
35
35
  } | {
36
36
  readonly type: typeof Skill;
37
37
  readonly name: string;
38
38
  readonly text: string;
39
39
  } | {
40
- readonly type: typeof Document;
40
+ readonly type: typeof InstructionFile;
41
41
  readonly path: string;
42
42
  readonly text: string;
43
43
  } | {
@@ -52,9 +52,10 @@ export type FakeSession = Partial<Omit<SessionData, 'id'>> & {
52
52
  export type FakeSessions = {
53
53
  answer(caller: string, method: string, input: unknown): unknown;
54
54
  add(draft: MessageDraft, task?: string): Message[];
55
+ draft(draft: MessageDraft, task?: string): Message;
55
56
  place(): Place;
56
57
  wants(mod: string, event: string): boolean;
57
- endTurn(): void;
58
+ endTurn(ending?: TurnEnding): void;
58
59
  compact(): void;
59
60
  startTask(task: {
60
61
  readonly title: string;
@@ -72,8 +73,9 @@ export type FakeSessions = {
72
73
  readonly as?: string;
73
74
  }[];
74
75
  };
75
- export declare function fakeSessions({ project, given, push, callTool }: {
76
+ export declare function fakeSessions({ project, cwd, given, push, callTool }: {
76
77
  readonly project: () => string;
78
+ readonly cwd: () => string;
77
79
  readonly given: readonly FakeSession[];
78
80
  readonly push: (mod: string, session: string, change: SessionChange) => void;
79
81
  readonly callTool: Claude['tool']['call'];
@@ -1 +1 @@
1
- {"version":3,"file":"fake-sessions.d.ts","sourceRoot":"","sources":["../src/testing/fake-sessions.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"fake-sessions.d.ts","sourceRoot":"","sources":["../src/testing/fake-sessions.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { isObject } from '../records.js';
2
- import { Document } from '../session/context/turn/message/document.js';
3
- import { Message, searchText, skillPrefix } from '../session/context/turn/message/message.js';
2
+ import { InstructionFile } from '../session/context/turn/message/instruction-file.js';
3
+ import { Message, messagesOf, noFiles, searchText, skillPrefix } from '../session/context/turn/message/message.js';
4
4
  import { Note } from '../session/context/turn/message/note.js';
5
5
  import { Notice } from '../session/context/turn/message/notice.js';
6
6
  import { Prompt } from '../session/context/turn/message/prompt.js';
@@ -15,7 +15,7 @@ import { createConversation, emptyConversation, searchLimit } from '../session/c
15
15
  import { conversationMethods, everySession, isHeardBy, resultOf } from '../runtime/sessions.js';
16
16
  import { receivedMatcher } from '../utils/matcher.js';
17
17
  import { firstLine, messageOf } from '../utils/text.js';
18
- export function fakeSessions({ project, given, push, callTool }) {
18
+ export function fakeSessions({ project, cwd, given, push, callTool }) {
19
19
  const kept = new Map();
20
20
  const heard = new Map();
21
21
  const watches = new Map();
@@ -49,7 +49,7 @@ export function fakeSessions({ project, given, push, callTool }) {
49
49
  };
50
50
  const add = (session, draft, task) => {
51
51
  const before = session.messages.length;
52
- record(session, session.conversation.add(rowOf(draft, `message-${(ids += 1)}`, now()), task));
52
+ record(session, session.conversation.add(rowOf(draft, `message-${(ids += 1)}`, now(), cwd()), task));
53
53
  return session.messages.slice(before);
54
54
  };
55
55
  for (const each of given) {
@@ -67,8 +67,8 @@ export function fakeSessions({ project, given, push, callTool }) {
67
67
  };
68
68
  const currentSession = () => sessionOf(current);
69
69
  const place = () => {
70
- const { session, context, contextOpenedAt, turn, tasks, taskTurns } = currentSession().conversation.state;
71
- return { session, context, contextOpenedAt, ...(turn === undefined ? {} : { turn }), tasks, taskTurns };
70
+ const { session, context, contextOpenedAt, turn, tasks, taskTurns, openCalls } = currentSession().conversation.state;
71
+ return { session, context, contextOpenedAt, ...(turn === undefined ? {} : { turn }), tasks, taskTurns, ...(openCalls === undefined ? {} : { openCalls }) };
72
72
  };
73
73
  const taskOf = (session, id) => {
74
74
  const task = session.tasks.get(id);
@@ -99,9 +99,9 @@ export function fakeSessions({ project, given, push, callTool }) {
99
99
  const task = request['task'];
100
100
  if (request['session'] !== undefined && message.session !== request['session'])
101
101
  return false;
102
- if (typeof task === 'string' && (message.task === undefined || !isUnder(session, message.task, task) || (request['isGoal'] === true && message.task === task)))
102
+ if (request['isAgent'] === true && message.task !== task)
103
103
  return false;
104
- if (task === undefined && request['isGoal'] === true && message.task === undefined)
104
+ if (typeof task === 'string' && (message.task === undefined || !isUnder(session, message.task, task)))
105
105
  return false;
106
106
  return (request['turn'] === undefined || message.turn === request['turn']) && (request['context'] === undefined || message.context === request['context']);
107
107
  };
@@ -112,7 +112,7 @@ export function fakeSessions({ project, given, push, callTool }) {
112
112
  .toSorted((first, second) => second.at.localeCompare(first.at));
113
113
  const before = isObject(request['before']) ? request['before'] : undefined;
114
114
  const start = before === undefined ? 0 : found.findIndex((message) => message.session === before['session'] && message.id === before['id']) + 1;
115
- return found.slice(start, start + (typeof request['limit'] === 'number' ? request['limit'] : searchLimit));
115
+ return found.slice(start, start + searchLimit);
116
116
  },
117
117
  [conversationMethods.messages](request) {
118
118
  const session = sessionOf(String(request['session']));
@@ -161,24 +161,30 @@ export function fakeSessions({ project, given, push, callTool }) {
161
161
  const task = typeof request['task'] === 'string' ? request['task'] : undefined;
162
162
  const isLive = task === undefined ? session.data.isRunning : session.data.isRunning && taskOf(session, task).closedAt === undefined;
163
163
  if (action === 'usage')
164
- return { model: task === undefined ? session.data.model : (taskOf(session, task).model ?? session.data.model), context: {} };
165
- if (action === 'clients')
164
+ return { model: task === undefined ? session.data.model : (taskOf(session, task).model ?? session.data.model), contextWindow: {} };
165
+ if (action === 'surfaces')
166
166
  return isLive ? ['terminal'] : [];
167
167
  if (!isLive)
168
168
  throw new Error(`session ${task ?? session.data.id} has ended`);
169
+ if (action === 'abort') {
170
+ const open = task === undefined ? session.conversation.state.turn : session.conversation.state.taskTurns[task];
171
+ if (open?.prompt.id !== input['turn'])
172
+ throw new Error(`turn ${String(input['turn'])} has ended, so there is nothing to abort.`);
173
+ return null;
174
+ }
169
175
  if (action === 'send') {
170
176
  sent.push({ session: session.data.id, ...(task === undefined ? {} : { task }), type: String(input['type']), text: String(input['text']), ...(typeof input['as'] === 'string' ? { as: input['as'] } : {}) });
171
177
  return null;
172
178
  }
173
179
  if (action === 'startTask') {
174
180
  const id = `task-${(ids += 1)}`;
175
- const data = { id, title: typeof input['name'] === 'string' ? input['name'] : '', agentType: typeof input['agentType'] === 'string' ? input['agentType'] : 'general-purpose', openedBy: '', openedAt: now(), ...(typeof input['model'] === 'string' ? { model: input['model'] } : {}) };
181
+ const data = { id, title: typeof input['title'] === 'string' ? input['title'] : '', agentType: typeof input['agentType'] === 'string' ? input['agentType'] : 'general-purpose', openedBy: '', openedAt: now(), ...(typeof input['model'] === 'string' ? { model: input['model'] } : {}) };
176
182
  record(session, session.conversation.startTask(data));
177
183
  return data;
178
184
  }
179
185
  if (session.data.id === current)
180
- return resultOf(place(), await callTool({ ...input['input'], tool: String(input['name']) }));
181
- return { id: '', type: ToolResult, at: now(), session: session.data.id, context: session.conversation.state.context, callId: '', text: '', isError: false };
186
+ return resultOf(place(), { name: String(input['name']), input: input['input'], cwd: project() }, await callTool({ ...input['input'], tool: String(input['name']) }));
187
+ return { id: '', type: ToolResult, at: now(), session: session.data.id, context: session.conversation.state.context, callId: '', name: '', input: {}, cwd: project(), files: noFiles, output: '', isError: false };
182
188
  },
183
189
  [conversationMethods.subscribe](request, caller) {
184
190
  const list = Array.isArray(request['subscriptions']) ? request['subscriptions'] : [];
@@ -201,11 +207,20 @@ export function fakeSessions({ project, given, push, callTool }) {
201
207
  }
202
208
  },
203
209
  add: (draft, task) => add(currentSession(), draft, task),
210
+ draft(draft, task) {
211
+ const where = place();
212
+ const [unplaced] = messagesOf(rowOf(draft, `message-${(ids += 1)}`, now(), cwd()), task !== undefined);
213
+ if (unplaced === undefined)
214
+ throw new Error(`A ${draft.type} draft makes no message.`);
215
+ const call = unplaced.type === ToolResult ? where.openCalls?.[unplaced.callId] : undefined;
216
+ const turn = task === undefined ? where.turn : where.taskTurns[task];
217
+ return { ...unplaced, ...call, session: where.session, context: task === undefined ? where.context : (where.tasks[task]?.context ?? where.context), ...(turn === undefined ? {} : { turn: turn.prompt.id }), ...(task === undefined ? {} : { task }) };
218
+ },
204
219
  place,
205
220
  wants: (mod, event) => [current, everySession].some((target) => (watches.get(mod)?.get(target) ?? []).includes(event)),
206
- endTurn() {
221
+ endTurn(ending = {}) {
207
222
  const session = currentSession();
208
- record(session, session.conversation.add({ id: `turn-end-${(ids += 1)}`, at: now(), type: 'system', name: 'turn_duration', isMeta: false, isSummary: false, content: [] }));
223
+ record(session, session.conversation.endTurn(now(), { reason: 'answer', ...ending }));
209
224
  },
210
225
  compact() {
211
226
  const session = currentSession();
@@ -227,7 +242,7 @@ export function fakeSessions({ project, given, push, callTool }) {
227
242
  sent,
228
243
  };
229
244
  }
230
- function rowOf(draft, id, at) {
245
+ function rowOf(draft, id, at, cwd) {
231
246
  const base = { id, at, isMeta: false, isSummary: false };
232
247
  const text = (value) => [{ type: 'text', text: value }];
233
248
  const origin = (from) => (from === undefined || from.type === Person ? { kind: 'human' } : from.type === Mod ? { kind: 'plugin', name: from.name, ...(from.as === Person ? { asUser: true } : {}) } : from.type === 'session' ? { kind: 'peer' } : from.type === Task ? { kind: 'task-notification' } : { kind: from.type === Schedule ? 'scheduled-trigger' : from.type, ...(from.name === undefined ? {} : { server: from.name }) });
@@ -238,12 +253,12 @@ function rowOf(draft, id, at) {
238
253
  if (draft.type === Reply)
239
254
  return { ...base, type: 'assistant', content: text(draft.text) };
240
255
  if (draft.type === ToolCall)
241
- return { ...base, type: 'assistant', content: [{ type: 'tool_use', id: draft.callId ?? `toolu_${id}`, name: draft.name, input: draft.input ?? {} }], cwd: '/test/project' };
256
+ return { ...base, type: 'assistant', content: [{ type: 'tool_use', id: draft.callId ?? `toolu_${id}`, name: draft.name, input: draft.input ?? {} }], cwd };
242
257
  if (draft.type === ToolResult)
243
- return { ...base, type: 'user', content: [{ type: 'tool_result', tool_use_id: draft.callId, content: draft.text, ...(draft.isError === true ? { is_error: true } : {}) }] };
258
+ return { ...base, type: 'user', content: [{ type: 'tool_result', tool_use_id: draft.callId, content: draft.output, ...(draft.isError === true ? { is_error: true } : {}) }] };
244
259
  if (draft.type === Skill)
245
260
  return { ...base, type: 'user', isMeta: true, content: text(`${skillPrefix} /skills/${draft.name}\n\n${draft.text}`) };
246
- if (draft.type === Document)
261
+ if (draft.type === InstructionFile)
247
262
  return { ...base, type: 'attachment', name: 'nested_memory', content: text(draft.text), path: draft.path };
248
263
  return { ...base, type: 'system', name: 'informational', content: text(draft.text) };
249
264
  }
package/testing.d.ts CHANGED
@@ -1,10 +1,11 @@
1
- import type { Args, ClassicHookInputs, CmodDependencies, EventResult, UiInputArgument } from 'claude-code';
1
+ import type { Args, CmodDependencies, EventResult, UiInputArgument } from 'claude-code';
2
2
  import type { CommandReply } from './jobs/slash-command.js';
3
- import type { Hook, ModDefinition } from './mod.js';
3
+ import type { ModDefinition } from './mod.js';
4
4
  import type { Options, OptionValues } from './options.js';
5
- import type { RoutedEvent } from './runtime/hooks.js';
6
5
  import type { ShownToast } from './runtime/toaster.js';
7
- import type { Message } from './session/context/turn/message/message.js';
6
+ import { Message } from './session/context/turn/message/message.js';
7
+ import { type Turn } from './session/context/turn/turn.js';
8
+ import { sessionEvents, type AnswerOf, type BeforeName, type CommandRun, type CommandRunAnswer, type Placement, type ProcessAnswer, type ProcessAsked, type ProcessName, type ProcessPayload } from './session/session.js';
8
9
  import { type Fakes, type Shown as ShownByClaude, type TestCall } from './testing/fake-claude.js';
9
10
  import { type FakeSession, type FakeSessions, type MessageDraft } from './testing/fake-sessions.js';
10
11
  import { type ComponentPlace, type PlaceProps } from './ui/places.js';
@@ -32,18 +33,46 @@ export type TestOptions<State extends object, Declared extends Options = Options
32
33
  readonly links?: Readonly<Record<string, string>>;
33
34
  readonly sessions?: readonly FakeSession[];
34
35
  };
35
- type FilledField = 'session_id' | 'transcript_path' | 'cwd' | 'hook_event_name' | 'tool_use_id';
36
- export type TestInput<H extends Hook> = Omit<ClassicHookInputs[H], FilledField> & Partial<Pick<ClassicHookInputs[H], FilledField & keyof ClassicHookInputs[H]>>;
36
+ type Placed<Payload> = Omit<Payload, keyof Placement> & Partial<Placement>;
37
+ type MessageBefore = Exclude<BeforeName, 'TaskStart' | 'TurnEnd' | 'ContextEnd'>;
38
+ type DraftOf<Name extends MessageBefore> = Omit<Extract<MessageDraft, {
39
+ readonly type: (typeof sessionEvents)[Name];
40
+ }>, 'type'>;
41
+ export type Raise = {
42
+ readonly [Name in MessageBefore as `before${Name}`]: (message: DraftOf<Name>, options?: {
43
+ readonly task?: string;
44
+ }) => Promise<AnswerOf<Name> | undefined>;
45
+ } & {
46
+ beforeTaskStart(task: {
47
+ readonly title: string;
48
+ readonly agentType?: string;
49
+ readonly model?: string;
50
+ }): Promise<AnswerOf<'TaskStart'> | undefined>;
51
+ beforeTurnEnd(ending?: Pick<Turn, 'answer' | 'failure'>): Promise<AnswerOf<'TurnEnd'> | undefined>;
52
+ beforeContextEnd(): Promise<AnswerOf<'ContextEnd'> | undefined>;
53
+ } & {
54
+ readonly [Name in ProcessName as `on${Name}`]: (payload: Placed<ProcessPayload[Name]>) => Promise<void>;
55
+ } & {
56
+ readonly [Name in keyof ProcessAnswer as `before${Name}`]: (payload: Placed<ProcessAsked[Name]>) => Promise<ProcessAnswer[Name] | undefined>;
57
+ } & {
58
+ onRun(run: Placed<CommandRun>): Promise<void>;
59
+ beforeRun(run: Placed<CommandRun>): Promise<CommandRunAnswer | undefined>;
60
+ };
61
+ type FiredEvent = 'ui.render' | 'ui.scroll' | 'ui.close' | 'cmod.call' | 'tool.check' | 'prompt.context';
37
62
  export type TestedMod<State extends object> = {
38
63
  start(): Promise<void>;
39
- fire<H extends Hook>(hook: H, input: TestInput<H>, below?: EventResult<`classic.${H}`>): Promise<EventResult<`classic.${H}`>>;
40
- fire<N extends RoutedEvent>(event: N, input: Args<N>, below?: EventResult<N>): Promise<EventResult<N>>;
64
+ readonly raise: Raise;
65
+ fire<N extends FiredEvent>(event: N, input: Args<N>, below?: EventResult<N>): Promise<EventResult<N>>;
41
66
  settle(): Promise<void>;
42
67
  add(message: MessageDraft, options?: {
43
68
  readonly task?: string;
44
69
  }): Promise<Message[]>;
45
- endTurn(): Promise<void>;
70
+ endTurn(ending?: Pick<Turn, 'answer' | 'failure'>): Promise<void>;
46
71
  compact(): Promise<void>;
72
+ startSession(start: {
73
+ readonly source: 'startup' | 'resume' | 'clear' | 'fork';
74
+ readonly id?: string;
75
+ }): Promise<void>;
47
76
  startTask(task: {
48
77
  readonly title: string;
49
78
  readonly agentType?: string;
package/testing.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["src/testing.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["src/testing.ts"],"names":[],"mappings":"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"}