@cmodjs/core 2.0.1 → 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 +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/runtime/before.d.ts +2 -1
- package/runtime/before.d.ts.map +1 -1
- package/runtime/before.js +4 -2
- package/runtime/engine.d.ts +1 -0
- package/runtime/engine.d.ts.map +1 -1
- package/runtime/hooks.d.ts +0 -1
- package/runtime/hooks.d.ts.map +1 -1
- package/runtime/hooks.js +0 -1
- package/runtime/lifecycle.d.ts.map +1 -1
- package/runtime/lifecycle.js +3 -7
- 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 +1 -0
- package/runtime/sessions.d.ts.map +1 -1
- package/runtime/sessions.js +6 -3
- package/src/jobs/permissions.ts +3 -1
- package/src/records.ts +1 -1
- package/src/runtime/before.ts +6 -3
- package/src/runtime/engine.ts +1 -0
- package/src/runtime/hooks.ts +0 -2
- package/src/runtime/lifecycle.ts +3 -7
- package/src/runtime/router.ts +0 -2
- package/src/runtime/sessions.ts +6 -2
- package/src/testing.ts +14 -8
- package/testing.d.ts +7 -2
- package/testing.d.ts.map +1 -1
- package/testing.js +10 -5
package/docs/commands.md
CHANGED
|
@@ -48,7 +48,7 @@ Runs every check this machine can run on the mod at `path` (default: the current
|
|
|
48
48
|
|
|
49
49
|
1. Installs its packages.
|
|
50
50
|
2. Checks its layout.
|
|
51
|
-
3. Checks that each step runs a script, and prints the permissions the person grants at install and can grant later, as the person reads them ([permissions.md](permissions.md)). It
|
|
51
|
+
3. Checks that each step runs a script, and prints the permissions the person grants at install and can grant later, as the person reads them ([permissions.md](permissions.md)). It adds `"approve": true` when the mod answers the permission check, with a `beforePermissionCheck` or `beforePermissionRequest` listener or the `permissions` job, and `hooks/register.ts` calls `registerPermissionCheck`. It fails a mod whose `src/` hears permissions while `register.ts` does not call `registerPermissionCheck`.
|
|
52
52
|
4. Writes the options `defineMod` declares into `.claude-plugin/plugin.json` `userConfig`, keeping the file's own formatting, so Claude Code shows them in `/config` ([options.md](options.md)). It loads `hooks/register.ts` to read them, without starting the mod.
|
|
53
53
|
5. Checks its imports.
|
|
54
54
|
6. Looks for prebuilt binaries outside `cli/`.
|
package/docs/jobs.md
CHANGED
|
@@ -189,7 +189,7 @@ type Rule<State> = Target & {
|
|
|
189
189
|
- When cmod cannot read the call or the session, it denies the call with the reason.
|
|
190
190
|
- For a PowerShell command, or a Bash command cmod cannot fully parse, a `command` rule matches when every word of its pattern appears in the command line. A `read` or `write` rule matches when the command line holds the last segment of its pattern, after the last `/`, and only when that segment holds none of `*?[]{}`. So `{ write: 'Domain.md' }` matches such a command that names `Domain.md`, and `{ write: '**/.env*' }` never matches one. A `!` pattern leaves nothing out of such a line, so the rule errs toward matching.
|
|
191
191
|
- `permissions({})` throws `permissions: give it a deny or an ask rule, or remove it from setup.`
|
|
192
|
-
- A mod that uses `permissions` calls `registerPermissionCheck(addHook)` after `registerMod` in `hooks/register.ts` ([mod.md](mod.md)). Without it
|
|
192
|
+
- A mod that uses `permissions` calls `registerPermissionCheck(addHook)` after `registerMod` in `hooks/register.ts` ([mod.md](mod.md)). Without it `mod.use(permissions(…))` throws, so a mod that uses it in `setup` does not start.
|
|
193
193
|
|
|
194
194
|
`when` gets the call, typed by the target's key. `jobs/permissions.js` exports each type, and `Call` is any of them:
|
|
195
195
|
|
package/docs/mod.md
CHANGED
|
@@ -59,7 +59,6 @@ When a step fails, the mod does not start. An error toast above the prompt names
|
|
|
59
59
|
- `its setup function threw: <error>` when `setup` throws or rejects.
|
|
60
60
|
- `its open panes did not load: <error>` when Claude Code cannot list the open panes.
|
|
61
61
|
- `the details of its session did not load: <error>` when Claude Code cannot name the session's id, model, or start time.
|
|
62
|
-
- `it decides permissions on <events>, so hooks/register.ts must call registerPermissionCheck(addHook) after registerMod` when `setup` adds a `beforePermissionCheck` or `beforePermissionRequest` listener, or a job that decides permissions, and `register.ts` does not register the permission check.
|
|
63
62
|
|
|
64
63
|
Each of these has `Retry`, which starts the mod again, and `Report` and `Hide` ([ui.md](ui.md#toasts)).
|
|
65
64
|
|
|
@@ -125,7 +124,7 @@ registeredMod(): ModDefinition | undefined
|
|
|
125
124
|
|
|
126
125
|
`registerMod` registers one handler per Claude Code event the mod can use, and routes each event to the mod. `options` is what Claude Code passes `register`: the values of the mod's options ([options.md](options.md)). `registeredMod` returns the definition `registerMod` got, for `cmod check` to read the mod's options without starting it. `registerMod` leaves out Claude Code's permission check, the events `tool.check` and `PermissionRequest`.
|
|
127
126
|
|
|
128
|
-
A mod that
|
|
127
|
+
A mod that hears permissions calls `registerPermissionCheck` after `registerMod`. That covers `sessions.current.onPermissionCheck`, `beforePermissionCheck`, `onPermissionRequest`, `beforePermissionRequest`, and the `permissions` job:
|
|
129
128
|
|
|
130
129
|
```ts
|
|
131
130
|
export function register(addHook: On, options: PluginOptions): void {
|
|
@@ -134,7 +133,7 @@ export function register(addHook: On, options: PluginOptions): void {
|
|
|
134
133
|
}
|
|
135
134
|
```
|
|
136
135
|
|
|
137
|
-
|
|
136
|
+
A mod that answers, with a `before` method or the `permissions` job, also declares `"approve": true` in its `package.json` `"cmod".permissions`, so the person grants it at install. `cmod check` adds the line when it is missing, and without the grant cmod drops every allow or ask the mod answers, so Claude Code decides those calls itself ([permissions.md](permissions.md)). A mod without `registerPermissionCheck` has no part in Claude Code's permission check, so the plugin directory reads it as one that never answers a permission. Without it, each of those methods and `mod.use(permissions(…))` throws `<mod>: <method> hears Claude Code's permission check, so hooks/register.ts must call registerPermissionCheck(addHook) after registerMod.` where it is called, so a mod that calls one in `setup` does not start. `cmod check` fails a mod whose `src/` uses one while `register.ts` does not call `registerPermissionCheck`.
|
|
138
137
|
|
|
139
138
|
Keep `register.ts` this small. Claude Code checks a hooks module before it loads it, and refuses some shapes, such as a `$` passed to a function in another module. The plugin directory reads the bundled module too, and flags it when the name of `register`'s first parameter is declared anywhere else in the bundle. `@cmodjs/core` declares `on` as a key, so name that parameter `addHook`. Declare `register` as a function, as here: `cmod publish` bundles the hooks module into one file, and Claude Code refuses a bundled `register` that is not one.
|
|
140
139
|
|
package/docs/permissions.md
CHANGED
|
@@ -29,7 +29,7 @@ They sit in the `package.json` `cmod` key, beside `install` and `keys`, because
|
|
|
29
29
|
|
|
30
30
|
Reading files, drawing panes and renders, toasts, slash commands, tools of the mod's own, listeners on the mod's own session, and a `refuse` answer need no permission. Writing a Claude Code settings file with `fs.write` is refused with every permission, and names the `settings` call to use instead ([mod.md](mod.md#settings-claude-code-s-settings-files)).
|
|
31
31
|
|
|
32
|
-
`cmod check` adds `"approve": true` to `package.json` when `
|
|
32
|
+
`cmod check` adds `"approve": true` to `package.json` when the mod answers the permission check, with a `beforePermissionCheck` or `beforePermissionRequest` listener or the `permissions` job, and the line is missing, and says so. A mod that only listens with `onPermissionCheck` or `onPermissionRequest` needs no `approve`.
|
|
33
33
|
|
|
34
34
|
## What the person sees
|
|
35
35
|
|
package/docs/session.md
CHANGED
|
@@ -157,7 +157,7 @@ A listener that throws shows the error toast `The <method> listener failed`, suc
|
|
|
157
157
|
|
|
158
158
|
### Give a listener time
|
|
159
159
|
|
|
160
|
-
A listener gets 10 seconds. `timeoutMs` changes that, a whole number above 0 and at most `600000`. The second argument a listener gets is its `deadline`, the time it ends as `Date.now()` counts, and a `signal` that aborts then, so a slow call such as `http.fetch` can stop with it
|
|
160
|
+
A listener gets 10 seconds. `timeoutMs` changes that, a whole number above 0 and at most `600000`. The second argument a listener gets is its `deadline`, the time it ends as `Date.now()` counts, and a `signal` that aborts then, so a slow call such as `http.fetch` can stop with it. Time a listener spends waiting on a call, such as `process.run`, never counts against the 10 seconds Claude Code gives a hook's own code, so a listener that waits can use its whole `timeoutMs`:
|
|
161
161
|
|
|
162
162
|
```ts
|
|
163
163
|
sessions.current.onTurnEnd(async (turn, { signal }) => {
|
|
@@ -220,6 +220,8 @@ An answer that changes text needs the `prompt` permission, a `beforeToolCall` an
|
|
|
220
220
|
| `beforeTodoCreate`, `onTodoCreate`, `beforeTodoComplete`, `onTodoComplete` | a todo is added to or ticked on the checklist | `Todo`: `id`, `subject`, `description?`, `teammate?` | `{ refuse }` |
|
|
221
221
|
| `beforeReplyDisplay`, `onReplyDisplay` | a reply is about to show | `ReplyDisplay`: `replyId`, `index`, `isLast`, `text` | `{ text }`, what the person sees |
|
|
222
222
|
|
|
223
|
+
The four `PermissionCheck` and `PermissionRequest` methods work only in a mod whose `hooks/register.ts` calls `registerPermissionCheck` ([mod.md](mod.md#register-the-mod-with-claude-code)). Without it they throw where they are called.
|
|
224
|
+
|
|
223
225
|
Every payload also carries where it happened: `session`, `cwd`, and `agentType?` and `permissionMode?` when Claude Code reports them. A matcher keeps the payloads it matches:
|
|
224
226
|
|
|
225
227
|
```ts
|
package/docs/testing.md
CHANGED
|
@@ -93,9 +93,10 @@ Starts the mod: loads its state, runs `setup`, and adds its listeners, panes, an
|
|
|
93
93
|
|
|
94
94
|
- Each process method takes its payload without `session` and `cwd`, which `raise` fills: `raise.beforeModelChange({ model: 'haiku', previous: 'opus', source: 'command', … })`, `raise.onCwdChange({ previous: '/work/old' })`, `raise.beforeRun({ name: 'compact', args: '', from: { type: Person } })`.
|
|
95
95
|
- Each message `before` method takes a `MessageDraft` without its `type`, placed in the open turn: `raise.beforeToolCall({ name: 'Bash', input: { command: 'rm -rf build' } })` and `raise.beforePrompt({ text: 'Deploy to prod' })`. `{ task }` places it in a task.
|
|
96
|
+
- `raise.beforeToolResult({ callId, output })` passes `output` to the listener as given, so a test gives what the tool answered Claude Code: `{ stdout: 'ok', stderr: '' }` for Bash, or Edit's `{ filePath, structuredPatch }`. A `ToolResult` that `tested.add` adds holds the text Claude read, as a transcript does.
|
|
96
97
|
- `raise.beforeTaskStart({ title, agentType?, model? })` asks about a task about to start.
|
|
97
98
|
- `raise.beforeTurnEnd({ answer?, failure? })` asks about the open turn ending. It rejects when no turn is open: add a `Prompt` first.
|
|
98
|
-
- `raise.beforeContextEnd()` asks about a compaction of the open context.
|
|
99
|
+
- `raise.beforeContextEnd()` asks about a compaction of the open context. `{ task }` asks about the compaction of a task's context, a task `tested.startTask` started.
|
|
99
100
|
|
|
100
101
|
```ts
|
|
101
102
|
test('a force push is refused', async () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../src/jobs/permissions.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,WAAW,CAAA;
|
|
1
|
+
{"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../src/jobs/permissions.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,WAAW,CAAA;AAKzC,OAAO,EAAqC,KAAK,eAAe,IAAI,QAAQ,EAAE,KAAK,IAAI,IAAI,OAAO,EAAgB,MAAM,oCAAoC,CAAA;AAK5J,YAAY,EAAE,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAA;AACtF,YAAY,EAAE,MAAM,EAAE,MAAM,+BAA+B,CAAA;AAC3D,MAAM,MAAM,IAAI,CAAC,KAAK,SAAS,MAAM,GAAG,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAA;AACnF,MAAM,MAAM,eAAe,CAAC,KAAK,SAAS,MAAM,GAAG,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAA;AAI/F,wBAAgB,WAAW,CAAC,KAAK,SAAS,MAAM,GAAG,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,KAAK,EAAE,eAAe,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,KAAK,eAAe,CAAC,KAAK,CAAC,CAAC,GAAG,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CA+BrK"}
|
package/jobs/permissions.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { engineOf } from '../runtime/engine.js';
|
|
2
|
+
import { withoutPermissionCheck } from '../runtime/sessions.js';
|
|
2
3
|
import { inputOf } from '../utils/call-effects.js';
|
|
3
4
|
import { decidePermission, stricterVerdict } from './permissions/decide-permission.js';
|
|
4
5
|
import { targetOf } from './permissions/match-target.js';
|
|
@@ -10,7 +11,9 @@ export function permissions(rules) {
|
|
|
10
11
|
if (count === 0)
|
|
11
12
|
throw new Error('permissions: give it a deny or an ask rule, or remove it from setup.');
|
|
12
13
|
return (job) => {
|
|
13
|
-
const { router, toolCalls } = engineOf(job.mod);
|
|
14
|
+
const { router, toolCalls, hasPermissionCheck } = engineOf(job.mod);
|
|
15
|
+
if (!hasPermissionCheck())
|
|
16
|
+
throw new Error(withoutPermissionCheck(job.mod.name, 'the permissions job'));
|
|
14
17
|
const readWorkspace = workspaceReader(job);
|
|
15
18
|
const verdictOf = async (e) => {
|
|
16
19
|
let current;
|
package/package.json
CHANGED
package/records.d.ts
CHANGED
|
@@ -74,7 +74,7 @@ export declare function marketplaceOf(root: string, name: string): string | unde
|
|
|
74
74
|
export declare function updatesToTurnOn(marketplace: string | undefined, settings: unknown, known: unknown): string | undefined;
|
|
75
75
|
export declare function consentPath(store: string): string;
|
|
76
76
|
export declare function parseConsent(value: unknown, path: string): Record<string, string[]>;
|
|
77
|
-
export declare const coreVersion = "2.0
|
|
77
|
+
export declare const coreVersion = "2.1.0";
|
|
78
78
|
export declare function oldestCmodFor(steps: Steps): string;
|
|
79
79
|
export declare function keyWords(keys: Readonly<Record<string, string>> | undefined): string;
|
|
80
80
|
export declare function scriptPaths(command: string): string[];
|
package/records.js
CHANGED
|
@@ -227,7 +227,7 @@ function readKeys(keys) {
|
|
|
227
227
|
}
|
|
228
228
|
return { keys: commands };
|
|
229
229
|
}
|
|
230
|
-
export const coreVersion = '2.0
|
|
230
|
+
export const coreVersion = '2.1.0';
|
|
231
231
|
export function oldestCmodFor(steps) {
|
|
232
232
|
if (steps.permissions?.some((item) => item.startsWith('config:')) === true)
|
|
233
233
|
return '1.6.0';
|
package/runtime/before.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Args, Frozen } from 'claude-code';
|
|
2
2
|
import type { Disposable } from '../mod.js';
|
|
3
|
-
import type { ConversationState, SessionChange } from '../session/conversation.js';
|
|
3
|
+
import type { ContextData, ConversationState, RunningTask, SessionChange } from '../session/conversation.js';
|
|
4
4
|
import { type BeforeEvent, type SessionEvent } from '../session/session.js';
|
|
5
5
|
import type { Claude } from './claude.js';
|
|
6
6
|
import type { Router } from './router.js';
|
|
@@ -30,6 +30,7 @@ export declare function installBefore({ claude, router, hooks }: {
|
|
|
30
30
|
readonly router: Router;
|
|
31
31
|
readonly hooks: BeforeHooks;
|
|
32
32
|
}): Disposable;
|
|
33
|
+
export declare function closingContext(where: Place, task: RunningTask | undefined, closedAt: string): ContextData;
|
|
33
34
|
export declare function withAnswer(change: SessionChange, answer: Partial<Answers>): SessionChange;
|
|
34
35
|
export declare const methodOf: (prefix: 'on' | 'before', event: SessionEvent) => string;
|
|
35
36
|
export declare const beforeAnswerKeys: Readonly<Record<BeforeEvent, readonly (keyof Answers)[]>>;
|
package/runtime/before.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"before.d.ts","sourceRoot":"","sources":["../src/runtime/before.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAC/C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AAa3C,OAAO,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAY,MAAM,4BAA4B,CAAA;
|
|
1
|
+
{"version":3,"file":"before.d.ts","sourceRoot":"","sources":["../src/runtime/before.ts"],"names":[],"mappings":"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"}
|
package/runtime/before.js
CHANGED
|
@@ -210,13 +210,15 @@ export function installBefore({ claude, router, hooks }) {
|
|
|
210
210
|
const task = e.agentId === undefined ? undefined : where.tasks[e.agentId];
|
|
211
211
|
if (e.agentId !== undefined && task === undefined)
|
|
212
212
|
return next(e);
|
|
213
|
-
const
|
|
214
|
-
const answer = await asked(ContextEnd, { type: ContextEnd, context: { ...context, closedAt: now() } });
|
|
213
|
+
const answer = await asked(ContextEnd, { type: ContextEnd, context: closingContext(where, task, now()) });
|
|
215
214
|
return answer.refuse === undefined ? next(e) : { skip: answer.refuse };
|
|
216
215
|
}),
|
|
217
216
|
];
|
|
218
217
|
return { dispose: () => added.forEach((each) => each.dispose()) };
|
|
219
218
|
}
|
|
219
|
+
export function closingContext(where, task, closedAt) {
|
|
220
|
+
return task === undefined ? { number: where.context, openedAt: where.contextOpenedAt, closedAt } : { number: task.context, openedAt: task.contextOpenedAt ?? task.openedAt, closedAt, task: task.id };
|
|
221
|
+
}
|
|
220
222
|
export function withAnswer(change, answer) {
|
|
221
223
|
if (change.type === Message && answer.output !== undefined && change.message.type === ToolResult)
|
|
222
224
|
return { ...change, message: { ...change.message, output: answer.output } };
|
package/runtime/engine.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ export type Engine = {
|
|
|
7
7
|
readonly router: Router;
|
|
8
8
|
readonly toolCalls: ToolCalls;
|
|
9
9
|
readonly report: (failure: Failure) => void;
|
|
10
|
+
readonly hasPermissionCheck: () => boolean;
|
|
10
11
|
};
|
|
11
12
|
export declare function keepEngine(mod: object, engine: Engine): void;
|
|
12
13
|
export declare function engineOf(mod: object): Engine;
|
package/runtime/engine.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/runtime/engine.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAC3C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAEhD,MAAM,MAAM,MAAM,GAAG;IACnB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAA;IAC7B,QAAQ,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAA;
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/runtime/engine.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAC3C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAEhD,MAAM,MAAM,MAAM,GAAG;IACnB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAA;IAC7B,QAAQ,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAA;IAC3C,QAAQ,CAAC,kBAAkB,EAAE,MAAM,OAAO,CAAA;CAC3C,CAAA;AAID,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAE5D;AAED,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAI5C"}
|
package/runtime/hooks.d.ts
CHANGED
|
@@ -7,7 +7,6 @@ export type Hook = Exclude<ClassicHookEvent, 'PreToolUse'>;
|
|
|
7
7
|
export type HookFields = Readonly<Record<string, unknown>>;
|
|
8
8
|
export type HookListener<H extends Hook> = (input: ClassicHookInputs[H]) => HookFields | undefined | Promise<HookFields | undefined>;
|
|
9
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';
|
|
10
|
-
export declare const permissionEvents: readonly RoutedEvent[];
|
|
11
10
|
type CallFiles = {
|
|
12
11
|
readonly read: string[];
|
|
13
12
|
readonly changed: string[];
|
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,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,
|
|
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,7 +3,6 @@ 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 const permissionEvents = ['tool.check', 'classic.PermissionRequest'];
|
|
7
6
|
export function classicHook(event, hook, report) {
|
|
8
7
|
const routed = async (e, next) => {
|
|
9
8
|
const ours = await Promise.resolve()
|
|
@@ -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';
|
|
@@ -932,7 +932,7 @@ async function createMod(definition, runtime) {
|
|
|
932
932
|
return served ?? answerCall(definition.name, api, e);
|
|
933
933
|
});
|
|
934
934
|
const agents = toolCalls(claude, router);
|
|
935
|
-
keepEngine(mod, { claude: checked, router, toolCalls: agents, report });
|
|
935
|
+
keepEngine(mod, { claude: checked, router, toolCalls: agents, report, hasPermissionCheck: () => runtime.permissionRoutes() !== undefined });
|
|
936
936
|
const names = new Set();
|
|
937
937
|
const reserveName = (type, name, taken) => {
|
|
938
938
|
const key = `${type}:${name}`;
|
|
@@ -949,10 +949,6 @@ async function createMod(definition, runtime) {
|
|
|
949
949
|
await failsAs('the details of its session did not load', () => followCurrent(undefined));
|
|
950
950
|
await failsAs('its setup function threw', () => definition.setup(mod));
|
|
951
951
|
isSetUp = true;
|
|
952
|
-
const permissionHooks = permissionEvents.filter((event) => router.has(event));
|
|
953
|
-
if (permissionHooks.length > 0 && runtime.permissionRoutes() === undefined) {
|
|
954
|
-
throw new Error(`it decides permissions on ${listed(permissionHooks)}, so hooks/register.ts must call registerPermissionCheck(addHook) after registerMod`);
|
|
955
|
-
}
|
|
956
952
|
await failsAs('its open panes did not load', () => area.restorePanes());
|
|
957
953
|
return { mod, added, imports, raise: client.raise };
|
|
958
954
|
}
|
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
|
@@ -55,6 +55,7 @@ export declare function usageOf(claude: Pick<Claude, 'session'>): Promise<Usage>
|
|
|
55
55
|
export declare function payloadOf(change: SessionChange): unknown;
|
|
56
56
|
export declare function isHeardBy(event: SessionEvent, matcher: unknown, change: SessionChange): boolean;
|
|
57
57
|
export declare function isInScope(scope: Scope, session: string, change: SessionChange, isUnder: (task: string, ancestor: string) => boolean): boolean;
|
|
58
|
+
export declare function withoutPermissionCheck(name: string, hearer: string): string;
|
|
58
59
|
export type HookOn = (hook: string, listener: (input: unknown) => HookFields | undefined | Promise<HookFields | undefined>) => Disposable;
|
|
59
60
|
export declare function createSessionsClient({ name, claude, report, isGranted, hookOn, routeOn, permissionRoutes }: {
|
|
60
61
|
readonly name: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sessions.d.ts","sourceRoot":"","sources":["../src/runtime/sessions.ts"],"names":[],"mappings":"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"}
|
|
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,EAAuD,KAAK,WAAW,EAA+F,KAAK,WAAW,EAA8D,KAAK,YAAY,EAAuC,KAAK,QAAQ,EAAkB,KAAK,aAAa,EAAE,KAAK,YAAY,EAAE,KAAK,KAAK,EAAE,MAAM,uBAAuB,CAAA;AACla,OAAO,EAAsC,KAAK,WAAW,EAAE,MAAM,qBAAqB,CAAA;AAC1F,OAAO,EAAkF,KAAK,KAAK,EAAE,MAAM,aAAa,CAAA;AACxH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAIzC,OAAO,EAA+B,KAAK,UAAU,EAAE,MAAM,YAAY,CAAA;AACzE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AAE7D,MAAM,MAAM,YAAY,GAAG;IAAE,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,WAAW,GAAG,SAAS,CAAA;CAAE,CAAA;AAEtG,eAAO,MAAM,YAAY,MAAM,CAAA;AAE/B,eAAO,MAAM,mBAAmB;aAC9B,QAAQ,EAAE,eAAe;aACzB,MAAM,EAAE,aAAa;aACrB,QAAQ,EAAE,eAAe;aACzB,KAAK,EAAE,YAAY;aACnB,QAAQ,EAAE,eAAe;aACzB,KAAK,EAAE,YAAY;aACnB,IAAI,EAAE,WAAW;aACjB,UAAU,EAAE,iBAAiB;aAC7B,KAAK,EAAE,YAAY;aACnB,SAAS,EAAE,gBAAgB;aAC3B,WAAW,EAAE,kBAAkB;aAC/B,GAAG,EAAE,UAAU;aACf,OAAO,EAAE,cAAc;aACvB,MAAM,EAAE,aAAa;CACb,CAAA;AAEV,MAAM,MAAM,GAAG,GAAG,MAAM,GAAG,WAAW,GAAG,UAAU,GAAG,OAAO,GAAG,UAAU,GAAG,OAAO,CAAA;AAQpF,eAAO,MAAM,gBAAgB,UAAW,WAAW,KAAG,MAAqF,CAAA;AAE3I,eAAO,MAAM,KAAK,WAAY,MAAM,KAAG,MAAM,IAAI,GAAwD,CAAA;AAEzG,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAE/D;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAE7E;AAED,MAAM,MAAM,KAAK,GAAG;IAAE,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,IAAI,CAAA;CAAE,CAAA;AAE7K,MAAM,MAAM,cAAc,GAAG;IAC3B,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAA;IAC3B,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,WAAW,EAAE,OAAO,GAAG,IAAI,CAAA;IAC3E,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,aAAa,EAAE,WAAW,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IAChH,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IACnF,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,OAAO,EAAE,GAAG,UAAU,CAAA;IAC5D,8DAA8D;IAC9D,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,WAAW,EAAE,WAAW,GAAG,QAAQ,CAAC,GAAG,IAAI,CAAA;CACjE,CAAA;AAMD,wBAAsB,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,CAI7E;AAED,wBAAgB,SAAS,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAUxD;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,aAAa,GAAG,OAAO,CAG/F;AAwBD,wBAAgB,SAAS,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,GAAG,OAAO,CAS7I;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAE3E;AAED,MAAM,MAAM,MAAM,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,UAAU,GAAG,SAAS,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,KAAK,UAAU,CAAA;AAEzI,wBAAgB,oBAAoB,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,gBAAgB,EAAE,EAAE;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC;IAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,gBAAgB,GAAG,SAAS,CAAA;CAAE,GAAG,cAAc,CAqala;AAED,MAAM,MAAM,SAAS,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,GAAG,KAAK,GAAG,MAAM,CAAA;CAAE,CAAA;AAEjL,MAAM,MAAM,OAAO,GAAG;IACpB,CAAC,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,SAAS,KAAK,OAAO,CAAC,OAAO,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,UAAU,CAAA;IACrH,CAAC,KAAK,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,IAAI,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,IAAI,CAAC,aAAa,CAAC,KAAK,OAAO,CAAC,gBAAgB,CAAC,KAAK,OAAO,CAAC,gBAAgB,CAAC,GAAG,UAAU,CAAA;CAC7J,CAAA;AAED,eAAO,MAAM,QAAQ,UAAW,OAAO,KAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAqH,CAAA;AAE/L,eAAO,MAAM,OAAO,WAAY,UAAU,KAAG,UAAmG,CAAA;AAqChJ,KAAK,iBAAiB,GAAG,OAAO,CAAC,WAAW,EAAE,iBAAiB,CAAC,CAAA;AAmChE,wBAAsB,SAAS,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,QAAQ,CAAC,CAarG;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,iBAAiB,EAAE,KAAK,EAAE,OAAO,GAAG,UAAU,CAGrF;AAiBD,wBAAgB,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,SAAS,GAAG,SAAS,GAAG,MAAM,CAAC,EAAE,IAAI,EAAE,YAAY,GAAG;IAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CAAE,EAAE,QAAQ,EAAE,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,UAAU,CAI7L"}
|
package/runtime/sessions.js
CHANGED
|
@@ -112,6 +112,9 @@ export function isInScope(scope, session, change, isUnder) {
|
|
|
112
112
|
return change.message.turn === scope.turn;
|
|
113
113
|
return (change.type === TurnStart || change.type === TurnEnd) && change.turn.prompt.id === scope.turn;
|
|
114
114
|
}
|
|
115
|
+
export function withoutPermissionCheck(name, hearer) {
|
|
116
|
+
return `${name}: ${hearer} hears Claude Code's permission check, so hooks/register.ts must call registerPermissionCheck(addHook) after registerMod.`;
|
|
117
|
+
}
|
|
115
118
|
export function createSessionsClient({ name, claude, report, isGranted, hookOn, routeOn, permissionRoutes }) {
|
|
116
119
|
const call = (method, input) => claude.cmod.call({ to: cmodPluginName, method, input });
|
|
117
120
|
const listening = new Map();
|
|
@@ -447,9 +450,9 @@ export function createSessionsClient({ name, claude, report, isGranted, hookOn,
|
|
|
447
450
|
const isBefore = method.startsWith('before');
|
|
448
451
|
if (named === 'PermissionCheck' || named === 'PermissionRequest') {
|
|
449
452
|
const routes = permissionRoutes?.();
|
|
450
|
-
if (routes
|
|
451
|
-
|
|
452
|
-
return
|
|
453
|
+
if (routes === undefined)
|
|
454
|
+
throw new Error(withoutPermissionCheck(name, method));
|
|
455
|
+
return routes(method, { raise, hookOn, routeOn, current: () => current });
|
|
453
456
|
}
|
|
454
457
|
const event = processEvents[named];
|
|
455
458
|
const hook = (isBefore ? event.before : undefined) ?? event.on;
|
package/src/jobs/permissions.ts
CHANGED
|
@@ -2,6 +2,7 @@ import type { Args, Frozen } from 'claude-code'
|
|
|
2
2
|
import type { Job, Mod } from '../mod.js'
|
|
3
3
|
import type { Deadline } from '../runtime/deadline.js'
|
|
4
4
|
import { engineOf } from '../runtime/engine.js'
|
|
5
|
+
import { withoutPermissionCheck } from '../runtime/sessions.js'
|
|
5
6
|
import { inputOf } from '../utils/call-effects.js'
|
|
6
7
|
import { decidePermission, stricterVerdict, type PermissionRules as RulesFor, type Rule as RuleFor, type Verdict } from './permissions/decide-permission.js'
|
|
7
8
|
import { targetOf } from './permissions/match-target.js'
|
|
@@ -20,7 +21,8 @@ export function permissions<State extends object = Record<never, never>>(rules:
|
|
|
20
21
|
if (count === 0) throw new Error('permissions: give it a deny or an ask rule, or remove it from setup.')
|
|
21
22
|
|
|
22
23
|
return (job) => {
|
|
23
|
-
const { router, toolCalls } = engineOf(job.mod)
|
|
24
|
+
const { router, toolCalls, hasPermissionCheck } = engineOf(job.mod)
|
|
25
|
+
if (!hasPermissionCheck()) throw new Error(withoutPermissionCheck(job.mod.name, 'the permissions job'))
|
|
24
26
|
const readWorkspace = workspaceReader(job)
|
|
25
27
|
|
|
26
28
|
const verdictOf = async (e: Frozen<Args<'tool.check'>>): Promise<Verdict | undefined> => {
|
package/src/records.ts
CHANGED
|
@@ -259,7 +259,7 @@ function readKeys(keys: unknown): Steps {
|
|
|
259
259
|
return { keys: commands }
|
|
260
260
|
}
|
|
261
261
|
|
|
262
|
-
export const coreVersion = '2.0
|
|
262
|
+
export const coreVersion = '2.1.0'
|
|
263
263
|
|
|
264
264
|
export function oldestCmodFor(steps: Steps): string {
|
|
265
265
|
if (steps.permissions?.some((item) => item.startsWith('config:')) === true) return '1.6.0'
|
package/src/runtime/before.ts
CHANGED
|
@@ -12,7 +12,7 @@ import { Skill } from '../session/context/turn/message/skill.js'
|
|
|
12
12
|
import { ToolCall } from '../session/context/turn/message/tool-call.js'
|
|
13
13
|
import { ToolResult } from '../session/context/turn/message/tool-result.js'
|
|
14
14
|
import { TurnEnd } from '../session/context/turn/turn.js'
|
|
15
|
-
import type { ConversationState, SessionChange, TaskData } from '../session/conversation.js'
|
|
15
|
+
import type { ContextData, ConversationState, RunningTask, SessionChange, TaskData } from '../session/conversation.js'
|
|
16
16
|
import { Task, TaskStart } from '../session/goal/task.js'
|
|
17
17
|
import { sessionEvents, type BeforeEvent, type SessionEvent } from '../session/session.js'
|
|
18
18
|
import type { Claude } from './claude.js'
|
|
@@ -210,14 +210,17 @@ export function installBefore({ claude, router, hooks }: { readonly claude: Clau
|
|
|
210
210
|
const where = await place()
|
|
211
211
|
const task = e.agentId === undefined ? undefined : where.tasks[e.agentId]
|
|
212
212
|
if (e.agentId !== undefined && task === undefined) return next(e)
|
|
213
|
-
const
|
|
214
|
-
const answer = await asked(ContextEnd, { type: ContextEnd, context: { ...context, closedAt: now() } })
|
|
213
|
+
const answer = await asked(ContextEnd, { type: ContextEnd, context: closingContext(where, task, now()) })
|
|
215
214
|
return answer.refuse === undefined ? next(e) : { skip: answer.refuse }
|
|
216
215
|
}),
|
|
217
216
|
]
|
|
218
217
|
return { dispose: () => added.forEach((each) => each.dispose()) }
|
|
219
218
|
}
|
|
220
219
|
|
|
220
|
+
export function closingContext(where: Place, task: RunningTask | undefined, closedAt: string): ContextData {
|
|
221
|
+
return task === undefined ? { number: where.context, openedAt: where.contextOpenedAt, closedAt } : { number: task.context, openedAt: task.contextOpenedAt ?? task.openedAt, closedAt, task: task.id }
|
|
222
|
+
}
|
|
223
|
+
|
|
221
224
|
export function withAnswer(change: SessionChange, answer: Partial<Answers>): SessionChange {
|
|
222
225
|
if (change.type === Message && answer.output !== undefined && change.message.type === ToolResult) return { ...change, message: { ...change.message, output: answer.output } }
|
|
223
226
|
if (change.type === Message && answer.text !== undefined) return { ...change, message: { ...change.message, text: answer.text } as Message }
|
package/src/runtime/engine.ts
CHANGED
package/src/runtime/hooks.ts
CHANGED
|
@@ -35,8 +35,6 @@ export type RoutedEvent =
|
|
|
35
35
|
| 'agent.spawn'
|
|
36
36
|
| 'turn.start'
|
|
37
37
|
|
|
38
|
-
export const permissionEvents: readonly RoutedEvent[] = ['tool.check', 'classic.PermissionRequest']
|
|
39
|
-
|
|
40
38
|
type CallFiles = { readonly read: string[]; readonly changed: string[] }
|
|
41
39
|
|
|
42
40
|
export function classicHook<H extends Hook>(event: H, hook: HookListener<H>, report: (failure: Failure) => void): RoutedHook<RoutedEvent> {
|
package/src/runtime/lifecycle.ts
CHANGED
|
@@ -4,7 +4,7 @@ import type { Allowed, FileChange, Disposable, Imports, Mod, ModDefinition, Pane
|
|
|
4
4
|
import type { Options, OptionValues } from '../options.js'
|
|
5
5
|
import { changelogPage, consentPath, dataFolder, finishStepsMethod, isAtLeast, marketplaceOf, oldestCmodFor, openPageMethod, parseConsent, pendingStepsMethod, parseEvent, permissionWords, readRecord, readSteps, recordPath, scriptsSha256, settingsPagesMethod, storeFolder, updatesToTurnOn, type ReadFile, type RunnerEvent, type Steps } from '../records.js'
|
|
6
6
|
import { homePrefix, ifMissing, relativePath } from '../utils/paths.js'
|
|
7
|
-
import { firstLine, formatExit,
|
|
7
|
+
import { firstLine, formatExit, messageOf } from '../utils/text.js'
|
|
8
8
|
import type { Claude } from './claude.js'
|
|
9
9
|
import { beforeDeadline } from './deadline.js'
|
|
10
10
|
import { announcedOf, announcementMs, announcementOf } from './announce.js'
|
|
@@ -12,7 +12,7 @@ import { bind } from './bound.js'
|
|
|
12
12
|
import { serveConversations } from './conversations.js'
|
|
13
13
|
import { answerCall, answeringOwnCalls, cmodPluginName, dependencyCalls, withBareRefusals } from './dependencies.js'
|
|
14
14
|
import { keepEngine } from './engine.js'
|
|
15
|
-
import { classicHook,
|
|
15
|
+
import { classicHook, userSkillHook, type Hook, type HookListener, type RoutedEvent } from './hooks.js'
|
|
16
16
|
import type { PermissionRoutes } from './permission-check.js'
|
|
17
17
|
import { checkedAnswer, checkingGrants, checkSettings, checksAnswers, checkWrite, isCovered, itemOf, passedDown, programAddresses, type AnswerCheck, type Grants } from './grants.js'
|
|
18
18
|
import { cmodError, lastLineOf, locatingPrograms, readLines, type Programs } from './programs.js'
|
|
@@ -957,7 +957,7 @@ async function createMod<State extends object, Declared extends Options>(definit
|
|
|
957
957
|
return served ?? answerCall(definition.name, api, e)
|
|
958
958
|
})
|
|
959
959
|
const agents = toolCalls(claude, router)
|
|
960
|
-
keepEngine(mod, { claude: checked, router, toolCalls: agents, report })
|
|
960
|
+
keepEngine(mod, { claude: checked, router, toolCalls: agents, report, hasPermissionCheck: () => runtime.permissionRoutes() !== undefined })
|
|
961
961
|
const names = new Set<string>()
|
|
962
962
|
const reserveName = (type: string, name: string, taken: string): Disposable => {
|
|
963
963
|
const key = `${type}:${name}`
|
|
@@ -972,10 +972,6 @@ async function createMod<State extends object, Declared extends Options>(definit
|
|
|
972
972
|
await failsAs('the details of its session did not load', () => followCurrent(undefined))
|
|
973
973
|
await failsAs('its setup function threw', () => definition.setup(mod))
|
|
974
974
|
isSetUp = true
|
|
975
|
-
const permissionHooks = permissionEvents.filter((event) => router.has(event))
|
|
976
|
-
if (permissionHooks.length > 0 && runtime.permissionRoutes() === undefined) {
|
|
977
|
-
throw new Error(`it decides permissions on ${listed(permissionHooks)}, so hooks/register.ts must call registerPermissionCheck(addHook) after registerMod`)
|
|
978
|
-
}
|
|
979
975
|
await failsAs('its open panes did not load', () => area.restorePanes())
|
|
980
976
|
return { mod, added, imports, raise: client.raise }
|
|
981
977
|
}
|
package/src/runtime/router.ts
CHANGED
|
@@ -8,7 +8,6 @@ export type RoutedHook<N extends RoutedEvent> = (e: Frozen<Args<N>>, next: Route
|
|
|
8
8
|
|
|
9
9
|
export type Router = {
|
|
10
10
|
add<N extends RoutedEvent>(event: N, hook: RoutedHook<N>): Disposable
|
|
11
|
-
has(event: RoutedEvent): boolean
|
|
12
11
|
dispatch<N extends RoutedEvent>(event: N, e: Frozen<Args<N>>, next: RouterNext<N>): Promise<EventResult<N>>
|
|
13
12
|
}
|
|
14
13
|
|
|
@@ -29,7 +28,6 @@ export function createRouter(): Router {
|
|
|
29
28
|
},
|
|
30
29
|
}
|
|
31
30
|
},
|
|
32
|
-
has: (event) => hooks.has(event),
|
|
33
31
|
dispatch<N extends RoutedEvent>(event: N, e: Frozen<Args<N>>, next: RouterNext<N>): Promise<EventResult<N>> {
|
|
34
32
|
const chain = hooks.get(event)
|
|
35
33
|
const call = async (index: number, current: unknown): Promise<unknown> => {
|
package/src/runtime/sessions.ts
CHANGED
|
@@ -133,6 +133,10 @@ export function isInScope(scope: Scope, session: string, change: SessionChange,
|
|
|
133
133
|
return (change.type === TurnStart || change.type === TurnEnd) && change.turn.prompt.id === scope.turn
|
|
134
134
|
}
|
|
135
135
|
|
|
136
|
+
export function withoutPermissionCheck(name: string, hearer: string): string {
|
|
137
|
+
return `${name}: ${hearer} hears Claude Code's permission check, so hooks/register.ts must call registerPermissionCheck(addHook) after registerMod.`
|
|
138
|
+
}
|
|
139
|
+
|
|
136
140
|
export type HookOn = (hook: string, listener: (input: unknown) => HookFields | undefined | Promise<HookFields | undefined>) => Disposable
|
|
137
141
|
|
|
138
142
|
export function createSessionsClient({ name, claude, report, isGranted, hookOn, routeOn, permissionRoutes }: { readonly name: string; readonly claude: Claude; readonly report: (id: string, message: string, error: unknown) => void; readonly isGranted: (permission: string) => boolean; readonly hookOn?: HookOn; readonly routeOn?: RouteOn; readonly permissionRoutes?: () => PermissionRoutes | undefined }): SessionsClient {
|
|
@@ -469,8 +473,8 @@ export function createSessionsClient({ name, claude, report, isGranted, hookOn,
|
|
|
469
473
|
const isBefore = method.startsWith('before')
|
|
470
474
|
if (named === 'PermissionCheck' || named === 'PermissionRequest') {
|
|
471
475
|
const routes = permissionRoutes?.()
|
|
472
|
-
if (routes
|
|
473
|
-
return
|
|
476
|
+
if (routes === undefined) throw new Error(withoutPermissionCheck(name, method))
|
|
477
|
+
return routes(method, { raise, hookOn, routeOn, current: () => current })
|
|
474
478
|
}
|
|
475
479
|
const event: { readonly on: string; readonly before?: string } = processEvents[named as ProcessName]
|
|
476
480
|
const hook = (isBefore ? event.before : undefined) ?? event.on
|
package/src/testing.ts
CHANGED
|
@@ -23,7 +23,7 @@ import type { Options, OptionValues } from './options.js'
|
|
|
23
23
|
import { readSteps, storeFolder, type Steps } from './records.js'
|
|
24
24
|
import type { Claude } from './runtime/claude.js'
|
|
25
25
|
import { answerCall, cmodPluginName, notInstalled } from './runtime/dependencies.js'
|
|
26
|
-
import { foldBefore, installBefore } from './runtime/before.js'
|
|
26
|
+
import { closingContext, foldBefore, installBefore, withAnswer } from './runtime/before.js'
|
|
27
27
|
import { permissionRoutes } from './runtime/permission-check.js'
|
|
28
28
|
import type { RoutedEvent } from './runtime/hooks.js'
|
|
29
29
|
import { keepClaudeCode, type ClaudeCode } from './testing/claude-code.js'
|
|
@@ -75,12 +75,14 @@ type MessageBefore = Exclude<BeforeName, 'TaskStart' | 'TurnEnd' | 'ContextEnd'>
|
|
|
75
75
|
|
|
76
76
|
type DraftOf<Name extends MessageBefore> = Omit<Extract<MessageDraft, { readonly type: (typeof sessionEvents)[Name] }>, 'type'>
|
|
77
77
|
|
|
78
|
+
type RaisedOf<Name extends MessageBefore> = Name extends 'ToolResult' ? Omit<DraftOf<Name>, 'output'> & { readonly output: unknown } : DraftOf<Name>
|
|
79
|
+
|
|
78
80
|
export type Raise = {
|
|
79
|
-
readonly [Name in MessageBefore as `before${Name}`]: (message:
|
|
81
|
+
readonly [Name in MessageBefore as `before${Name}`]: (message: RaisedOf<Name>, options?: { readonly task?: string }) => Promise<AnswerOf<Name> | undefined>
|
|
80
82
|
} & {
|
|
81
83
|
beforeTaskStart(task: { readonly title: string; readonly agentType?: string; readonly model?: string }): Promise<AnswerOf<'TaskStart'> | undefined>
|
|
82
84
|
beforeTurnEnd(ending?: Pick<Turn, 'answer' | 'failure'>): Promise<AnswerOf<'TurnEnd'> | undefined>
|
|
83
|
-
beforeContextEnd(): Promise<AnswerOf<'ContextEnd'> | undefined>
|
|
85
|
+
beforeContextEnd(options?: { readonly task?: string }): Promise<AnswerOf<'ContextEnd'> | undefined>
|
|
84
86
|
} & {
|
|
85
87
|
readonly [Name in ProcessName as `on${Name}`]: (payload: Placed<ProcessPayload[Name]>) => Promise<void>
|
|
86
88
|
} & {
|
|
@@ -277,9 +279,11 @@ export function testMod<State extends object, Declared extends Options = Options
|
|
|
277
279
|
const raise = Object.fromEntries([
|
|
278
280
|
...beforeEvents
|
|
279
281
|
.filter((named) => named !== 'TaskStart' && named !== 'TurnEnd' && named !== 'ContextEnd')
|
|
280
|
-
.map((named) => [`before${named}`, async (draft:
|
|
282
|
+
.map((named) => [`before${named}`, async (draft: { readonly output?: unknown }, placed?: { readonly task?: string }) => {
|
|
281
283
|
await start()
|
|
282
|
-
|
|
284
|
+
const isResult = named === 'ToolResult'
|
|
285
|
+
const message = conversations.draft({ ...draft, ...(isResult ? { output: '' } : {}), type: sessionEvents[named] } as MessageDraft, placed?.task)
|
|
286
|
+
return asked(sessionEvents[named], withAnswer({ type: Message, message }, { output: draft.output }))
|
|
283
287
|
}]),
|
|
284
288
|
['beforeTaskStart', async ({ title, agentType = 'general-purpose', model }: { readonly title: string; readonly agentType?: string; readonly model?: string }) => {
|
|
285
289
|
await start()
|
|
@@ -291,10 +295,12 @@ export function testMod<State extends object, Declared extends Options = Options
|
|
|
291
295
|
if (turn === undefined) throw new Error(`${name} has no turn open to end. Open one with tested.add({ type: Prompt, text: '…' }).`)
|
|
292
296
|
return asked(TurnEnd, { type: TurnEnd, turn: { ...turn, ...ending, closedAt: new Date().toISOString() } })
|
|
293
297
|
}],
|
|
294
|
-
['beforeContextEnd', async () => {
|
|
298
|
+
['beforeContextEnd', async (placed: { readonly task?: string } = {}) => {
|
|
295
299
|
await start()
|
|
296
|
-
const
|
|
297
|
-
|
|
300
|
+
const where = conversations.place()
|
|
301
|
+
const task = placed.task === undefined ? undefined : where.tasks[placed.task]
|
|
302
|
+
if (placed.task !== undefined && task === undefined) throw new Error(`${name} has no task ${placed.task}. Start it with tested.startTask.`)
|
|
303
|
+
return asked(ContextEnd, { type: ContextEnd, context: closingContext(where, task, new Date().toISOString()) })
|
|
298
304
|
}],
|
|
299
305
|
...[...Object.entries(processEvents).flatMap(([named, event]) => [`on${named}`, ...('before' in event ? [`before${named}`] : [])]), 'onRun', 'beforeRun'].map((method) => [method, async (payload: object) => {
|
|
300
306
|
await start()
|
package/testing.d.ts
CHANGED
|
@@ -38,8 +38,11 @@ type MessageBefore = Exclude<BeforeName, 'TaskStart' | 'TurnEnd' | 'ContextEnd'>
|
|
|
38
38
|
type DraftOf<Name extends MessageBefore> = Omit<Extract<MessageDraft, {
|
|
39
39
|
readonly type: (typeof sessionEvents)[Name];
|
|
40
40
|
}>, 'type'>;
|
|
41
|
+
type RaisedOf<Name extends MessageBefore> = Name extends 'ToolResult' ? Omit<DraftOf<Name>, 'output'> & {
|
|
42
|
+
readonly output: unknown;
|
|
43
|
+
} : DraftOf<Name>;
|
|
41
44
|
export type Raise = {
|
|
42
|
-
readonly [Name in MessageBefore as `before${Name}`]: (message:
|
|
45
|
+
readonly [Name in MessageBefore as `before${Name}`]: (message: RaisedOf<Name>, options?: {
|
|
43
46
|
readonly task?: string;
|
|
44
47
|
}) => Promise<AnswerOf<Name> | undefined>;
|
|
45
48
|
} & {
|
|
@@ -49,7 +52,9 @@ export type Raise = {
|
|
|
49
52
|
readonly model?: string;
|
|
50
53
|
}): Promise<AnswerOf<'TaskStart'> | undefined>;
|
|
51
54
|
beforeTurnEnd(ending?: Pick<Turn, 'answer' | 'failure'>): Promise<AnswerOf<'TurnEnd'> | undefined>;
|
|
52
|
-
beforeContextEnd(
|
|
55
|
+
beforeContextEnd(options?: {
|
|
56
|
+
readonly task?: string;
|
|
57
|
+
}): Promise<AnswerOf<'ContextEnd'> | undefined>;
|
|
53
58
|
} & {
|
|
54
59
|
readonly [Name in ProcessName as `on${Name}`]: (payload: Placed<ProcessPayload[Name]>) => Promise<void>;
|
|
55
60
|
} & {
|
package/testing.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["src/testing.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["src/testing.ts"],"names":[],"mappings":"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"}
|
package/testing.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { readSteps, storeFolder } from './records.js';
|
|
2
2
|
import { answerCall, cmodPluginName, notInstalled } from './runtime/dependencies.js';
|
|
3
|
-
import { foldBefore, installBefore } from './runtime/before.js';
|
|
3
|
+
import { closingContext, foldBefore, installBefore, withAnswer } from './runtime/before.js';
|
|
4
4
|
import { permissionRoutes } from './runtime/permission-check.js';
|
|
5
5
|
import { keepClaudeCode } from './testing/claude-code.js';
|
|
6
6
|
import { createRouter } from './runtime/router.js';
|
|
@@ -179,7 +179,9 @@ export function testMod(definition, options = {}) {
|
|
|
179
179
|
.filter((named) => named !== 'TaskStart' && named !== 'TurnEnd' && named !== 'ContextEnd')
|
|
180
180
|
.map((named) => [`before${named}`, async (draft, placed) => {
|
|
181
181
|
await start();
|
|
182
|
-
|
|
182
|
+
const isResult = named === 'ToolResult';
|
|
183
|
+
const message = conversations.draft({ ...draft, ...(isResult ? { output: '' } : {}), type: sessionEvents[named] }, placed?.task);
|
|
184
|
+
return asked(sessionEvents[named], withAnswer({ type: Message, message }, { output: draft.output }));
|
|
183
185
|
}]),
|
|
184
186
|
['beforeTaskStart', async ({ title, agentType = 'general-purpose', model }) => {
|
|
185
187
|
await start();
|
|
@@ -192,10 +194,13 @@ export function testMod(definition, options = {}) {
|
|
|
192
194
|
throw new Error(`${name} has no turn open to end. Open one with tested.add({ type: Prompt, text: '…' }).`);
|
|
193
195
|
return asked(TurnEnd, { type: TurnEnd, turn: { ...turn, ...ending, closedAt: new Date().toISOString() } });
|
|
194
196
|
}],
|
|
195
|
-
['beforeContextEnd', async () => {
|
|
197
|
+
['beforeContextEnd', async (placed = {}) => {
|
|
196
198
|
await start();
|
|
197
|
-
const
|
|
198
|
-
|
|
199
|
+
const where = conversations.place();
|
|
200
|
+
const task = placed.task === undefined ? undefined : where.tasks[placed.task];
|
|
201
|
+
if (placed.task !== undefined && task === undefined)
|
|
202
|
+
throw new Error(`${name} has no task ${placed.task}. Start it with tested.startTask.`);
|
|
203
|
+
return asked(ContextEnd, { type: ContextEnd, context: closingContext(where, task, new Date().toISOString()) });
|
|
199
204
|
}],
|
|
200
205
|
...[...Object.entries(processEvents).flatMap(([named, event]) => [`on${named}`, ...('before' in event ? [`before${named}`] : [])]), 'onRun', 'beforeRun'].map((method) => [method, async (payload) => {
|
|
201
206
|
await start();
|