@cmodjs/core 2.0.0 → 2.1.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 +4 -4
- package/docs/dependencies.md +1 -1
- package/docs/jobs.md +1 -1
- package/docs/mod.md +2 -3
- package/docs/permissions.md +1 -1
- package/docs/session.md +3 -1
- package/docs/testing.md +2 -1
- package/jobs/permissions.d.ts.map +1 -1
- package/jobs/permissions.js +4 -1
- package/package.json +1 -1
- package/records.d.ts +1 -1
- package/records.js +1 -1
- package/register.d.ts.map +1 -1
- package/register.js +5 -4
- package/runtime/before.d.ts +8 -4
- package/runtime/before.d.ts.map +1 -1
- package/runtime/before.js +63 -39
- package/runtime/conversations.d.ts.map +1 -1
- package/runtime/conversations.js +38 -13
- package/runtime/engine.d.ts +1 -0
- package/runtime/engine.d.ts.map +1 -1
- package/runtime/hooks.d.ts +9 -23
- package/runtime/hooks.d.ts.map +1 -1
- package/runtime/hooks.js +4 -59
- package/runtime/lifecycle.d.ts +2 -1
- package/runtime/lifecycle.d.ts.map +1 -1
- package/runtime/lifecycle.js +36 -23
- package/runtime/permission-check.d.ts +15 -0
- package/runtime/permission-check.d.ts.map +1 -0
- package/runtime/permission-check.js +37 -0
- package/runtime/router.d.ts +0 -1
- package/runtime/router.d.ts.map +1 -1
- package/runtime/router.js +0 -1
- package/runtime/sessions.d.ts +13 -8
- package/runtime/sessions.d.ts.map +1 -1
- package/runtime/sessions.js +44 -80
- package/runtime/state.d.ts.map +1 -1
- package/runtime/state.js +14 -11
- package/session/context/turn/message/message.d.ts +1 -0
- package/session/context/turn/message/message.d.ts.map +1 -1
- package/session/context/turn/message/message.js +5 -2
- package/src/jobs/permissions.ts +3 -1
- package/src/records.ts +1 -1
- package/src/register.ts +5 -4
- package/src/runtime/before.ts +66 -42
- package/src/runtime/conversations.ts +35 -13
- package/src/runtime/engine.ts +1 -0
- package/src/runtime/hooks.ts +13 -86
- package/src/runtime/lifecycle.ts +51 -37
- package/src/runtime/permission-check.ts +47 -0
- package/src/runtime/router.ts +0 -2
- package/src/runtime/sessions.ts +55 -84
- package/src/runtime/state.ts +15 -8
- package/src/session/context/turn/message/message.ts +6 -2
- package/src/testing.ts +17 -10
- package/testing.d.ts +7 -2
- package/testing.d.ts.map +1 -1
- package/testing.js +13 -7
package/runtime/hooks.d.ts
CHANGED
|
@@ -1,36 +1,22 @@
|
|
|
1
|
-
import type { ClassicHookEvent, ClassicHookInputs
|
|
1
|
+
import type { ClassicHookEvent, ClassicHookInputs } from 'claude-code';
|
|
2
2
|
import type { Claude } from './claude.js';
|
|
3
3
|
import type { RoutedHook } from './router.js';
|
|
4
4
|
import type { Failure } from './toaster.js';
|
|
5
5
|
import { type CallBase } from '../utils/call-effects.js';
|
|
6
6
|
export type Hook = Exclude<ClassicHookEvent, 'PreToolUse'>;
|
|
7
|
-
export type
|
|
8
|
-
|
|
9
|
-
reason?: string;
|
|
10
|
-
hookSpecificOutput?: {
|
|
11
|
-
hookEventName?: Hook;
|
|
12
|
-
additionalContext?: string;
|
|
13
|
-
permissionDecision?: 'deny' | 'ask';
|
|
14
|
-
permissionDecisionReason?: string;
|
|
15
|
-
sessionTitle?: string;
|
|
16
|
-
initialUserMessage?: string;
|
|
17
|
-
watchPaths?: string[];
|
|
18
|
-
reloadSkills?: boolean;
|
|
19
|
-
decision?: PermissionRequestDecision;
|
|
20
|
-
retry?: boolean;
|
|
21
|
-
displayContent?: string;
|
|
22
|
-
worktreePath?: string;
|
|
23
|
-
};
|
|
24
|
-
};
|
|
25
|
-
export type HookListener<H extends Hook> = (input: ClassicHookInputs[H]) => HookAnswer | void | Promise<HookAnswer | void>;
|
|
7
|
+
export type HookFields = Readonly<Record<string, unknown>>;
|
|
8
|
+
export type HookListener<H extends Hook> = (input: ClassicHookInputs[H]) => HookFields | undefined | Promise<HookFields | undefined>;
|
|
26
9
|
export type RoutedEvent = `classic.${Hook}` | 'tool.check' | 'tool.call' | 'prompt.submit' | 'prompt.context' | 'prompt.attachment' | 'command.run' | 'session.measure' | 'skill.prompt' | 'ui.render' | 'ui.press' | 'ui.scroll' | 'ui.close' | 'cmod.call' | 'session.append' | 'session.compact' | 'session.receive' | 'agent.spawn' | 'turn.start';
|
|
27
|
-
export declare const permissionEvents: readonly RoutedEvent[];
|
|
28
10
|
type CallFiles = {
|
|
29
11
|
readonly read: string[];
|
|
30
12
|
readonly changed: string[];
|
|
31
13
|
};
|
|
32
|
-
export declare function classicHook<H extends Hook>(
|
|
14
|
+
export declare function classicHook<H extends Hook>(event: H, hook: HookListener<H>, report: (failure: Failure) => void): RoutedHook<RoutedEvent>;
|
|
33
15
|
export declare function userSkillHook(claude: Claude): RoutedHook<'skill.prompt'>;
|
|
34
|
-
export
|
|
16
|
+
export type HomeFolders = {
|
|
17
|
+
readonly home: string | undefined;
|
|
18
|
+
readonly configRoot: string | undefined;
|
|
19
|
+
};
|
|
20
|
+
export declare function callFiles(name: string, claude: Claude, folders: Promise<HomeFolders>, use: CallBase, cwd: string): Promise<CallFiles>;
|
|
35
21
|
export {};
|
|
36
22
|
//# 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":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../src/runtime/hooks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAEtE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAC7C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAC3C,OAAO,EAAe,KAAK,QAAQ,EAAmB,MAAM,0BAA0B,CAAA;AAKtF,MAAM,MAAM,IAAI,GAAG,OAAO,CAAC,gBAAgB,EAAE,YAAY,CAAC,CAAA;AAE1D,MAAM,MAAM,UAAU,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;AAE1D,MAAM,MAAM,YAAY,CAAC,CAAC,SAAS,IAAI,IAAI,CAAC,KAAK,EAAE,iBAAiB,CAAC,CAAC,CAAC,KAAK,UAAU,GAAG,SAAS,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAAA;AAEpI,MAAM,MAAM,WAAW,GACnB,WAAW,IAAI,EAAE,GACjB,YAAY,GACZ,WAAW,GACX,eAAe,GACf,gBAAgB,GAChB,mBAAmB,GACnB,aAAa,GACb,iBAAiB,GACjB,cAAc,GACd,WAAW,GACX,UAAU,GACV,WAAW,GACX,UAAU,GACV,WAAW,GACX,gBAAgB,GAChB,iBAAiB,GACjB,iBAAiB,GACjB,aAAa,GACb,YAAY,CAAA;AAEhB,KAAK,SAAS,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAAA;AAExE,wBAAgB,WAAW,CAAC,CAAC,SAAS,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,GAAG,UAAU,CAAC,WAAW,CAAC,CAYxI;AAMD,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,CAAC,cAAc,CAAC,CAexE;AAED,MAAM,MAAM,WAAW,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,CAAA;AAExG,wBAAsB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,WAAW,CAAC,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAgB3I"}
|
package/runtime/hooks.js
CHANGED
|
@@ -3,52 +3,11 @@ import { callEffects } from '../utils/call-effects.js';
|
|
|
3
3
|
import { dynamicPattern } from '../utils/parse-shell.js';
|
|
4
4
|
import { isMissing } from '../utils/paths.js';
|
|
5
5
|
import { messageOf } from '../utils/text.js';
|
|
6
|
-
export
|
|
7
|
-
const flags = ['reloadSkills', 'retry'];
|
|
8
|
-
const readFields = {
|
|
9
|
-
Setup: ['additionalContext'],
|
|
10
|
-
SessionStart: ['additionalContext', 'initialUserMessage', 'sessionTitle', 'watchPaths', 'reloadSkills'],
|
|
11
|
-
SessionEnd: [],
|
|
12
|
-
UserPromptSubmit: ['additionalContext', 'sessionTitle'],
|
|
13
|
-
UserPromptExpansion: ['additionalContext'],
|
|
14
|
-
InstructionsLoaded: [],
|
|
15
|
-
ConfigChange: [],
|
|
16
|
-
DirectoryAdded: [],
|
|
17
|
-
PreModelSwitch: ['permissionDecision', 'permissionDecisionReason'],
|
|
18
|
-
PostModelSwitch: ['additionalContext'],
|
|
19
|
-
PermissionRequest: ['decision'],
|
|
20
|
-
PermissionDenied: ['retry'],
|
|
21
|
-
PostToolUse: ['additionalContext'],
|
|
22
|
-
PostToolUseFailure: ['additionalContext'],
|
|
23
|
-
PostToolBatch: ['additionalContext'],
|
|
24
|
-
MessageDisplay: ['displayContent'],
|
|
25
|
-
SubagentStart: ['additionalContext'],
|
|
26
|
-
SubagentStop: ['additionalContext'],
|
|
27
|
-
TaskCreated: [],
|
|
28
|
-
TaskCompleted: [],
|
|
29
|
-
TeammateIdle: [],
|
|
30
|
-
Elicitation: [],
|
|
31
|
-
ElicitationResult: [],
|
|
32
|
-
Notification: [],
|
|
33
|
-
PreCompact: [],
|
|
34
|
-
PostCompact: [],
|
|
35
|
-
Stop: ['additionalContext'],
|
|
36
|
-
StopFailure: [],
|
|
37
|
-
CwdChanged: [],
|
|
38
|
-
FileChanged: [],
|
|
39
|
-
WorktreeCreate: ['worktreePath'],
|
|
40
|
-
WorktreeRemove: [],
|
|
41
|
-
};
|
|
42
|
-
export function classicHook(name, event, hook, report) {
|
|
6
|
+
export function classicHook(event, hook, report) {
|
|
43
7
|
const routed = async (e, next) => {
|
|
44
8
|
const ours = await Promise.resolve()
|
|
45
|
-
.then(
|
|
46
|
-
const answer = await hook(e);
|
|
47
|
-
return answer === undefined ? undefined : classicResult(event, answer);
|
|
48
|
-
})
|
|
9
|
+
.then(() => hook(e))
|
|
49
10
|
.catch((error) => {
|
|
50
|
-
if (event === 'PermissionRequest')
|
|
51
|
-
return { decision: { behavior: 'deny', message: `${name}: the ${event} listener failed: ${messageOf(error)}` } };
|
|
52
11
|
report({ id: `hook:${event}`, message: `The ${event} listener failed`, error });
|
|
53
12
|
return undefined;
|
|
54
13
|
});
|
|
@@ -80,9 +39,9 @@ export function userSkillHook(claude) {
|
|
|
80
39
|
return next(e);
|
|
81
40
|
};
|
|
82
41
|
}
|
|
83
|
-
export async function callFiles(name, claude, use, cwd) {
|
|
42
|
+
export async function callFiles(name, claude, folders, use, cwd) {
|
|
84
43
|
try {
|
|
85
|
-
const
|
|
44
|
+
const { home, configRoot } = await folders;
|
|
86
45
|
if (home === undefined)
|
|
87
46
|
throw new Error('HOME is not set, so ~ in a path has no meaning.');
|
|
88
47
|
const { shell, reads, writes } = callEffects(use, { cwd, home, ...(configRoot === undefined ? {} : { configRoot }), fs: claude.fs });
|
|
@@ -100,20 +59,6 @@ export async function callFiles(name, claude, use, cwd) {
|
|
|
100
59
|
return { read: [], changed: [] };
|
|
101
60
|
}
|
|
102
61
|
}
|
|
103
|
-
function classicResult(event, answer) {
|
|
104
|
-
const result = {};
|
|
105
|
-
if (answer.decision === 'block')
|
|
106
|
-
result['block'] = answer.reason ?? '';
|
|
107
|
-
const specific = answer.hookSpecificOutput ?? {};
|
|
108
|
-
for (const [field, value] of Object.entries(specific)) {
|
|
109
|
-
if (field === 'hookEventName' || (value === false && flags.includes(field)))
|
|
110
|
-
continue;
|
|
111
|
-
if (!readFields[event].includes(field))
|
|
112
|
-
throw new Error(`it answered ${field}, which ${event} does not read.`);
|
|
113
|
-
result[field] = field === 'additionalContext' ? [value] : value;
|
|
114
|
-
}
|
|
115
|
-
return result;
|
|
116
|
-
}
|
|
117
62
|
function mergeClassic(below, ours) {
|
|
118
63
|
const merged = { ...below, ...ours };
|
|
119
64
|
const context = [...(below['additionalContext'] ?? []), ...(ours['additionalContext'] ?? [])];
|
package/runtime/lifecycle.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ import type { Options } from '../options.js';
|
|
|
4
4
|
import { type Steps } from '../records.js';
|
|
5
5
|
import type { Claude } from './claude.js';
|
|
6
6
|
import { type RoutedEvent } from './hooks.js';
|
|
7
|
+
import type { PermissionRoutes } from './permission-check.js';
|
|
7
8
|
import { type RouterNext } from './router.js';
|
|
8
9
|
import { type ShownToast } from './toaster.js';
|
|
9
10
|
export type Plugin = {
|
|
@@ -27,5 +28,5 @@ export type Lifecycle<State extends object> = {
|
|
|
27
28
|
raise(method: string, payload: Readonly<Record<string, unknown>>): Promise<unknown>;
|
|
28
29
|
};
|
|
29
30
|
export declare function readPlugin(claude: Claude): Promise<Plugin>;
|
|
30
|
-
export declare function createLifecycle<State extends object, Declared extends Options = Options>(definition: ModDefinition<State, string, Declared>,
|
|
31
|
+
export declare function createLifecycle<State extends object, Declared extends Options = Options>(definition: ModDefinition<State, string, Declared>, permissionRoutes?: () => PermissionRoutes | undefined, options?: PluginOptions, asksPerson?: boolean): Lifecycle<State>;
|
|
31
32
|
//# sourceMappingURL=lifecycle.d.ts.map
|
|
@@ -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,EAAc,aAAa,EAAwB,MAAM,aAAa,CAAA;AAE7G,OAAO,KAAK,EAA4C,GAAG,EAAE,aAAa,EAAmF,MAAM,WAAW,CAAA;AAC9K,OAAO,KAAK,EAAE,OAAO,EAAgB,MAAM,eAAe,CAAA;AAC1D,OAAO,EAA2T,KAAK,KAAK,EAAE,MAAM,eAAe,CAAA;AAGnW,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAOzC,OAAO,
|
|
1
|
+
{"version":3,"file":"lifecycle.d.ts","sourceRoot":"","sources":["../src/runtime/lifecycle.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAc,aAAa,EAAwB,MAAM,aAAa,CAAA;AAE7G,OAAO,KAAK,EAA4C,GAAG,EAAE,aAAa,EAAmF,MAAM,WAAW,CAAA;AAC9K,OAAO,KAAK,EAAE,OAAO,EAAgB,MAAM,eAAe,CAAA;AAC1D,OAAO,EAA2T,KAAK,KAAK,EAAE,MAAM,eAAe,CAAA;AAGnW,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAOzC,OAAO,EAA4D,KAAK,WAAW,EAAE,MAAM,YAAY,CAAA;AACvG,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AAO7D,OAAO,EAA6B,KAAK,UAAU,EAAE,MAAM,aAAa,CAAA;AAMxE,OAAO,EAA+B,KAAK,UAAU,EAAgB,MAAM,cAAc,CAAA;AAMzF,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;IAC9B,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAA;IACrB,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAA;CACpC,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,QAAQ,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE,CAAA;IACtC,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;IACxG,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;CACpF,CAAA;AA2CD,wBAAsB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAwBhE;AAkCD,wBAAgB,eAAe,CAAC,KAAK,SAAS,MAAM,EAAE,QAAQ,SAAS,OAAO,GAAG,OAAO,EACtF,UAAU,EAAE,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,EAClD,gBAAgB,GAAE,MAAM,gBAAgB,GAAG,SAA2B,EACtE,OAAO,GAAE,aAAkB,EAC3B,UAAU,UAAO,GAChB,SAAS,CAAC,KAAK,CAAC,CAsdlB"}
|
package/runtime/lifecycle.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { changelogPage, consentPath, dataFolder, finishStepsMethod, isAtLeast, marketplaceOf, oldestCmodFor, openPageMethod, parseConsent, pendingStepsMethod, parseEvent, permissionWords, readRecord, readSteps, recordPath, scriptsSha256, settingsPagesMethod, storeFolder, updatesToTurnOn } from '../records.js';
|
|
2
2
|
import { homePrefix, ifMissing, relativePath } from '../utils/paths.js';
|
|
3
|
-
import { firstLine, formatExit,
|
|
3
|
+
import { firstLine, formatExit, messageOf } from '../utils/text.js';
|
|
4
4
|
import { beforeDeadline } from './deadline.js';
|
|
5
5
|
import { announcedOf, announcementMs, announcementOf } from './announce.js';
|
|
6
6
|
import { bind } from './bound.js';
|
|
7
7
|
import { serveConversations } from './conversations.js';
|
|
8
8
|
import { answerCall, answeringOwnCalls, cmodPluginName, dependencyCalls, withBareRefusals } from './dependencies.js';
|
|
9
9
|
import { keepEngine } from './engine.js';
|
|
10
|
-
import { classicHook,
|
|
10
|
+
import { classicHook, userSkillHook } from './hooks.js';
|
|
11
11
|
import { checkedAnswer, checkingGrants, checkSettings, checksAnswers, checkWrite, isCovered, itemOf, passedDown, programAddresses } from './grants.js';
|
|
12
12
|
import { cmodError, lastLineOf, locatingPrograms, readLines } from './programs.js';
|
|
13
13
|
import { createModFiles, resolvedPath } from './metadata.js';
|
|
@@ -28,6 +28,7 @@ const installId = 'cmod:install';
|
|
|
28
28
|
const installRetrySeconds = [2, 4, 8, 16, 32, 64, 128];
|
|
29
29
|
const cmodCheckMs = 1000;
|
|
30
30
|
const cmodWaitMs = 60_000;
|
|
31
|
+
const cmodSlowCheckMs = 10_000;
|
|
31
32
|
const startHoldMs = 10_000 - 1_000;
|
|
32
33
|
const dependencyCallMs = 30_000;
|
|
33
34
|
const cannotStart = /failed to start: /;
|
|
@@ -92,7 +93,7 @@ async function cmodVersion(claude) {
|
|
|
92
93
|
throw new Error(`cmod --version ${formatExit(result.exitCode, lastLineOf(result.stderr) ?? '')}`);
|
|
93
94
|
return result.stdout.trim().split(/\s+/).at(-1);
|
|
94
95
|
}
|
|
95
|
-
export function createLifecycle(definition,
|
|
96
|
+
export function createLifecycle(definition, permissionRoutes = () => undefined, options = {}, asksPerson = true) {
|
|
96
97
|
let router = createRouter();
|
|
97
98
|
let phase = 'starting';
|
|
98
99
|
let runtime;
|
|
@@ -250,7 +251,7 @@ export function createLifecycle(definition, checksPermissions = () => true, opti
|
|
|
250
251
|
if (runtime === undefined || plugin === undefined)
|
|
251
252
|
return;
|
|
252
253
|
const activeRouter = createRouter();
|
|
253
|
-
const active = await createMod(definition, { ...runtime, router: activeRouter, dataFolder: dataFolder(plugin.store, plugin.name), store: plugin.store, steps: plugin.steps, granted, refreshGrants,
|
|
254
|
+
const active = await createMod(definition, { ...runtime, router: activeRouter, dataFolder: dataFolder(plugin.store, plugin.name), store: plugin.store, steps: plugin.steps, granted, refreshGrants, permissionRoutes, options: pluginOptions }).catch(async (error) => {
|
|
254
255
|
if (error instanceof MissingOptions && (await askOptions(error)))
|
|
255
256
|
return undefined;
|
|
256
257
|
fail(messageOf(error), error instanceof MissingOptions ? `Set ${error.keys.length === 1 ? 'it' : 'them'} in /config.` : undefined, begin);
|
|
@@ -268,12 +269,19 @@ export function createLifecycle(definition, checksPermissions = () => true, opti
|
|
|
268
269
|
void runSteps(active.mod).catch((error) => toastFailure({ id: 'cmod:steps', message: 'Its installer stopped', error }));
|
|
269
270
|
const missed = missedSessionStart;
|
|
270
271
|
missedSessionStart = undefined;
|
|
271
|
-
const
|
|
272
|
+
const replay = (e) => (definition.name === cmodPluginName ? activeRouter.dispatch('classic.SessionStart', e, async () => ({})) : checkedRoute('classic.SessionStart', e, async () => ({})));
|
|
273
|
+
const lateAnswer = missed === undefined ? {} : await replay(missed).catch((error) => {
|
|
272
274
|
toastFailure({ id: 'classic.SessionStart', message: 'The SessionStart hook failed', error });
|
|
273
275
|
return {};
|
|
274
276
|
});
|
|
275
|
-
|
|
276
|
-
|
|
277
|
+
const { additionalContext, ...unread } = lateAnswer;
|
|
278
|
+
for (const text of additionalContext ?? []) {
|
|
279
|
+
const added = await runtime.claude.session.append({ message: { type: 'user', content: [{ type: 'text', text }] } });
|
|
280
|
+
if (added.deny !== undefined)
|
|
281
|
+
runtime.claude.ui.log(`${definition.name}: Claude Code refused its SessionStart note: ${added.deny}`, { to: 'debug' });
|
|
282
|
+
}
|
|
283
|
+
if (Object.keys(unread).length > 0) {
|
|
284
|
+
runtime.claude.ui.log(`${definition.name} started after Claude Code's SessionStart, so Claude Code did not read ${Object.keys(unread).join(', ')} from its SessionStart hooks.`, { to: 'debug' });
|
|
277
285
|
}
|
|
278
286
|
const version = plugin.version ?? '';
|
|
279
287
|
const announced = announcedOf(await runtime.claude.store.get(announcedKey));
|
|
@@ -359,7 +367,7 @@ export function createLifecycle(definition, checksPermissions = () => true, opti
|
|
|
359
367
|
timer.cancel();
|
|
360
368
|
longWait.cancel();
|
|
361
369
|
};
|
|
362
|
-
const
|
|
370
|
+
const poll = (ms) => claude().clock.every(ms, () => {
|
|
363
371
|
check ??= cmodVersion(claude())
|
|
364
372
|
.then((version) => {
|
|
365
373
|
check = undefined;
|
|
@@ -374,9 +382,14 @@ export function createLifecycle(definition, checksPermissions = () => true, opti
|
|
|
374
382
|
report(error);
|
|
375
383
|
});
|
|
376
384
|
});
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
385
|
+
let timer = poll(cmodCheckMs);
|
|
386
|
+
const longWait = claude().clock.after(cmodWaitMs, () => {
|
|
387
|
+
timer.cancel();
|
|
388
|
+
timer = poll(cmodSlowCheckMs);
|
|
389
|
+
installing(latest === undefined
|
|
390
|
+
? "Still waiting for cmod to download cmod. See cmod's own line."
|
|
391
|
+
: `PATH finds cmod ${latest}, and ${definition.name} needs cmod ${oldestCmodFor(plugin?.steps ?? {})} or later. Run npm i -g @cmodjs/cli, or put ~/.local/bin ahead of the old cmod on PATH.`);
|
|
392
|
+
});
|
|
380
393
|
};
|
|
381
394
|
const bootstrap = async (root) => {
|
|
382
395
|
installing();
|
|
@@ -544,8 +557,10 @@ export function createLifecycle(definition, checksPermissions = () => true, opti
|
|
|
544
557
|
if (event === 'cmod.call' && !isCallToThisMod)
|
|
545
558
|
return next(e);
|
|
546
559
|
await (event === 'classic.SessionStart' || isCallToThisMod ? holdUntilStarted() : whenActive());
|
|
547
|
-
if (event === 'classic.SessionStart' && phase !== 'active')
|
|
560
|
+
if (event === 'classic.SessionStart' && phase !== 'active') {
|
|
548
561
|
missedSessionStart = e;
|
|
562
|
+
return next(e);
|
|
563
|
+
}
|
|
549
564
|
if (isCallToThisMod && phase !== 'active') {
|
|
550
565
|
const isStopped = phase === 'declined' || phase === 'failed';
|
|
551
566
|
return { deny: isStopped ? `${definition.name} is not set up. Its toast says why.` : `${definition.name} is installing. Try again when it's ready.` };
|
|
@@ -646,7 +661,7 @@ async function createMod(definition, runtime) {
|
|
|
646
661
|
}));
|
|
647
662
|
const modState = createState({ name: definition.name, initial: definition.state ?? {}, session, root, claude, report, changed: area.changed, forkParent });
|
|
648
663
|
const modOptions = createOptions({ name: definition.name, declared: definition.options ?? {}, fromClaude: runtime.options, claude, report, changed: modState.changed });
|
|
649
|
-
const hookOn = (hook, listener) => router.add(`classic.${hook}`, classicHook(
|
|
664
|
+
const hookOn = (hook, listener) => router.add(`classic.${hook}`, classicHook(hook, listener, report));
|
|
650
665
|
const expand = (path) => (homePrefix.test(path) ? resolvedPath(path, places) : path);
|
|
651
666
|
const settingsFile = (source) => ({
|
|
652
667
|
read: () => checked.settings.read({ source }),
|
|
@@ -662,6 +677,7 @@ async function createMod(definition, runtime) {
|
|
|
662
677
|
isGranted: (permission) => flag(permission),
|
|
663
678
|
hookOn: (hook, listener) => hookOn(hook, listener),
|
|
664
679
|
routeOn: (event, hook) => router.add(event, hook),
|
|
680
|
+
permissionRoutes: runtime.permissionRoutes,
|
|
665
681
|
});
|
|
666
682
|
let followed;
|
|
667
683
|
let isSetUp = false;
|
|
@@ -706,8 +722,8 @@ async function createMod(definition, runtime) {
|
|
|
706
722
|
const change = { source: source === 'skills' ? 'skills' : source.replace('_settings', ''), ...(file_path === undefined ? {} : { path: file_path }) };
|
|
707
723
|
if (matcher !== undefined && !matches(change, matcher))
|
|
708
724
|
return undefined;
|
|
709
|
-
const
|
|
710
|
-
return
|
|
725
|
+
const refuse = (await listener(change))?.refuse;
|
|
726
|
+
return typeof refuse === 'string' ? { block: refuse } : undefined;
|
|
711
727
|
});
|
|
712
728
|
},
|
|
713
729
|
},
|
|
@@ -729,11 +745,12 @@ async function createMod(definition, runtime) {
|
|
|
729
745
|
const watch = { paths, listener };
|
|
730
746
|
watches.add(watch);
|
|
731
747
|
if (watches.size === 1) {
|
|
732
|
-
hookOn('SessionStart', () => ({
|
|
748
|
+
hookOn('SessionStart', () => ({ watchPaths: [...new Set([...watches].flatMap((each) => each.paths))] }));
|
|
733
749
|
hookOn('FileChanged', ({ file_path, event }) => {
|
|
734
750
|
for (const each of watches)
|
|
735
751
|
if (each.paths.some((watched) => relativePath(watched, file_path) !== undefined))
|
|
736
752
|
void Promise.resolve(each.listener({ path: file_path, type: event })).catch((error) => report({ id: 'fs:onChange', message: 'The fs.onChange listener failed', error }));
|
|
753
|
+
return undefined;
|
|
737
754
|
});
|
|
738
755
|
}
|
|
739
756
|
return { dispose: () => void watches.delete(watch) };
|
|
@@ -915,7 +932,7 @@ async function createMod(definition, runtime) {
|
|
|
915
932
|
return served ?? answerCall(definition.name, api, e);
|
|
916
933
|
});
|
|
917
934
|
const agents = toolCalls(claude, router);
|
|
918
|
-
keepEngine(mod, { claude: checked, router, toolCalls: agents, report });
|
|
935
|
+
keepEngine(mod, { claude: checked, router, toolCalls: agents, report, hasPermissionCheck: () => runtime.permissionRoutes() !== undefined });
|
|
919
936
|
const names = new Set();
|
|
920
937
|
const reserveName = (type, name, taken) => {
|
|
921
938
|
const key = `${type}:${name}`;
|
|
@@ -932,10 +949,6 @@ async function createMod(definition, runtime) {
|
|
|
932
949
|
await failsAs('the details of its session did not load', () => followCurrent(undefined));
|
|
933
950
|
await failsAs('its setup function threw', () => definition.setup(mod));
|
|
934
951
|
isSetUp = true;
|
|
935
|
-
const permissionHooks = permissionEvents.filter((event) => router.has(event));
|
|
936
|
-
if (permissionHooks.length > 0 && !runtime.checksPermissions()) {
|
|
937
|
-
throw new Error(`it decides permissions on ${listed(permissionHooks)}, so hooks/register.ts must call registerPermissionCheck(addHook) after registerMod`);
|
|
938
|
-
}
|
|
939
952
|
await failsAs('its open panes did not load', () => area.restorePanes());
|
|
940
953
|
return { mod, added, imports, raise: client.raise };
|
|
941
954
|
}
|
|
@@ -943,7 +956,7 @@ function checkingKeys(claude, toast, keys) {
|
|
|
943
956
|
const bound = Object.entries(keys);
|
|
944
957
|
if (bound.length === 0)
|
|
945
958
|
return claude;
|
|
946
|
-
const
|
|
959
|
+
const addCommand = (command) => {
|
|
947
960
|
for (const [key, commandName] of bound) {
|
|
948
961
|
if (commandName === command.name && command.immediate !== true) {
|
|
949
962
|
toast.warning(`${key} runs /${command.name}, which waits for Claude's turn to end`, { id: `key:${key}`, description: `It adds a row to the conversation. Give /${command.name} immediate: true.`, duration: Infinity });
|
|
@@ -951,7 +964,7 @@ function checkingKeys(claude, toast, keys) {
|
|
|
951
964
|
}
|
|
952
965
|
return claude.command.register(command);
|
|
953
966
|
};
|
|
954
|
-
return { ...claude, command: { ...claude.command, register } };
|
|
967
|
+
return { ...claude, command: { ...claude.command, register: addCommand } };
|
|
955
968
|
}
|
|
956
969
|
const longestTimerMs = 2_147_483_647;
|
|
957
970
|
function checkedMs(name, subject, ms) {
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Disposable } from '../mod.js';
|
|
2
|
+
import type { HookFields } from './hooks.js';
|
|
3
|
+
import { type HookOn, type RouteOn } from './sessions.js';
|
|
4
|
+
export type PermissionUse = {
|
|
5
|
+
readonly raise: (method: string, payload: HookFields) => Promise<HookFields | undefined>;
|
|
6
|
+
readonly hookOn: HookOn;
|
|
7
|
+
readonly routeOn: RouteOn;
|
|
8
|
+
readonly current: () => {
|
|
9
|
+
readonly id: string;
|
|
10
|
+
readonly cwd: string;
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
export type PermissionRoutes = (method: string, use: PermissionUse) => Disposable;
|
|
14
|
+
export declare const permissionRoutes: PermissionRoutes;
|
|
15
|
+
//# sourceMappingURL=permission-check.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permission-check.d.ts","sourceRoot":"","sources":["../src/runtime/permission-check.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AAC3C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAC5C,OAAO,EAAuC,KAAK,MAAM,EAAE,KAAK,OAAO,EAAkB,MAAM,eAAe,CAAA;AAE9G,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,KAAK,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAAA;IACxF,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM;QAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAA;CACtE,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,aAAa,KAAK,UAAU,CAAA;AAMjF,eAAO,MAAM,gBAAgB,EAAE,gBA6B9B,CAAA"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { defined, processPayloadOf, recordOf } from './sessions.js';
|
|
2
|
+
const verdictName = (decision) => (decision === 'deny' ? 'refuse' : decision);
|
|
3
|
+
export const permissionRoutes = (method, { raise, hookOn, routeOn, current }) => {
|
|
4
|
+
const isBefore = method.startsWith('before');
|
|
5
|
+
if (method.endsWith('PermissionCheck')) {
|
|
6
|
+
return routeOn('tool.check', async (e, next) => {
|
|
7
|
+
const below = (await next(e));
|
|
8
|
+
const { id, cwd } = current();
|
|
9
|
+
const payload = { session: id, cwd, ...defined({ task: e.agentId, callId: e.tool_use_id, reason: below.reason, rule: below.rule, ceiling: e.ceiling === undefined ? undefined : verdictName(e.ceiling) }), name: e.tool, input: recordOf(e.input), decision: verdictName(below.decision) };
|
|
10
|
+
if (!isBefore) {
|
|
11
|
+
void raise(method, payload);
|
|
12
|
+
return below;
|
|
13
|
+
}
|
|
14
|
+
const answer = await raise(method, payload);
|
|
15
|
+
if (answer === undefined || below.decision === 'deny')
|
|
16
|
+
return below;
|
|
17
|
+
if (typeof answer['refuse'] === 'string')
|
|
18
|
+
return { decision: 'deny', reason: answer['refuse'] };
|
|
19
|
+
if (typeof answer['ask'] === 'string')
|
|
20
|
+
return { decision: 'ask', reason: answer['ask'] };
|
|
21
|
+
return answer['allow'] === true ? { decision: 'allow' } : below;
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
return hookOn('PermissionRequest', async (input) => {
|
|
25
|
+
const payload = processPayloadOf('PermissionRequest', input);
|
|
26
|
+
if (!isBefore) {
|
|
27
|
+
void raise(method, payload);
|
|
28
|
+
return undefined;
|
|
29
|
+
}
|
|
30
|
+
const answer = await raise(method, payload);
|
|
31
|
+
if (answer === undefined)
|
|
32
|
+
return undefined;
|
|
33
|
+
if (typeof answer['refuse'] === 'string')
|
|
34
|
+
return { decision: defined({ behavior: 'deny', message: answer['refuse'], interrupt: answer['interrupt'] }) };
|
|
35
|
+
return answer['allow'] === true ? { decision: defined({ behavior: 'allow', updatedInput: answer['input'], updatedPermissions: answer['updates'] }) } : undefined;
|
|
36
|
+
});
|
|
37
|
+
};
|
package/runtime/router.d.ts
CHANGED
|
@@ -5,7 +5,6 @@ export type RouterNext<N extends RoutedEvent> = (e: Frozen<Args<N>>) => Promise<
|
|
|
5
5
|
export type RoutedHook<N extends RoutedEvent> = (e: Frozen<Args<N>>, next: RouterNext<N>) => EventResult<N> | Promise<EventResult<N>>;
|
|
6
6
|
export type Router = {
|
|
7
7
|
add<N extends RoutedEvent>(event: N, hook: RoutedHook<N>): Disposable;
|
|
8
|
-
has(event: RoutedEvent): boolean;
|
|
9
8
|
dispatch<N extends RoutedEvent>(event: N, e: Frozen<Args<N>>, next: RouterNext<N>): Promise<EventResult<N>>;
|
|
10
9
|
};
|
|
11
10
|
export declare function createRouter(): Router;
|
package/runtime/router.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../src/runtime/router.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAC5D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AAC3C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAE7C,MAAM,MAAM,UAAU,CAAC,CAAC,SAAS,WAAW,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAA;AAE/F,MAAM,MAAM,UAAU,CAAC,CAAC,SAAS,WAAW,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,WAAW,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAA;AAErI,MAAM,MAAM,MAAM,GAAG;IACnB,GAAG,CAAC,CAAC,SAAS,WAAW,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,UAAU,CAAA;IACrE,
|
|
1
|
+
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../src/runtime/router.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAC5D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AAC3C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAE7C,MAAM,MAAM,UAAU,CAAC,CAAC,SAAS,WAAW,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAA;AAE/F,MAAM,MAAM,UAAU,CAAC,CAAC,SAAS,WAAW,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,WAAW,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAA;AAErI,MAAM,MAAM,MAAM,GAAG;IACnB,GAAG,CAAC,CAAC,SAAS,WAAW,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,UAAU,CAAA;IACrE,QAAQ,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;CAC5G,CAAA;AAID,wBAAgB,YAAY,IAAI,MAAM,CAyBrC"}
|
package/runtime/router.js
CHANGED
package/runtime/sessions.d.ts
CHANGED
|
@@ -2,11 +2,12 @@ import type { Args, CommandRunResult } from 'claude-code';
|
|
|
2
2
|
import type { Disposable } from '../mod.js';
|
|
3
3
|
import { ToolResult } from '../session/context/turn/message/tool-result.js';
|
|
4
4
|
import { type SessionChange, type SessionData, type TaskData } from '../session/conversation.js';
|
|
5
|
-
import {
|
|
5
|
+
import { type BeforeEvent, type ProcessName, type SessionEvent, type Sessions, type TaskStartArgs, type ToolCallArgs, type Usage } from '../session/session.js';
|
|
6
6
|
import { type SentMatcher } from '../utils/matcher.js';
|
|
7
7
|
import { type Place } from './before.js';
|
|
8
8
|
import type { Claude } from './claude.js';
|
|
9
|
-
import { type
|
|
9
|
+
import { type HookFields } from './hooks.js';
|
|
10
|
+
import type { PermissionRoutes } from './permission-check.js';
|
|
10
11
|
export type Subscription = {
|
|
11
12
|
readonly event: SessionEvent;
|
|
12
13
|
readonly matcher: SentMatcher | undefined;
|
|
@@ -54,16 +55,18 @@ export declare function usageOf(claude: Pick<Claude, 'session'>): Promise<Usage>
|
|
|
54
55
|
export declare function payloadOf(change: SessionChange): unknown;
|
|
55
56
|
export declare function isHeardBy(event: SessionEvent, matcher: unknown, change: SessionChange): boolean;
|
|
56
57
|
export declare function isInScope(scope: Scope, session: string, change: SessionChange, isUnder: (task: string, ancestor: string) => boolean): boolean;
|
|
57
|
-
export declare function
|
|
58
|
+
export declare function withoutPermissionCheck(name: string, hearer: string): string;
|
|
59
|
+
export type HookOn = (hook: string, listener: (input: unknown) => HookFields | undefined | Promise<HookFields | undefined>) => Disposable;
|
|
60
|
+
export declare function createSessionsClient({ name, claude, report, isGranted, hookOn, routeOn, permissionRoutes }: {
|
|
58
61
|
readonly name: string;
|
|
59
62
|
readonly claude: Claude;
|
|
60
63
|
readonly report: (id: string, message: string, error: unknown) => void;
|
|
61
64
|
readonly isGranted: (permission: string) => boolean;
|
|
62
|
-
readonly hookOn?:
|
|
65
|
+
readonly hookOn?: HookOn;
|
|
63
66
|
readonly routeOn?: RouteOn;
|
|
67
|
+
readonly permissionRoutes?: () => PermissionRoutes | undefined;
|
|
64
68
|
}): SessionsClient;
|
|
65
|
-
type
|
|
66
|
-
type ToolCheck = {
|
|
69
|
+
export type ToolCheck = {
|
|
67
70
|
readonly tool: string;
|
|
68
71
|
readonly input: unknown;
|
|
69
72
|
readonly tool_use_id?: string;
|
|
@@ -74,9 +77,11 @@ export type RouteOn = {
|
|
|
74
77
|
(event: 'tool.check', hook: (e: ToolCheck, next: (e: ToolCheck) => Promise<unknown>) => Promise<unknown>): Disposable;
|
|
75
78
|
(event: 'command.run', hook: (e: Args<'command.run'>, next: (e: Args<'command.run'>) => Promise<CommandRunResult>) => Promise<CommandRunResult>): Disposable;
|
|
76
79
|
};
|
|
80
|
+
export declare const recordOf: (value: unknown) => Readonly<Record<string, unknown>>;
|
|
81
|
+
export declare const defined: (fields: HookFields) => HookFields;
|
|
82
|
+
type ProcessFieldsName = Exclude<ProcessName, 'PermissionCheck'>;
|
|
77
83
|
export declare function spawnTask(claude: Pick<Claude, 'agent'>, task: TaskStartArgs): Promise<TaskData>;
|
|
78
|
-
export declare function processPayloadOf(named:
|
|
79
|
-
export declare function hookAnswerOf(named: string, hook: string, answer: HookFields): HookAnswer | undefined;
|
|
84
|
+
export declare function processPayloadOf(named: ProcessFieldsName, input: unknown): HookFields;
|
|
80
85
|
export declare function resultOf(where: Pick<Place, 'session' | 'context' | 'turn'>, call: ToolCallArgs & {
|
|
81
86
|
readonly cwd: string;
|
|
82
87
|
}, answered: Awaited<ReturnType<Claude['tool']['call']>>): ToolResult;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sessions.d.ts","sourceRoot":"","sources":["../src/runtime/sessions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AACzD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AAM3C,OAAO,EAAE,UAAU,EAAE,MAAM,gDAAgD,CAAA;AAE3E,OAAO,EAAgD,KAAK,aAAa,EAAE,KAAK,WAAW,EAAE,KAAK,QAAQ,EAAiB,MAAM,4BAA4B,CAAA;AAG7J,OAAO,
|
|
1
|
+
{"version":3,"file":"sessions.d.ts","sourceRoot":"","sources":["../src/runtime/sessions.ts"],"names":[],"mappings":"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"}
|