@cmodjs/core 0.1.8 → 0.1.9
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 +2 -2
- package/docs/hooks.md +62 -6
- package/docs/index.md +6 -4
- package/docs/install-steps.md +3 -3
- package/docs/jobs.md +5 -4
- package/docs/mod.md +39 -7
- package/docs/testing.md +25 -9
- package/docs/ui.md +27 -3
- package/jobs/check.js +2 -2
- package/jobs/context.d.ts.map +1 -1
- package/jobs/context.js +2 -0
- package/jobs/permissions/decide-permission.js +2 -2
- package/jobs/permissions/find-project-scope.d.ts +1 -1
- package/jobs/permissions/find-project-scope.d.ts.map +1 -1
- package/jobs/permissions/find-project-scope.js +9 -9
- package/jobs/permissions/match-target.d.ts.map +1 -1
- package/jobs/permissions/match-target.js +4 -3
- package/mod.d.ts +15 -5
- package/mod.d.ts.map +1 -1
- package/package.json +2 -1
- package/path.d.ts +2 -0
- package/path.d.ts.map +1 -0
- package/path.js +1 -0
- package/register.d.ts.map +1 -1
- package/register.js +8 -2
- package/runtime/claude.d.ts +4 -1
- package/runtime/claude.d.ts.map +1 -1
- package/runtime/hooks.d.ts +10 -2
- package/runtime/hooks.d.ts.map +1 -1
- package/runtime/hooks.js +56 -18
- package/runtime/lifecycle.d.ts.map +1 -1
- package/runtime/lifecycle.js +12 -2
- package/runtime/ui.d.ts.map +1 -1
- package/runtime/ui.js +38 -8
- package/shell.d.ts +2 -0
- package/shell.d.ts.map +1 -0
- package/shell.js +1 -0
- package/src/jobs/check.ts +2 -2
- package/src/jobs/context.ts +2 -0
- package/src/jobs/permissions/decide-permission.ts +2 -2
- package/src/jobs/permissions/find-project-scope.ts +11 -10
- package/src/jobs/permissions/match-target.ts +4 -3
- package/src/mod.ts +22 -3
- package/src/path.ts +1 -0
- package/src/register.ts +8 -2
- package/src/runtime/claude.ts +11 -1
- package/src/runtime/hooks.ts +62 -23
- package/src/runtime/lifecycle.ts +11 -4
- package/src/runtime/ui.ts +35 -8
- package/src/shell.ts +1 -0
- package/src/testing/fake-claude.ts +14 -5
- package/src/testing/fake-elements.ts +5 -7
- package/src/testing/fake-files.ts +5 -5
- package/src/testing.ts +83 -11
- package/src/ui/define-pane.ts +5 -1
- package/src/utils/call-effects.ts +12 -11
- package/src/utils/parse-shell.ts +28 -36
- package/src/utils/paths.ts +4 -19
- package/src/vendor.ts +1 -0
- package/testing/fake-claude.d.ts +5 -0
- package/testing/fake-claude.d.ts.map +1 -1
- package/testing/fake-claude.js +13 -3
- package/testing/fake-elements.d.ts +5 -8
- package/testing/fake-elements.d.ts.map +1 -1
- package/testing/fake-elements.js +6 -6
- package/testing/fake-files.js +5 -5
- package/testing.d.ts +4 -2
- package/testing.d.ts.map +1 -1
- package/testing.js +65 -9
- package/ui/define-pane.d.ts +5 -1
- package/ui/define-pane.d.ts.map +1 -1
- package/utils/call-effects.d.ts.map +1 -1
- package/utils/call-effects.js +12 -11
- package/utils/parse-shell.d.ts +5 -9
- package/utils/parse-shell.d.ts.map +1 -1
- package/utils/parse-shell.js +5 -10
- package/utils/paths.d.ts +0 -3
- package/utils/paths.d.ts.map +1 -1
- package/utils/paths.js +3 -18
- package/vendor.d.ts +1 -0
- package/vendor.d.ts.map +1 -1
- package/vendor.js +209 -12
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"match-target.d.ts","sourceRoot":"","sources":["../../src/jobs/permissions/match-target.ts"],"names":[],"mappings":"AAEA,OAAO,EAAc,KAAK,QAAQ,EAAE,KAAK,WAAW,EAAE,KAAK,WAAW,EAAE,KAAK,SAAS,EAAE,KAAK,UAAU,EAAE,KAAK,QAAQ,EAAE,KAAK,QAAQ,EAAE,KAAK,OAAO,EAAE,MAAM,6BAA6B,CAAA;AACxL,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;
|
|
1
|
+
{"version":3,"file":"match-target.d.ts","sourceRoot":"","sources":["../../src/jobs/permissions/match-target.ts"],"names":[],"mappings":"AAEA,OAAO,EAAc,KAAK,QAAQ,EAAE,KAAK,WAAW,EAAE,KAAK,WAAW,EAAE,KAAK,SAAS,EAAE,KAAK,UAAU,EAAE,KAAK,QAAQ,EAAE,KAAK,QAAQ,EAAE,KAAK,OAAO,EAAE,MAAM,6BAA6B,CAAA;AACxL,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AAIxD,MAAM,MAAM,WAAW,GAAG;IAAE,OAAO,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,SAAS,CAAC;IAAC,QAAQ,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,QAAQ,CAAA;CAAE,CAAA;AACzI,MAAM,MAAM,SAAS,GAAG,MAAM,WAAW,CAAA;AACzC,MAAM,MAAM,QAAQ,CAAC,GAAG,SAAS,SAAS,IAAI,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC,EAAE,KAAK,CAAC,CAAC,CAAA;AAC9H,MAAM,MAAM,MAAM,GAAG;KAAG,GAAG,IAAI,SAAS,GAAG,QAAQ,CAAC,GAAG,CAAC;CAAE,CAAC,SAAS,CAAC,CAAA;AACrE,MAAM,MAAM,WAAW,GAAG;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,UAAU,GAAG,SAAS,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAA;AAI5F,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG;IAAE,GAAG,EAAE,SAAS,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAE,CAQ/E;AAED,wBAAsB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CA6BlI;AA4BD,wBAAsB,aAAa,CAAC,KAAK,EAAE,WAAW,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,EAAE,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAI/H"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { matchesGlob } from '../../utils/matches-glob.js';
|
|
2
2
|
import { parseShell } from '../../utils/parse-shell.js';
|
|
3
3
|
import { callBaseOf } from '../../utils/call-effects.js';
|
|
4
|
-
import {
|
|
4
|
+
import { realPathOf, relativePath } from '../../utils/paths.js';
|
|
5
|
+
import { basename } from '../../vendor.js';
|
|
5
6
|
const targetKeys = ['command', 'read', 'write', 'fetch', 'subagent', 'tool'];
|
|
6
7
|
export function targetOf(target) {
|
|
7
8
|
const keys = targetKeys.filter((key) => key in target);
|
|
@@ -51,10 +52,10 @@ function commandPattern(pattern) {
|
|
|
51
52
|
const command = parseShell(pattern).commands[0];
|
|
52
53
|
if (command === undefined)
|
|
53
54
|
throw new Error(`The command pattern '${pattern}' names no program.`);
|
|
54
|
-
return command;
|
|
55
|
+
return command.argv;
|
|
55
56
|
}
|
|
56
57
|
function commandMatches(pattern, argv) {
|
|
57
|
-
if (
|
|
58
|
+
if (basename(argv[0]) !== basename(pattern[0]))
|
|
58
59
|
return false;
|
|
59
60
|
const wanted = splitArguments(pattern.slice(1));
|
|
60
61
|
const actual = splitArguments(argv.slice(1));
|
package/mod.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AskOptions, ClassicHookInputs, CmodDependencies, FsEntry, HookStream, HttpInit, HttpResponse, PermissionRequestDecision, ProcessRunInit, ProcessRunResult, ProcessSpawnChunk, ProcessSpawnRequest, ProcessSpawnResult, RenderElement, Settings, SettingsReadArgs } from 'claude-code';
|
|
1
|
+
import type { AgentSpawnArgs, AgentSpawnResult, AskOptions, ClassicHookInputs, CmodDependencies, FsEntry, FsStat, FsStatOptions, HookStream, HttpInit, HttpResponse, PaneOpenArgs, PermissionRequestDecision, ProcessRunInit, ProcessRunResult, ProcessSpawnChunk, ProcessSpawnRequest, ProcessSpawnResult, RenderElement, Settings, SettingsReadArgs, UiScrollArgs, UiScrollResult } from 'claude-code';
|
|
2
2
|
import type { Claude } from './runtime/claude.js';
|
|
3
3
|
import type { RoutedEvent } from './runtime/hooks.js';
|
|
4
4
|
import type { RoutedHook } from './runtime/router.js';
|
|
@@ -11,16 +11,16 @@ export type ProgressStep = {
|
|
|
11
11
|
readonly label?: string;
|
|
12
12
|
};
|
|
13
13
|
export type PaneHandle = {
|
|
14
|
-
open(): Promise<void>;
|
|
14
|
+
open(options?: Readonly<Pick<PaneOpenArgs, 'focus'>>): Promise<void>;
|
|
15
15
|
close(): Promise<void>;
|
|
16
|
-
toggle(): Promise<void>;
|
|
16
|
+
toggle(options?: Readonly<Pick<PaneOpenArgs, 'focus'>>): Promise<void>;
|
|
17
17
|
readonly isOpen: boolean;
|
|
18
18
|
};
|
|
19
19
|
export type { Claude, RoutedEvent, RoutedHook, ToolCalls };
|
|
20
20
|
export { longestMs } from './runtime/deadline.js';
|
|
21
21
|
export { notInstalled } from './runtime/dependencies.js';
|
|
22
22
|
export { messageOf } from './utils/text.js';
|
|
23
|
-
export type ModEvent = 'SessionStart' | 'SessionEnd' | 'UserPromptSubmit' | 'InstructionsLoaded' | 'PreToolUse' | 'PermissionRequest' | 'PermissionDenied' | 'PostToolUse' | 'PostToolUseFailure' | 'PostToolBatch' | 'SubagentStart' | 'SubagentStop' | 'Notification' | 'PreCompact' | 'Stop' | 'StopFailure' | 'CwdChanged';
|
|
23
|
+
export type ModEvent = 'SessionStart' | 'SessionEnd' | 'UserPromptSubmit' | 'InstructionsLoaded' | 'PreToolUse' | 'PermissionRequest' | 'PermissionDenied' | 'PostToolUse' | 'PostToolUseFailure' | 'PostToolBatch' | 'SubagentStart' | 'SubagentStop' | 'Notification' | 'PreCompact' | 'Stop' | 'StopFailure' | 'CwdChanged' | 'FileChanged';
|
|
24
24
|
export type HookAnswer = {
|
|
25
25
|
continue?: boolean;
|
|
26
26
|
stopReason?: string;
|
|
@@ -69,7 +69,8 @@ type HookInputs = Omit<ClassicHookInputs, 'PreToolUse' | 'PostToolUse' | 'PostTo
|
|
|
69
69
|
};
|
|
70
70
|
CwdChanged: Omit<ClassicHookInputs['CwdChanged'], 'transcript_path'>;
|
|
71
71
|
};
|
|
72
|
-
export type
|
|
72
|
+
export type HookInput<E extends ModEvent> = HookInputs[E];
|
|
73
|
+
export type ModHook<E extends ModEvent> = (input: HookInput<E>) => HookAnswer | void | Promise<HookAnswer | void>;
|
|
73
74
|
export type Mod<State extends object = Record<never, never>> = {
|
|
74
75
|
readonly name: string;
|
|
75
76
|
readonly state: Readonly<State>;
|
|
@@ -82,6 +83,7 @@ export type Mod<State extends object = Record<never, never>> = {
|
|
|
82
83
|
toast(text: string): void;
|
|
83
84
|
progress<T>(title: string, task: (report: (step: ProgressStep) => void) => Promise<T>): Promise<T>;
|
|
84
85
|
ask(question: string, options?: readonly string[] | AskOptions): Promise<string>;
|
|
86
|
+
scroll(args: UiScrollArgs): Promise<UiScrollResult>;
|
|
85
87
|
};
|
|
86
88
|
readonly process: {
|
|
87
89
|
run(argv: readonly string[], init?: ProcessRunInit): Promise<ProcessRunResult>;
|
|
@@ -91,6 +93,8 @@ export type Mod<State extends object = Record<never, never>> = {
|
|
|
91
93
|
read(path: string): Promise<string>;
|
|
92
94
|
write(path: string, text: string): Promise<void>;
|
|
93
95
|
list(path?: string): Promise<FsEntry[]>;
|
|
96
|
+
exists(path: string): Promise<boolean>;
|
|
97
|
+
stat(path: string, options?: FsStatOptions): Promise<FsStat>;
|
|
94
98
|
};
|
|
95
99
|
readonly http: {
|
|
96
100
|
fetch(url: string, init?: HttpInit): Promise<HttpResponse>;
|
|
@@ -98,6 +102,12 @@ export type Mod<State extends object = Record<never, never>> = {
|
|
|
98
102
|
readonly settings: {
|
|
99
103
|
read(args?: SettingsReadArgs): Promise<Settings>;
|
|
100
104
|
};
|
|
105
|
+
readonly session: {
|
|
106
|
+
messages: Claude['session']['messages'];
|
|
107
|
+
};
|
|
108
|
+
readonly agent: {
|
|
109
|
+
spawn(args: AgentSpawnArgs): Promise<AgentSpawnResult>;
|
|
110
|
+
};
|
|
101
111
|
readonly projectRoot: string;
|
|
102
112
|
readonly cwd: string;
|
|
103
113
|
readonly dependencies: CmodDependencies;
|
package/mod.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["src/mod.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,UAAU,EACV,iBAAiB,EACjB,gBAAgB,EAChB,OAAO,EACP,UAAU,EACV,QAAQ,EACR,YAAY,EACZ,yBAAyB,EACzB,cAAc,EACd,gBAAgB,EAChB,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,EAClB,aAAa,EACb,QAAQ,EACR,gBAAgB,
|
|
1
|
+
{"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["src/mod.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cmodjs/core",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.9",
|
|
4
4
|
"description": "Build Claude Code mods: hooks, panes, permissions, checks, and an install that just works.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -43,6 +43,7 @@
|
|
|
43
43
|
"mdast-util-to-string": "^4.0.0",
|
|
44
44
|
"micromark-extension-gfm": "^3.0.0",
|
|
45
45
|
"oxlint": "1.86.0",
|
|
46
|
+
"pathe": "^2.0.3",
|
|
46
47
|
"picomatch": "^4.0.7",
|
|
47
48
|
"shell-quote": "^1.12.0",
|
|
48
49
|
"typescript": "^7.0.2"
|
package/path.d.ts
ADDED
package/path.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"path.d.ts","sourceRoot":"","sources":["src/path.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA"}
|
package/path.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { basename, dirname, extname, isAbsolute, join, normalize, relative, resolve } from './vendor.js';
|
package/register.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"register.d.ts","sourceRoot":"","sources":["src/register.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAoD,EAAE,EAAE,MAAM,aAAa,CAAA;AACvF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;
|
|
1
|
+
{"version":3,"file":"register.d.ts","sourceRoot":"","sources":["src/register.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAoD,EAAE,EAAE,MAAM,aAAa,CAAA;AACvF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AA+E7C,wBAAgB,WAAW,CAAC,KAAK,SAAS,MAAM,EAAE,OAAO,EAAE,EAAE,EAAE,UAAU,EAAE,aAAa,CAAC,KAAK,CAAC,GAAG,IAAI,CA8BrG;AAED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,EAAE,GAAG,IAAI,CAIzD"}
|
package/register.js
CHANGED
|
@@ -14,6 +14,7 @@ async function startMod($, eventInput, passOn) {
|
|
|
14
14
|
open: (pane) => $.ui.open(pane),
|
|
15
15
|
close: (pane) => $.ui.close(pane),
|
|
16
16
|
panes: () => $.ui.panes(),
|
|
17
|
+
scroll: (args) => $.ui.scroll(args),
|
|
17
18
|
resolve: (render) => $.ui.resolve(render),
|
|
18
19
|
},
|
|
19
20
|
process: {
|
|
@@ -47,10 +48,14 @@ async function startMod($, eventInput, passOn) {
|
|
|
47
48
|
model: () => $.session.model(),
|
|
48
49
|
usage: () => $.session.usage(),
|
|
49
50
|
surfaces: () => $.session.surfaces(),
|
|
51
|
+
messages: ((args) => (args === undefined ? $.session.messages() : $.session.messages(args))),
|
|
50
52
|
},
|
|
51
53
|
command: { register: (command) => $.command.register(command) },
|
|
52
54
|
tool: { register: (tool) => $.tool.register(tool) },
|
|
53
|
-
agent: {
|
|
55
|
+
agent: {
|
|
56
|
+
list: () => $.agent.list(),
|
|
57
|
+
spawn: (args) => $.agent.spawn(args),
|
|
58
|
+
},
|
|
54
59
|
env: {
|
|
55
60
|
home: () => $.env.get('HOME'),
|
|
56
61
|
dataHome: () => $.env.get('XDG_DATA_HOME'),
|
|
@@ -82,6 +87,7 @@ export function registerMod(addHook, definition) {
|
|
|
82
87
|
addHook('classic.PreCompact', routeToMod);
|
|
83
88
|
addHook('classic.Stop', routeToMod);
|
|
84
89
|
addHook('classic.StopFailure', routeToMod);
|
|
90
|
+
addHook('classic.FileChanged', routeToMod);
|
|
85
91
|
addHook('tool.call', routeToMod);
|
|
86
92
|
addHook('prompt.submit', routeToMod);
|
|
87
93
|
addHook('prompt.context', routeToMod);
|
|
@@ -90,12 +96,12 @@ export function registerMod(addHook, definition) {
|
|
|
90
96
|
addHook('skill.prompt', routeToMod);
|
|
91
97
|
addHook('ui.render', routeToMod);
|
|
92
98
|
addHook('ui.press', routeToMod);
|
|
99
|
+
addHook('ui.scroll', routeToMod);
|
|
93
100
|
addHook('ui.close', routeToMod);
|
|
94
101
|
addHook('cmod.call', routeToMod);
|
|
95
102
|
}
|
|
96
103
|
export function registerPermissionCheck(addHook) {
|
|
97
104
|
checksPermissions = true;
|
|
98
105
|
addHook('tool.check', routeToMod);
|
|
99
|
-
addHook('classic.PreToolUse', routeToMod);
|
|
100
106
|
addHook('classic.PermissionRequest', routeToMod);
|
|
101
107
|
}
|
package/runtime/claude.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AgentInfo, Args, AskOptions, CommandSpec, ElementTable, FsEntry, FsStat, FsStatOptions, HookStream, HttpInit, HttpResponse, InvalidatableEventName, PaneCloseArgs, PaneOpenArgs, ProcessRunInit, ProcessRunResult, ProcessSpawnChunk, ProcessSpawnRequest, ProcessSpawnResult, RenderSurface, ResolveInput, SessionUsage, Settings, SettingsReadArgs, Timer, ToastOptions, ToolSpec, UiLogOptions, UiOpenResult, UiPane } from 'claude-code';
|
|
1
|
+
import type { AgentInfo, AgentSpawnArgs, AgentSpawnResult, Args, EngineInterface, AskOptions, CommandSpec, ElementTable, FsEntry, FsStat, FsStatOptions, HookStream, HttpInit, HttpResponse, InvalidatableEventName, PaneCloseArgs, PaneOpenArgs, ProcessRunInit, ProcessRunResult, ProcessSpawnChunk, ProcessSpawnRequest, ProcessSpawnResult, RenderSurface, ResolveInput, SessionUsage, Settings, SettingsReadArgs, Timer, ToastOptions, ToolSpec, UiLogOptions, UiOpenResult, UiPane, UiScrollArgs, UiScrollResult } from 'claude-code';
|
|
2
2
|
export type Claude = {
|
|
3
3
|
readonly plugin: {
|
|
4
4
|
readonly name: string;
|
|
@@ -14,6 +14,7 @@ export type Claude = {
|
|
|
14
14
|
open(pane: PaneOpenArgs): Promise<UiOpenResult>;
|
|
15
15
|
close(pane: PaneCloseArgs): Promise<void>;
|
|
16
16
|
panes(): Promise<readonly UiPane[]>;
|
|
17
|
+
scroll(args: UiScrollArgs): Promise<UiScrollResult>;
|
|
17
18
|
resolve(e: ResolveInput): ElementTable<RenderSurface>;
|
|
18
19
|
};
|
|
19
20
|
readonly process: {
|
|
@@ -51,6 +52,7 @@ export type Claude = {
|
|
|
51
52
|
model(): Promise<string>;
|
|
52
53
|
usage(): Promise<SessionUsage>;
|
|
53
54
|
surfaces(): Promise<readonly RenderSurface[]>;
|
|
55
|
+
messages: EngineInterface['session']['messages'];
|
|
54
56
|
};
|
|
55
57
|
readonly command: {
|
|
56
58
|
register(command: CommandSpec): Promise<{
|
|
@@ -64,6 +66,7 @@ export type Claude = {
|
|
|
64
66
|
};
|
|
65
67
|
readonly agent: {
|
|
66
68
|
list(): Promise<AgentInfo[]>;
|
|
69
|
+
spawn(args: AgentSpawnArgs): Promise<AgentSpawnResult>;
|
|
67
70
|
};
|
|
68
71
|
readonly env: {
|
|
69
72
|
home(): Promise<string | undefined>;
|
package/runtime/claude.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude.d.ts","sourceRoot":"","sources":["../src/runtime/claude.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,SAAS,EACT,IAAI,EACJ,UAAU,EACV,WAAW,EACX,YAAY,EACZ,OAAO,EACP,MAAM,EACN,aAAa,EACb,UAAU,EACV,QAAQ,EACR,YAAY,EACZ,sBAAsB,EACtB,aAAa,EACb,YAAY,EACZ,cAAc,EACd,gBAAgB,EAChB,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,EAClB,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,QAAQ,EACR,gBAAgB,EAChB,KAAK,EACL,YAAY,EACZ,QAAQ,EACR,YAAY,EACZ,YAAY,EACZ,MAAM,
|
|
1
|
+
{"version":3,"file":"claude.d.ts","sourceRoot":"","sources":["../src/runtime/claude.ts"],"names":[],"mappings":"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"}
|
package/runtime/hooks.d.ts
CHANGED
|
@@ -2,9 +2,17 @@ import type { ModEvent, ModHook } from '../mod.js';
|
|
|
2
2
|
import type { Claude } from './claude.js';
|
|
3
3
|
import type { RoutedHook } from './router.js';
|
|
4
4
|
import { type ToolCalls } from './tool-calls.js';
|
|
5
|
-
export type RoutedEvent = `classic.${ModEvent}` | 'tool.check' | 'tool.call' | 'prompt.submit' | 'prompt.context' | 'command.run' | 'session.measure' | 'skill.prompt' | 'ui.render' | 'ui.press' | 'ui.close' | 'cmod.call';
|
|
5
|
+
export type RoutedEvent = `classic.${Exclude<ModEvent, 'PreToolUse'>}` | 'tool.check' | 'tool.call' | 'prompt.submit' | 'prompt.context' | 'command.run' | 'session.measure' | 'skill.prompt' | 'ui.render' | 'ui.press' | 'ui.scroll' | 'ui.close' | 'cmod.call';
|
|
6
6
|
export declare const permissionEvents: readonly RoutedEvent[];
|
|
7
|
-
export declare function classicHook<E extends ModEvent
|
|
7
|
+
export declare function classicHook<E extends Exclude<ModEvent, 'PreToolUse'>>(name: string, event: E, hook: ModHook<E>, claude: Claude, calls: ToolCalls): RoutedHook<RoutedEvent>;
|
|
8
|
+
type HeldDecision = {
|
|
9
|
+
readonly decision: 'allow' | 'ask';
|
|
10
|
+
readonly reason?: string;
|
|
11
|
+
};
|
|
12
|
+
export type HeldDecisions = Map<string, HeldDecision>;
|
|
13
|
+
export declare function preToolUseHook(name: string, hook: ModHook<'PreToolUse'>, claude: Claude, calls: ToolCalls, held: HeldDecisions | undefined): RoutedHook<'tool.call'>;
|
|
14
|
+
export declare function heldDecisionHook(held: HeldDecisions): RoutedHook<'tool.check'>;
|
|
8
15
|
export declare function userSkillHook(claude: Claude): RoutedHook<'skill.prompt'>;
|
|
9
16
|
export declare const strictness: readonly ['allow', 'ask', 'deny'];
|
|
17
|
+
export {};
|
|
10
18
|
//# sourceMappingURL=hooks.d.ts.map
|
package/runtime/hooks.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../src/runtime/hooks.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../src/runtime/hooks.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAyB,QAAQ,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAEzE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAC7C,OAAO,EAA6B,KAAK,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAK3E,MAAM,MAAM,WAAW,GACnB,WAAW,OAAO,CAAC,QAAQ,EAAE,YAAY,CAAC,EAAE,GAC5C,YAAY,GACZ,WAAW,GACX,eAAe,GACf,gBAAgB,GAChB,aAAa,GACb,iBAAiB,GACjB,cAAc,GACd,WAAW,GACX,UAAU,GACV,WAAW,GACX,UAAU,GACV,WAAW,CAAA;AAEf,eAAO,MAAM,gBAAgB,EAAE,SAAS,WAAW,EAAgD,CAAA;AA6BnG,wBAAgB,WAAW,CAAC,CAAC,SAAS,OAAO,CAAC,QAAQ,EAAE,YAAY,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,GAAG,UAAU,CAAC,WAAW,CAAC,CAwB1K;AAED,KAAK,YAAY,GAAG;IAAE,QAAQ,CAAC,QAAQ,EAAE,OAAO,GAAG,KAAK,CAAC;IAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;AAEpF,MAAM,MAAM,aAAa,GAAG,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAAA;AAErD,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,YAAY,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,aAAa,GAAG,SAAS,GAAG,UAAU,CAAC,WAAW,CAAC,CA6BpK;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,aAAa,GAAG,UAAU,CAAC,YAAY,CAAC,CAM9E;AAYD,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,CAAC,cAAc,CAAC,CAexE;AA4DD,eAAO,MAAM,UAAU,YAAI,OAAO,EAAE,KAAK,EAAE,MAAM,CAAU,CAAA"}
|
package/runtime/hooks.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { configFolders } from '../records.js';
|
|
2
|
-
import { toolInputOf } from './tool-calls.js';
|
|
2
|
+
import { reservedKeys, toolInputOf } from './tool-calls.js';
|
|
3
3
|
import { callEffects } from '../utils/call-effects.js';
|
|
4
4
|
import { dynamicPattern } from '../utils/parse-shell.js';
|
|
5
5
|
import { messageOf } from '../utils/text.js';
|
|
6
|
-
export const permissionEvents = ['tool.check', 'classic.
|
|
6
|
+
export const permissionEvents = ['tool.check', 'classic.PermissionRequest'];
|
|
7
7
|
const flags = ['suppressOriginalPrompt', 'reloadSkills', 'retry'];
|
|
8
8
|
const readFields = {
|
|
9
9
|
SessionStart: ['additionalContext', 'initialUserMessage', 'sessionTitle', 'watchPaths', 'reloadSkills'],
|
|
@@ -23,11 +23,10 @@ const readFields = {
|
|
|
23
23
|
Stop: ['additionalContext'],
|
|
24
24
|
StopFailure: [],
|
|
25
25
|
CwdChanged: [],
|
|
26
|
+
FileChanged: [],
|
|
26
27
|
};
|
|
27
28
|
export function classicHook(name, event, hook, claude, calls) {
|
|
28
29
|
const inputOf = async (e) => {
|
|
29
|
-
if (event === 'PreToolUse')
|
|
30
|
-
return preToolUseInput(name, e, claude, calls.agentOf);
|
|
31
30
|
if (event !== 'PostToolUse' && event !== 'PostToolUseFailure')
|
|
32
31
|
return e;
|
|
33
32
|
const input = e;
|
|
@@ -45,8 +44,6 @@ export function classicHook(name, event, hook, claude, calls) {
|
|
|
45
44
|
const routed = async (e, next) => {
|
|
46
45
|
const ours = await resultOf(e).catch((error) => {
|
|
47
46
|
const reason = `${name}: the ${event} hook failed: ${messageOf(error)}`;
|
|
48
|
-
if (event === 'PreToolUse')
|
|
49
|
-
return { deny: reason };
|
|
50
47
|
if (event === 'PermissionRequest')
|
|
51
48
|
return { decision: { behavior: 'deny', message: reason } };
|
|
52
49
|
claude.ui.log(reason);
|
|
@@ -54,10 +51,61 @@ export function classicHook(name, event, hook, claude, calls) {
|
|
|
54
51
|
});
|
|
55
52
|
if (ours === undefined)
|
|
56
53
|
return next(e);
|
|
57
|
-
return mergeClassic(
|
|
54
|
+
return mergeClassic((await next(e)), ours);
|
|
58
55
|
};
|
|
59
56
|
return routed;
|
|
60
57
|
}
|
|
58
|
+
export function preToolUseHook(name, hook, claude, calls, held) {
|
|
59
|
+
return async (e, next) => {
|
|
60
|
+
let ours;
|
|
61
|
+
try {
|
|
62
|
+
const answer = await hook(await preToolUseInput(name, e, claude, calls.agentOf));
|
|
63
|
+
if (answer?.systemMessage !== undefined)
|
|
64
|
+
claude.ui.log(answer.systemMessage);
|
|
65
|
+
ours = answer === undefined ? {} : classicResult('PreToolUse', answer);
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
return { deny: `${name}: the PreToolUse hook failed: ${messageOf(error)}` };
|
|
69
|
+
}
|
|
70
|
+
if (typeof ours['deny'] === 'string')
|
|
71
|
+
return { deny: ours['deny'] };
|
|
72
|
+
const decided = heldDecisionOf(ours);
|
|
73
|
+
if (decided !== undefined && held === undefined) {
|
|
74
|
+
return { deny: `${name}: the PreToolUse hook answered permissionDecision "${decided.decision}", so hooks/register.ts must call registerPermissionCheck(addHook) after registerMod.` };
|
|
75
|
+
}
|
|
76
|
+
const updated = ours['updatedInput'];
|
|
77
|
+
const reserved = Object.fromEntries(Object.entries(e).filter(([key]) => reservedKeys.includes(key)));
|
|
78
|
+
const earlier = held?.get(e.tool_use_id);
|
|
79
|
+
if (decided !== undefined)
|
|
80
|
+
held?.set(e.tool_use_id, earlier !== undefined && strictness.indexOf(earlier.decision) >= strictness.indexOf(decided.decision) ? earlier : decided);
|
|
81
|
+
let result;
|
|
82
|
+
try {
|
|
83
|
+
result = await next(updated === undefined ? e : { ...reserved, ...updated });
|
|
84
|
+
}
|
|
85
|
+
finally {
|
|
86
|
+
if (decided !== undefined)
|
|
87
|
+
held?.delete(e.tool_use_id);
|
|
88
|
+
}
|
|
89
|
+
const context = ours['additionalContext'];
|
|
90
|
+
if (context === undefined || result.deny !== undefined)
|
|
91
|
+
return result;
|
|
92
|
+
return { ...result, context: [...(result.context ?? []), ...context] };
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
export function heldDecisionHook(held) {
|
|
96
|
+
return async (e, next) => {
|
|
97
|
+
const below = await next(e);
|
|
98
|
+
const ours = e.tool_use_id === undefined ? undefined : held.get(e.tool_use_id);
|
|
99
|
+
return ours === undefined || below.decision === 'deny' ? below : ours;
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
function heldDecisionOf(ours) {
|
|
103
|
+
if (ours['allow'] !== undefined)
|
|
104
|
+
return { decision: 'allow' };
|
|
105
|
+
if (typeof ours['ask'] !== 'string')
|
|
106
|
+
return undefined;
|
|
107
|
+
return ours['ask'] === '' ? { decision: 'ask' } : { decision: 'ask', reason: ours['ask'] };
|
|
108
|
+
}
|
|
61
109
|
const frontmatter = /^---\r?\n[\s\S]*?\r?\n---[ \t]*(?:\r?\n|$)/;
|
|
62
110
|
const baseDirectoryLine = /^Base directory for this skill: [^\n]*\n\n/;
|
|
63
111
|
export function userSkillHook(claude) {
|
|
@@ -149,20 +197,10 @@ function classicResult(event, answer) {
|
|
|
149
197
|
return result;
|
|
150
198
|
}
|
|
151
199
|
export const strictness = ['allow', 'ask', 'deny'];
|
|
152
|
-
function
|
|
153
|
-
return strictness.findLastIndex((decision) => result[decision] !== undefined);
|
|
154
|
-
}
|
|
155
|
-
function mergeClassic(event, below, ours) {
|
|
200
|
+
function mergeClassic(below, ours) {
|
|
156
201
|
const merged = { ...below, ...ours };
|
|
157
202
|
const context = [...(below['additionalContext'] ?? []), ...(ours['additionalContext'] ?? [])];
|
|
158
203
|
if (context.length > 0)
|
|
159
204
|
merged['additionalContext'] = context;
|
|
160
|
-
if (event !== 'PreToolUse')
|
|
161
|
-
return merged;
|
|
162
|
-
const strictest = strictness[Math.max(strictnessOf(below), strictnessOf(ours))];
|
|
163
|
-
for (const decision of strictness)
|
|
164
|
-
delete merged[decision];
|
|
165
|
-
if (strictest !== undefined)
|
|
166
|
-
merged[strictest] = ours[strictest] ?? below[strictest];
|
|
167
205
|
return merged;
|
|
168
206
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lifecycle.d.ts","sourceRoot":"","sources":["../src/runtime/lifecycle.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAiE,MAAM,aAAa,CAAA;AAC3H,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"lifecycle.d.ts","sourceRoot":"","sources":["../src/runtime/lifecycle.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAiE,MAAM,aAAa,CAAA;AAC3H,OAAO,KAAK,EAAa,GAAG,EAAE,aAAa,EAAqB,MAAM,WAAW,CAAA;AAIjF,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAGzC,OAAO,EAAsG,KAAK,WAAW,EAAE,MAAM,YAAY,CAAA;AACjJ,OAAO,EAA6B,KAAK,UAAU,EAAE,MAAM,aAAa,CAAA;AAKxE,MAAM,MAAM,MAAM,GAAG;IACnB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,CAAA;IACpC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAA;IAC7B,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAA;CAC/B,CAAA;AAED,MAAM,MAAM,KAAK,GAAG,UAAU,GAAG,YAAY,GAAG,SAAS,GAAG,UAAU,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,CAAA;AAEtG,MAAM,MAAM,SAAS,CAAC,KAAK,SAAS,MAAM,IAAI;IAC5C,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAA;IACrB,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC,KAAK,CAAC,GAAG,SAAS,CAAA;IACpC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC/E,KAAK,CAAC,CAAC,SAAS,WAAW,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAA;CACzG,CAAA;AAiCD,wBAAsB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAyBhE;AAkCD,wBAAgB,eAAe,CAAC,KAAK,SAAS,MAAM,EAAE,UAAU,EAAE,aAAa,CAAC,KAAK,CAAC,EAAE,iBAAiB,GAAE,MAAM,OAAoB,GAAG,SAAS,CAAC,KAAK,CAAC,CAkOvJ"}
|
package/runtime/lifecycle.js
CHANGED
|
@@ -3,7 +3,7 @@ import { relativePath } from '../utils/paths.js';
|
|
|
3
3
|
import { formatExit, listed, messageOf } from '../utils/text.js';
|
|
4
4
|
import { beforeDeadline } from './deadline.js';
|
|
5
5
|
import { answerCall, dependencyCalls, notInstalled } from './dependencies.js';
|
|
6
|
-
import { classicHook, permissionEvents, userSkillHook } from './hooks.js';
|
|
6
|
+
import { classicHook, heldDecisionHook, permissionEvents, preToolUseHook, userSkillHook } from './hooks.js';
|
|
7
7
|
import { createRouter } from './router.js';
|
|
8
8
|
import { createState } from './state.js';
|
|
9
9
|
import { toolCalls } from './tool-calls.js';
|
|
@@ -332,6 +332,7 @@ async function createMod(definition, runtime) {
|
|
|
332
332
|
let staleCwd;
|
|
333
333
|
const area = createUi({ name: definition.name, claude, router, progress, announce, mod: () => mod });
|
|
334
334
|
const modState = createState({ name: definition.name, initial: definition.state ?? {}, session, root, claude, changed: area.changed });
|
|
335
|
+
const held = runtime.checksPermissions() ? new Map() : undefined;
|
|
335
336
|
const mod = {
|
|
336
337
|
name: definition.name,
|
|
337
338
|
state: modState.state,
|
|
@@ -339,7 +340,10 @@ async function createMod(definition, runtime) {
|
|
|
339
340
|
on(event, hook) {
|
|
340
341
|
if (!hookEvents.includes(event))
|
|
341
342
|
hookEvents.push(event);
|
|
342
|
-
|
|
343
|
+
if (event === 'PreToolUse')
|
|
344
|
+
router.add('tool.call', preToolUseHook(definition.name, hook, claude, agents, held));
|
|
345
|
+
else
|
|
346
|
+
router.add(`classic.${event}`, classicHook(definition.name, event, hook, claude, agents));
|
|
343
347
|
},
|
|
344
348
|
use: (job) => job({ mod, claude, on: (event, hook) => router.add(event, hook), announce, reserveName, toolCalls: agents }),
|
|
345
349
|
ui: area.ui,
|
|
@@ -351,9 +355,13 @@ async function createMod(definition, runtime) {
|
|
|
351
355
|
read: (path) => claude.fs.read(path),
|
|
352
356
|
write: (path, text) => claude.fs.write(path, text),
|
|
353
357
|
list: (path) => claude.fs.list(path),
|
|
358
|
+
exists: (path) => claude.fs.exists(path),
|
|
359
|
+
stat: (path, options) => claude.fs.stat(path, options),
|
|
354
360
|
},
|
|
355
361
|
http: { fetch: (url, init) => claude.http.fetch(url, init) },
|
|
356
362
|
settings: { read: (args) => claude.settings.read(args) },
|
|
363
|
+
session: { messages: claude.session.messages },
|
|
364
|
+
agent: { spawn: (args) => claude.agent.spawn(args) },
|
|
357
365
|
get projectRoot() {
|
|
358
366
|
return modState.root;
|
|
359
367
|
},
|
|
@@ -433,6 +441,8 @@ async function createMod(definition, runtime) {
|
|
|
433
441
|
if (permissionHooks.length > 0 && !runtime.checksPermissions()) {
|
|
434
442
|
throw new Error(`it decides permissions on ${listed(permissionHooks)}, so hooks/register.ts must call registerPermissionCheck(addHook) after registerMod`);
|
|
435
443
|
}
|
|
444
|
+
if (held !== undefined && hookEvents.includes('PreToolUse'))
|
|
445
|
+
router.add('tool.check', heldDecisionHook(held));
|
|
436
446
|
await failsAs('its open panes did not load', () => area.restorePanes());
|
|
437
447
|
if (hookEvents.length > 0)
|
|
438
448
|
added.push(`${hookEvents.length === 1 ? 'a hook' : 'hooks'} on ${listed(hookEvents)}`);
|
package/runtime/ui.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../src/runtime/ui.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAA+B,aAAa,EAAS,MAAM,aAAa,CAAA;AAClG,OAAO,KAAK,EAAE,GAAG,EAAc,YAAY,EAAE,MAAM,WAAW,CAAA;AAM9D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAEzC,MAAM,MAAM,YAAY,GAAG;IACzB,MAAM,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI,CAAA;IAChC,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;IACvC,GAAG,IAAI,IAAI,CAAA;CACZ,CAAA;AAED,MAAM,MAAM,QAAQ,GAAG;IACrB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,YAAY,CAAA;IAClC,IAAI,CAAC,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,aAAa,CAAA;CAC5F,CAAA;AAkBD,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ,CAqDvD;AAqHD,MAAM,MAAM,SAAS,CAAC,KAAK,SAAS,MAAM,IAAI;IAC5C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAA;IAC3B,QAAQ,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;IAC5C,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,CAAC,KAAK,CAAC,CAAA;CAC/B,CAAA;AAED,MAAM,MAAM,MAAM,CAAC,KAAK,SAAS,MAAM,IAAI;IACzC,QAAQ,CAAC,EAAE,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAA;IAC7B,OAAO,IAAI,IAAI,CAAA;IACf,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CAC9B,CAAA;AAED,wBAAgB,QAAQ,CAAC,KAAK,SAAS,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,EAAE,EAAE,SAAS,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,
|
|
1
|
+
{"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../src/runtime/ui.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAA+B,aAAa,EAAS,MAAM,aAAa,CAAA;AAClG,OAAO,KAAK,EAAE,GAAG,EAAc,YAAY,EAAE,MAAM,WAAW,CAAA;AAM9D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAEzC,MAAM,MAAM,YAAY,GAAG;IACzB,MAAM,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI,CAAA;IAChC,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;IACvC,GAAG,IAAI,IAAI,CAAA;CACZ,CAAA;AAED,MAAM,MAAM,QAAQ,GAAG;IACrB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,YAAY,CAAA;IAClC,IAAI,CAAC,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,aAAa,CAAA;CAC5F,CAAA;AAkBD,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ,CAqDvD;AAqHD,MAAM,MAAM,SAAS,CAAC,KAAK,SAAS,MAAM,IAAI;IAC5C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAA;IAC3B,QAAQ,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;IAC5C,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,CAAC,KAAK,CAAC,CAAA;CAC/B,CAAA;AAED,MAAM,MAAM,MAAM,CAAC,KAAK,SAAS,MAAM,IAAI;IACzC,QAAQ,CAAC,EAAE,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAA;IAC7B,OAAO,IAAI,IAAI,CAAA;IACf,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CAC9B,CAAA;AAED,wBAAgB,QAAQ,CAAC,KAAK,SAAS,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,EAAE,EAAE,SAAS,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAmNjI"}
|
package/runtime/ui.js
CHANGED
|
@@ -165,6 +165,7 @@ function drawPieces(pieces, place) {
|
|
|
165
165
|
}
|
|
166
166
|
export function createUi({ name, claude, router, progress, announce, mod }) {
|
|
167
167
|
const panes = new Map();
|
|
168
|
+
const paneLogs = new Map();
|
|
168
169
|
const openPanes = new Set();
|
|
169
170
|
const requestedSizes = new Map();
|
|
170
171
|
const renders = new Set();
|
|
@@ -231,9 +232,10 @@ export function createUi({ name, claude, router, progress, announce, mod }) {
|
|
|
231
232
|
return drawWith(table, () => drawPieces(drawn, e.props.isFirstOfReply ? 'opensReply' : 'inReply'));
|
|
232
233
|
});
|
|
233
234
|
};
|
|
234
|
-
const openAt = (pane, size) => {
|
|
235
|
+
const openAt = (pane, size, focus) => {
|
|
235
236
|
requestedSizes.set(pane.id, size);
|
|
236
|
-
|
|
237
|
+
const { id, title, closeOnEscape, holdToasts } = pane;
|
|
238
|
+
return claude.ui.open({ id, title, ...size, ...(closeOnEscape === true ? { closeOnEscape } : {}), ...(holdToasts === true ? { holdToasts } : {}), ...(focus === true ? { focus } : {}) });
|
|
237
239
|
};
|
|
238
240
|
const resize = async (pane) => {
|
|
239
241
|
try {
|
|
@@ -257,27 +259,54 @@ export function createUi({ name, claude, router, progress, announce, mod }) {
|
|
|
257
259
|
return next(e);
|
|
258
260
|
openPanes.add(pane.id);
|
|
259
261
|
const table = claude.ui.resolve(e);
|
|
260
|
-
|
|
262
|
+
try {
|
|
263
|
+
return drawWith(table, () => pane.render(mod(), e.props), markdownIn(table));
|
|
264
|
+
}
|
|
265
|
+
catch (error) {
|
|
266
|
+
paneLogs.get(pane.id)?.(`threw: ${messageOf(error)}`);
|
|
267
|
+
return drawWith(table, () => Text({ color: 'error', children: `The ${pane.title} pane could not draw: ${messageOf(error)}` }));
|
|
268
|
+
}
|
|
261
269
|
});
|
|
262
|
-
router.add('ui.
|
|
270
|
+
router.add('ui.scroll', async (e, next) => {
|
|
271
|
+
const pane = panes.get(e.requestId);
|
|
272
|
+
const moved = await next(e);
|
|
273
|
+
if (pane?.onScroll === undefined || e.component !== 'Pane' || moved.deny !== undefined)
|
|
274
|
+
return moved;
|
|
275
|
+
await handle(pane, 'onScroll', () => pane.onScroll?.(mod(), e));
|
|
276
|
+
return moved;
|
|
277
|
+
});
|
|
278
|
+
router.add('ui.close', async (e, next) => {
|
|
263
279
|
openPanes.delete(e.id);
|
|
264
|
-
|
|
280
|
+
const closed = await next(e);
|
|
281
|
+
const pane = panes.get(e.id);
|
|
282
|
+
if (pane?.onClose !== undefined)
|
|
283
|
+
await handle(pane, 'onClose', () => pane.onClose?.(mod(), e));
|
|
284
|
+
return closed;
|
|
265
285
|
});
|
|
266
286
|
};
|
|
287
|
+
const handle = async (pane, handler, run) => {
|
|
288
|
+
try {
|
|
289
|
+
await run();
|
|
290
|
+
}
|
|
291
|
+
catch (error) {
|
|
292
|
+
claude.ui.log(`${name}: the ${pane.title} pane's ${handler} threw: ${messageOf(error)}`);
|
|
293
|
+
}
|
|
294
|
+
};
|
|
267
295
|
return {
|
|
268
296
|
ui: {
|
|
269
297
|
pane(pane) {
|
|
270
298
|
if (panes.has(pane.id))
|
|
271
299
|
throw new Error(`${name}: the pane "${pane.id}" is already added. Give each pane its own id.`);
|
|
272
300
|
panes.set(pane.id, pane);
|
|
301
|
+
paneLogs.set(pane.id, logOnce(`${pane.title} pane`));
|
|
273
302
|
announce(`the ${pane.title} pane`);
|
|
274
303
|
route();
|
|
275
304
|
const handle = {
|
|
276
305
|
get isOpen() {
|
|
277
306
|
return openPanes.has(pane.id);
|
|
278
307
|
},
|
|
279
|
-
async open() {
|
|
280
|
-
const { isPlaced } = await openAt(pane, paneSize(pane, mod().state));
|
|
308
|
+
async open(options) {
|
|
309
|
+
const { isPlaced } = await openAt(pane, paneSize(pane, mod().state), options?.focus);
|
|
281
310
|
if (isPlaced)
|
|
282
311
|
openPanes.add(pane.id);
|
|
283
312
|
},
|
|
@@ -285,7 +314,7 @@ export function createUi({ name, claude, router, progress, announce, mod }) {
|
|
|
285
314
|
await claude.ui.close({ id: pane.id });
|
|
286
315
|
openPanes.delete(pane.id);
|
|
287
316
|
},
|
|
288
|
-
toggle: () => (openPanes.has(pane.id) ? handle.close() : handle.open()),
|
|
317
|
+
toggle: (options) => (openPanes.has(pane.id) ? handle.close() : handle.open(options)),
|
|
289
318
|
};
|
|
290
319
|
return handle;
|
|
291
320
|
},
|
|
@@ -329,6 +358,7 @@ export function createUi({ name, claude, router, progress, announce, mod }) {
|
|
|
329
358
|
}
|
|
330
359
|
},
|
|
331
360
|
ask: (question, options) => claude.ui.ask(question, options),
|
|
361
|
+
scroll: (args) => claude.ui.scroll(args),
|
|
332
362
|
},
|
|
333
363
|
changed() {
|
|
334
364
|
if (panes.size === 0 && renders.size === 0)
|
package/shell.d.ts
ADDED
package/shell.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shell.d.ts","sourceRoot":"","sources":["src/shell.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,KAAK,WAAW,EAAE,KAAK,YAAY,EAAE,MAAM,wBAAwB,CAAA"}
|
package/shell.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { parseShell } from './utils/parse-shell.js';
|
package/src/jobs/check.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Job } from '../mod.js'
|
|
2
2
|
import { longestMs, type Deadline } from '../runtime/deadline.js'
|
|
3
3
|
import { callEffects, type ToolUse } from '../utils/call-effects.js'
|
|
4
|
-
import {
|
|
4
|
+
import { dirname } from '../vendor.js'
|
|
5
5
|
import { listed, messageOf } from '../utils/text.js'
|
|
6
6
|
import { afterCall, modOf, targetWords } from './context.js'
|
|
7
7
|
import type { Workspace } from './permissions/find-project-scope.js'
|
|
@@ -52,6 +52,6 @@ async function triggeredRun(after: readonly Target[], run: readonly string[], us
|
|
|
52
52
|
const existing: string[] = []
|
|
53
53
|
for (const path of paths) if (await workspace.fs.exists(path)) existing.push(path)
|
|
54
54
|
const last = existing.at(-1)
|
|
55
|
-
if (last !== undefined) return { command: [...run, ...existing], folder:
|
|
55
|
+
if (last !== undefined) return { command: [...run, ...existing], folder: dirname(last) }
|
|
56
56
|
return commandFolder === undefined ? undefined : { command: [...run], folder: commandFolder }
|
|
57
57
|
}
|
package/src/jobs/context.ts
CHANGED
|
@@ -77,6 +77,8 @@ export function modWithin<State extends object>({ mod, claude }: JobContext<Stat
|
|
|
77
77
|
read: (path) => within('mod.fs.read', mod.fs.read(path)),
|
|
78
78
|
write: (path, text) => within('mod.fs.write', mod.fs.write(path, text)),
|
|
79
79
|
list: (path) => within('mod.fs.list', mod.fs.list(path)),
|
|
80
|
+
exists: (path) => within('mod.fs.exists', mod.fs.exists(path)),
|
|
81
|
+
stat: (path, options) => within('mod.fs.stat', mod.fs.stat(path, options)),
|
|
80
82
|
},
|
|
81
83
|
http: { fetch: (url, init) => within('mod.http.fetch', mod.http.fetch(url, init)) },
|
|
82
84
|
dependencies: dependencyCalls(claude, within),
|