@cmodjs/core 3.1.0 → 4.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.
- package/docs/commands.md +38 -21
- package/docs/dependencies.md +27 -20
- package/docs/index.md +21 -17
- package/docs/install-steps.md +37 -29
- package/docs/jobs.md +25 -52
- package/docs/mod.md +93 -65
- package/docs/options.md +2 -2
- package/docs/permissions.md +4 -4
- package/docs/session.md +14 -12
- package/docs/testing.md +55 -32
- package/docs/ui.md +255 -263
- package/hotkeys.d.ts +22 -0
- package/hotkeys.d.ts.map +1 -0
- package/hotkeys.js +26 -0
- package/installer.d.ts +1 -1
- package/installer.d.ts.map +1 -1
- package/installer.js +11 -6
- package/jobs/check.d.ts +2 -1
- package/jobs/check.d.ts.map +1 -1
- package/jobs/check.js +2 -2
- package/jobs/context.d.ts +2 -1
- package/jobs/context.d.ts.map +1 -1
- package/jobs/context.js +1 -1
- package/jobs/permissions.d.ts +2 -1
- package/jobs/permissions.d.ts.map +1 -1
- package/jobs/permissions.js +2 -2
- package/jobs/program.js +1 -1
- package/jobs/prompt.d.ts +2 -1
- package/jobs/prompt.d.ts.map +1 -1
- package/jobs/prompt.js +20 -13
- package/jobs/schedule.d.ts +2 -1
- package/jobs/schedule.d.ts.map +1 -1
- package/jobs/schedule.js +15 -1
- package/jobs/slash-command.d.ts +6 -2
- package/jobs/slash-command.d.ts.map +1 -1
- package/jobs/slash-command.js +6 -5
- package/jobs/tool.d.ts +6 -4
- package/jobs/tool.d.ts.map +1 -1
- package/jobs/tool.js +3 -3
- package/mod.d.ts +63 -42
- package/mod.d.ts.map +1 -1
- package/mod.js +11 -1
- package/package.json +1 -1
- package/records.d.ts +13 -8
- package/records.d.ts.map +1 -1
- package/records.js +41 -31
- package/register.d.ts.map +1 -1
- package/register.js +1 -2
- package/runtime/announce.d.ts +1 -1
- package/runtime/announce.d.ts.map +1 -1
- package/runtime/announce.js +6 -7
- package/runtime/before.d.ts +2 -2
- package/runtime/before.d.ts.map +1 -1
- package/runtime/before.js +1 -1
- package/runtime/claude.d.ts +0 -1
- package/runtime/claude.d.ts.map +1 -1
- package/runtime/conversations.d.ts +4 -1
- package/runtime/conversations.d.ts.map +1 -1
- package/runtime/conversations.js +42 -14
- package/runtime/dependencies.d.ts.map +1 -1
- package/runtime/dependencies.js +2 -1
- package/runtime/engine.d.ts +5 -0
- package/runtime/engine.d.ts.map +1 -1
- package/runtime/grants.js +2 -2
- package/runtime/hooks.d.ts +1 -1
- package/runtime/hooks.d.ts.map +1 -1
- package/runtime/hotkeys.d.ts +15 -0
- package/runtime/hotkeys.d.ts.map +1 -0
- package/runtime/hotkeys.js +58 -0
- package/runtime/installer.d.ts +5 -2
- package/runtime/installer.d.ts.map +1 -1
- package/runtime/installer.js +23 -12
- package/runtime/lifecycle.d.ts.map +1 -1
- package/runtime/lifecycle.js +190 -141
- package/runtime/options.js +2 -2
- package/runtime/pages.d.ts +28 -0
- package/runtime/pages.d.ts.map +1 -0
- package/runtime/pages.js +98 -0
- package/runtime/parts.d.ts +14 -0
- package/runtime/parts.d.ts.map +1 -0
- package/runtime/parts.js +59 -0
- package/runtime/permission-check.d.ts +2 -2
- package/runtime/permission-check.d.ts.map +1 -1
- package/runtime/programs.js +1 -1
- package/runtime/router.d.ts +2 -2
- package/runtime/router.d.ts.map +1 -1
- package/runtime/router.js +1 -1
- package/runtime/sessions.d.ts +10 -9
- package/runtime/sessions.d.ts.map +1 -1
- package/runtime/sessions.js +14 -5
- package/runtime/state.d.ts +2 -1
- package/runtime/state.d.ts.map +1 -1
- package/runtime/state.js +1 -0
- package/runtime/toaster.d.ts +1 -1
- package/runtime/toaster.d.ts.map +1 -1
- package/runtime/toaster.js +10 -4
- package/runtime/ui.d.ts +87 -5
- package/runtime/ui.d.ts.map +1 -1
- package/runtime/ui.js +374 -109
- package/runtime/watches.d.ts +9 -0
- package/runtime/watches.d.ts.map +1 -0
- package/runtime/watches.js +73 -0
- package/runtime/widgets.d.ts +48 -0
- package/runtime/widgets.d.ts.map +1 -0
- package/runtime/widgets.js +219 -0
- package/session/context/turn/message/message.d.ts.map +1 -1
- package/session/context/turn/message/message.js +7 -2
- package/session/session.d.ts +11 -5
- package/session/session.d.ts.map +1 -1
- package/src/hotkeys.ts +51 -0
- package/src/installer.ts +8 -4
- package/src/jobs/check.ts +4 -3
- package/src/jobs/context.ts +3 -2
- package/src/jobs/permissions.ts +4 -3
- package/src/jobs/program.ts +1 -1
- package/src/jobs/prompt.ts +23 -14
- package/src/jobs/schedule.ts +16 -2
- package/src/jobs/slash-command.ts +10 -7
- package/src/jobs/tool.ts +7 -5
- package/src/mod.ts +59 -47
- package/src/records.ts +46 -31
- package/src/register.ts +2 -3
- package/src/runtime/announce.ts +6 -7
- package/src/runtime/before.ts +4 -4
- package/src/runtime/claude.ts +0 -1
- package/src/runtime/conversations.ts +66 -20
- package/src/runtime/dependencies.ts +2 -1
- package/src/runtime/engine.ts +5 -0
- package/src/runtime/grants.ts +2 -2
- package/src/runtime/hooks.ts +1 -0
- package/src/runtime/hotkeys.ts +80 -0
- package/src/runtime/installer.ts +24 -12
- package/src/runtime/lifecycle.ts +189 -136
- package/src/runtime/options.ts +2 -2
- package/src/runtime/pages.ts +127 -0
- package/src/runtime/parts.ts +70 -0
- package/src/runtime/permission-check.ts +2 -2
- package/src/runtime/programs.ts +1 -1
- package/src/runtime/router.ts +3 -3
- package/src/runtime/sessions.ts +24 -15
- package/src/runtime/state.ts +3 -1
- package/src/runtime/toaster.ts +10 -4
- package/src/runtime/ui.ts +407 -115
- package/src/runtime/watches.ts +75 -0
- package/src/runtime/widgets.ts +287 -0
- package/src/session/context/turn/message/message.ts +7 -2
- package/src/session/session.ts +10 -6
- package/src/testing/fake-claude.ts +9 -6
- package/src/testing/fake-elements.ts +7 -4
- package/src/testing/fake-sessions.ts +6 -4
- package/src/testing.ts +203 -46
- package/src/ui/areas.ts +27 -0
- package/src/ui/elements.ts +35 -0
- package/src/ui/markdown.ts +18 -18
- package/src/ui/panes.ts +73 -0
- package/src/ui/styles.ts +53 -0
- package/src/utils/subscription.ts +1 -0
- package/testing/fake-claude.d.ts +0 -1
- package/testing/fake-claude.d.ts.map +1 -1
- package/testing/fake-claude.js +9 -5
- package/testing/fake-elements.js +7 -4
- package/testing/fake-sessions.d.ts +2 -1
- package/testing/fake-sessions.d.ts.map +1 -1
- package/testing/fake-sessions.js +1 -0
- package/testing.d.ts +21 -6
- package/testing.d.ts.map +1 -1
- package/testing.js +206 -45
- package/ui/areas.d.ts +29 -0
- package/ui/areas.d.ts.map +1 -0
- package/ui/areas.js +6 -0
- package/ui/elements.d.ts +3 -0
- package/ui/elements.d.ts.map +1 -1
- package/ui/elements.js +36 -0
- package/ui/markdown.d.ts +14 -14
- package/ui/markdown.d.ts.map +1 -1
- package/ui/markdown.js +11 -11
- package/ui/panes.d.ts +71 -0
- package/ui/panes.d.ts.map +1 -0
- package/ui/panes.js +16 -0
- package/ui/styles.d.ts +44 -0
- package/ui/styles.d.ts.map +1 -0
- package/ui/styles.js +24 -0
- package/utils/subscription.d.ts +4 -0
- package/utils/subscription.d.ts.map +1 -0
- package/jobs/status-line.d.ts +0 -6
- package/jobs/status-line.d.ts.map +0 -1
- package/jobs/status-line.js +0 -39
- package/src/jobs/status-line.ts +0 -44
- package/src/ui/define-pane.ts +0 -27
- package/src/ui/places.ts +0 -49
- package/src/utils/disposable.ts +0 -3
- package/ui/define-pane.d.ts +0 -15
- package/ui/define-pane.d.ts.map +0 -1
- package/ui/define-pane.js +0 -12
- package/ui/places.d.ts +0 -43
- package/ui/places.d.ts.map +0 -1
- package/ui/places.js +0 -31
- package/utils/disposable.d.ts +0 -4
- package/utils/disposable.d.ts.map +0 -1
- /package/utils/{disposable.js → subscription.js} +0 -0
package/src/jobs/prompt.ts
CHANGED
|
@@ -3,6 +3,7 @@ import type { Deadline } from '../runtime/deadline.js'
|
|
|
3
3
|
import { engineOf } from '../runtime/engine.js'
|
|
4
4
|
import { onStateChange } from '../runtime/state.js'
|
|
5
5
|
import { modNote } from '../session/context/turn/message/note.js'
|
|
6
|
+
import type { Subscription } from '../utils/subscription.js'
|
|
6
7
|
import { listed, messageOf } from '../utils/text.js'
|
|
7
8
|
import { callEffects, type Call } from '../utils/call-effects.js'
|
|
8
9
|
import { matchTarget, targetOf, type Target } from './permissions/match-target.js'
|
|
@@ -18,13 +19,13 @@ type PromptOptions<State extends object> = {
|
|
|
18
19
|
|
|
19
20
|
const deadline: Deadline = { ms: 5000, job: 'prompt' }
|
|
20
21
|
|
|
21
|
-
export function prompt<State extends object = Record<never, never>>({ name, prompt: text, after }: PromptOptions<State>): Job<
|
|
22
|
+
export function prompt<State extends object = Record<never, never>>({ name, prompt: text, after }: PromptOptions<State>): Job<Subscription, State> {
|
|
22
23
|
if (name.trim() === '') throw new Error('prompt: give the block a name. Claude reads the text under it.')
|
|
23
24
|
const targets = after === undefined ? [] : Array.isArray(after) ? after : [after]
|
|
24
25
|
for (const target of targets) targetOf(target)
|
|
25
26
|
|
|
26
27
|
return (job) => {
|
|
27
|
-
job.reserveName('prompt', name, `prompt: ${job.mod.name} adds the name "${name}" two times. Give each prompt its own name.`)
|
|
28
|
+
const reserved = job.reserveName('prompt', name, `prompt: ${job.mod.name} adds the name "${name}" two times. Give each prompt its own name.`)
|
|
28
29
|
|
|
29
30
|
const log = (reason: string) => job.mod.log(`prompt "${name}" added nothing: ${reason}`)
|
|
30
31
|
const textFor = async (input: PromptInput) => {
|
|
@@ -42,29 +43,30 @@ export function prompt<State extends object = Record<never, never>>({ name, prom
|
|
|
42
43
|
return value === undefined ? undefined : `# ${name}\n${value}`
|
|
43
44
|
}
|
|
44
45
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
46
|
+
job.announce(targets.length > 0 ? `the ${name} prompt after ${listed(targets.map(targetWords))}` : `the ${name} prompt`)
|
|
47
|
+
const added = targets.length > 0 ? addAfterCalls(job, targets, headedText, log) : addKeptCurrent(job, name, () => textFor({}), log)
|
|
48
|
+
return {
|
|
49
|
+
remove() {
|
|
50
|
+
added.remove()
|
|
51
|
+
reserved.remove()
|
|
52
|
+
},
|
|
51
53
|
}
|
|
52
54
|
}
|
|
53
55
|
}
|
|
54
56
|
|
|
55
|
-
function addKeptCurrent<State extends object>(job: JobContext<State>, name: string, textFor: () => Promise<string | undefined>, log: (reason: string) => void):
|
|
57
|
+
function addKeptCurrent<State extends object>(job: JobContext<State>, name: string, textFor: () => Promise<string | undefined>, log: (reason: string) => void): Subscription {
|
|
56
58
|
const { claude, router } = engineOf(job.mod)
|
|
57
59
|
let given: string | undefined
|
|
58
60
|
let hasStarted = false
|
|
59
61
|
let isQueued = false
|
|
60
62
|
let updates = Promise.resolve()
|
|
61
63
|
|
|
62
|
-
router.add('classic.SessionStart', (e, next) => {
|
|
64
|
+
const starting = router.add('classic.SessionStart', (e, next) => {
|
|
63
65
|
hasStarted = e.source === 'resume' || e.source === 'compact'
|
|
64
66
|
if (!hasStarted) given = undefined
|
|
65
67
|
return next(e)
|
|
66
68
|
})
|
|
67
|
-
router.add('prompt.context', async (e, next) => {
|
|
69
|
+
const adding = router.add('prompt.context', async (e, next) => {
|
|
68
70
|
const below = await next(e)
|
|
69
71
|
hasStarted = true
|
|
70
72
|
if (below.blocks.some((block) => block.name === name)) {
|
|
@@ -85,15 +87,22 @@ function addKeptCurrent<State extends object>(job: JobContext<State>, name: stri
|
|
|
85
87
|
if (added.deny !== undefined) log(`Claude Code refused the new text: ${added.deny}`)
|
|
86
88
|
})
|
|
87
89
|
}
|
|
88
|
-
onStateChange(job.mod.state, () => {
|
|
90
|
+
const following = onStateChange(job.mod.state, () => {
|
|
89
91
|
if (isQueued) return
|
|
90
92
|
isQueued = true
|
|
91
93
|
updates = updates.then(update).catch((error: unknown) => log(messageOf(error)))
|
|
92
94
|
})
|
|
95
|
+
return {
|
|
96
|
+
remove() {
|
|
97
|
+
starting.remove()
|
|
98
|
+
adding.remove()
|
|
99
|
+
following.remove()
|
|
100
|
+
},
|
|
101
|
+
}
|
|
93
102
|
}
|
|
94
103
|
|
|
95
|
-
function addAfterCalls<State extends object>(job: JobContext<State>, targets: Target[], textFor: (input: PromptInput) => Promise<string | undefined>, log: (reason: string) => void):
|
|
96
|
-
afterCall(
|
|
104
|
+
function addAfterCalls<State extends object>(job: JobContext<State>, targets: Target[], textFor: (input: PromptInput) => Promise<string | undefined>, log: (reason: string) => void): Subscription {
|
|
105
|
+
return afterCall(
|
|
97
106
|
job,
|
|
98
107
|
async (use, workspace) => {
|
|
99
108
|
const effects = callEffects(use, workspace)
|
package/src/jobs/schedule.ts
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import type { Job } from '../mod.js'
|
|
2
2
|
import { onStateChange } from '../runtime/state.js'
|
|
3
3
|
import { engineOf } from '../runtime/engine.js'
|
|
4
|
+
import type { Subscription } from '../utils/subscription.js'
|
|
4
5
|
|
|
5
6
|
export type ScheduledPrompt = { readonly cron: string; readonly prompt: string }
|
|
6
7
|
|
|
7
8
|
const scheduleCounts = new WeakMap<object, number>()
|
|
8
9
|
|
|
9
|
-
export function schedule<State extends object = Record<never, never>>(entry: ScheduledPrompt | ((state: State) => ScheduledPrompt | undefined)): Job<
|
|
10
|
+
export function schedule<State extends object = Record<never, never>>(entry: ScheduledPrompt | ((state: State) => ScheduledPrompt | undefined)): Job<Subscription, State> {
|
|
10
11
|
if (typeof entry !== 'function') checked(entry)
|
|
11
12
|
|
|
12
13
|
return (job) => {
|
|
@@ -51,12 +52,25 @@ export function schedule<State extends object = Record<never, never>>(entry: Sch
|
|
|
51
52
|
.then((left) => (typeof left === 'string' ? remove(left) : undefined))
|
|
52
53
|
.then(update)
|
|
53
54
|
.catch((error: unknown) => report('failed', error))
|
|
54
|
-
onStateChange(mod.state, () => {
|
|
55
|
+
const following = onStateChange(mod.state, () => {
|
|
55
56
|
if (isQueued) return
|
|
56
57
|
isQueued = true
|
|
57
58
|
updates = updates.then(update).catch((error: unknown) => report('failed', error))
|
|
58
59
|
})
|
|
59
60
|
job.announce(typeof entry === 'function' ? 'a schedule from its state' : `a schedule at ${entry.cron}`)
|
|
61
|
+
return {
|
|
62
|
+
remove() {
|
|
63
|
+
following.remove()
|
|
64
|
+
updates = updates
|
|
65
|
+
.then(async () => {
|
|
66
|
+
if (current === undefined) return
|
|
67
|
+
const { id } = current
|
|
68
|
+
current = undefined
|
|
69
|
+
await remove(id)
|
|
70
|
+
})
|
|
71
|
+
.catch((error: unknown) => report('failed', error))
|
|
72
|
+
},
|
|
73
|
+
}
|
|
60
74
|
}
|
|
61
75
|
}
|
|
62
76
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { CommandRunResult } from 'claude-code'
|
|
2
|
-
import type {
|
|
2
|
+
import type { Job, Mod } from '../mod.js'
|
|
3
3
|
import { parse } from '../vendor.js'
|
|
4
4
|
import type { Deadline } from '../runtime/deadline.js'
|
|
5
5
|
import { engineOf } from '../runtime/engine.js'
|
|
@@ -9,6 +9,8 @@ import { withinDeadline } from './context.js'
|
|
|
9
9
|
|
|
10
10
|
export type CommandReply = string | { text?: string; note?: string } | undefined
|
|
11
11
|
|
|
12
|
+
export type SlashCommand = { readonly name: string; remove(): void }
|
|
13
|
+
|
|
12
14
|
const deadline: Deadline = { ms: 30000, job: 'slashCommand' }
|
|
13
15
|
|
|
14
16
|
const commandName = /^[A-Za-z0-9_-]{1,64}$/
|
|
@@ -19,11 +21,11 @@ export function slashCommand<State extends object = Record<never, never>>(option
|
|
|
19
21
|
readonly argumentHint?: string
|
|
20
22
|
readonly immediate?: true
|
|
21
23
|
readonly reply: (input: { args: string; positionals: string[] }, mod: Mod<State>) => CommandReply | void | Promise<CommandReply | void>
|
|
22
|
-
}): Job<
|
|
24
|
+
}): Job<SlashCommand, State> {
|
|
23
25
|
const { name, description, argumentHint, immediate, reply } = options
|
|
24
26
|
return (job) => {
|
|
25
27
|
const { mod, announce, reserveName } = job
|
|
26
|
-
const { claude, router, report } = engineOf(mod)
|
|
28
|
+
const { claude, router, report, answerInput } = engineOf(mod)
|
|
27
29
|
if (!commandName.test(name)) throw new Error(`${mod.name}: "${name}" is not a slash command name. Use 1 to 64 letters, digits, "_", or "-", without the slash.`)
|
|
28
30
|
const reserved = reserveName('slashCommand', name, `${mod.name}: the slash command /${name} is already added. Give each slashCommand its own name.`)
|
|
29
31
|
|
|
@@ -41,15 +43,16 @@ export function slashCommand<State extends object = Record<never, never>>(option
|
|
|
41
43
|
const answering = router.add('command.run', async (e, next) => {
|
|
42
44
|
if (e.command !== registered) return next(e)
|
|
43
45
|
try {
|
|
44
|
-
return answerOf(mod.name, await withinDeadline(mod, deadline, `/${name}`, () => reply({ args: e.args, positionals: splitWords(e.args) }, mod)))
|
|
46
|
+
return await answerInput(async () => answerOf(mod.name, await withinDeadline(mod, deadline, `/${name}`, () => reply({ args: e.args, positionals: splitWords(e.args) }, mod))), () => next(e))
|
|
45
47
|
} catch (error) {
|
|
46
48
|
return { text: `/${name} failed: ${oneLine(error)}` }
|
|
47
49
|
}
|
|
48
50
|
})
|
|
49
51
|
return {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
52
|
+
name,
|
|
53
|
+
remove() {
|
|
54
|
+
answering.remove()
|
|
55
|
+
reserved.remove()
|
|
53
56
|
},
|
|
54
57
|
}
|
|
55
58
|
}
|
package/src/jobs/tool.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { FromSchema, JSONSchema } from 'json-schema-to-ts'
|
|
2
|
-
import type {
|
|
2
|
+
import type { Job, Mod } from '../mod.js'
|
|
3
3
|
import { Validator } from '../vendor.js'
|
|
4
4
|
import { toolDeadline } from '../runtime/deadline.js'
|
|
5
5
|
import { engineOf } from '../runtime/engine.js'
|
|
@@ -9,12 +9,14 @@ import { withinDeadline } from './context.js'
|
|
|
9
9
|
|
|
10
10
|
const toolName = /^[A-Za-z0-9_-]{1,64}$/
|
|
11
11
|
|
|
12
|
+
export type Tool = { readonly name: string; remove(): void }
|
|
13
|
+
|
|
12
14
|
export function tool<const Schema extends object = { type: 'object' }, State extends object = Record<never, never>>(options: {
|
|
13
15
|
readonly name: string
|
|
14
16
|
readonly description: string
|
|
15
17
|
readonly inputSchema?: Schema
|
|
16
18
|
readonly execute: (input: Schema extends JSONSchema ? FromSchema<Schema> : never, mod: Mod<State>) => unknown
|
|
17
|
-
}): Job<
|
|
19
|
+
}): Job<Tool, State> {
|
|
18
20
|
const { name, description, inputSchema, execute } = options
|
|
19
21
|
return (job) => {
|
|
20
22
|
const { mod, announce, reserveName } = job
|
|
@@ -50,9 +52,9 @@ export function tool<const Schema extends object = { type: 'object' }, State ext
|
|
|
50
52
|
})
|
|
51
53
|
return {
|
|
52
54
|
name: `mcp__${claude.plugin.name}__${name}`,
|
|
53
|
-
|
|
54
|
-
answering.
|
|
55
|
-
named.
|
|
55
|
+
remove() {
|
|
56
|
+
answering.remove()
|
|
57
|
+
named.remove()
|
|
56
58
|
},
|
|
57
59
|
}
|
|
58
60
|
}
|
package/src/mod.ts
CHANGED
|
@@ -9,7 +9,6 @@ import type {
|
|
|
9
9
|
ModelCompleteOptions,
|
|
10
10
|
ModelCompleteRequest,
|
|
11
11
|
ModelCompleteResult,
|
|
12
|
-
PaneOpenArgs,
|
|
13
12
|
ProcessRunInit,
|
|
14
13
|
ProcessRunResult,
|
|
15
14
|
ProcessSpawnChunk,
|
|
@@ -17,20 +16,24 @@ import type {
|
|
|
17
16
|
ProcessSpawnResult,
|
|
18
17
|
RenderElement,
|
|
19
18
|
Settings,
|
|
20
|
-
UiScrollArgs,
|
|
21
|
-
UiScrollResult,
|
|
22
19
|
} from 'claude-code'
|
|
23
|
-
import type
|
|
20
|
+
import { checkHotkeys, type Hotkey, type HotkeyInit, type Hotkeys } from './hotkeys.js'
|
|
21
|
+
import { checkSteps, type Step } from './installer.js'
|
|
24
22
|
import { checkOptions, type Option, type Options, type OptionValues } from './options.js'
|
|
25
23
|
import { bound } from './runtime/bound.js'
|
|
26
24
|
import { Mod as modSender } from './session/context/turn/message/sender.js'
|
|
27
25
|
import { sessionEvents, type BeforeMethod, type CommandRun, type CommandRunAnswer, type OnMethod, type OnMethods, type Sessions } from './session/session.js'
|
|
28
|
-
import type {
|
|
29
|
-
import type {
|
|
30
|
-
import type {
|
|
26
|
+
import type { Widget, WidgetInit } from './ui/areas.js'
|
|
27
|
+
import type { Page, PageInit, Pane, PaneInit } from './ui/panes.js'
|
|
28
|
+
import type { Kind, Style, StyleInit } from './ui/styles.js'
|
|
31
29
|
import type { Matcher } from './utils/matcher.js'
|
|
30
|
+
import type { Subscription } from './utils/subscription.js'
|
|
32
31
|
|
|
33
|
-
export type {
|
|
32
|
+
export type { Subscription }
|
|
33
|
+
|
|
34
|
+
export type Timer = { readonly isRunning: boolean; stop(): void }
|
|
35
|
+
|
|
36
|
+
export type Reservation = { remove(): void }
|
|
34
37
|
|
|
35
38
|
export type ToastId = string | number
|
|
36
39
|
|
|
@@ -56,15 +59,6 @@ export type Toast = {
|
|
|
56
59
|
dismiss(id?: ToastId): void
|
|
57
60
|
}
|
|
58
61
|
|
|
59
|
-
export type PaneHandle = {
|
|
60
|
-
open(options?: Readonly<Pick<PaneOpenArgs, 'focus'>>): Promise<void>
|
|
61
|
-
close(): Promise<void>
|
|
62
|
-
toggle(options?: Readonly<Pick<PaneOpenArgs, 'focus'>>): Promise<void>
|
|
63
|
-
readonly isOpen: boolean
|
|
64
|
-
readonly isShown: boolean
|
|
65
|
-
readonly isFocused: boolean
|
|
66
|
-
}
|
|
67
|
-
|
|
68
62
|
export type Metadata = Readonly<Record<string, string>>
|
|
69
63
|
|
|
70
64
|
export type FileMatch = {
|
|
@@ -138,8 +132,8 @@ export type Imports = {
|
|
|
138
132
|
readonly user: SettingsFile
|
|
139
133
|
readonly project: SettingsFile
|
|
140
134
|
readonly local: SettingsFile
|
|
141
|
-
beforeFileChange(listener: SettingsFileChangeListener):
|
|
142
|
-
beforeFileChange(matcher: Matcher<SettingsFileChange>, listener: SettingsFileChangeListener):
|
|
135
|
+
beforeFileChange(listener: SettingsFileChangeListener): Subscription
|
|
136
|
+
beforeFileChange(matcher: Matcher<SettingsFileChange>, listener: SettingsFileChangeListener): Subscription
|
|
143
137
|
}
|
|
144
138
|
readonly model: { complete(request: ModelCompleteRequest, options?: ModelCompleteOptions): Promise<ModelCompleteResult> }
|
|
145
139
|
readonly fs: {
|
|
@@ -149,7 +143,7 @@ export type Imports = {
|
|
|
149
143
|
find(glob: string | readonly string[]): Promise<readonly FileMatch[]>
|
|
150
144
|
list(path?: string): Promise<Entry[]>
|
|
151
145
|
stat(path: string, options?: FsStatOptions): Promise<Stat>
|
|
152
|
-
onChange(matcher: { readonly path: string | readonly string[] }, listener: (change: FileChange) => unknown):
|
|
146
|
+
onChange(matcher: { readonly path: string | readonly string[] }, listener: (change: FileChange) => unknown): Subscription
|
|
153
147
|
}
|
|
154
148
|
readonly metadata: {
|
|
155
149
|
read(path: string): Promise<Metadata>
|
|
@@ -160,6 +154,7 @@ export type Imports = {
|
|
|
160
154
|
spawn(argv: readonly string[], init?: Omit<ProcessSpawnRequest, 'argv'>): HookStream<ProcessSpawnChunk, ProcessSpawnResult>
|
|
161
155
|
}
|
|
162
156
|
readonly http: { fetch(url: string, init?: HttpInit): Promise<HttpResponse> }
|
|
157
|
+
readonly clipboard: { write(text: string): Promise<void> }
|
|
163
158
|
}
|
|
164
159
|
|
|
165
160
|
export const sessions: Imports['sessions'] = {
|
|
@@ -168,7 +163,7 @@ export const sessions: Imports['sessions'] = {
|
|
|
168
163
|
},
|
|
169
164
|
list: (options) => bound().sessions.list(options),
|
|
170
165
|
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[]) =>
|
|
166
|
+
...(Object.fromEntries(Object.keys(sessionEvents).map((named) => [`on${named}`, (...args: unknown[]) => (bound().sessions[`on${named}` as keyof OnMethods] as (...each: unknown[]) => Subscription)(...args)])) as OnMethods),
|
|
172
167
|
}
|
|
173
168
|
|
|
174
169
|
export const settings: Imports['settings'] = {
|
|
@@ -181,8 +176,8 @@ export const settings: Imports['settings'] = {
|
|
|
181
176
|
export const commands: Imports['commands'] = {
|
|
182
177
|
list: () => bound().commands.list(),
|
|
183
178
|
run: (name, args) => bound().commands.run(name, args),
|
|
184
|
-
beforeRun: ((...args: never[]) => (bound().commands.beforeRun as (...each: never[]) =>
|
|
185
|
-
onRun: ((...args: never[]) => (bound().commands.onRun as (...each: never[]) =>
|
|
179
|
+
beforeRun: ((...args: never[]) => (bound().commands.beforeRun as (...each: never[]) => Subscription)(...args)) as Imports['commands']['beforeRun'],
|
|
180
|
+
onRun: ((...args: never[]) => (bound().commands.onRun as (...each: never[]) => Subscription)(...args)) as Imports['commands']['onRun'],
|
|
186
181
|
}
|
|
187
182
|
|
|
188
183
|
export const config: Imports['config'] = {
|
|
@@ -217,30 +212,32 @@ export const http: Imports['http'] = {
|
|
|
217
212
|
fetch: (url, init) => bound().http.fetch(url, init),
|
|
218
213
|
}
|
|
219
214
|
|
|
220
|
-
export
|
|
215
|
+
export const clipboard: Imports['clipboard'] = {
|
|
216
|
+
write: (text) => bound().clipboard.write(text),
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
export type Mod<State extends object = Record<never, never>, Declared extends Options = Options, Keys extends Hotkeys = Hotkeys> = {
|
|
221
220
|
readonly name: string
|
|
222
221
|
readonly folder: string
|
|
223
222
|
readonly dataFolder: string
|
|
224
223
|
readonly state: Readonly<State>
|
|
225
224
|
readonly options: OptionValues<Declared>
|
|
226
225
|
readonly permissions: Permissions
|
|
227
|
-
|
|
228
|
-
|
|
226
|
+
readonly hotkeys: { readonly [Key in keyof Keys]: Hotkey }
|
|
227
|
+
every(ms: number, listener: () => unknown): Timer
|
|
228
|
+
after(ms: number, listener: () => unknown): Timer
|
|
229
229
|
use<Handle>(job: Job<Handle, State>): Handle
|
|
230
230
|
log(text: string, options?: { readonly to?: 'debug' | 'transcript' }): void
|
|
231
|
-
readonly
|
|
232
|
-
|
|
233
|
-
render<P extends Place>(place: P, Component: (props: PlaceProps<P>) => RenderElement): Disposable
|
|
234
|
-
readonly toast: Toast
|
|
235
|
-
ask(question: string, options?: readonly string[] | AskOptions): Promise<string>
|
|
236
|
-
copy(text: string): Promise<void>
|
|
237
|
-
scroll(args: UiScrollArgs): Promise<UiScrollResult>
|
|
238
|
-
notice(callId: string, text: string | undefined): void
|
|
239
|
-
}
|
|
231
|
+
readonly panes: { add<Params = undefined>(pane: PaneInit<State, Params>): Pane<Params> }
|
|
232
|
+
readonly sidebar: { add<Params = undefined>(page: PageInit<State, Params>): Page<Params> }
|
|
240
233
|
readonly settings: {
|
|
241
|
-
|
|
242
|
-
open(
|
|
234
|
+
add<Params = undefined>(page: PageInit<State, Params>): Page<Params>
|
|
235
|
+
open(): Promise<void>
|
|
243
236
|
}
|
|
237
|
+
readonly widgets: { add(widget: WidgetInit<State>): Widget }
|
|
238
|
+
readonly styles: { add<K extends Kind>(style: StyleInit<K, State>): Style }
|
|
239
|
+
readonly toast: Toast
|
|
240
|
+
ask(question: string, options?: readonly string[] | AskOptions): Promise<string>
|
|
244
241
|
readonly dependencies: CmodDependencies
|
|
245
242
|
}
|
|
246
243
|
|
|
@@ -253,36 +250,51 @@ type StateGroups = {
|
|
|
253
250
|
readonly global?: object
|
|
254
251
|
}
|
|
255
252
|
|
|
256
|
-
type
|
|
257
|
-
|
|
258
|
-
|
|
253
|
+
type AnyApi = { readonly [method: string]: (input: never) => unknown } | void
|
|
254
|
+
|
|
255
|
+
type Api<Name extends string> = 0 extends 1 & CmodDependencies
|
|
256
|
+
? AnyApi
|
|
257
|
+
: Name extends keyof CmodDependencies
|
|
258
|
+
? { readonly [Method in keyof CmodDependencies[Name]]: CmodDependencies[Name][Method] extends (input: infer Input) => infer Result ? (input: Input) => Result | Awaited<Result> : never }
|
|
259
|
+
: AnyApi
|
|
259
260
|
|
|
260
|
-
export type ModDefinition<State extends StateGroups = Record<never, never>, Name extends string = string, Declared extends Options = Record<never, Option>> = {
|
|
261
|
+
export type ModDefinition<State extends StateGroups = Record<never, never>, Name extends string = string, Declared extends Options = Record<never, Option>, Keys extends Hotkeys = Record<never, HotkeyInit>> = {
|
|
261
262
|
readonly name: Name
|
|
262
263
|
readonly state?: State
|
|
263
264
|
readonly options?: Declared
|
|
264
|
-
readonly
|
|
265
|
+
readonly hotkeys?: Keys
|
|
265
266
|
readonly installer?: readonly Step<State>[]
|
|
266
|
-
setup(mod: Mod<State, Declared>):
|
|
267
|
+
setup(mod: Mod<State, Declared, Keys>): Api<Name> | Promise<Api<Name>>
|
|
267
268
|
}
|
|
268
269
|
|
|
269
270
|
export type JobContext<State extends object = Record<never, never>> = {
|
|
270
271
|
readonly mod: Mod<State>
|
|
271
272
|
announce(feature: string): void
|
|
272
|
-
reserveName(type: string, name: string, taken: string):
|
|
273
|
+
reserveName(type: string, name: string, taken: string): Reservation
|
|
273
274
|
}
|
|
274
275
|
|
|
275
276
|
export type Job<Handle, State extends object = Record<never, never>> = (context: JobContext<State>) => Handle
|
|
276
277
|
|
|
277
|
-
export function defineMod<State extends StateGroups = Record<never, never>, Name extends string = string, const Declared extends Options = Record<never, Option
|
|
278
|
+
export function defineMod<State extends StateGroups = Record<never, never>, Name extends string = string, const Declared extends Options = Record<never, Option>, const Keys extends Hotkeys = Record<never, HotkeyInit>>(
|
|
279
|
+
definition: ModDefinition<State, Name, Declared, Keys>,
|
|
280
|
+
): ModDefinition<State, Name, Declared, Keys> {
|
|
278
281
|
if (definition.name.trim() === '') throw new Error('defineMod: the mod needs a name, such as the name in .claude-plugin/plugin.json.')
|
|
279
282
|
if (definition.options !== undefined) checkOptions(definition.name, definition.options)
|
|
283
|
+
if (definition.hotkeys !== undefined) checkHotkeys(definition.name, definition.hotkeys)
|
|
284
|
+
if (definition.installer !== undefined) checkSteps(definition.name, definition.installer)
|
|
280
285
|
return definition
|
|
281
286
|
}
|
|
282
287
|
|
|
283
288
|
export type { Matcher } from './utils/matcher.js'
|
|
284
|
-
export type {
|
|
285
|
-
export {
|
|
289
|
+
export type { Combo, Hotkey, HotkeyInit, Key } from './hotkeys.js'
|
|
290
|
+
export type { OpenOptions, Page, PageInit, PageProps, Pane, PaneInit, PaneProps, ScrollOptions, ScrollTarget } from './ui/panes.js'
|
|
291
|
+
export type { Kind, Row, Style, StyleInit, StyleProps } from './ui/styles.js'
|
|
292
|
+
export type { Block } from './ui/markdown.js'
|
|
293
|
+
export { AskUserQuestion, CommandOutput, ToolGroup, ToolProgress } from './ui/styles.js'
|
|
294
|
+
export { AbovePrompt, BelowPrompt, Dashboard, TurnEnd, Working, type Area, type Widget, type WidgetContext, type WidgetInit } from './ui/areas.js'
|
|
295
|
+
export type { Step } from './installer.js'
|
|
296
|
+
export type { SlashCommand } from './jobs/slash-command.js'
|
|
297
|
+
export type { Tool } from './jobs/tool.js'
|
|
286
298
|
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
299
|
export type { Context } from './session/context/context.js'
|
|
288
300
|
export type { Turn } from './session/context/turn/turn.js'
|
package/src/records.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { checkHotkeys, type HotkeyInit, type Hotkeys } from './hotkeys.js'
|
|
1
2
|
import { listed, messageOf } from './utils/text.js'
|
|
2
3
|
|
|
3
4
|
export type InstallRecord = {
|
|
@@ -15,7 +16,7 @@ export type Steps = {
|
|
|
15
16
|
install?: string
|
|
16
17
|
uninstall?: string
|
|
17
18
|
program?: string
|
|
18
|
-
|
|
19
|
+
hotkeys?: Hotkeys
|
|
19
20
|
permissions?: readonly string[]
|
|
20
21
|
}
|
|
21
22
|
|
|
@@ -39,7 +40,7 @@ export type ReadFile = (path: string) => Promise<string | undefined>
|
|
|
39
40
|
export type RunnerEvent =
|
|
40
41
|
| { type: 'progress'; done: number; total: number; label: string }
|
|
41
42
|
| { type: 'log'; text: string }
|
|
42
|
-
| { type: 'needs-consent'; sha256: string; install: string; uninstall: string;
|
|
43
|
+
| { type: 'needs-consent'; sha256: string; install: string; uninstall: string; hotkeys: string; permissions: readonly string[] }
|
|
43
44
|
| { type: 'done'; name: string; version?: string }
|
|
44
45
|
| { type: 'missing'; name: string }
|
|
45
46
|
| { type: 'retries'; when: 'changed' | 'later' }
|
|
@@ -139,7 +140,7 @@ export function readSteps(pkg: unknown): Steps | undefined {
|
|
|
139
140
|
...readCommand(steps, 'install'),
|
|
140
141
|
...readCommand(steps, 'uninstall'),
|
|
141
142
|
...(program === undefined ? {} : { program }),
|
|
142
|
-
...
|
|
143
|
+
...readHotkeys(steps['hotkeys']),
|
|
143
144
|
...(permissions.length === 0 ? {} : { permissions }),
|
|
144
145
|
}
|
|
145
146
|
}
|
|
@@ -173,6 +174,12 @@ function readPermissions(steps: Record<string, unknown>): string[] {
|
|
|
173
174
|
return items
|
|
174
175
|
}
|
|
175
176
|
|
|
177
|
+
export const grantFix = 'Turn it on in Settings.'
|
|
178
|
+
|
|
179
|
+
export const installFix = 'Install it in Plugins.'
|
|
180
|
+
|
|
181
|
+
export const secretFix = 'Set it in /config, where Claude Code keeps it in your keychain.'
|
|
182
|
+
|
|
176
183
|
export function permissionWords(item: string): string {
|
|
177
184
|
const split = item.indexOf(':')
|
|
178
185
|
const target = item.slice(split + 1)
|
|
@@ -211,12 +218,6 @@ export function isSettingCovered(granted: Iterable<string>, path: string): boole
|
|
|
211
218
|
return [...granted].some((each) => item === each || item.startsWith(`${each}.`))
|
|
212
219
|
}
|
|
213
220
|
|
|
214
|
-
export const settingsPagesMethod = 'cmod:settingsPages'
|
|
215
|
-
|
|
216
|
-
export const changelogPage = 'changelog'
|
|
217
|
-
|
|
218
|
-
export const openPageMethod = 'cmod:openPage'
|
|
219
|
-
|
|
220
221
|
export const pendingStepsMethod = 'cmod:pendingSteps'
|
|
221
222
|
|
|
222
223
|
export const finishStepsMethod = 'cmod:finishSteps'
|
|
@@ -239,6 +240,14 @@ export function consentPath(store: string): string {
|
|
|
239
240
|
return `${store}/consent.json`
|
|
240
241
|
}
|
|
241
242
|
|
|
243
|
+
export function pluginsChangedPath(store: string): string {
|
|
244
|
+
return `${store}/plugins-changed`
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
export function widgetsPath(store: string): string {
|
|
248
|
+
return `${store}/widgets.json`
|
|
249
|
+
}
|
|
250
|
+
|
|
242
251
|
export function parseConsent(value: unknown, path: string): Record<string, string[]> {
|
|
243
252
|
if (value === undefined) return Object.create(null)
|
|
244
253
|
if (!isObject(value) || Object.values(value).some((items) => !Array.isArray(items) || items.some((item) => typeof item !== 'string'))) {
|
|
@@ -247,29 +256,35 @@ export function parseConsent(value: unknown, path: string): Record<string, strin
|
|
|
247
256
|
return Object.assign(Object.create(null), value) as Record<string, string[]>
|
|
248
257
|
}
|
|
249
258
|
|
|
250
|
-
function
|
|
251
|
-
if (
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
259
|
+
function readHotkeys(hotkeys: unknown): Steps {
|
|
260
|
+
if (hotkeys === undefined) return {}
|
|
261
|
+
const fix = 'cmod check writes it from the hotkeys defineMod declares, so run cmod check.'
|
|
262
|
+
if (!isObject(hotkeys) || !Object.values(hotkeys).every((each) => isObject(each) && typeof each['title'] === 'string' && typeof each['default'] === 'string')) throw new Error(`package.json "cmod.hotkeys" is not a map of hotkeys to their title and default combo. ${fix}`)
|
|
263
|
+
return { hotkeys: checkHotkeys('package.json "cmod"', hotkeys as Record<string, HotkeyInit>) }
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
export const coreVersion = '4.0.1'
|
|
267
|
+
|
|
268
|
+
export function hotkeyCommand(mod: string, hotkey: string): string {
|
|
269
|
+
return `${mod}--${hotkey}`
|
|
260
270
|
}
|
|
261
271
|
|
|
262
|
-
export
|
|
272
|
+
export function hotkeyBindings(mod: string, hotkeys: Hotkeys | undefined): Record<string, string> {
|
|
273
|
+
return Object.fromEntries(Object.entries(hotkeys ?? {}).map(([name, { default: combo }]) => [combo, hotkeyCommand(mod, name)]))
|
|
274
|
+
}
|
|
263
275
|
|
|
264
|
-
export function
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
276
|
+
export function boundCombos(keybindings: unknown): Map<string, string> {
|
|
277
|
+
const blocks = isObject(keybindings) && Array.isArray(keybindings['bindings']) ? keybindings['bindings'] : []
|
|
278
|
+
const combos = new Map<string, string>()
|
|
279
|
+
for (const block of blocks) {
|
|
280
|
+
if (!isObject(block) || block['context'] !== 'Chat' || !isObject(block['bindings'])) continue
|
|
281
|
+
for (const [combo, action] of Object.entries(block['bindings'])) if (typeof action === 'string' && action.startsWith('command:')) combos.set(action.slice('command:'.length), combo)
|
|
282
|
+
}
|
|
283
|
+
return combos
|
|
269
284
|
}
|
|
270
285
|
|
|
271
|
-
export function
|
|
272
|
-
return listed(Object.
|
|
286
|
+
export function hotkeyWords(hotkeys: Hotkeys | undefined): string {
|
|
287
|
+
return listed(Object.values(hotkeys ?? {}).map(({ title, default: combo }) => `${combo} to ${title}`))
|
|
273
288
|
}
|
|
274
289
|
|
|
275
290
|
function readCommand(steps: Record<string, unknown>, key: 'install' | 'uninstall'): Steps {
|
|
@@ -314,7 +329,7 @@ export async function scriptsSha256(steps: Steps, files: { read: ReadFile; list:
|
|
|
314
329
|
steps.install ?? '',
|
|
315
330
|
steps.uninstall ?? '',
|
|
316
331
|
steps.program ?? '',
|
|
317
|
-
...(steps.
|
|
332
|
+
...(steps.hotkeys === undefined ? [] : [JSON.stringify(Object.entries(steps.hotkeys).sort())]),
|
|
318
333
|
...(steps.permissions === undefined ? [] : [JSON.stringify([...steps.permissions].sort())]),
|
|
319
334
|
].join('\0')
|
|
320
335
|
for (const folder of [...folders].sort()) {
|
|
@@ -336,7 +351,7 @@ export function formatEvent(event: RunnerEvent): string {
|
|
|
336
351
|
case 'log':
|
|
337
352
|
return `log ${event.text}`
|
|
338
353
|
case 'needs-consent':
|
|
339
|
-
return `needs-consent ${[event.sha256, event.install, event.uninstall, event.
|
|
354
|
+
return `needs-consent ${[event.sha256, event.install, event.uninstall, event.hotkeys, ...event.permissions].join('\t')}`
|
|
340
355
|
case 'done':
|
|
341
356
|
return event.version === undefined ? `done ${event.name}` : `done ${event.name} ${event.version}`
|
|
342
357
|
case 'missing':
|
|
@@ -353,8 +368,8 @@ export function parseEvent(line: string): RunnerEvent {
|
|
|
353
368
|
if (progress !== null) return { type: 'progress', done: Number(progress[1]), total: Number(progress[2]), label: progress[3] ?? '' }
|
|
354
369
|
const consent = /^needs-consent (\S+)\t([^\t]*)\t([^\t]*)(?:\t(.*))?$/.exec(line)
|
|
355
370
|
if (consent !== null) {
|
|
356
|
-
const [
|
|
357
|
-
return { type: 'needs-consent', sha256: consent[1] as string, install: consent[2] as string, uninstall: consent[3] as string,
|
|
371
|
+
const [hotkeys = '', ...permissions] = (consent[4] ?? '').split('\t')
|
|
372
|
+
return { type: 'needs-consent', sha256: consent[1] as string, install: consent[2] as string, uninstall: consent[3] as string, hotkeys, permissions: permissions.filter((item) => item !== '') }
|
|
358
373
|
}
|
|
359
374
|
const done = /^done (\S+)(?: (\S+))?$/.exec(line)
|
|
360
375
|
if (done !== null) return { type: 'done', name: done[1] as string, ...(done[2] === undefined ? {} : { version: done[2] }) }
|
package/src/register.ts
CHANGED
|
@@ -21,7 +21,6 @@ async function startMod($: EngineInterface, eventInput: Frozen<Args<'session.sta
|
|
|
21
21
|
const claude: Claude = {
|
|
22
22
|
plugin: { name: $.plugin.name, root: $.plugin.root },
|
|
23
23
|
ui: {
|
|
24
|
-
status: (text) => $.ui.status(text),
|
|
25
24
|
log: (text, options) => $.ui.log(text, options),
|
|
26
25
|
notice: (toolUseId, text) => $.ui.notice(toolUseId, text),
|
|
27
26
|
invalidate: (event) => $.ui.invalidate(event),
|
|
@@ -112,7 +111,7 @@ function routeCallFailure(_$: EngineInterface, eventInput: Frozen<Args<'cmod.cal
|
|
|
112
111
|
|
|
113
112
|
export function registerMod<State extends object, Declared extends Options>(addHook: On, definition: ModDefinition<State, string, Declared>, options: PluginOptions): void {
|
|
114
113
|
permissionCheck = undefined
|
|
115
|
-
registered = definition
|
|
114
|
+
registered = definition
|
|
116
115
|
lifecycle = createLifecycle(definition, () => permissionCheck, options)
|
|
117
116
|
addHook('session.start', startMod)
|
|
118
117
|
addHook('classic.Setup', routeToMod).catch(routeFailure)
|
|
@@ -142,13 +141,13 @@ export function registerMod<State extends object, Declared extends Options>(addH
|
|
|
142
141
|
addHook('classic.PostCompact', routeToMod).catch(routeFailure)
|
|
143
142
|
addHook('classic.Stop', routeToMod).catch(routeFailure)
|
|
144
143
|
addHook('classic.StopFailure', routeToMod).catch(routeFailure)
|
|
145
|
-
addHook('classic.FileChanged', routeToMod).catch(routeFailure)
|
|
146
144
|
addHook('classic.WorktreeCreate', routeToMod).catch(routeFailure)
|
|
147
145
|
addHook('classic.WorktreeRemove', routeToMod).catch(routeFailure)
|
|
148
146
|
addHook('tool.call', routeToMod).catch(routeFailure)
|
|
149
147
|
addHook('prompt.submit', routeToMod).catch(routeFailure)
|
|
150
148
|
addHook('prompt.context', routeToMod).catch(routeFailure)
|
|
151
149
|
addHook('command.run', routeToMod).catch(routeFailure)
|
|
150
|
+
addHook('command.describe', routeToMod).catch(routeFailure)
|
|
152
151
|
addHook('session.measure', routeToMod).catch(routeFailure)
|
|
153
152
|
addHook('skill.prompt', routeToMod).catch(routeFailure)
|
|
154
153
|
addHook('ui.render', routeToMod).catch(routeFailure)
|