@cmodjs/core 1.0.0 → 1.5.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 +22 -11
- package/docs/dependencies.md +6 -4
- package/docs/hooks.md +26 -3
- package/docs/index.md +1 -1
- package/docs/install-steps.md +5 -3
- package/docs/mod.md +29 -3
- package/docs/permissions.md +4 -4
- package/docs/session.md +126 -63
- package/docs/testing.md +7 -5
- package/docs/ui.md +9 -1
- package/jobs/program.d.ts.map +1 -1
- package/jobs/program.js +7 -2
- package/mod.d.ts +30 -6
- package/mod.d.ts.map +1 -1
- package/mod.js +34 -1
- package/package.json +1 -1
- package/records.d.ts +4 -1
- package/records.d.ts.map +1 -1
- package/records.js +6 -1
- package/register.d.ts.map +1 -1
- package/register.js +17 -0
- package/runtime/announce.d.ts.map +1 -1
- package/runtime/announce.js +2 -0
- package/runtime/before.d.ts +32 -0
- package/runtime/before.d.ts.map +1 -0
- package/runtime/before.js +214 -0
- package/runtime/claude.d.ts +2 -1
- package/runtime/claude.d.ts.map +1 -1
- package/runtime/conversations.d.ts +1 -0
- package/runtime/conversations.d.ts.map +1 -1
- package/runtime/conversations.js +333 -61
- package/runtime/dependencies.js +1 -1
- package/runtime/engine.d.ts +2 -6
- package/runtime/engine.d.ts.map +1 -1
- package/runtime/grants.d.ts.map +1 -1
- package/runtime/grants.js +8 -8
- package/runtime/hooks.d.ts +1 -1
- package/runtime/hooks.d.ts.map +1 -1
- package/runtime/hooks.js +19 -4
- package/runtime/installer.d.ts +1 -1
- package/runtime/installer.d.ts.map +1 -1
- package/runtime/installer.js +6 -5
- package/runtime/lifecycle.d.ts.map +1 -1
- package/runtime/lifecycle.js +129 -58
- package/runtime/metadata.d.ts.map +1 -1
- package/runtime/metadata.js +5 -4
- package/runtime/sessions.d.ts +26 -4
- package/runtime/sessions.d.ts.map +1 -1
- package/runtime/sessions.js +315 -117
- package/runtime/toaster.d.ts +5 -12
- package/runtime/toaster.d.ts.map +1 -1
- package/runtime/toaster.js +133 -23
- package/runtime/ui.d.ts.map +1 -1
- package/runtime/ui.js +26 -6
- package/session/context/context.d.ts +3 -1
- package/session/context/context.d.ts.map +1 -1
- package/session/context/turn/message/message.d.ts +1 -0
- package/session/context/turn/message/message.d.ts.map +1 -1
- package/session/context/turn/message/message.js +42 -1
- package/session/context/turn/turn.d.ts +2 -1
- package/session/context/turn/turn.d.ts.map +1 -1
- package/session/conversation.d.ts +20 -11
- package/session/conversation.d.ts.map +1 -1
- package/session/conversation.js +50 -27
- package/session/goal/goal.d.ts +3 -2
- package/session/goal/goal.d.ts.map +1 -1
- package/session/goal/task.d.ts +4 -4
- package/session/goal/task.d.ts.map +1 -1
- package/session/session.d.ts +80 -21
- package/session/session.d.ts.map +1 -1
- package/session/session.js +1 -0
- package/src/jobs/program.ts +7 -2
- package/src/mod.ts +48 -5
- package/src/records.ts +6 -1
- package/src/register.ts +17 -0
- package/src/runtime/announce.ts +2 -0
- package/src/runtime/before.ts +200 -0
- package/src/runtime/claude.ts +3 -0
- package/src/runtime/conversations.ts +337 -60
- package/src/runtime/dependencies.ts +1 -1
- package/src/runtime/engine.ts +2 -1
- package/src/runtime/grants.ts +8 -10
- package/src/runtime/hooks.ts +20 -4
- package/src/runtime/installer.ts +6 -5
- package/src/runtime/lifecycle.ts +135 -55
- package/src/runtime/metadata.ts +5 -4
- package/src/runtime/sessions.ts +316 -111
- package/src/runtime/toaster.ts +160 -44
- package/src/runtime/ui.ts +23 -4
- package/src/session/context/context.ts +3 -1
- package/src/session/context/turn/message/message.ts +39 -1
- package/src/session/context/turn/turn.ts +2 -1
- package/src/session/conversation.ts +56 -31
- package/src/session/goal/goal.ts +3 -2
- package/src/session/goal/task.ts +4 -4
- package/src/session/session.ts +62 -15
- package/src/testing/fake-claude.ts +4 -2
- package/src/testing/fake-sessions.ts +94 -20
- package/src/testing.ts +27 -3
- package/src/utils/call-effects.ts +2 -2
- package/src/utils/disposable.ts +3 -0
- package/src/utils/matcher.ts +1 -1
- package/src/utils/paths.ts +6 -3
- package/testing/fake-claude.d.ts +1 -0
- package/testing/fake-claude.d.ts.map +1 -1
- package/testing/fake-claude.js +3 -1
- package/testing/fake-sessions.d.ts +8 -1
- package/testing/fake-sessions.d.ts.map +1 -1
- package/testing/fake-sessions.js +97 -18
- package/testing.d.ts +1 -0
- package/testing.d.ts.map +1 -1
- package/testing.js +23 -2
- package/utils/call-effects.d.ts +1 -0
- package/utils/call-effects.d.ts.map +1 -1
- package/utils/call-effects.js +1 -1
- package/utils/disposable.d.ts +4 -0
- package/utils/disposable.d.ts.map +1 -0
- package/utils/disposable.js +1 -0
- package/utils/matcher.js +1 -1
- package/utils/paths.d.ts +2 -1
- package/utils/paths.d.ts.map +1 -1
- package/utils/paths.js +6 -3
package/session/conversation.js
CHANGED
|
@@ -11,19 +11,38 @@ export const searchLimit = 50;
|
|
|
11
11
|
const agentTools = ['Agent', 'Task'];
|
|
12
12
|
const asyncLaunch = 'Async agent launched';
|
|
13
13
|
export function emptyConversation(session) {
|
|
14
|
-
return { session, context: 0, contextOpenedAt: '', agentCalls: [], endedCalls: {}, tasks: {} };
|
|
14
|
+
return { session, context: 0, contextOpenedAt: '', agentCalls: [], endedCalls: {}, tasks: {}, taskTurns: {} };
|
|
15
15
|
}
|
|
16
16
|
export function createConversation(start) {
|
|
17
17
|
let { context, contextOpenedAt, turn, goal } = start;
|
|
18
18
|
const agentCalls = new Set(start.agentCalls);
|
|
19
19
|
const endedCalls = new Map(Object.entries(start.endedCalls));
|
|
20
20
|
const tasks = new Map(Object.entries(start.tasks));
|
|
21
|
+
const taskTurns = new Map(Object.entries(start.taskTurns));
|
|
22
|
+
const endTaskTurn = (task, at) => {
|
|
23
|
+
const open = taskTurns.get(task);
|
|
24
|
+
if (open === undefined)
|
|
25
|
+
return [];
|
|
26
|
+
taskTurns.delete(task);
|
|
27
|
+
return open.closedAt === undefined ? [{ type: TurnEnd, turn: { ...open, closedAt: at } }] : [];
|
|
28
|
+
};
|
|
21
29
|
const startContext = (at) => {
|
|
22
30
|
context += 1;
|
|
23
31
|
contextOpenedAt = at;
|
|
24
32
|
return [{ type: ContextStart, context: { number: context, openedAt: at } }];
|
|
25
33
|
};
|
|
26
34
|
const endContext = (at) => (context === 0 ? [] : [{ type: ContextEnd, context: { number: context, openedAt: contextOpenedAt, closedAt: at } }]);
|
|
35
|
+
const compactTask = (task, at) => {
|
|
36
|
+
const owner = tasks.get(task);
|
|
37
|
+
if (owner === undefined)
|
|
38
|
+
return [];
|
|
39
|
+
const next = { ...owner, context: owner.context + 1, contextOpenedAt: at };
|
|
40
|
+
tasks.set(task, next);
|
|
41
|
+
return [
|
|
42
|
+
{ type: ContextEnd, context: { number: owner.context, openedAt: owner.contextOpenedAt ?? owner.openedAt, closedAt: at, task } },
|
|
43
|
+
{ type: ContextStart, context: { number: next.context, openedAt: at, task } },
|
|
44
|
+
];
|
|
45
|
+
};
|
|
27
46
|
const endTurn = (at) => {
|
|
28
47
|
if (turn === undefined)
|
|
29
48
|
return [];
|
|
@@ -31,19 +50,22 @@ export function createConversation(start) {
|
|
|
31
50
|
turn = undefined;
|
|
32
51
|
return [{ type: TurnEnd, turn: ended }];
|
|
33
52
|
};
|
|
34
|
-
const endTask = (call, at) => {
|
|
35
|
-
const
|
|
36
|
-
if (
|
|
53
|
+
const endTask = (call, at, only) => {
|
|
54
|
+
const opened = [...tasks.values()].filter((each) => each.openedBy === call && (only === undefined || each.id === only));
|
|
55
|
+
if (opened.length === 0) {
|
|
37
56
|
if (agentCalls.has(call))
|
|
38
57
|
endedCalls.set(call, at);
|
|
39
58
|
return [];
|
|
40
59
|
}
|
|
41
|
-
if (
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
60
|
+
if (only === undefined)
|
|
61
|
+
agentCalls.delete(call);
|
|
62
|
+
return opened.flatMap((task) => {
|
|
63
|
+
if (task.closedAt !== undefined)
|
|
64
|
+
return [];
|
|
65
|
+
const ended = { ...task, closedAt: at };
|
|
66
|
+
tasks.set(task.id, ended);
|
|
67
|
+
return [...endTaskTurn(task.id, at), { type: TaskEnd, task: ended }];
|
|
68
|
+
});
|
|
47
69
|
};
|
|
48
70
|
const changeGoal = (text) => {
|
|
49
71
|
goal = text;
|
|
@@ -56,28 +78,31 @@ export function createConversation(start) {
|
|
|
56
78
|
changes.push(...startContext(row.at));
|
|
57
79
|
if (task === undefined && row.type === 'system' && row.name === 'turn_duration')
|
|
58
80
|
return [...changes, ...endTurn(row.at)];
|
|
59
|
-
if (
|
|
60
|
-
return [...changes, ...endContext(row.at), ...startContext(row.at)];
|
|
81
|
+
if (row.type === 'system' && row.name === 'compact_boundary')
|
|
82
|
+
return [...changes, ...(task === undefined ? [...endContext(row.at), ...startContext(row.at)] : compactTask(task, row.at))];
|
|
61
83
|
const owner = task === undefined ? undefined : tasks.get(task);
|
|
84
|
+
const placedIn = owner?.context ?? context;
|
|
62
85
|
for (const unplaced of messagesOf(row, task !== undefined)) {
|
|
63
|
-
if (
|
|
64
|
-
changes.push(...endTurn(row.at));
|
|
65
|
-
const opened = { prompt: { ...unplaced, session: start.session, context, turn: unplaced.id }, context, openedAt: row.at };
|
|
66
|
-
|
|
86
|
+
if (unplaced.type === Prompt) {
|
|
87
|
+
changes.push(...(task === undefined ? endTurn(row.at) : endTaskTurn(task, row.at)));
|
|
88
|
+
const opened = { prompt: { ...unplaced, session: start.session, context: placedIn, turn: unplaced.id, ...(task === undefined ? {} : { task }) }, context: placedIn, openedAt: row.at, ...(owner?.closedAt === undefined ? {} : { closedAt: owner.closedAt }) };
|
|
89
|
+
if (task === undefined)
|
|
90
|
+
turn = opened;
|
|
91
|
+
else
|
|
92
|
+
taskTurns.set(task, opened);
|
|
67
93
|
changes.push({ type: TurnStart, turn: opened });
|
|
68
|
-
if (goal === undefined)
|
|
94
|
+
if (task === undefined && goal === undefined)
|
|
69
95
|
changes.push(...changeGoal(unplaced.text));
|
|
70
96
|
}
|
|
97
|
+
const open = task === undefined ? turn : taskTurns.get(task);
|
|
71
98
|
const placed = {
|
|
72
99
|
...unplaced,
|
|
73
100
|
session: start.session,
|
|
74
|
-
context:
|
|
75
|
-
...(
|
|
101
|
+
context: placedIn,
|
|
102
|
+
...(open === undefined ? {} : { turn: open.prompt.id }),
|
|
76
103
|
...(task === undefined ? {} : { task }),
|
|
77
104
|
};
|
|
78
105
|
changes.push({ type: Message, message: placed });
|
|
79
|
-
if (task !== undefined)
|
|
80
|
-
continue;
|
|
81
106
|
if (placed.type === ToolCall && agentTools.includes(placed.name))
|
|
82
107
|
agentCalls.add(placed.callId);
|
|
83
108
|
if (placed.type === ToolResult && agentCalls.has(placed.callId) && !placed.text.startsWith(asyncLaunch))
|
|
@@ -85,7 +110,7 @@ export function createConversation(start) {
|
|
|
85
110
|
if (placed.type === Note && placed.from.type === Task) {
|
|
86
111
|
const call = tagOf(textOf(row.content), 'tool-use-id');
|
|
87
112
|
if (call !== undefined && agentCalls.has(call))
|
|
88
|
-
changes.push(...endTask(call, row.at));
|
|
113
|
+
changes.push(...endTask(call, row.at, tagOf(textOf(row.content), 'task-id')));
|
|
89
114
|
}
|
|
90
115
|
}
|
|
91
116
|
return changes;
|
|
@@ -98,13 +123,10 @@ export function createConversation(start) {
|
|
|
98
123
|
agentCalls.add(data.openedBy);
|
|
99
124
|
const changes = [{ type: TaskStart, task: started }];
|
|
100
125
|
const endedAt = endedCalls.get(data.openedBy);
|
|
101
|
-
if (endedAt !== undefined)
|
|
102
|
-
|
|
103
|
-
changes.push(...endTask(data.openedBy, endedAt));
|
|
104
|
-
}
|
|
126
|
+
if (endedAt !== undefined)
|
|
127
|
+
changes.push(...endTask(data.openedBy, endedAt, data.id));
|
|
105
128
|
return changes;
|
|
106
129
|
},
|
|
107
|
-
endContext,
|
|
108
130
|
startContext,
|
|
109
131
|
changeGoal,
|
|
110
132
|
get state() {
|
|
@@ -117,6 +139,7 @@ export function createConversation(start) {
|
|
|
117
139
|
agentCalls: [...agentCalls],
|
|
118
140
|
endedCalls: Object.fromEntries(endedCalls),
|
|
119
141
|
tasks: Object.fromEntries(tasks),
|
|
142
|
+
taskTurns: Object.fromEntries(taskTurns),
|
|
120
143
|
};
|
|
121
144
|
},
|
|
122
145
|
};
|
package/session/goal/goal.d.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
import type { RecordPart } from '../session.js';
|
|
1
2
|
import type { Task } from './task.js';
|
|
2
3
|
export declare const GoalChange = "goalChange";
|
|
3
|
-
export type Goal = {
|
|
4
|
+
export type Goal = RecordPart & {
|
|
4
5
|
readonly text: string;
|
|
6
|
+
tasks(): Promise<Task[]>;
|
|
5
7
|
update(change: {
|
|
6
8
|
readonly text: string;
|
|
7
9
|
}): Promise<void>;
|
|
8
|
-
tasks(): Promise<Task[]>;
|
|
9
10
|
};
|
|
10
11
|
//# sourceMappingURL=goal.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"goal.d.ts","sourceRoot":"","sources":["../../src/session/goal/goal.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAErC,eAAO,MAAM,UAAU,eAAe,CAAA;AAEtC,MAAM,MAAM,IAAI,GAAG;
|
|
1
|
+
{"version":3,"file":"goal.d.ts","sourceRoot":"","sources":["../../src/session/goal/goal.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAC/C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAErC,eAAO,MAAM,UAAU,eAAe,CAAA;AAEtC,MAAM,MAAM,IAAI,GAAG,UAAU,GAAG;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,KAAK,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC,CAAA;IACxB,MAAM,CAAC,MAAM,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CACzD,CAAA"}
|
package/session/goal/task.d.ts
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import type { Message } from '../context/turn/message/message.js';
|
|
2
|
+
import type { RecordPart, Session } from '../session.js';
|
|
2
3
|
export declare const Task = "task";
|
|
3
4
|
export declare const TaskStart = "taskStart";
|
|
4
5
|
export declare const TaskEnd = "taskEnd";
|
|
5
|
-
export type Task = {
|
|
6
|
+
export type Task = RecordPart & {
|
|
6
7
|
readonly id: string;
|
|
7
8
|
readonly title: string;
|
|
8
|
-
readonly
|
|
9
|
-
readonly model?: string;
|
|
9
|
+
readonly owner: Session;
|
|
10
10
|
readonly openedBy: string;
|
|
11
11
|
readonly openedAt: string;
|
|
12
12
|
readonly closedAt?: string;
|
|
13
|
-
messages(): Promise<Message[]>;
|
|
14
13
|
tasks(): Promise<Task[]>;
|
|
14
|
+
messages(): Promise<Message[]>;
|
|
15
15
|
};
|
|
16
16
|
//# sourceMappingURL=task.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"task.d.ts","sourceRoot":"","sources":["../../src/session/goal/task.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oCAAoC,CAAA;
|
|
1
|
+
{"version":3,"file":"task.d.ts","sourceRoot":"","sources":["../../src/session/goal/task.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oCAAoC,CAAA;AACjE,OAAO,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AAExD,eAAO,MAAM,IAAI,SAAS,CAAA;AAE1B,eAAO,MAAM,SAAS,cAAc,CAAA;AAEpC,eAAO,MAAM,OAAO,YAAY,CAAA;AAEhC,MAAM,MAAM,IAAI,GAAG,UAAU,GAAG;IAC9B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;IACvB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;IAC1B,KAAK,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC,CAAA;IACxB,QAAQ,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC,CAAA;CAC/B,CAAA"}
|
package/session/session.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Disposable } from '../
|
|
1
|
+
import type { Disposable } from '../utils/disposable.js';
|
|
2
2
|
import type { Matcher } from '../utils/matcher.js';
|
|
3
3
|
import type { Context, ContextEnd, ContextStart } from './context/context.js';
|
|
4
4
|
import type { Document } from './context/turn/message/document.js';
|
|
@@ -15,7 +15,8 @@ import type { Turn, TurnEnd, TurnStart } from './context/turn/turn.js';
|
|
|
15
15
|
import type { Goal, GoalChange } from './goal/goal.js';
|
|
16
16
|
import type { Task, TaskEnd, TaskStart } from './goal/task.js';
|
|
17
17
|
export declare const Session = "session";
|
|
18
|
-
export
|
|
18
|
+
export declare const UsageChange = "usageChange";
|
|
19
|
+
export type SessionEvent = typeof Message | MessageType | typeof ContextStart | typeof ContextEnd | typeof TurnStart | typeof TurnEnd | typeof TaskStart | typeof TaskEnd | typeof GoalChange | typeof UsageChange;
|
|
19
20
|
export type SessionPayload = {
|
|
20
21
|
readonly message: Message;
|
|
21
22
|
readonly prompt: Prompt;
|
|
@@ -33,19 +34,73 @@ export type SessionPayload = {
|
|
|
33
34
|
readonly taskStart: Task;
|
|
34
35
|
readonly taskEnd: Task;
|
|
35
36
|
readonly goalChange: Goal;
|
|
37
|
+
readonly usageChange: Usage;
|
|
36
38
|
};
|
|
39
|
+
export type Refusal = {
|
|
40
|
+
readonly refuse: string;
|
|
41
|
+
};
|
|
42
|
+
export type BeforeAnswer = {
|
|
43
|
+
readonly prompt: {
|
|
44
|
+
readonly text: string;
|
|
45
|
+
} | Refusal;
|
|
46
|
+
readonly note: {
|
|
47
|
+
readonly text: string;
|
|
48
|
+
};
|
|
49
|
+
readonly skill: {
|
|
50
|
+
readonly text: string;
|
|
51
|
+
};
|
|
52
|
+
readonly document: {
|
|
53
|
+
readonly text: string;
|
|
54
|
+
} | Refusal;
|
|
55
|
+
readonly reply: {
|
|
56
|
+
readonly text: string;
|
|
57
|
+
};
|
|
58
|
+
readonly toolCall: {
|
|
59
|
+
readonly input: Readonly<Record<string, unknown>>;
|
|
60
|
+
} | {
|
|
61
|
+
readonly result: string;
|
|
62
|
+
} | Refusal;
|
|
63
|
+
readonly toolResult: {
|
|
64
|
+
readonly text: string;
|
|
65
|
+
};
|
|
66
|
+
readonly notice: {
|
|
67
|
+
readonly text: string;
|
|
68
|
+
};
|
|
69
|
+
readonly taskStart: {
|
|
70
|
+
readonly owner: {
|
|
71
|
+
readonly model: string;
|
|
72
|
+
};
|
|
73
|
+
} | Refusal;
|
|
74
|
+
readonly taskEnd: Refusal;
|
|
75
|
+
readonly turnEnd: Refusal;
|
|
76
|
+
readonly contextEnd: Refusal;
|
|
77
|
+
};
|
|
78
|
+
export type BeforeEvent = keyof BeforeAnswer;
|
|
37
79
|
export type Usage = {
|
|
38
80
|
readonly model: string;
|
|
39
81
|
readonly context: {
|
|
40
82
|
readonly tokens?: number;
|
|
41
|
-
readonly window
|
|
83
|
+
readonly window?: number;
|
|
42
84
|
readonly percent?: number;
|
|
43
85
|
};
|
|
44
86
|
readonly cost?: {
|
|
45
87
|
readonly usd: number;
|
|
46
88
|
};
|
|
47
89
|
};
|
|
90
|
+
export type Client = 'terminal' | 'desktop' | 'mobile' | 'vscode';
|
|
48
91
|
export type Listener<Event extends SessionEvent> = (payload: SessionPayload[Event]) => unknown;
|
|
92
|
+
export type BeforeListener<Event extends BeforeEvent> = (payload: SessionPayload[Event]) => BeforeAnswer[Event] | void | Promise<BeforeAnswer[Event] | void>;
|
|
93
|
+
export type SearchOptions = {
|
|
94
|
+
readonly limit?: number;
|
|
95
|
+
readonly before?: Pick<Message, 'session' | 'id'>;
|
|
96
|
+
};
|
|
97
|
+
export type RecordPart = {
|
|
98
|
+
search(text: string, options?: SearchOptions): Promise<Message[]>;
|
|
99
|
+
on<Event extends SessionEvent>(event: Event, listener: Listener<Event>): Disposable;
|
|
100
|
+
on<Event extends SessionEvent>(event: Event, matcher: Matcher<SessionPayload[Event]>, listener: Listener<Event>): Disposable;
|
|
101
|
+
before<Event extends BeforeEvent>(event: Event, listener: BeforeListener<Event>): Disposable;
|
|
102
|
+
before<Event extends BeforeEvent>(event: Event, matcher: Matcher<SessionPayload[Event]>, listener: BeforeListener<Event>): Disposable;
|
|
103
|
+
};
|
|
49
104
|
export type SessionSend = {
|
|
50
105
|
readonly type: typeof Prompt | typeof Note;
|
|
51
106
|
readonly text: string;
|
|
@@ -58,42 +113,46 @@ export type TaskStartArgs = {
|
|
|
58
113
|
readonly name?: string;
|
|
59
114
|
readonly cwd?: string;
|
|
60
115
|
};
|
|
61
|
-
export type
|
|
116
|
+
export type ToolCallArgs = {
|
|
117
|
+
readonly name: string;
|
|
118
|
+
readonly input: Readonly<Record<string, unknown>>;
|
|
119
|
+
};
|
|
120
|
+
export type Session = RecordPart & {
|
|
62
121
|
readonly id: string;
|
|
63
122
|
readonly title: string;
|
|
64
123
|
readonly project: string;
|
|
65
|
-
readonly
|
|
124
|
+
readonly agentType?: string;
|
|
66
125
|
readonly model: string;
|
|
126
|
+
readonly cwd: string;
|
|
127
|
+
readonly isRunning: boolean;
|
|
67
128
|
readonly startedAt: string;
|
|
68
129
|
readonly lastAt: string;
|
|
69
130
|
readonly forkedFrom?: string;
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
131
|
+
goal(): Promise<Goal>;
|
|
132
|
+
context(): Promise<Context>;
|
|
133
|
+
contexts(): Promise<Context[]>;
|
|
134
|
+
turn(): Promise<Turn | undefined>;
|
|
135
|
+
turns(options?: {
|
|
136
|
+
readonly last?: number;
|
|
137
|
+
}): Promise<Turn[]>;
|
|
76
138
|
messages(options?: {
|
|
77
139
|
readonly after?: string;
|
|
78
140
|
readonly last?: number;
|
|
79
141
|
}): Promise<Message[]>;
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
142
|
+
send(message: SessionSend): Promise<void>;
|
|
143
|
+
startTask(task: TaskStartArgs): Promise<Task>;
|
|
144
|
+
callTool(call: ToolCallArgs): Promise<ToolResult>;
|
|
145
|
+
usage(): Promise<Usage>;
|
|
146
|
+
clients(): Promise<Client[]>;
|
|
85
147
|
};
|
|
86
148
|
export type SessionScope = {
|
|
87
149
|
readonly running?: boolean;
|
|
88
150
|
readonly since?: string;
|
|
89
151
|
readonly everyProject?: boolean;
|
|
90
152
|
};
|
|
91
|
-
export type Sessions = {
|
|
153
|
+
export type Sessions = Omit<RecordPart, 'search'> & {
|
|
92
154
|
readonly current: Session;
|
|
93
155
|
list(options?: SessionScope): Promise<Session[]>;
|
|
94
|
-
search(text: string, options?: SessionScope &
|
|
95
|
-
readonly limit?: number;
|
|
96
|
-
readonly before?: Pick<Message, 'session' | 'id'>;
|
|
97
|
-
}): Promise<Message[]>;
|
|
156
|
+
search(text: string, options?: SessionScope & SearchOptions): Promise<Message[]>;
|
|
98
157
|
};
|
|
99
158
|
//# sourceMappingURL=session.d.ts.map
|
package/session/session.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../src/session/session.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../src/session/session.ts"],"names":[],"mappings":"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"}
|
package/session/session.js
CHANGED
package/src/jobs/program.ts
CHANGED
|
@@ -28,7 +28,12 @@ export function program(options: { readonly command: readonly string[]; readonly
|
|
|
28
28
|
const stop = (reason: string) => {
|
|
29
29
|
state = 'fatal'
|
|
30
30
|
failure = new Error(`${mod.name}: the ${executable} program stopped: ${reason}`)
|
|
31
|
-
|
|
31
|
+
const retry = () => {
|
|
32
|
+
exits = 0
|
|
33
|
+
failure = undefined
|
|
34
|
+
void start()
|
|
35
|
+
}
|
|
36
|
+
report({ id: `program:${executable}`, message: `The ${executable} program stopped`, description: reason, retry })
|
|
32
37
|
for (const waiter of waiting.splice(0)) waiter.reject(failure)
|
|
33
38
|
}
|
|
34
39
|
|
|
@@ -66,7 +71,7 @@ export function program(options: { readonly command: readonly string[]; readonly
|
|
|
66
71
|
exits += 1
|
|
67
72
|
const wait = backoffSeconds[exits - 1]
|
|
68
73
|
if (wait === undefined) {
|
|
69
|
-
stop(`it did not start again after ${backoffSeconds.length} tries: ${lastError === '' ? 'no standard error' : lastError}
|
|
74
|
+
stop(`it did not start again after ${backoffSeconds.length} tries: ${lastError === '' ? 'no standard error' : lastError}.`)
|
|
70
75
|
return
|
|
71
76
|
}
|
|
72
77
|
state = 'backoff'
|
package/src/mod.ts
CHANGED
|
@@ -2,6 +2,7 @@ import type {
|
|
|
2
2
|
AskOptions,
|
|
3
3
|
ClassicHookInputs,
|
|
4
4
|
CmodDependencies,
|
|
5
|
+
ConfigRow,
|
|
5
6
|
FsStatOptions,
|
|
6
7
|
HookStream,
|
|
7
8
|
HttpInit,
|
|
@@ -28,11 +29,10 @@ import { Mod as modSender } from './session/context/turn/message/sender.js'
|
|
|
28
29
|
import type { Sessions } from './session/session.js'
|
|
29
30
|
import type { Pane } from './ui/define-pane.js'
|
|
30
31
|
import type { Place, PlaceProps } from './ui/places.js'
|
|
32
|
+
import type { Disposable } from './utils/disposable.js'
|
|
31
33
|
import type { Matcher } from './utils/matcher.js'
|
|
32
34
|
|
|
33
|
-
export type Disposable
|
|
34
|
-
dispose(): void
|
|
35
|
-
}
|
|
35
|
+
export type { Disposable }
|
|
36
36
|
|
|
37
37
|
export type ToastId = string | number
|
|
38
38
|
|
|
@@ -63,6 +63,8 @@ export type PaneHandle = {
|
|
|
63
63
|
close(): Promise<void>
|
|
64
64
|
toggle(options?: Readonly<Pick<PaneOpenArgs, 'focus'>>): Promise<void>
|
|
65
65
|
readonly isOpen: boolean
|
|
66
|
+
readonly isShown: boolean
|
|
67
|
+
readonly isFocused: boolean
|
|
66
68
|
}
|
|
67
69
|
|
|
68
70
|
export const SessionStart = 'SessionStart'
|
|
@@ -83,26 +85,56 @@ export const Stop = 'Stop'
|
|
|
83
85
|
export const StopFailure = 'StopFailure'
|
|
84
86
|
export const CwdChanged = 'CwdChanged'
|
|
85
87
|
export const FileChanged = 'FileChanged'
|
|
88
|
+
export const UserPromptExpansion = 'UserPromptExpansion'
|
|
89
|
+
export const Setup = 'Setup'
|
|
90
|
+
export const ConfigChange = 'ConfigChange'
|
|
91
|
+
export const DirectoryAdded = 'DirectoryAdded'
|
|
92
|
+
export const PreModelSwitch = 'PreModelSwitch'
|
|
93
|
+
export const PostModelSwitch = 'PostModelSwitch'
|
|
94
|
+
export const PostCompact = 'PostCompact'
|
|
95
|
+
export const MessageDisplay = 'MessageDisplay'
|
|
96
|
+
export const TodoCreated = 'TaskCreated'
|
|
97
|
+
export const TodoCompleted = 'TaskCompleted'
|
|
98
|
+
export const TeammateIdle = 'TeammateIdle'
|
|
99
|
+
export const Elicitation = 'Elicitation'
|
|
100
|
+
export const ElicitationResult = 'ElicitationResult'
|
|
101
|
+
export const WorktreeCreate = 'WorktreeCreate'
|
|
102
|
+
export const WorktreeRemove = 'WorktreeRemove'
|
|
86
103
|
|
|
87
104
|
export const hooks = [
|
|
105
|
+
Setup,
|
|
88
106
|
SessionStart,
|
|
89
107
|
SessionEnd,
|
|
90
108
|
UserPromptSubmit,
|
|
109
|
+
UserPromptExpansion,
|
|
91
110
|
InstructionsLoaded,
|
|
111
|
+
ConfigChange,
|
|
112
|
+
DirectoryAdded,
|
|
113
|
+
PreModelSwitch,
|
|
114
|
+
PostModelSwitch,
|
|
92
115
|
PreToolUse,
|
|
93
116
|
PermissionRequest,
|
|
94
117
|
PermissionDenied,
|
|
95
118
|
PostToolUse,
|
|
96
119
|
PostToolUseFailure,
|
|
97
120
|
PostToolBatch,
|
|
121
|
+
MessageDisplay,
|
|
98
122
|
SubagentStart,
|
|
99
123
|
SubagentStop,
|
|
124
|
+
TodoCreated,
|
|
125
|
+
TodoCompleted,
|
|
126
|
+
TeammateIdle,
|
|
127
|
+
Elicitation,
|
|
128
|
+
ElicitationResult,
|
|
100
129
|
Notification,
|
|
101
130
|
PreCompact,
|
|
131
|
+
PostCompact,
|
|
102
132
|
Stop,
|
|
103
133
|
StopFailure,
|
|
104
134
|
CwdChanged,
|
|
105
135
|
FileChanged,
|
|
136
|
+
WorktreeCreate,
|
|
137
|
+
WorktreeRemove,
|
|
106
138
|
] as const
|
|
107
139
|
|
|
108
140
|
export type Hook = (typeof hooks)[number]
|
|
@@ -129,6 +161,8 @@ export type HookAnswer = {
|
|
|
129
161
|
updatedToolOutput?: unknown
|
|
130
162
|
updatedMCPToolOutput?: unknown
|
|
131
163
|
retry?: boolean
|
|
164
|
+
displayContent?: string
|
|
165
|
+
worktreePath?: string
|
|
132
166
|
}
|
|
133
167
|
}
|
|
134
168
|
|
|
@@ -203,9 +237,15 @@ export type SettingsFile = {
|
|
|
203
237
|
update(values: Readonly<Record<string, unknown>>): Promise<void>
|
|
204
238
|
}
|
|
205
239
|
|
|
240
|
+
export type Setting = Pick<ConfigRow, 'key' | 'label' | 'kind' | 'value' | 'isLocked'> & {
|
|
241
|
+
readonly description?: string
|
|
242
|
+
readonly options?: readonly string[]
|
|
243
|
+
readonly plugin?: string
|
|
244
|
+
}
|
|
245
|
+
|
|
206
246
|
export type Imports = {
|
|
207
247
|
readonly sessions: Sessions
|
|
208
|
-
readonly settings: { readonly user: SettingsFile; readonly project: SettingsFile; readonly local: SettingsFile }
|
|
248
|
+
readonly settings: { list(): Promise<Setting[]>; readonly user: SettingsFile; readonly project: SettingsFile; readonly local: SettingsFile }
|
|
209
249
|
readonly model: { complete(request: ModelCompleteRequest, options?: ModelCompleteOptions): Promise<ModelCompleteResult> }
|
|
210
250
|
readonly fs: {
|
|
211
251
|
read(path: string): Promise<string>
|
|
@@ -232,9 +272,12 @@ export const sessions: Imports['sessions'] = {
|
|
|
232
272
|
},
|
|
233
273
|
list: (options) => bound().sessions.list(options),
|
|
234
274
|
search: (text, options) => bound().sessions.search(text, options),
|
|
275
|
+
on: ((...args: Parameters<Imports['sessions']['on']>) => bound().sessions.on(...args)) as Imports['sessions']['on'],
|
|
276
|
+
before: ((...args: Parameters<Imports['sessions']['before']>) => bound().sessions.before(...args)) as Imports['sessions']['before'],
|
|
235
277
|
}
|
|
236
278
|
|
|
237
279
|
export const settings: Imports['settings'] = {
|
|
280
|
+
list: () => bound().settings.list(),
|
|
238
281
|
user: { read: () => bound().settings.user.read(), update: (values) => bound().settings.user.update(values) },
|
|
239
282
|
project: { read: () => bound().settings.project.read(), update: (values) => bound().settings.project.update(values) },
|
|
240
283
|
local: { read: () => bound().settings.local.read(), update: (values) => bound().settings.local.update(values) },
|
|
@@ -335,7 +378,7 @@ export function defineMod<State extends StateGroups = Record<never, never>, Name
|
|
|
335
378
|
export type { Matcher } from './utils/matcher.js'
|
|
336
379
|
export type { Place, PlaceProps } from './ui/places.js'
|
|
337
380
|
export { AbovePrompt, AskUserQuestion, CommandOutput, PromptHint, SessionMode, Spinner, ToolGroup, ToolProgress, TurnDuration } from './ui/places.js'
|
|
338
|
-
export { Session, type SessionEvent, type SessionPayload, type SessionScope, type SessionSend, type Sessions, type TaskStartArgs, type Usage } from './session/session.js'
|
|
381
|
+
export { Session, UsageChange, type BeforeAnswer, type BeforeEvent, type BeforeListener, type Client, type Listener, type RecordPart, type Refusal, type SearchOptions, type SessionEvent, type SessionPayload, type SessionScope, type SessionSend, type Sessions, type TaskStartArgs, type ToolCallArgs, type Usage } from './session/session.js'
|
|
339
382
|
export { ContextEnd, ContextStart, type Context } from './session/context/context.js'
|
|
340
383
|
export { TurnEnd, TurnStart, type Turn } from './session/context/turn/turn.js'
|
|
341
384
|
export { Message, type MessageType } from './session/context/turn/message/message.js'
|
package/src/records.ts
CHANGED
|
@@ -42,6 +42,7 @@ export type RunnerEvent =
|
|
|
42
42
|
| { type: 'needs-consent'; sha256: string; install: string; uninstall: string; keys: string; permissions: readonly string[] }
|
|
43
43
|
| { type: 'done'; name: string; version?: string }
|
|
44
44
|
| { type: 'missing'; name: string }
|
|
45
|
+
| { type: 'retries'; when: 'changed' | 'later' }
|
|
45
46
|
| { type: 'failed'; code: number; message: string }
|
|
46
47
|
|
|
47
48
|
export const pluginName = /^[A-Za-z0-9][A-Za-z0-9._-]*$/
|
|
@@ -249,7 +250,7 @@ function readKeys(keys: unknown): Steps {
|
|
|
249
250
|
return { keys: commands }
|
|
250
251
|
}
|
|
251
252
|
|
|
252
|
-
export const coreVersion = '1.
|
|
253
|
+
export const coreVersion = '1.5.0'
|
|
253
254
|
|
|
254
255
|
export function oldestCmodFor(steps: Steps): string {
|
|
255
256
|
if (steps.permissions?.some((item) => item === 'tasks' || item.startsWith('config:')) === true) return '1.0.0'
|
|
@@ -328,6 +329,8 @@ export function formatEvent(event: RunnerEvent): string {
|
|
|
328
329
|
return `missing ${event.name}`
|
|
329
330
|
case 'failed':
|
|
330
331
|
return `failed ${event.code}\t${event.message.replace(/\s*\n\s*/g, ' ')}`
|
|
332
|
+
case 'retries':
|
|
333
|
+
return `retries ${event.when}`
|
|
331
334
|
}
|
|
332
335
|
}
|
|
333
336
|
|
|
@@ -345,6 +348,8 @@ export function parseEvent(line: string): RunnerEvent {
|
|
|
345
348
|
if (missing !== null) return { type: 'missing', name: missing[1] as string }
|
|
346
349
|
const failed = /^failed (-?\d+)(?:\t(.*))?$/.exec(line)
|
|
347
350
|
if (failed !== null) return { type: 'failed', code: Number(failed[1]), message: failed[2] ?? '' }
|
|
351
|
+
const retries = /^retries (changed|later)$/.exec(line)
|
|
352
|
+
if (retries !== null) return { type: 'retries', when: retries[1] as 'changed' | 'later' }
|
|
348
353
|
return { type: 'log', text: line.replace(/^log /, '') }
|
|
349
354
|
}
|
|
350
355
|
|
package/src/register.ts
CHANGED
|
@@ -30,6 +30,7 @@ async function startMod($: EngineInterface, eventInput: Frozen<Args<'session.sta
|
|
|
30
30
|
panes: () => $.ui.panes(),
|
|
31
31
|
scroll: (args) => $.ui.scroll(args),
|
|
32
32
|
copy: (args) => $.ui.copy(args),
|
|
33
|
+
focus: (args) => $.ui.focus(args),
|
|
33
34
|
resolve: (render) => $.ui.resolve(render),
|
|
34
35
|
},
|
|
35
36
|
process: {
|
|
@@ -101,21 +102,36 @@ export function registerMod<State extends object, Declared extends Options>(addH
|
|
|
101
102
|
registered = definition as ModDefinition<object>
|
|
102
103
|
lifecycle = createLifecycle(definition, () => checksPermissions, options)
|
|
103
104
|
addHook('session.start', startMod)
|
|
105
|
+
addHook('classic.Setup', routeToMod)
|
|
104
106
|
addHook('classic.SessionStart', routeToMod)
|
|
105
107
|
addHook('classic.SessionEnd', routeToMod)
|
|
106
108
|
addHook('classic.UserPromptSubmit', routeToMod)
|
|
109
|
+
addHook('classic.UserPromptExpansion', routeToMod)
|
|
107
110
|
addHook('classic.InstructionsLoaded', routeToMod)
|
|
111
|
+
addHook('classic.ConfigChange', routeToMod)
|
|
112
|
+
addHook('classic.DirectoryAdded', routeToMod)
|
|
113
|
+
addHook('classic.PreModelSwitch', routeToMod)
|
|
114
|
+
addHook('classic.PostModelSwitch', routeToMod)
|
|
108
115
|
addHook('classic.PermissionDenied', routeToMod)
|
|
109
116
|
addHook('classic.PostToolUse', routeToMod)
|
|
110
117
|
addHook('classic.PostToolUseFailure', routeToMod)
|
|
111
118
|
addHook('classic.PostToolBatch', routeToMod)
|
|
119
|
+
addHook('classic.MessageDisplay', routeToMod)
|
|
112
120
|
addHook('classic.SubagentStart', routeToMod)
|
|
113
121
|
addHook('classic.SubagentStop', routeToMod)
|
|
122
|
+
addHook('classic.TaskCreated', routeToMod)
|
|
123
|
+
addHook('classic.TaskCompleted', routeToMod)
|
|
124
|
+
addHook('classic.TeammateIdle', routeToMod)
|
|
125
|
+
addHook('classic.Elicitation', routeToMod)
|
|
126
|
+
addHook('classic.ElicitationResult', routeToMod)
|
|
114
127
|
addHook('classic.Notification', routeToMod)
|
|
115
128
|
addHook('classic.PreCompact', routeToMod)
|
|
129
|
+
addHook('classic.PostCompact', routeToMod)
|
|
116
130
|
addHook('classic.Stop', routeToMod)
|
|
117
131
|
addHook('classic.StopFailure', routeToMod)
|
|
118
132
|
addHook('classic.FileChanged', routeToMod)
|
|
133
|
+
addHook('classic.WorktreeCreate', routeToMod)
|
|
134
|
+
addHook('classic.WorktreeRemove', routeToMod)
|
|
119
135
|
addHook('tool.call', routeToMod)
|
|
120
136
|
addHook('prompt.submit', routeToMod)
|
|
121
137
|
addHook('prompt.context', routeToMod)
|
|
@@ -132,6 +148,7 @@ export function registerMod<State extends object, Declared extends Options>(addH
|
|
|
132
148
|
addHook('session.compact', routeToMod)
|
|
133
149
|
addHook('session.receive', routeToMod)
|
|
134
150
|
addHook('agent.spawn', routeToMod)
|
|
151
|
+
addHook('prompt.attachment', routeToMod)
|
|
135
152
|
}
|
|
136
153
|
|
|
137
154
|
export function registerPermissionCheck(addHook: On): void {
|
package/src/runtime/announce.ts
CHANGED
|
@@ -27,9 +27,11 @@ export async function announcementOf(claude: Claude, plugin: Plugin, granted: Re
|
|
|
27
27
|
const open = (page?: string) => () => claude.cmod.call({ to: cmodPluginName, method: 'openSettings', input: { mod: plugin.name, ...(page === undefined ? {} : { page }) } })
|
|
28
28
|
if (previous === undefined) {
|
|
29
29
|
const { program, keys } = plugin.steps
|
|
30
|
+
const rules = (await claude.fs.list(`${plugin.root}/rules`).catch(ifMissing([]))).filter((entry) => entry.kind === 'file' && entry.name.endsWith('.md')).map((entry) => entry.name.slice(0, -'.md'.length)).toSorted()
|
|
30
31
|
const lines = [
|
|
31
32
|
field('description'),
|
|
32
33
|
added.length > 0 ? `Adds ${listed(added)}.` : undefined,
|
|
34
|
+
rules.length > 0 ? `Adds ${rules.length} ${rules.length === 1 ? 'rule' : 'rules'}: ${listed(rules)}.` : undefined,
|
|
33
35
|
program === undefined ? undefined : `Installed the ${program} program.`,
|
|
34
36
|
...Object.entries(keys ?? {}).map(([key, command]) => `Binds ${key} to /${command}.`),
|
|
35
37
|
...[...granted].map((item) => `${permissionWords(item)}.`),
|