@cmodjs/core 1.6.0 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/docs/commands.md +7 -7
- package/docs/dependencies.md +1 -1
- package/docs/index.md +12 -11
- package/docs/jobs.md +12 -16
- package/docs/mod.md +111 -36
- package/docs/permissions.md +14 -18
- package/docs/session.md +171 -82
- package/docs/state.md +5 -5
- package/docs/testing.md +57 -41
- package/docs/ui.md +9 -9
- package/jobs/permissions/decide-permission.d.ts.map +1 -1
- package/jobs/permissions/decide-permission.js +1 -1
- package/jobs/prompt.d.ts +1 -3
- package/jobs/prompt.d.ts.map +1 -1
- package/jobs/prompt.js +2 -21
- package/jobs/slash-command.d.ts +1 -1
- package/jobs/slash-command.d.ts.map +1 -1
- package/jobs/slash-command.js +1 -1
- package/jobs/status-line.d.ts +0 -1
- package/jobs/status-line.d.ts.map +1 -1
- package/jobs/status-line.js +3 -4
- package/mod.d.ts +53 -105
- package/mod.d.ts.map +1 -1
- package/mod.js +18 -80
- package/package.json +1 -1
- package/records.d.ts +1 -1
- package/records.js +1 -1
- package/register.d.ts.map +1 -1
- package/register.js +8 -5
- package/runtime/before.d.ts +11 -4
- package/runtime/before.d.ts.map +1 -1
- package/runtime/before.js +131 -67
- package/runtime/claude.d.ts +6 -1
- package/runtime/claude.d.ts.map +1 -1
- package/runtime/conversations.d.ts.map +1 -1
- package/runtime/conversations.js +82 -38
- package/runtime/deadline.d.ts +17 -0
- package/runtime/deadline.d.ts.map +1 -1
- package/runtime/deadline.js +34 -0
- package/runtime/dependencies.d.ts +2 -0
- package/runtime/dependencies.d.ts.map +1 -1
- package/runtime/dependencies.js +12 -0
- package/runtime/grants.d.ts.map +1 -1
- package/runtime/grants.js +13 -8
- package/runtime/hooks.d.ts +15 -11
- package/runtime/hooks.d.ts.map +1 -1
- package/runtime/hooks.js +8 -165
- package/runtime/lifecycle.d.ts +4 -2
- package/runtime/lifecycle.d.ts.map +1 -1
- package/runtime/lifecycle.js +96 -62
- 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/sessions.d.ts +35 -5
- package/runtime/sessions.d.ts.map +1 -1
- package/runtime/sessions.js +304 -82
- package/runtime/state.d.ts.map +1 -1
- package/runtime/state.js +14 -11
- package/runtime/tool-calls.d.ts +0 -1
- package/runtime/tool-calls.d.ts.map +1 -1
- package/runtime/tool-calls.js +0 -19
- package/session/context/turn/message/instruction-file.d.ts +9 -0
- package/session/context/turn/message/instruction-file.d.ts.map +1 -0
- package/session/context/turn/message/instruction-file.js +4 -0
- package/session/context/turn/message/message.d.ts +6 -4
- package/session/context/turn/message/message.d.ts.map +1 -1
- package/session/context/turn/message/message.js +12 -8
- package/session/context/turn/message/sender.d.ts +2 -1
- package/session/context/turn/message/sender.d.ts.map +1 -1
- package/session/context/turn/message/sender.js +4 -1
- package/session/context/turn/message/tool-call.d.ts +5 -0
- package/session/context/turn/message/tool-call.d.ts.map +1 -1
- package/session/context/turn/message/tool-result.d.ts +6 -1
- package/session/context/turn/message/tool-result.d.ts.map +1 -1
- package/session/context/turn/turn.d.ts +7 -0
- package/session/context/turn/turn.d.ts.map +1 -1
- package/session/conversation.d.ts +10 -3
- package/session/conversation.d.ts.map +1 -1
- package/session/conversation.js +14 -5
- package/session/goal/goal.d.ts +1 -1
- package/session/goal/goal.d.ts.map +1 -1
- package/session/goal/task.d.ts +2 -2
- package/session/goal/task.d.ts.map +1 -1
- package/session/session.d.ts +361 -26
- package/session/session.d.ts.map +1 -1
- package/session/session.js +40 -0
- package/src/jobs/permissions/decide-permission.ts +2 -1
- package/src/jobs/prompt.ts +3 -20
- package/src/jobs/slash-command.ts +2 -2
- package/src/jobs/status-line.ts +4 -7
- package/src/mod.ts +52 -147
- package/src/records.ts +1 -1
- package/src/register.ts +8 -5
- package/src/runtime/before.ts +140 -66
- package/src/runtime/claude.ts +5 -1
- package/src/runtime/conversations.ts +75 -37
- package/src/runtime/deadline.ts +38 -0
- package/src/runtime/dependencies.ts +12 -0
- package/src/runtime/grants.ts +11 -7
- package/src/runtime/hooks.ts +24 -163
- package/src/runtime/lifecycle.ts +110 -77
- package/src/runtime/permission-check.ts +47 -0
- package/src/runtime/sessions.ts +334 -91
- package/src/runtime/state.ts +15 -8
- package/src/runtime/tool-calls.ts +0 -19
- package/src/session/context/turn/message/instruction-file.ts +13 -0
- package/src/session/context/turn/message/message.ts +17 -11
- package/src/session/context/turn/message/sender.ts +5 -2
- package/src/session/context/turn/message/tool-call.ts +3 -0
- package/src/session/context/turn/message/tool-result.ts +6 -1
- package/src/session/context/turn/turn.ts +4 -0
- package/src/session/conversation.ts +21 -8
- package/src/session/goal/goal.ts +1 -1
- package/src/session/goal/task.ts +2 -2
- package/src/session/session.ts +227 -24
- package/src/testing/claude-code.ts +23 -0
- package/src/testing/fake-claude.ts +5 -1
- package/src/testing/fake-sessions.ts +38 -24
- package/src/testing.ts +88 -19
- package/testing/claude-code.d.ts +12 -0
- package/testing/claude-code.d.ts.map +1 -0
- package/testing/claude-code.js +10 -0
- package/testing/fake-claude.d.ts +4 -0
- package/testing/fake-claude.d.ts.map +1 -1
- package/testing/fake-claude.js +4 -1
- package/testing/fake-sessions.d.ts +8 -6
- package/testing/fake-sessions.d.ts.map +1 -1
- package/testing/fake-sessions.js +35 -20
- package/testing.d.ts +38 -9
- package/testing.d.ts.map +1 -1
- package/testing.js +58 -8
- package/docs/hooks.md +0 -259
- package/session/context/turn/message/document.d.ts +0 -7
- package/session/context/turn/message/document.d.ts.map +0 -1
- package/session/context/turn/message/document.js +0 -1
- package/src/session/context/turn/message/document.ts +0 -8
package/runtime/deadline.js
CHANGED
|
@@ -1,5 +1,39 @@
|
|
|
1
1
|
export const longestMs = 600_000;
|
|
2
2
|
export const toolDeadline = { ms: 30000, job: 'tool' };
|
|
3
|
+
export const listenerMs = 10_000;
|
|
4
|
+
export class PassedTimeout extends Error {
|
|
5
|
+
}
|
|
6
|
+
const timers = globalThis;
|
|
7
|
+
export function listenerOf(name, method, args) {
|
|
8
|
+
const hasMatcher = typeof args[1] === 'function';
|
|
9
|
+
const listener = (hasMatcher ? args[1] : args[0]);
|
|
10
|
+
const options = ((hasMatcher ? args[2] : args[1]) ?? {});
|
|
11
|
+
if (typeof listener !== 'function')
|
|
12
|
+
throw new Error(`${name}: ${method} takes a listener, or a matcher and then a listener.`);
|
|
13
|
+
const { timeoutMs, onFailure } = options;
|
|
14
|
+
if (timeoutMs !== undefined && (typeof timeoutMs !== 'number' || !Number.isInteger(timeoutMs) || timeoutMs <= 0 || timeoutMs > longestMs))
|
|
15
|
+
throw new Error(`${name}: ${method}'s timeoutMs is ${String(timeoutMs)}. Give a whole number of milliseconds above 0 and at most ${longestMs}.`);
|
|
16
|
+
if (onFailure !== undefined && onFailure !== 'pass' && onFailure !== 'refuse')
|
|
17
|
+
throw new Error(`${name}: ${method}'s onFailure is ${String(onFailure)}. Give 'pass' or 'refuse'.`);
|
|
18
|
+
return { matcher: hasMatcher ? args[0] : undefined, listener, options };
|
|
19
|
+
}
|
|
20
|
+
export async function withinTime(clock, method, { timeoutMs = listenerMs }, run) {
|
|
21
|
+
const controller = new AbortController();
|
|
22
|
+
const deadline = (await clock.now()) + timeoutMs;
|
|
23
|
+
let timer;
|
|
24
|
+
const passed = new Promise((_resolve, reject) => {
|
|
25
|
+
timer = timers.setTimeout(() => {
|
|
26
|
+
controller.abort();
|
|
27
|
+
reject(new PassedTimeout(`${method} passed its ${timeoutMs / 1000} s timeout`));
|
|
28
|
+
}, timeoutMs);
|
|
29
|
+
});
|
|
30
|
+
try {
|
|
31
|
+
return await Promise.race([Promise.resolve().then(() => run({ deadline, signal: controller.signal })), passed]);
|
|
32
|
+
}
|
|
33
|
+
finally {
|
|
34
|
+
timers.clearTimeout(timer);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
3
37
|
export function beforeDeadline(claude, { ms, job }, call, task) {
|
|
4
38
|
return new Promise((resolve, reject) => {
|
|
5
39
|
const passed = job === undefined ? `its ${ms / 1000} s deadline` : `the ${ms / 1000} s deadline of ${job}`;
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import type { Args, CmodDependencies, EventResult, Frozen } from 'claude-code';
|
|
2
2
|
import type { Claude } from './claude.js';
|
|
3
|
+
import type { Router } from './router.js';
|
|
3
4
|
export declare const cmodPluginName = "cmod";
|
|
4
5
|
export declare function answerCall(name: string, api: {
|
|
5
6
|
readonly [method: string]: (input: never) => unknown;
|
|
6
7
|
}, e: Frozen<Args<'cmod.call'>>): Promise<EventResult<'cmod.call'>>;
|
|
7
8
|
export declare function dependencyCalls(claude: Claude, within: (call: string, task: Promise<unknown>) => Promise<unknown>): CmodDependencies;
|
|
8
9
|
export declare function withBareRefusals(claude: Claude): Claude;
|
|
10
|
+
export declare function answeringOwnCalls(claude: Claude, router: Router): Claude;
|
|
9
11
|
export declare function notInstalled(name: string): string;
|
|
10
12
|
//# sourceMappingURL=dependencies.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dependencies.d.ts","sourceRoot":"","sources":["../src/runtime/dependencies.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAE9E,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAEzC,eAAO,MAAM,cAAc,SAAS,CAAA;AAEpC,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE;IAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,GAAG,CAAC,KAAK,EAAE,KAAK,KAAK,OAAO,CAAA;CAAE,EAAE,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC,CAQ7K;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,gBAAgB,CAOpI;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAQvD;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEjD"}
|
|
1
|
+
{"version":3,"file":"dependencies.d.ts","sourceRoot":"","sources":["../src/runtime/dependencies.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAE9E,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAEzC,eAAO,MAAM,cAAc,SAAS,CAAA;AAEpC,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE;IAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,GAAG,CAAC,KAAK,EAAE,KAAK,KAAK,OAAO,CAAA;CAAE,EAAE,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC,CAQ7K;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,gBAAgB,CAOpI;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAQvD;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CASxE;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEjD"}
|
package/runtime/dependencies.js
CHANGED
|
@@ -23,6 +23,18 @@ export function withBareRefusals(claude) {
|
|
|
23
23
|
});
|
|
24
24
|
return { ...claude, cmod: { call } };
|
|
25
25
|
}
|
|
26
|
+
export function answeringOwnCalls(claude, router) {
|
|
27
|
+
const name = claude.plugin.name;
|
|
28
|
+
const call = async (input) => {
|
|
29
|
+
if (input.to !== name)
|
|
30
|
+
return claude.cmod.call(input);
|
|
31
|
+
const answer = await router.dispatch('cmod.call', { ...input, caller: name }, async () => ({ deny: `${name} has no method ${input.method}.` }));
|
|
32
|
+
if (answer.deny !== undefined)
|
|
33
|
+
throw new Error(answer.deny);
|
|
34
|
+
return answer.value;
|
|
35
|
+
};
|
|
36
|
+
return { ...claude, cmod: { call } };
|
|
37
|
+
}
|
|
26
38
|
export function notInstalled(name) {
|
|
27
39
|
return `${name} is not installed. Add it with /plugin.`;
|
|
28
40
|
}
|
package/runtime/grants.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"grants.d.ts","sourceRoot":"","sources":["../src/runtime/grants.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAEzC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAG7C,MAAM,MAAM,MAAM,GAAG;IACnB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAA;IACpC,QAAQ,CAAC,OAAO,EAAE,MAAM,WAAW,CAAC,MAAM,CAAC,CAAA;IAC3C,QAAQ,CAAC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IACrC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAA;IACjC,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,CAAA;IACvC,QAAQ,CAAC,WAAW,EAAE,MAAM,MAAM,CAAA;IAClC,QAAQ,CAAC,WAAW,EAAE,MAAM,SAAS,MAAM,EAAE,CAAA;IAC7C,QAAQ,CAAC,aAAa,EAAE,MAAM,WAAW,CAAC,MAAM,CAAC,CAAA;CAClD,CAAA;AAED,qBAAa,iBAAkB,SAAQ,KAAK;CAAG;AAI/C,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAIzD;AAkBD,wBAAsB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAItG;AAED,wBAAsB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE1F;AAED,wBAAsB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAElJ;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"grants.d.ts","sourceRoot":"","sources":["../src/runtime/grants.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAEzC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAG7C,MAAM,MAAM,MAAM,GAAG;IACnB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAA;IACpC,QAAQ,CAAC,OAAO,EAAE,MAAM,WAAW,CAAC,MAAM,CAAC,CAAA;IAC3C,QAAQ,CAAC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IACrC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAA;IACjC,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,CAAA;IACvC,QAAQ,CAAC,WAAW,EAAE,MAAM,MAAM,CAAA;IAClC,QAAQ,CAAC,WAAW,EAAE,MAAM,SAAS,MAAM,EAAE,CAAA;IAC7C,QAAQ,CAAC,aAAa,EAAE,MAAM,WAAW,CAAC,MAAM,CAAC,CAAA;CAClD,CAAA;AAED,qBAAa,iBAAkB,SAAQ,KAAK;CAAG;AAI/C,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAIzD;AAkBD,wBAAsB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAItG;AAED,wBAAsB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE1F;AAED,wBAAsB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAElJ;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAwFrE;AAmBD,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED,wBAAgB,SAAS,CAAC,OAAO,EAAE,WAAW,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAWvG;AAiBD,wBAAgB,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,GAAG,MAAM,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAI9G;AA0BD,MAAM,MAAM,WAAW,GAAG;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAA;IAChC,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;CAC1C,CAAA;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAEzD;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,WAAW,GAAG,OAAO,CAa9G;AAED,wBAAsB,aAAa,CAAC,KAAK,EAAE,WAAW,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,CA+BxJ"}
|
package/runtime/grants.js
CHANGED
|
@@ -72,10 +72,6 @@ export function checkingGrants(claude, grants) {
|
|
|
72
72
|
},
|
|
73
73
|
session: {
|
|
74
74
|
...claude.session,
|
|
75
|
-
messages: (async (...args) => {
|
|
76
|
-
await gate('session.messages', 'conversation');
|
|
77
|
-
return claude.session.messages(...args);
|
|
78
|
-
}),
|
|
79
75
|
append: async (args) => {
|
|
80
76
|
await gate('send', 'prompt');
|
|
81
77
|
return claude.session.append(args);
|
|
@@ -91,13 +87,24 @@ export function checkingGrants(claude, grants) {
|
|
|
91
87
|
return claude.prompt.submit(args);
|
|
92
88
|
},
|
|
93
89
|
},
|
|
90
|
+
command: {
|
|
91
|
+
...claude.command,
|
|
92
|
+
run: async (args) => {
|
|
93
|
+
await gate(`commands.run(${args.command})`, 'prompt');
|
|
94
|
+
return claude.command.run(args);
|
|
95
|
+
},
|
|
96
|
+
},
|
|
94
97
|
cmod: {
|
|
95
98
|
async call(args) {
|
|
96
99
|
const named = args.to === cmodPluginName ? conversationCalls[args.method] : undefined;
|
|
97
100
|
const given = args.method === conversationMethods.act && isObject(args.input) ? String(args.input['action']) : undefined;
|
|
98
101
|
const action = given !== undefined && isAct(given) ? given : undefined;
|
|
99
|
-
|
|
100
|
-
|
|
102
|
+
const isThisSession = isObject(args.input) && args.input['session'] === (await claude.session.id());
|
|
103
|
+
const isDropping = (args.method === conversationMethods.subscribe || args.method === conversationMethods.watchBefore) && isObject(args.input) && Array.isArray(args.input['subscriptions']) && args.input['subscriptions'].length === 0;
|
|
104
|
+
if (named !== undefined && action !== undefined)
|
|
105
|
+
await gate(action, actPermission(action, isObject(args.input) ? args.input['input'] : undefined));
|
|
106
|
+
else if (named !== undefined && !isThisSession && !isDropping)
|
|
107
|
+
await gate(named, 'conversation');
|
|
101
108
|
return claude.cmod.call(args);
|
|
102
109
|
},
|
|
103
110
|
},
|
|
@@ -191,10 +198,8 @@ function declaration(item, home) {
|
|
|
191
198
|
const classicParts = {
|
|
192
199
|
additionalContext: 'prompt',
|
|
193
200
|
initialUserMessage: 'prompt',
|
|
194
|
-
suppressOriginalPrompt: 'prompt',
|
|
195
201
|
updatedToolOutput: 'prompt',
|
|
196
202
|
updatedMCPToolOutput: 'prompt',
|
|
197
|
-
updatedInput: 'tools',
|
|
198
203
|
retry: 'approve',
|
|
199
204
|
};
|
|
200
205
|
const blocksKeepWorking = ['classic.Stop', 'classic.PostToolUse'];
|
package/runtime/hooks.d.ts
CHANGED
|
@@ -1,19 +1,23 @@
|
|
|
1
|
-
import type {
|
|
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
|
-
import { type
|
|
6
|
-
export type
|
|
5
|
+
import { type CallBase } from '../utils/call-effects.js';
|
|
6
|
+
export type Hook = Exclude<ClassicHookEvent, 'PreToolUse'>;
|
|
7
|
+
export type HookFields = Readonly<Record<string, unknown>>;
|
|
8
|
+
export type HookListener<H extends Hook> = (input: ClassicHookInputs[H]) => HookFields | undefined | Promise<HookFields | undefined>;
|
|
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';
|
|
7
10
|
export declare const permissionEvents: readonly RoutedEvent[];
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
readonly
|
|
11
|
-
readonly reason?: string;
|
|
11
|
+
type CallFiles = {
|
|
12
|
+
readonly read: string[];
|
|
13
|
+
readonly changed: string[];
|
|
12
14
|
};
|
|
13
|
-
export
|
|
14
|
-
export declare function preToolUseHook(name: string, hook: HookListener<'PreToolUse'>, claude: Claude, calls: ToolCalls, held: HeldDecisions | undefined): RoutedHook<'tool.call'>;
|
|
15
|
-
export declare function heldDecisionHook(held: HeldDecisions): RoutedHook<'tool.check'>;
|
|
15
|
+
export declare function classicHook<H extends Hook>(event: H, hook: HookListener<H>, report: (failure: Failure) => void): RoutedHook<RoutedEvent>;
|
|
16
16
|
export declare function userSkillHook(claude: Claude): RoutedHook<'skill.prompt'>;
|
|
17
|
-
export
|
|
17
|
+
export type HomeFolders = {
|
|
18
|
+
readonly home: string | undefined;
|
|
19
|
+
readonly configRoot: string | undefined;
|
|
20
|
+
};
|
|
21
|
+
export declare function callFiles(name: string, claude: Claude, folders: Promise<HomeFolders>, use: CallBase, cwd: string): Promise<CallFiles>;
|
|
18
22
|
export {};
|
|
19
23
|
//# 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":"
|
|
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,eAAO,MAAM,gBAAgB,EAAE,SAAS,WAAW,EAAgD,CAAA;AAEnG,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
|
@@ -1,67 +1,15 @@
|
|
|
1
1
|
import { configFolders } from '../records.js';
|
|
2
|
-
import {
|
|
3
|
-
import { callEffects, inputOf } from '../utils/call-effects.js';
|
|
2
|
+
import { callEffects } from '../utils/call-effects.js';
|
|
4
3
|
import { dynamicPattern } from '../utils/parse-shell.js';
|
|
5
4
|
import { isMissing } from '../utils/paths.js';
|
|
6
5
|
import { messageOf } from '../utils/text.js';
|
|
7
6
|
export const permissionEvents = ['tool.check', 'classic.PermissionRequest'];
|
|
8
|
-
|
|
9
|
-
const readFields = {
|
|
10
|
-
Setup: ['additionalContext'],
|
|
11
|
-
SessionStart: ['additionalContext', 'initialUserMessage', 'sessionTitle', 'watchPaths', 'reloadSkills'],
|
|
12
|
-
SessionEnd: [],
|
|
13
|
-
UserPromptSubmit: ['additionalContext', 'sessionTitle', 'suppressOriginalPrompt'],
|
|
14
|
-
UserPromptExpansion: ['additionalContext', 'suppressOriginalPrompt'],
|
|
15
|
-
InstructionsLoaded: [],
|
|
16
|
-
ConfigChange: [],
|
|
17
|
-
DirectoryAdded: [],
|
|
18
|
-
PreModelSwitch: ['permissionDecision', 'permissionDecisionReason'],
|
|
19
|
-
PostModelSwitch: ['additionalContext'],
|
|
20
|
-
PreToolUse: ['additionalContext', 'permissionDecision', 'permissionDecisionReason', 'updatedInput'],
|
|
21
|
-
PermissionRequest: ['decision'],
|
|
22
|
-
PermissionDenied: ['retry'],
|
|
23
|
-
PostToolUse: ['additionalContext', 'updatedToolOutput', 'updatedMCPToolOutput'],
|
|
24
|
-
PostToolUseFailure: ['additionalContext'],
|
|
25
|
-
PostToolBatch: ['additionalContext'],
|
|
26
|
-
MessageDisplay: ['displayContent'],
|
|
27
|
-
SubagentStart: ['additionalContext'],
|
|
28
|
-
SubagentStop: ['additionalContext'],
|
|
29
|
-
TaskCreated: [],
|
|
30
|
-
TaskCompleted: [],
|
|
31
|
-
TeammateIdle: [],
|
|
32
|
-
Elicitation: [],
|
|
33
|
-
ElicitationResult: [],
|
|
34
|
-
Notification: [],
|
|
35
|
-
PreCompact: [],
|
|
36
|
-
PostCompact: [],
|
|
37
|
-
Stop: ['additionalContext'],
|
|
38
|
-
StopFailure: [],
|
|
39
|
-
CwdChanged: [],
|
|
40
|
-
FileChanged: [],
|
|
41
|
-
WorktreeCreate: ['worktreePath'],
|
|
42
|
-
WorktreeRemove: [],
|
|
43
|
-
};
|
|
44
|
-
export function classicHook(name, event, hook, claude, calls, report) {
|
|
45
|
-
const hookInputOf = async (e) => {
|
|
46
|
-
if (event !== 'PostToolUse' && event !== 'PostToolUseFailure')
|
|
47
|
-
return e;
|
|
48
|
-
const input = e;
|
|
49
|
-
const cwd = calls.cwdOf(input.tool_use_id) ?? input.cwd;
|
|
50
|
-
return { ...input, files: await callFiles(name, claude, { tool: input.tool_name, input: inputOf(input.tool_input) }, cwd) };
|
|
51
|
-
};
|
|
52
|
-
const resultOf = async (e) => {
|
|
53
|
-
const answer = await hook((await hookInputOf(e)));
|
|
54
|
-
if (answer === undefined)
|
|
55
|
-
return undefined;
|
|
56
|
-
if (answer.systemMessage !== undefined)
|
|
57
|
-
claude.ui.log(answer.systemMessage);
|
|
58
|
-
return classicResult(event, answer);
|
|
59
|
-
};
|
|
7
|
+
export function classicHook(event, hook, report) {
|
|
60
8
|
const routed = async (e, next) => {
|
|
61
|
-
const ours = await
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
report({ id: `hook:${event}`, message: `The ${event}
|
|
9
|
+
const ours = await Promise.resolve()
|
|
10
|
+
.then(() => hook(e))
|
|
11
|
+
.catch((error) => {
|
|
12
|
+
report({ id: `hook:${event}`, message: `The ${event} listener failed`, error });
|
|
65
13
|
return undefined;
|
|
66
14
|
});
|
|
67
15
|
if (ours === undefined)
|
|
@@ -70,57 +18,6 @@ export function classicHook(name, event, hook, claude, calls, report) {
|
|
|
70
18
|
};
|
|
71
19
|
return routed;
|
|
72
20
|
}
|
|
73
|
-
export function preToolUseHook(name, hook, claude, calls, held) {
|
|
74
|
-
return async (e, next) => {
|
|
75
|
-
let ours;
|
|
76
|
-
try {
|
|
77
|
-
const answer = await hook(await preToolUseInput(name, e, claude, calls.agentOf));
|
|
78
|
-
if (answer?.systemMessage !== undefined)
|
|
79
|
-
claude.ui.log(answer.systemMessage);
|
|
80
|
-
ours = answer === undefined ? {} : classicResult('PreToolUse', answer);
|
|
81
|
-
}
|
|
82
|
-
catch (error) {
|
|
83
|
-
return { deny: `${name}: the PreToolUse hook failed: ${messageOf(error)}` };
|
|
84
|
-
}
|
|
85
|
-
if (typeof ours['deny'] === 'string')
|
|
86
|
-
return { deny: ours['deny'] };
|
|
87
|
-
const decided = heldDecisionOf(ours);
|
|
88
|
-
if (decided !== undefined && held === undefined) {
|
|
89
|
-
return { deny: `${name}: the PreToolUse hook answered permissionDecision "${decided.decision}", so hooks/register.ts must call registerPermissionCheck(addHook) after registerMod.` };
|
|
90
|
-
}
|
|
91
|
-
const updated = ours['updatedInput'];
|
|
92
|
-
const reserved = Object.fromEntries(Object.entries(e).filter(([key]) => reservedKeys.includes(key)));
|
|
93
|
-
const earlier = held?.get(e.tool_use_id);
|
|
94
|
-
if (decided !== undefined)
|
|
95
|
-
held?.set(e.tool_use_id, earlier !== undefined && strictness.indexOf(earlier.decision) >= strictness.indexOf(decided.decision) ? earlier : decided);
|
|
96
|
-
let result;
|
|
97
|
-
try {
|
|
98
|
-
result = await next(updated === undefined ? e : { ...reserved, ...updated });
|
|
99
|
-
}
|
|
100
|
-
finally {
|
|
101
|
-
if (decided !== undefined)
|
|
102
|
-
held?.delete(e.tool_use_id);
|
|
103
|
-
}
|
|
104
|
-
const context = ours['additionalContext'];
|
|
105
|
-
if (context === undefined || result.deny !== undefined)
|
|
106
|
-
return result;
|
|
107
|
-
return { ...result, context: [...(result.context ?? []), ...context] };
|
|
108
|
-
};
|
|
109
|
-
}
|
|
110
|
-
export function heldDecisionHook(held) {
|
|
111
|
-
return async (e, next) => {
|
|
112
|
-
const below = await next(e);
|
|
113
|
-
const ours = e.tool_use_id === undefined ? undefined : held.get(e.tool_use_id);
|
|
114
|
-
return ours === undefined || below.decision === 'deny' ? below : ours;
|
|
115
|
-
};
|
|
116
|
-
}
|
|
117
|
-
function heldDecisionOf(ours) {
|
|
118
|
-
if (ours['allow'] !== undefined)
|
|
119
|
-
return { decision: 'allow' };
|
|
120
|
-
if (typeof ours['ask'] !== 'string')
|
|
121
|
-
return undefined;
|
|
122
|
-
return ours['ask'] === '' ? { decision: 'ask' } : { decision: 'ask', reason: ours['ask'] };
|
|
123
|
-
}
|
|
124
21
|
const frontmatter = /^---\r?\n[\s\S]*?\r?\n---[ \t]*(?:\r?\n|$)/;
|
|
125
22
|
const baseDirectoryLine = /^Base directory for this skill: [^\n]*\n\n/;
|
|
126
23
|
export function userSkillHook(claude) {
|
|
@@ -143,25 +40,9 @@ export function userSkillHook(claude) {
|
|
|
143
40
|
return next(e);
|
|
144
41
|
};
|
|
145
42
|
}
|
|
146
|
-
async function
|
|
147
|
-
const { tool, tool_use_id } = envelope;
|
|
148
|
-
const [session_id, cwd, { agentId, agentType }] = await Promise.all([claude.session.id(), claude.session.cwd(), agentOf(tool_use_id)]);
|
|
149
|
-
const tool_input = toolInputOf(envelope);
|
|
150
|
-
return {
|
|
151
|
-
session_id,
|
|
152
|
-
cwd,
|
|
153
|
-
hook_event_name: 'PreToolUse',
|
|
154
|
-
tool_name: tool,
|
|
155
|
-
tool_input,
|
|
156
|
-
tool_use_id,
|
|
157
|
-
...(agentId === undefined ? {} : { agent_id: agentId }),
|
|
158
|
-
...(agentType === undefined ? {} : { agent_type: agentType }),
|
|
159
|
-
files: await callFiles(name, claude, { tool, input: tool_input }, cwd),
|
|
160
|
-
};
|
|
161
|
-
}
|
|
162
|
-
async function callFiles(name, claude, use, cwd) {
|
|
43
|
+
export async function callFiles(name, claude, folders, use, cwd) {
|
|
163
44
|
try {
|
|
164
|
-
const
|
|
45
|
+
const { home, configRoot } = await folders;
|
|
165
46
|
if (home === undefined)
|
|
166
47
|
throw new Error('HOME is not set, so ~ in a path has no meaning.');
|
|
167
48
|
const { shell, reads, writes } = callEffects(use, { cwd, home, ...(configRoot === undefined ? {} : { configRoot }), fs: claude.fs });
|
|
@@ -179,44 +60,6 @@ async function callFiles(name, claude, use, cwd) {
|
|
|
179
60
|
return { read: [], changed: [] };
|
|
180
61
|
}
|
|
181
62
|
}
|
|
182
|
-
function classicResult(event, answer) {
|
|
183
|
-
const result = {};
|
|
184
|
-
const unread = (field) => new Error(`it answered ${field}, which ${event} does not read. Remove it from the answer.`);
|
|
185
|
-
if (event === 'PreToolUse') {
|
|
186
|
-
if (answer.continue === false || answer.stopReason !== undefined)
|
|
187
|
-
throw unread('continue or stopReason');
|
|
188
|
-
if (answer.decision === 'block')
|
|
189
|
-
result['deny'] = answer.reason ?? '';
|
|
190
|
-
}
|
|
191
|
-
else {
|
|
192
|
-
if (answer.continue === false)
|
|
193
|
-
result['preventContinuation'] = true;
|
|
194
|
-
if (answer.stopReason !== undefined)
|
|
195
|
-
result['stopReason'] = answer.stopReason;
|
|
196
|
-
if (answer.decision === 'block')
|
|
197
|
-
result['block'] = answer.reason ?? '';
|
|
198
|
-
}
|
|
199
|
-
const specific = answer.hookSpecificOutput ?? {};
|
|
200
|
-
if (specific.hookEventName !== undefined && specific.hookEventName !== event) {
|
|
201
|
-
throw new Error(`it answered hookSpecificOutput.hookEventName "${specific.hookEventName}". Set it to "${event}" or leave it out.`);
|
|
202
|
-
}
|
|
203
|
-
for (const [field, value] of Object.entries(specific)) {
|
|
204
|
-
if (field === 'hookEventName' || value === undefined || (value === false && flags.includes(field)))
|
|
205
|
-
continue;
|
|
206
|
-
if (!readFields[event].includes(field))
|
|
207
|
-
throw unread(`hookSpecificOutput.${field}`);
|
|
208
|
-
if (field === 'additionalContext')
|
|
209
|
-
result['additionalContext'] = [value];
|
|
210
|
-
else if (field === 'permissionDecision' && event === 'PreToolUse') {
|
|
211
|
-
const reason = specific.permissionDecisionReason ?? '';
|
|
212
|
-
result[value] = value === 'allow' ? true : reason;
|
|
213
|
-
}
|
|
214
|
-
else if (field !== 'permissionDecisionReason' || event !== 'PreToolUse')
|
|
215
|
-
result[field] = value;
|
|
216
|
-
}
|
|
217
|
-
return result;
|
|
218
|
-
}
|
|
219
|
-
export const strictness = ['allow', 'ask', 'deny'];
|
|
220
63
|
function mergeClassic(below, ours) {
|
|
221
64
|
const merged = { ...below, ...ours };
|
|
222
65
|
const context = [...(below['additionalContext'] ?? []), ...(ours['additionalContext'] ?? [])];
|
package/runtime/lifecycle.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import type { Args, EventResult, Frozen, PluginOptions } from 'claude-code';
|
|
2
|
-
import {
|
|
2
|
+
import type { Mod, ModDefinition } from '../mod.js';
|
|
3
3
|
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 = {
|
|
@@ -24,7 +25,8 @@ export type Lifecycle<State extends object> = {
|
|
|
24
25
|
readonly toasts: readonly ShownToast[];
|
|
25
26
|
start(claude: Claude, read: (claude: Claude) => Promise<Plugin>): Promise<void>;
|
|
26
27
|
route<N extends RoutedEvent>(event: N, e: Frozen<Args<N>>, next: RouterNext<N>): Promise<EventResult<N>>;
|
|
28
|
+
raise(method: string, payload: Readonly<Record<string, unknown>>): Promise<unknown>;
|
|
27
29
|
};
|
|
28
30
|
export declare function readPlugin(claude: Claude): Promise<Plugin>;
|
|
29
|
-
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>;
|
|
30
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,
|
|
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,EAA8E,KAAK,WAAW,EAAE,MAAM,YAAY,CAAA;AACzH,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"}
|