@cmodjs/core 1.5.1 → 2.0.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.
- package/docs/commands.md +5 -5
- package/docs/index.md +12 -11
- package/docs/jobs.md +12 -16
- package/docs/mod.md +117 -39
- package/docs/permissions.md +17 -21
- package/docs/session.md +171 -82
- package/docs/state.md +5 -5
- package/docs/testing.md +57 -41
- package/docs/ui.md +9 -9
- package/jobs/permissions/decide-permission.d.ts.map +1 -1
- package/jobs/permissions/decide-permission.js +1 -1
- package/jobs/prompt.d.ts +1 -3
- package/jobs/prompt.d.ts.map +1 -1
- package/jobs/prompt.js +2 -21
- package/jobs/slash-command.d.ts +1 -1
- package/jobs/slash-command.d.ts.map +1 -1
- package/jobs/slash-command.js +1 -1
- package/jobs/status-line.d.ts +0 -1
- package/jobs/status-line.d.ts.map +1 -1
- package/jobs/status-line.js +3 -4
- package/mod.d.ts +53 -105
- package/mod.d.ts.map +1 -1
- package/mod.js +18 -80
- package/package.json +1 -1
- package/records.d.ts +3 -1
- package/records.d.ts.map +1 -1
- package/records.js +14 -5
- package/register.d.ts.map +1 -1
- package/register.js +3 -1
- package/runtime/before.d.ts +5 -1
- package/runtime/before.d.ts.map +1 -1
- package/runtime/before.js +81 -39
- package/runtime/claude.d.ts +6 -1
- package/runtime/claude.d.ts.map +1 -1
- package/runtime/conversations.d.ts.map +1 -1
- package/runtime/conversations.js +45 -26
- package/runtime/deadline.d.ts +17 -0
- package/runtime/deadline.d.ts.map +1 -1
- package/runtime/deadline.js +34 -0
- package/runtime/dependencies.d.ts +2 -0
- package/runtime/dependencies.d.ts.map +1 -1
- package/runtime/dependencies.js +12 -0
- package/runtime/grants.d.ts +1 -1
- package/runtime/grants.d.ts.map +1 -1
- package/runtime/grants.js +19 -12
- package/runtime/hooks.d.ts +28 -11
- package/runtime/hooks.d.ts.map +1 -1
- package/runtime/hooks.js +20 -123
- package/runtime/lifecycle.d.ts +2 -1
- package/runtime/lifecycle.d.ts.map +1 -1
- package/runtime/lifecycle.js +67 -50
- package/runtime/sessions.d.ts +31 -5
- package/runtime/sessions.d.ts.map +1 -1
- package/runtime/sessions.js +342 -81
- package/runtime/tool-calls.d.ts +0 -1
- package/runtime/tool-calls.d.ts.map +1 -1
- package/runtime/tool-calls.js +0 -19
- package/session/context/turn/message/instruction-file.d.ts +9 -0
- package/session/context/turn/message/instruction-file.d.ts.map +1 -0
- package/session/context/turn/message/instruction-file.js +4 -0
- package/session/context/turn/message/message.d.ts +5 -4
- package/session/context/turn/message/message.d.ts.map +1 -1
- package/session/context/turn/message/message.js +7 -6
- package/session/context/turn/message/sender.d.ts +2 -1
- package/session/context/turn/message/sender.d.ts.map +1 -1
- package/session/context/turn/message/sender.js +4 -1
- package/session/context/turn/message/tool-call.d.ts +5 -0
- package/session/context/turn/message/tool-call.d.ts.map +1 -1
- package/session/context/turn/message/tool-result.d.ts +6 -1
- package/session/context/turn/message/tool-result.d.ts.map +1 -1
- package/session/context/turn/turn.d.ts +7 -0
- package/session/context/turn/turn.d.ts.map +1 -1
- package/session/conversation.d.ts +10 -3
- package/session/conversation.d.ts.map +1 -1
- package/session/conversation.js +14 -5
- package/session/goal/goal.d.ts +1 -1
- package/session/goal/goal.d.ts.map +1 -1
- package/session/goal/task.d.ts +2 -2
- package/session/goal/task.d.ts.map +1 -1
- package/session/session.d.ts +361 -26
- package/session/session.d.ts.map +1 -1
- package/session/session.js +40 -0
- package/src/jobs/permissions/decide-permission.ts +2 -1
- package/src/jobs/prompt.ts +3 -20
- package/src/jobs/slash-command.ts +2 -2
- package/src/jobs/status-line.ts +4 -7
- package/src/mod.ts +52 -147
- package/src/records.ts +15 -5
- package/src/register.ts +3 -1
- package/src/runtime/before.ts +90 -37
- package/src/runtime/claude.ts +5 -1
- package/src/runtime/conversations.ts +41 -25
- package/src/runtime/deadline.ts +38 -0
- package/src/runtime/dependencies.ts +12 -0
- package/src/runtime/grants.ts +15 -10
- package/src/runtime/hooks.ts +48 -116
- package/src/runtime/lifecycle.ts +66 -51
- package/src/runtime/sessions.ts +366 -90
- package/src/runtime/tool-calls.ts +0 -19
- package/src/session/context/turn/message/instruction-file.ts +13 -0
- package/src/session/context/turn/message/message.ts +11 -9
- package/src/session/context/turn/message/sender.ts +5 -2
- package/src/session/context/turn/message/tool-call.ts +3 -0
- package/src/session/context/turn/message/tool-result.ts +6 -1
- package/src/session/context/turn/turn.ts +4 -0
- package/src/session/conversation.ts +21 -8
- package/src/session/goal/goal.ts +1 -1
- package/src/session/goal/task.ts +2 -2
- package/src/session/session.ts +227 -24
- package/src/testing/claude-code.ts +23 -0
- package/src/testing/fake-claude.ts +5 -1
- package/src/testing/fake-sessions.ts +38 -24
- package/src/testing.ts +84 -16
- package/testing/claude-code.d.ts +12 -0
- package/testing/claude-code.d.ts.map +1 -0
- package/testing/claude-code.js +10 -0
- package/testing/fake-claude.d.ts +4 -0
- package/testing/fake-claude.d.ts.map +1 -1
- package/testing/fake-claude.js +4 -1
- package/testing/fake-sessions.d.ts +8 -6
- package/testing/fake-sessions.d.ts.map +1 -1
- package/testing/fake-sessions.js +35 -20
- package/testing.d.ts +38 -9
- package/testing.d.ts.map +1 -1
- package/testing.js +54 -5
- package/docs/hooks.md +0 -259
- package/session/context/turn/message/document.d.ts +0 -7
- package/session/context/turn/message/document.d.ts.map +0 -1
- package/session/context/turn/message/document.js +0 -1
- package/src/session/context/turn/message/document.ts +0 -8
package/src/testing.ts
CHANGED
|
@@ -18,25 +18,29 @@ import type {
|
|
|
18
18
|
UiSelectArgument,
|
|
19
19
|
} from 'claude-code'
|
|
20
20
|
import type { CommandReply } from './jobs/slash-command.js'
|
|
21
|
-
import type {
|
|
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
26
|
import { foldAnswers, installBefore } from './runtime/before.js'
|
|
27
27
|
import type { RoutedEvent } from './runtime/hooks.js'
|
|
28
|
+
import { keepClaudeCode, type ClaudeCode } from './testing/claude-code.js'
|
|
28
29
|
import { createRouter } from './runtime/router.js'
|
|
29
30
|
import { toolInputOf } from './runtime/tool-calls.js'
|
|
30
31
|
import { createLifecycle } from './runtime/lifecycle.js'
|
|
31
32
|
import { MissingOptions } from './runtime/options.js'
|
|
32
33
|
import { conversationMethods } from './runtime/sessions.js'
|
|
33
34
|
import type { ShownToast } from './runtime/toaster.js'
|
|
34
|
-
import
|
|
35
|
+
import { Message } from './session/context/turn/message/message.js'
|
|
35
36
|
import { Note } from './session/context/turn/message/note.js'
|
|
36
37
|
import { Prompt } from './session/context/turn/message/prompt.js'
|
|
37
38
|
import { Mod, Person } from './session/context/turn/message/sender.js'
|
|
38
39
|
import type { SessionChange } from './session/conversation.js'
|
|
39
|
-
import type
|
|
40
|
+
import { TurnEnd, type Turn } from './session/context/turn/turn.js'
|
|
41
|
+
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'
|
|
42
|
+
import { ContextEnd } from './session/context/context.js'
|
|
43
|
+
import { TaskStart } from './session/goal/task.js'
|
|
40
44
|
import { calledAnswer, fakeClaude, type Fakes, type Shown as ShownByClaude, type TestCall } from './testing/fake-claude.js'
|
|
41
45
|
import { elements, findElement, rowsOf } from './testing/fake-elements.js'
|
|
42
46
|
import { fakeFiles } from './testing/fake-files.js'
|
|
@@ -64,18 +68,38 @@ export type TestOptions<State extends object, Declared extends Options = Options
|
|
|
64
68
|
readonly sessions?: readonly FakeSession[]
|
|
65
69
|
}
|
|
66
70
|
|
|
67
|
-
type
|
|
71
|
+
type Placed<Payload> = Omit<Payload, keyof Placement> & Partial<Placement>
|
|
68
72
|
|
|
69
|
-
|
|
73
|
+
type MessageBefore = Exclude<BeforeName, 'TaskStart' | 'TurnEnd' | 'ContextEnd'>
|
|
74
|
+
|
|
75
|
+
type DraftOf<Name extends MessageBefore> = Omit<Extract<MessageDraft, { readonly type: (typeof sessionEvents)[Name] }>, 'type'>
|
|
76
|
+
|
|
77
|
+
export type Raise = {
|
|
78
|
+
readonly [Name in MessageBefore as `before${Name}`]: (message: DraftOf<Name>, options?: { readonly task?: string }) => Promise<AnswerOf<Name> | undefined>
|
|
79
|
+
} & {
|
|
80
|
+
beforeTaskStart(task: { readonly title: string; readonly agentType?: string; readonly model?: string }): Promise<AnswerOf<'TaskStart'> | undefined>
|
|
81
|
+
beforeTurnEnd(ending?: Pick<Turn, 'answer' | 'failure'>): Promise<AnswerOf<'TurnEnd'> | undefined>
|
|
82
|
+
beforeContextEnd(): Promise<AnswerOf<'ContextEnd'> | undefined>
|
|
83
|
+
} & {
|
|
84
|
+
readonly [Name in ProcessName as `on${Name}`]: (payload: Placed<ProcessPayload[Name]>) => Promise<void>
|
|
85
|
+
} & {
|
|
86
|
+
readonly [Name in keyof ProcessAnswer as `before${Name}`]: (payload: Placed<ProcessAsked[Name]>) => Promise<ProcessAnswer[Name] | undefined>
|
|
87
|
+
} & {
|
|
88
|
+
onRun(run: Placed<CommandRun>): Promise<void>
|
|
89
|
+
beforeRun(run: Placed<CommandRun>): Promise<CommandRunAnswer | undefined>
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
type FiredEvent = 'ui.render' | 'ui.scroll' | 'ui.close' | 'cmod.call' | 'tool.check' | 'prompt.context'
|
|
70
93
|
|
|
71
94
|
export type TestedMod<State extends object> = {
|
|
72
95
|
start(): Promise<void>
|
|
73
|
-
|
|
74
|
-
fire<N extends
|
|
96
|
+
readonly raise: Raise
|
|
97
|
+
fire<N extends FiredEvent>(event: N, input: Args<N>, below?: EventResult<N>): Promise<EventResult<N>>
|
|
75
98
|
settle(): Promise<void>
|
|
76
99
|
add(message: MessageDraft, options?: { readonly task?: string }): Promise<Message[]>
|
|
77
|
-
endTurn(): Promise<void>
|
|
100
|
+
endTurn(ending?: Pick<Turn, 'answer' | 'failure'>): Promise<void>
|
|
78
101
|
compact(): Promise<void>
|
|
102
|
+
startSession(start: { readonly source: 'startup' | 'resume' | 'clear' | 'fork'; readonly id?: string }): Promise<void>
|
|
79
103
|
startTask(task: { readonly title: string; readonly agentType?: string; readonly model?: string; readonly openedBy?: string; readonly parent?: string }): Promise<string>
|
|
80
104
|
lines(paneId: string): Promise<string[]>
|
|
81
105
|
lines<P extends ComponentPlace>(place: P, props: Omit<PlaceProps<P>, 'Default'>, requestId?: string): Promise<string[]>
|
|
@@ -97,7 +121,7 @@ const defaultRows = 24
|
|
|
97
121
|
|
|
98
122
|
const presentation: CommandPresentation = { isFullscreen: false, columns: defaultColumns }
|
|
99
123
|
|
|
100
|
-
const toolUseEvents: readonly string[] = ['PreToolUse', 'PostToolUse', 'PostToolUseFailure', 'PermissionDenied']
|
|
124
|
+
const toolUseEvents: readonly string[] = ['PreToolUse', 'PostToolUse', 'PostToolUseFailure', 'PermissionDenied']
|
|
101
125
|
|
|
102
126
|
export function testMod<State extends object, Declared extends Options = Options>(definition: ModDefinition<State, string, Declared>, options: TestOptions<State, Declared> = {}): TestedMod<State> {
|
|
103
127
|
installJsx()
|
|
@@ -117,6 +141,7 @@ export function testMod<State extends object, Declared extends Options = Options
|
|
|
117
141
|
const conversations = fakeSessions({
|
|
118
142
|
callTool: (args: Parameters<Claude["tool"]["call"]>[0]) => fake.claude.tool.call(args),
|
|
119
143
|
project: () => projectRoot,
|
|
144
|
+
cwd: () => cwd,
|
|
120
145
|
given: options.sessions ?? [],
|
|
121
146
|
push: (mod, session, change) => {
|
|
122
147
|
if (mod !== name) return
|
|
@@ -239,9 +264,44 @@ export function testMod<State extends object, Declared extends Options = Options
|
|
|
239
264
|
const transcript = `/test/transcripts/${sessionId}.jsonl`
|
|
240
265
|
const filled = { session_id: sessionId, transcript_path: transcript, cwd, hook_event_name: event, ...toolUse, ...input }
|
|
241
266
|
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
|
|
267
|
+
if (event !== 'PreToolUse') return route(`classic.${event}` as RoutedEvent, filled, below)
|
|
243
268
|
return firePreToolUse(filled as ClassicHookInputs['PreToolUse'], below as { deny?: string } | undefined)
|
|
244
|
-
}) as
|
|
269
|
+
}) as ClaudeCode['fire']
|
|
270
|
+
|
|
271
|
+
const asked = async (event: BeforeEvent, change: SessionChange) => {
|
|
272
|
+
await start()
|
|
273
|
+
return (await askMod(event, change)) ?? undefined
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
const raise = Object.fromEntries([
|
|
277
|
+
...beforeEvents
|
|
278
|
+
.filter((named) => named !== 'TaskStart' && named !== 'TurnEnd' && named !== 'ContextEnd')
|
|
279
|
+
.map((named) => [`before${named}`, async (draft: object, placed?: { readonly task?: string }) => {
|
|
280
|
+
await start()
|
|
281
|
+
return asked(sessionEvents[named], { type: Message, message: conversations.draft({ ...draft, type: sessionEvents[named] } as MessageDraft, placed?.task) })
|
|
282
|
+
}]),
|
|
283
|
+
['beforeTaskStart', async ({ title, agentType = 'general-purpose', model }: { readonly title: string; readonly agentType?: string; readonly model?: string }) => {
|
|
284
|
+
await start()
|
|
285
|
+
return asked(TaskStart, { type: TaskStart, task: { id: '', title, agentType, openedBy: '', openedAt: new Date().toISOString(), context: conversations.place().context, ...(model === undefined ? {} : { model }) } })
|
|
286
|
+
}],
|
|
287
|
+
['beforeTurnEnd', async (ending: Pick<Turn, 'answer' | 'failure'> = {}) => {
|
|
288
|
+
await start()
|
|
289
|
+
const { turn } = conversations.place()
|
|
290
|
+
if (turn === undefined) throw new Error(`${name} has no turn open to end. Open one with tested.add({ type: Prompt, text: '…' }).`)
|
|
291
|
+
return asked(TurnEnd, { type: TurnEnd, turn: { ...turn, ...ending, closedAt: new Date().toISOString() } })
|
|
292
|
+
}],
|
|
293
|
+
['beforeContextEnd', async () => {
|
|
294
|
+
await start()
|
|
295
|
+
const { context, contextOpenedAt } = conversations.place()
|
|
296
|
+
return asked(ContextEnd, { type: ContextEnd, context: { number: context, openedAt: contextOpenedAt, closedAt: new Date().toISOString() } })
|
|
297
|
+
}],
|
|
298
|
+
...[...Object.entries(processEvents).flatMap(([named, event]) => [`on${named}`, ...('before' in event ? [`before${named}`] : [])]), 'onRun', 'beforeRun'].map((method) => [method, async (payload: object) => {
|
|
299
|
+
await start()
|
|
300
|
+
const answer = await lifecycle.raise(method, { session: sessionId, cwd, ...payload })
|
|
301
|
+
await fake.settle()
|
|
302
|
+
return answer
|
|
303
|
+
}]),
|
|
304
|
+
]) as Raise
|
|
245
305
|
|
|
246
306
|
const firePreToolUse = async ({ tool_name, tool_input, tool_use_id, agent_id, agent_type }: ClassicHookInputs['PreToolUse'], below: { deny?: string } | undefined) => {
|
|
247
307
|
await start()
|
|
@@ -269,22 +329,28 @@ export function testMod<State extends object, Declared extends Options = Options
|
|
|
269
329
|
return value
|
|
270
330
|
}
|
|
271
331
|
|
|
272
|
-
|
|
332
|
+
const tested: TestedMod<State> = {
|
|
273
333
|
start,
|
|
334
|
+
raise,
|
|
274
335
|
fire,
|
|
275
336
|
settle: fake.settle,
|
|
276
337
|
add: async (message, added) => {
|
|
277
338
|
await start()
|
|
278
339
|
return settled(conversations.add(message, added?.task))
|
|
279
340
|
},
|
|
280
|
-
endTurn: async () => {
|
|
341
|
+
endTurn: async (ending) => {
|
|
281
342
|
await start()
|
|
282
|
-
await settled(conversations.endTurn())
|
|
343
|
+
await settled(conversations.endTurn(ending === undefined ? undefined : { ...ending, ...(ending.failure === undefined ? {} : { reason: 'error' as const }) }))
|
|
283
344
|
},
|
|
284
345
|
compact: async () => {
|
|
285
346
|
await start()
|
|
286
347
|
await settled(conversations.compact())
|
|
287
348
|
},
|
|
349
|
+
startSession: async ({ source, id }) => {
|
|
350
|
+
await start()
|
|
351
|
+
await fire('SessionStart', { source, ...(id === undefined ? {} : { session_id: id }) })
|
|
352
|
+
await fake.settle()
|
|
353
|
+
},
|
|
288
354
|
startTask: async (task) => {
|
|
289
355
|
await start()
|
|
290
356
|
return settled(conversations.startTask(task))
|
|
@@ -353,7 +419,7 @@ export function testMod<State extends object, Declared extends Options = Options
|
|
|
353
419
|
},
|
|
354
420
|
get state() {
|
|
355
421
|
const mod = lifecycle.mod
|
|
356
|
-
if (mod === undefined) throw new Error(`${name} has not started. Await tested.start()
|
|
422
|
+
if (mod === undefined) throw new Error(`${name} has not started. Await tested.start() first.`)
|
|
357
423
|
return mod.state
|
|
358
424
|
},
|
|
359
425
|
calls: fake.calls,
|
|
@@ -366,6 +432,8 @@ export function testMod<State extends object, Declared extends Options = Options
|
|
|
366
432
|
sent: conversations.sent,
|
|
367
433
|
},
|
|
368
434
|
}
|
|
435
|
+
keepClaudeCode(tested, { fire })
|
|
436
|
+
return tested
|
|
369
437
|
}
|
|
370
438
|
|
|
371
439
|
function fakeDependencies(caller: string, dependencies: NonNullable<TestOptions<object>['dependencies']>, conversations: FakeSessions): Claude['cmod']['call'] {
|
|
@@ -395,7 +463,7 @@ function plainOutput({ component, props }: Args<'ui.render'>): RenderElement {
|
|
|
395
463
|
}
|
|
396
464
|
|
|
397
465
|
function replyOf({ text, context }: CommandRunResult): CommandReply {
|
|
398
|
-
return { ...(text === undefined ? {} : { text }), ...(context === undefined ? {} : {
|
|
466
|
+
return { ...(text === undefined ? {} : { text }), ...(context === undefined ? {} : { note: context.join('\n') }) }
|
|
399
467
|
}
|
|
400
468
|
|
|
401
469
|
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
|
+
}
|
package/testing/fake-claude.d.ts
CHANGED
|
@@ -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":"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"}
|
package/testing/fake-claude.js
CHANGED
|
@@ -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 {
|
|
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
|
|
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
|
|
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":"AACA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"fake-sessions.d.ts","sourceRoot":"","sources":["../src/testing/fake-sessions.ts"],"names":[],"mappings":"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"}
|
package/testing/fake-sessions.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { isObject } from '../records.js';
|
|
2
|
-
import {
|
|
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 (
|
|
102
|
+
if (request['isAgent'] === true && message.task !== task)
|
|
103
103
|
return false;
|
|
104
|
-
if (task ===
|
|
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 +
|
|
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),
|
|
165
|
-
if (action === '
|
|
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['
|
|
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: '',
|
|
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.
|
|
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
|
|
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.
|
|
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 ===
|
|
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,
|
|
1
|
+
import type { Args, CmodDependencies, EventResult, UiInputArgument } from 'claude-code';
|
|
2
2
|
import type { CommandReply } from './jobs/slash-command.js';
|
|
3
|
-
import type {
|
|
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
|
|
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
|
|
36
|
-
|
|
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
|
-
|
|
40
|
-
fire<N extends
|
|
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":"AAAA,OAAO,KAAK,EACV,IAAI,
|
|
1
|
+
{"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["src/testing.ts"],"names":[],"mappings":"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"}
|