@cmodjs/core 0.3.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 +61 -10
- package/docs/dependencies.md +16 -14
- package/docs/hooks.md +64 -29
- package/docs/index.md +29 -25
- package/docs/install-steps.md +13 -9
- package/docs/jobs.md +59 -111
- package/docs/mod.md +227 -175
- package/docs/options.md +2 -2
- package/docs/permissions.md +27 -16
- package/docs/session.md +311 -0
- package/docs/state.md +11 -7
- package/docs/testing.md +68 -23
- package/docs/ui.md +116 -76
- package/jobs/check.d.ts.map +1 -1
- package/jobs/check.js +5 -2
- package/jobs/context.d.ts +7 -8
- package/jobs/context.d.ts.map +1 -1
- package/jobs/context.js +23 -73
- package/jobs/permissions/decide-permission.d.ts +5 -3
- package/jobs/permissions/decide-permission.d.ts.map +1 -1
- package/jobs/permissions/decide-permission.js +6 -4
- package/jobs/permissions/find-project-scope.d.ts +1 -1
- package/jobs/permissions/find-project-scope.d.ts.map +1 -1
- package/jobs/permissions/find-project-scope.js +8 -11
- package/jobs/permissions/match-target.d.ts +2 -2
- package/jobs/permissions/match-target.d.ts.map +1 -1
- package/jobs/permissions.d.ts +1 -1
- package/jobs/permissions.d.ts.map +1 -1
- package/jobs/permissions.js +6 -4
- package/jobs/program.d.ts.map +1 -1
- package/jobs/program.js +14 -4
- package/jobs/prompt.d.ts +4 -2
- package/jobs/prompt.d.ts.map +1 -1
- package/jobs/prompt.js +16 -15
- package/jobs/schedule.d.ts +2 -2
- package/jobs/schedule.d.ts.map +1 -1
- package/jobs/schedule.js +9 -9
- package/jobs/slash-command.d.ts +4 -4
- package/jobs/slash-command.d.ts.map +1 -1
- package/jobs/slash-command.js +14 -9
- package/jobs/status-line.d.ts +1 -11
- package/jobs/status-line.d.ts.map +1 -1
- package/jobs/status-line.js +8 -12
- package/jobs/tool.d.ts +2 -2
- package/jobs/tool.d.ts.map +1 -1
- package/jobs/tool.js +15 -9
- package/mod.d.ts +178 -75
- package/mod.d.ts.map +1 -1
- package/mod.js +127 -3
- package/options.d.ts +2 -2
- package/options.js +19 -19
- package/package.json +3 -3
- package/records.d.ts +13 -8
- package/records.d.ts.map +1 -1
- package/records.js +33 -17
- package/register.d.ts.map +1 -1
- package/register.js +34 -5
- package/runtime/announce.d.ts +18 -0
- package/runtime/announce.d.ts.map +1 -0
- package/runtime/announce.js +68 -0
- package/runtime/before.d.ts +32 -0
- package/runtime/before.d.ts.map +1 -0
- package/runtime/before.js +214 -0
- package/runtime/bound.d.ts +4 -0
- package/runtime/bound.d.ts.map +1 -0
- package/runtime/bound.js +9 -0
- package/runtime/claude.d.ts +4 -2
- package/runtime/claude.d.ts.map +1 -1
- package/runtime/conversations.d.ts +17 -0
- package/runtime/conversations.d.ts.map +1 -0
- package/runtime/conversations.js +563 -0
- package/runtime/deadline.d.ts +0 -1
- package/runtime/deadline.d.ts.map +1 -1
- package/runtime/deadline.js +1 -1
- package/runtime/dependencies.d.ts +2 -0
- package/runtime/dependencies.d.ts.map +1 -1
- package/runtime/dependencies.js +10 -1
- package/runtime/engine.d.ts +13 -0
- package/runtime/engine.d.ts.map +1 -0
- package/runtime/engine.js +10 -0
- package/runtime/grants.d.ts +4 -0
- package/runtime/grants.d.ts.map +1 -1
- package/runtime/grants.js +68 -31
- package/runtime/hooks.d.ts +5 -4
- package/runtime/hooks.d.ts.map +1 -1
- package/runtime/hooks.js +29 -9
- package/runtime/installer.d.ts +1 -1
- package/runtime/installer.d.ts.map +1 -1
- package/runtime/installer.js +17 -14
- package/runtime/lifecycle.d.ts +3 -1
- package/runtime/lifecycle.d.ts.map +1 -1
- package/runtime/lifecycle.js +414 -212
- package/runtime/metadata.d.ts +3 -1
- package/runtime/metadata.d.ts.map +1 -1
- package/runtime/metadata.js +25 -14
- package/runtime/options.d.ts +3 -1
- package/runtime/options.d.ts.map +1 -1
- package/runtime/options.js +4 -4
- package/runtime/programs.d.ts +8 -0
- package/runtime/programs.d.ts.map +1 -1
- package/runtime/programs.js +39 -1
- package/runtime/router.d.ts +2 -1
- package/runtime/router.d.ts.map +1 -1
- package/runtime/router.js +11 -3
- package/runtime/sessions.d.ts +58 -0
- package/runtime/sessions.d.ts.map +1 -0
- package/runtime/sessions.js +433 -0
- package/runtime/state.d.ts +6 -2
- package/runtime/state.d.ts.map +1 -1
- package/runtime/state.js +46 -13
- package/runtime/toaster.d.ts +24 -0
- package/runtime/toaster.d.ts.map +1 -0
- package/runtime/toaster.js +286 -0
- package/runtime/ui.d.ts +6 -17
- package/runtime/ui.d.ts.map +1 -1
- package/runtime/ui.js +62 -118
- package/session/context/context.d.ts +12 -0
- package/session/context/context.d.ts.map +1 -0
- package/session/context/context.js +2 -0
- package/session/context/turn/message/document.d.ts +7 -0
- package/session/context/turn/message/document.d.ts.map +1 -0
- package/session/context/turn/message/document.js +1 -0
- package/session/context/turn/message/message.d.ts +55 -0
- package/session/context/turn/message/message.d.ts.map +1 -0
- package/session/context/turn/message/message.js +178 -0
- package/session/context/turn/message/note.d.ts +8 -0
- package/session/context/turn/message/note.d.ts.map +1 -0
- package/session/context/turn/message/note.js +1 -0
- package/session/context/turn/message/notice.d.ts +6 -0
- package/session/context/turn/message/notice.d.ts.map +1 -0
- package/session/context/turn/message/notice.js +1 -0
- package/session/context/turn/message/prompt.d.ts +8 -0
- package/session/context/turn/message/prompt.d.ts.map +1 -0
- package/session/context/turn/message/prompt.js +1 -0
- package/session/context/turn/message/reply.d.ts +6 -0
- package/session/context/turn/message/reply.d.ts.map +1 -0
- package/session/context/turn/message/reply.js +1 -0
- package/session/context/turn/message/sender.d.ts +14 -0
- package/session/context/turn/message/sender.d.ts.map +1 -0
- package/session/context/turn/message/sender.js +30 -0
- package/session/context/turn/message/skill.d.ts +7 -0
- package/session/context/turn/message/skill.d.ts.map +1 -0
- package/session/context/turn/message/skill.js +1 -0
- package/session/context/turn/message/tool-call.d.ts +9 -0
- package/session/context/turn/message/tool-call.d.ts.map +1 -0
- package/session/context/turn/message/tool-call.js +1 -0
- package/session/context/turn/message/tool-result.d.ts +8 -0
- package/session/context/turn/message/tool-result.d.ts.map +1 -0
- package/session/context/turn/message/tool-result.js +1 -0
- package/session/context/turn/turn.d.ts +13 -0
- package/session/context/turn/turn.d.ts.map +1 -0
- package/session/context/turn/turn.js +2 -0
- package/session/conversation.d.ts +73 -0
- package/session/conversation.d.ts.map +1 -0
- package/session/conversation.js +146 -0
- package/session/goal/goal.d.ts +11 -0
- package/session/goal/goal.d.ts.map +1 -0
- package/session/goal/goal.js +1 -0
- package/session/goal/task.d.ts +16 -0
- package/session/goal/task.d.ts.map +1 -0
- package/session/goal/task.js +3 -0
- package/session/session.d.ts +158 -0
- package/session/session.d.ts.map +1 -0
- package/session/session.js +2 -0
- package/src/jobs/check.ts +7 -4
- package/src/jobs/context.ts +24 -82
- package/src/jobs/permissions/decide-permission.ts +10 -8
- package/src/jobs/permissions/find-project-scope.ts +8 -14
- package/src/jobs/permissions/match-target.ts +3 -3
- package/src/jobs/permissions.ts +8 -6
- package/src/jobs/program.ts +13 -4
- package/src/jobs/prompt.ts +21 -24
- package/src/jobs/schedule.ts +14 -14
- package/src/jobs/slash-command.ts +20 -14
- package/src/jobs/status-line.ts +9 -21
- package/src/jobs/tool.ts +17 -11
- package/src/mod.ts +252 -97
- package/src/options.ts +22 -22
- package/src/records.ts +40 -23
- package/src/register.ts +34 -5
- package/src/runtime/announce.ts +76 -0
- package/src/runtime/before.ts +200 -0
- package/src/runtime/bound.ts +12 -0
- package/src/runtime/claude.ts +7 -2
- package/src/runtime/conversations.ts +579 -0
- package/src/runtime/deadline.ts +2 -2
- package/src/runtime/dependencies.ts +13 -1
- package/src/runtime/engine.ts +23 -0
- package/src/runtime/grants.ts +69 -29
- package/src/runtime/hooks.ts +39 -14
- package/src/runtime/installer.ts +16 -14
- package/src/runtime/lifecycle.ts +413 -201
- package/src/runtime/metadata.ts +37 -14
- package/src/runtime/options.ts +19 -4
- package/src/runtime/programs.ts +40 -1
- package/src/runtime/router.ts +11 -4
- package/src/runtime/sessions.ts +447 -0
- package/src/runtime/state.ts +50 -14
- package/src/runtime/toaster.ts +334 -0
- package/src/runtime/ui.ts +65 -143
- package/src/session/context/context.ts +14 -0
- package/src/session/context/turn/message/document.ts +8 -0
- package/src/session/context/turn/message/message.ts +203 -0
- package/src/session/context/turn/message/note.ts +9 -0
- package/src/session/context/turn/message/notice.ts +7 -0
- package/src/session/context/turn/message/prompt.ts +9 -0
- package/src/session/context/turn/message/reply.ts +7 -0
- package/src/session/context/turn/message/sender.ts +38 -0
- package/src/session/context/turn/message/skill.ts +8 -0
- package/src/session/context/turn/message/tool-call.ts +10 -0
- package/src/session/context/turn/message/tool-result.ts +9 -0
- package/src/session/context/turn/turn.ts +15 -0
- package/src/session/conversation.ts +194 -0
- package/src/session/goal/goal.ts +10 -0
- package/src/session/goal/task.ts +19 -0
- package/src/session/session.ts +141 -0
- package/src/testing/fake-claude.ts +25 -17
- package/src/testing/fake-elements.ts +3 -2
- package/src/testing/fake-files.ts +1 -1
- package/src/testing/fake-sessions.ts +277 -0
- package/src/testing.ts +138 -35
- package/src/ui/components.ts +3 -3
- package/src/ui/elements.ts +22 -8
- package/src/ui/markdown.ts +22 -26
- package/src/ui/places.ts +49 -0
- package/src/utils/call-effects.ts +5 -5
- package/src/utils/changelog.ts +32 -0
- package/src/utils/disposable.ts +3 -0
- package/src/utils/matcher.ts +37 -0
- package/src/utils/metadata.ts +17 -15
- package/src/utils/parse-shell.ts +9 -8
- package/src/utils/paths.ts +21 -4
- package/src/utils/text.ts +4 -0
- package/testing/fake-claude.d.ts +5 -1
- package/testing/fake-claude.d.ts.map +1 -1
- package/testing/fake-claude.js +21 -12
- package/testing/fake-elements.js +4 -2
- package/testing/fake-files.js +1 -1
- package/testing/fake-sessions.d.ts +81 -0
- package/testing/fake-sessions.d.ts.map +1 -0
- package/testing/fake-sessions.js +249 -0
- package/testing.d.ts +34 -13
- package/testing.d.ts.map +1 -1
- package/testing.js +115 -23
- package/ui/components.d.ts +2 -3
- package/ui/components.d.ts.map +1 -1
- package/ui/components.js +3 -3
- package/ui/elements.d.ts.map +1 -1
- package/ui/elements.js +19 -9
- package/ui/markdown.d.ts +35 -33
- package/ui/markdown.d.ts.map +1 -1
- package/ui/markdown.js +14 -16
- package/ui/places.d.ts +43 -0
- package/ui/places.d.ts.map +1 -0
- package/ui/places.js +31 -0
- package/utils/call-effects.d.ts +2 -1
- package/utils/call-effects.d.ts.map +1 -1
- package/utils/call-effects.js +3 -3
- package/utils/changelog.d.ts +9 -0
- package/utils/changelog.d.ts.map +1 -0
- package/utils/changelog.js +29 -0
- package/utils/disposable.d.ts +4 -0
- package/utils/disposable.d.ts.map +1 -0
- package/utils/disposable.js +1 -0
- package/utils/matcher.d.ts +13 -0
- package/utils/matcher.d.ts.map +1 -0
- package/utils/matcher.js +32 -0
- package/utils/metadata.d.ts +3 -3
- package/utils/metadata.js +18 -14
- package/utils/parse-shell.js +9 -7
- package/utils/paths.d.ts +4 -1
- package/utils/paths.d.ts.map +1 -1
- package/utils/paths.js +19 -4
- package/utils/text.d.ts +1 -0
- package/utils/text.d.ts.map +1 -1
- package/utils/text.js +3 -0
- package/src/ui/slots.ts +0 -36
- package/ui/slots.d.ts +0 -208
- package/ui/slots.d.ts.map +0 -1
- package/ui/slots.js +0 -19
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { ContextEnd, ContextStart } from './context/context.js';
|
|
2
|
+
import { Message, messagesOf, tagOf, textOf } from './context/turn/message/message.js';
|
|
3
|
+
import { Note } from './context/turn/message/note.js';
|
|
4
|
+
import { Prompt } from './context/turn/message/prompt.js';
|
|
5
|
+
import { ToolCall } from './context/turn/message/tool-call.js';
|
|
6
|
+
import { ToolResult } from './context/turn/message/tool-result.js';
|
|
7
|
+
import { TurnEnd, TurnStart } from './context/turn/turn.js';
|
|
8
|
+
import { GoalChange } from './goal/goal.js';
|
|
9
|
+
import { Task, TaskEnd, TaskStart } from './goal/task.js';
|
|
10
|
+
export const searchLimit = 50;
|
|
11
|
+
const agentTools = ['Agent', 'Task'];
|
|
12
|
+
const asyncLaunch = 'Async agent launched';
|
|
13
|
+
export function emptyConversation(session) {
|
|
14
|
+
return { session, context: 0, contextOpenedAt: '', agentCalls: [], endedCalls: {}, tasks: {}, taskTurns: {} };
|
|
15
|
+
}
|
|
16
|
+
export function createConversation(start) {
|
|
17
|
+
let { context, contextOpenedAt, turn, goal } = start;
|
|
18
|
+
const agentCalls = new Set(start.agentCalls);
|
|
19
|
+
const endedCalls = new Map(Object.entries(start.endedCalls));
|
|
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
|
+
};
|
|
29
|
+
const startContext = (at) => {
|
|
30
|
+
context += 1;
|
|
31
|
+
contextOpenedAt = at;
|
|
32
|
+
return [{ type: ContextStart, context: { number: context, openedAt: at } }];
|
|
33
|
+
};
|
|
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
|
+
};
|
|
46
|
+
const endTurn = (at) => {
|
|
47
|
+
if (turn === undefined)
|
|
48
|
+
return [];
|
|
49
|
+
const ended = { ...turn, closedAt: at };
|
|
50
|
+
turn = undefined;
|
|
51
|
+
return [{ type: TurnEnd, turn: ended }];
|
|
52
|
+
};
|
|
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) {
|
|
56
|
+
if (agentCalls.has(call))
|
|
57
|
+
endedCalls.set(call, at);
|
|
58
|
+
return [];
|
|
59
|
+
}
|
|
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
|
+
});
|
|
69
|
+
};
|
|
70
|
+
const changeGoal = (text) => {
|
|
71
|
+
goal = text;
|
|
72
|
+
return [{ type: GoalChange, goal: { text } }];
|
|
73
|
+
};
|
|
74
|
+
return {
|
|
75
|
+
add(row, task) {
|
|
76
|
+
const changes = [];
|
|
77
|
+
if (task === undefined && context === 0)
|
|
78
|
+
changes.push(...startContext(row.at));
|
|
79
|
+
if (task === undefined && row.type === 'system' && row.name === 'turn_duration')
|
|
80
|
+
return [...changes, ...endTurn(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))];
|
|
83
|
+
const owner = task === undefined ? undefined : tasks.get(task);
|
|
84
|
+
const placedIn = owner?.context ?? context;
|
|
85
|
+
for (const unplaced of messagesOf(row, task !== undefined)) {
|
|
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);
|
|
93
|
+
changes.push({ type: TurnStart, turn: opened });
|
|
94
|
+
if (task === undefined && goal === undefined)
|
|
95
|
+
changes.push(...changeGoal(unplaced.text));
|
|
96
|
+
}
|
|
97
|
+
const open = task === undefined ? turn : taskTurns.get(task);
|
|
98
|
+
const placed = {
|
|
99
|
+
...unplaced,
|
|
100
|
+
session: start.session,
|
|
101
|
+
context: placedIn,
|
|
102
|
+
...(open === undefined ? {} : { turn: open.prompt.id }),
|
|
103
|
+
...(task === undefined ? {} : { task }),
|
|
104
|
+
};
|
|
105
|
+
changes.push({ type: Message, message: placed });
|
|
106
|
+
if (placed.type === ToolCall && agentTools.includes(placed.name))
|
|
107
|
+
agentCalls.add(placed.callId);
|
|
108
|
+
if (placed.type === ToolResult && agentCalls.has(placed.callId) && !placed.text.startsWith(asyncLaunch))
|
|
109
|
+
changes.push(...endTask(placed.callId, row.at));
|
|
110
|
+
if (placed.type === Note && placed.from.type === Task) {
|
|
111
|
+
const call = tagOf(textOf(row.content), 'tool-use-id');
|
|
112
|
+
if (call !== undefined && agentCalls.has(call))
|
|
113
|
+
changes.push(...endTask(call, row.at, tagOf(textOf(row.content), 'task-id')));
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return changes;
|
|
117
|
+
},
|
|
118
|
+
startTask(data) {
|
|
119
|
+
if (tasks.has(data.id))
|
|
120
|
+
return [];
|
|
121
|
+
const started = { ...data, context };
|
|
122
|
+
tasks.set(data.id, started);
|
|
123
|
+
agentCalls.add(data.openedBy);
|
|
124
|
+
const changes = [{ type: TaskStart, task: started }];
|
|
125
|
+
const endedAt = endedCalls.get(data.openedBy);
|
|
126
|
+
if (endedAt !== undefined)
|
|
127
|
+
changes.push(...endTask(data.openedBy, endedAt, data.id));
|
|
128
|
+
return changes;
|
|
129
|
+
},
|
|
130
|
+
startContext,
|
|
131
|
+
changeGoal,
|
|
132
|
+
get state() {
|
|
133
|
+
return {
|
|
134
|
+
session: start.session,
|
|
135
|
+
context,
|
|
136
|
+
contextOpenedAt,
|
|
137
|
+
...(turn === undefined ? {} : { turn }),
|
|
138
|
+
...(goal === undefined ? {} : { goal }),
|
|
139
|
+
agentCalls: [...agentCalls],
|
|
140
|
+
endedCalls: Object.fromEntries(endedCalls),
|
|
141
|
+
tasks: Object.fromEntries(tasks),
|
|
142
|
+
taskTurns: Object.fromEntries(taskTurns),
|
|
143
|
+
};
|
|
144
|
+
},
|
|
145
|
+
};
|
|
146
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { RecordPart } from '../session.js';
|
|
2
|
+
import type { Task } from './task.js';
|
|
3
|
+
export declare const GoalChange = "goalChange";
|
|
4
|
+
export type Goal = RecordPart & {
|
|
5
|
+
readonly text: string;
|
|
6
|
+
tasks(): Promise<Task[]>;
|
|
7
|
+
update(change: {
|
|
8
|
+
readonly text: string;
|
|
9
|
+
}): Promise<void>;
|
|
10
|
+
};
|
|
11
|
+
//# sourceMappingURL=goal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const GoalChange = 'goalChange';
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Message } from '../context/turn/message/message.js';
|
|
2
|
+
import type { RecordPart, Session } from '../session.js';
|
|
3
|
+
export declare const Task = "task";
|
|
4
|
+
export declare const TaskStart = "taskStart";
|
|
5
|
+
export declare const TaskEnd = "taskEnd";
|
|
6
|
+
export type Task = RecordPart & {
|
|
7
|
+
readonly id: string;
|
|
8
|
+
readonly title: string;
|
|
9
|
+
readonly owner: Session;
|
|
10
|
+
readonly openedBy: string;
|
|
11
|
+
readonly openedAt: string;
|
|
12
|
+
readonly closedAt?: string;
|
|
13
|
+
tasks(): Promise<Task[]>;
|
|
14
|
+
messages(): Promise<Message[]>;
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=task.d.ts.map
|
|
@@ -0,0 +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;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"}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import type { Disposable } from '../utils/disposable.js';
|
|
2
|
+
import type { Matcher } from '../utils/matcher.js';
|
|
3
|
+
import type { Context, ContextEnd, ContextStart } from './context/context.js';
|
|
4
|
+
import type { Document } from './context/turn/message/document.js';
|
|
5
|
+
import type { Message, MessageType } from './context/turn/message/message.js';
|
|
6
|
+
import type { Note } from './context/turn/message/note.js';
|
|
7
|
+
import type { Notice } from './context/turn/message/notice.js';
|
|
8
|
+
import type { Prompt } from './context/turn/message/prompt.js';
|
|
9
|
+
import type { Reply } from './context/turn/message/reply.js';
|
|
10
|
+
import type { Person } from './context/turn/message/sender.js';
|
|
11
|
+
import type { Skill } from './context/turn/message/skill.js';
|
|
12
|
+
import type { ToolCall } from './context/turn/message/tool-call.js';
|
|
13
|
+
import type { ToolResult } from './context/turn/message/tool-result.js';
|
|
14
|
+
import type { Turn, TurnEnd, TurnStart } from './context/turn/turn.js';
|
|
15
|
+
import type { Goal, GoalChange } from './goal/goal.js';
|
|
16
|
+
import type { Task, TaskEnd, TaskStart } from './goal/task.js';
|
|
17
|
+
export declare const Session = "session";
|
|
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;
|
|
20
|
+
export type SessionPayload = {
|
|
21
|
+
readonly message: Message;
|
|
22
|
+
readonly prompt: Prompt;
|
|
23
|
+
readonly note: Note;
|
|
24
|
+
readonly reply: Reply;
|
|
25
|
+
readonly toolCall: ToolCall;
|
|
26
|
+
readonly toolResult: ToolResult;
|
|
27
|
+
readonly skill: Skill;
|
|
28
|
+
readonly document: Document;
|
|
29
|
+
readonly notice: Notice;
|
|
30
|
+
readonly contextStart: Context;
|
|
31
|
+
readonly contextEnd: Context;
|
|
32
|
+
readonly turnStart: Turn;
|
|
33
|
+
readonly turnEnd: Turn;
|
|
34
|
+
readonly taskStart: Task;
|
|
35
|
+
readonly taskEnd: Task;
|
|
36
|
+
readonly goalChange: Goal;
|
|
37
|
+
readonly usageChange: Usage;
|
|
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;
|
|
79
|
+
export type Usage = {
|
|
80
|
+
readonly model: string;
|
|
81
|
+
readonly context: {
|
|
82
|
+
readonly tokens?: number;
|
|
83
|
+
readonly window?: number;
|
|
84
|
+
readonly percent?: number;
|
|
85
|
+
};
|
|
86
|
+
readonly cost?: {
|
|
87
|
+
readonly usd: number;
|
|
88
|
+
};
|
|
89
|
+
};
|
|
90
|
+
export type Client = 'terminal' | 'desktop' | 'mobile' | 'vscode';
|
|
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
|
+
};
|
|
104
|
+
export type SessionSend = {
|
|
105
|
+
readonly type: typeof Prompt | typeof Note;
|
|
106
|
+
readonly text: string;
|
|
107
|
+
readonly as?: typeof Person | typeof Session;
|
|
108
|
+
};
|
|
109
|
+
export type TaskStartArgs = {
|
|
110
|
+
readonly prompt: string;
|
|
111
|
+
readonly agentType?: string;
|
|
112
|
+
readonly model?: string;
|
|
113
|
+
readonly name?: string;
|
|
114
|
+
readonly cwd?: string;
|
|
115
|
+
};
|
|
116
|
+
export type ToolCallArgs = {
|
|
117
|
+
readonly name: string;
|
|
118
|
+
readonly input: Readonly<Record<string, unknown>>;
|
|
119
|
+
};
|
|
120
|
+
export type Session = RecordPart & {
|
|
121
|
+
readonly id: string;
|
|
122
|
+
readonly title: string;
|
|
123
|
+
readonly project: string;
|
|
124
|
+
readonly agentType?: string;
|
|
125
|
+
readonly model: string;
|
|
126
|
+
readonly cwd: string;
|
|
127
|
+
readonly isRunning: boolean;
|
|
128
|
+
readonly startedAt: string;
|
|
129
|
+
readonly lastAt: string;
|
|
130
|
+
readonly forkedFrom?: string;
|
|
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[]>;
|
|
138
|
+
messages(options?: {
|
|
139
|
+
readonly after?: string;
|
|
140
|
+
readonly last?: number;
|
|
141
|
+
}): Promise<Message[]>;
|
|
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[]>;
|
|
147
|
+
};
|
|
148
|
+
export type SessionScope = {
|
|
149
|
+
readonly running?: boolean;
|
|
150
|
+
readonly since?: string;
|
|
151
|
+
readonly everyProject?: boolean;
|
|
152
|
+
};
|
|
153
|
+
export type Sessions = Omit<RecordPart, 'search'> & {
|
|
154
|
+
readonly current: Session;
|
|
155
|
+
list(options?: SessionScope): Promise<Session[]>;
|
|
156
|
+
search(text: string, options?: SessionScope & SearchOptions): Promise<Message[]>;
|
|
157
|
+
};
|
|
158
|
+
//# sourceMappingURL=session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../src/session/session.ts"],"names":[],"mappings":"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"}
|
package/src/jobs/check.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import type { Job } from '../mod.js'
|
|
2
2
|
import { longestMs, type Deadline } from '../runtime/deadline.js'
|
|
3
|
-
import { callEffects, type
|
|
3
|
+
import { callEffects, type Call } from '../utils/call-effects.js'
|
|
4
4
|
import { dirname } from '../vendor.js'
|
|
5
5
|
import { listed, messageOf } from '../utils/text.js'
|
|
6
|
-
import {
|
|
6
|
+
import { engineOf } from '../runtime/engine.js'
|
|
7
|
+
import { afterCall, targetWords, withinDeadline } from './context.js'
|
|
7
8
|
import type { Workspace } from './permissions/find-project-scope.js'
|
|
8
9
|
import { matchTarget, targetOf, type Target } from './permissions/match-target.js'
|
|
9
10
|
|
|
@@ -27,7 +28,9 @@ export function check<State extends object = Record<never, never>>(options: { re
|
|
|
27
28
|
if (triggered === undefined) return []
|
|
28
29
|
try {
|
|
29
30
|
const { command, folder } = triggered
|
|
30
|
-
const
|
|
31
|
+
const workTree = await workspace.scope?.workTreeOf(folder)
|
|
32
|
+
const { claude } = engineOf(job.mod)
|
|
33
|
+
const { exitCode, stdout, stderr } = await withinDeadline(job.mod, deadline, command.join(' '), () => claude.process.run(command, { ...(workTree === undefined ? {} : { cwd: workTree }), timeoutMs }))
|
|
31
34
|
return exitCode === 0 ? [] : [`${command.join(' ')} exited with ${exitCode}:\n${`${stdout}${stderr}`.trim()}`]
|
|
32
35
|
} catch (error) {
|
|
33
36
|
return [`The ${named} failed: ${messageOf(error)}`]
|
|
@@ -39,7 +42,7 @@ export function check<State extends object = Record<never, never>>(options: { re
|
|
|
39
42
|
}
|
|
40
43
|
}
|
|
41
44
|
|
|
42
|
-
async function triggeredRun(after: readonly Target[], run: readonly string[], use:
|
|
45
|
+
async function triggeredRun(after: readonly Target[], run: readonly string[], use: Call, workspace: Workspace): Promise<{ command: string[]; folder: string } | undefined> {
|
|
43
46
|
const effects = callEffects(use, workspace)
|
|
44
47
|
const paths = new Set<string>()
|
|
45
48
|
let commandFolder: string | undefined
|
package/src/jobs/context.ts
CHANGED
|
@@ -1,48 +1,42 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type { JobContext, Mod } from '../mod.js'
|
|
3
|
-
import type { Claude } from '../runtime/claude.js'
|
|
1
|
+
import type { JobContext } from '../mod.js'
|
|
4
2
|
import { beforeDeadline, type Deadline } from '../runtime/deadline.js'
|
|
5
|
-
import {
|
|
3
|
+
import { engineOf } from '../runtime/engine.js'
|
|
6
4
|
import { toolInputOf } from '../runtime/tool-calls.js'
|
|
7
5
|
import { listed } from '../utils/text.js'
|
|
8
|
-
import type {
|
|
6
|
+
import type { Call } from '../utils/call-effects.js'
|
|
9
7
|
import { findProjectScope, type Workspace } from './permissions/find-project-scope.js'
|
|
10
8
|
import { targetOf, type Target } from './permissions/match-target.js'
|
|
11
9
|
import type { FileSystem } from '../utils/paths.js'
|
|
12
10
|
|
|
13
11
|
type Session = Omit<Workspace, 'projectRoot' | 'cwd'>
|
|
14
12
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
export function workspaceReader({ mod: { claude } }: JobContext): () => Promise<Workspace> {
|
|
13
|
+
export function workspaceReader({ mod }: JobContext): () => Promise<Workspace> {
|
|
14
|
+
const { claude } = engineOf(mod)
|
|
18
15
|
let session: Promise<Session> | undefined
|
|
19
16
|
return async () => {
|
|
20
|
-
session ??= readSession(
|
|
17
|
+
session ??= readSession()
|
|
21
18
|
const [{ home, scope, fs }, projectRoot, cwd] = await Promise.all([session, claude.session.root(), claude.session.cwd()])
|
|
22
19
|
return { projectRoot, cwd, home, fs, scope }
|
|
23
20
|
}
|
|
24
|
-
}
|
|
25
21
|
|
|
26
|
-
async function readSession(
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
22
|
+
async function readSession(): Promise<Session> {
|
|
23
|
+
const fs: FileSystem = {
|
|
24
|
+
read: (path) => claude.fs.read(path),
|
|
25
|
+
stat: (path) => claude.fs.stat(path, { resolve: true }),
|
|
26
|
+
exists: (path) => claude.fs.exists(path),
|
|
27
|
+
}
|
|
28
|
+
const home = await claude.env.home()
|
|
29
|
+
if (home === undefined) throw new Error('HOME is not set, so ~ in a path has no meaning. Start Claude Code with HOME set.')
|
|
30
|
+
return { home, fs, scope: await findProjectScope(claude.plugin.root, home, fs) }
|
|
31
31
|
}
|
|
32
|
-
const home = await claude.env.home()
|
|
33
|
-
if (home === undefined) throw new Error('HOME is not set, so ~ in a path has no meaning. Start Claude Code with HOME set.')
|
|
34
|
-
return { home, fs, scope: await findProjectScope(claude.plugin.root, home, fs) }
|
|
35
32
|
}
|
|
36
33
|
|
|
37
|
-
export function afterCall<State extends object>(
|
|
38
|
-
job
|
|
39
|
-
contextAfter: (call: ToolCall, workspace: Workspace) => Promise<readonly string[]>,
|
|
40
|
-
failed: (error: unknown) => readonly string[],
|
|
41
|
-
): void {
|
|
34
|
+
export function afterCall<State extends object>(job: JobContext<State>, contextAfter: (call: Call, workspace: Workspace) => Promise<readonly string[]>, failed: (error: unknown) => readonly string[]): void {
|
|
35
|
+
const { router, toolCalls } = engineOf(job.mod)
|
|
42
36
|
const readWorkspace = workspaceReader(job)
|
|
43
|
-
|
|
44
|
-
const before = Promise.all([
|
|
45
|
-
await
|
|
37
|
+
router.add('tool.call', async (e, next) => {
|
|
38
|
+
const before = Promise.all([toolCalls.agentOf(e.tool_use_id).then((agent): Call => ({ tool: e.tool, input: toolInputOf(e), ...agent })), readWorkspace()])
|
|
39
|
+
await Promise.allSettled([before])
|
|
46
40
|
const result = await next(e)
|
|
47
41
|
if (result.deny !== undefined || result.isError === true) return result
|
|
48
42
|
const added = await before.then(([use, workspace]) => contextAfter(use, workspace)).catch(failed)
|
|
@@ -50,64 +44,12 @@ export function afterCall<State extends object>(
|
|
|
50
44
|
})
|
|
51
45
|
}
|
|
52
46
|
|
|
53
|
-
async function
|
|
54
|
-
return {
|
|
47
|
+
export async function inFolder(call: Call, folder: string, workspace: Workspace): Promise<Call & { readonly folder: string }> {
|
|
48
|
+
return { ...call, folder: (await workspace.scope?.workTreeOf('path' in call ? call.path : folder)) ?? folder }
|
|
55
49
|
}
|
|
56
50
|
|
|
57
|
-
export function
|
|
58
|
-
return
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
export function modWithin<State extends object>({ mod }: JobContext<State>, deadline: Deadline, workTree: () => Promise<string | undefined> = async () => undefined): Mod<State> {
|
|
62
|
-
const { claude } = mod
|
|
63
|
-
const within = <Value>(call: string, task: Promise<Value>) => beforeDeadline(claude, deadline, call, task)
|
|
64
|
-
const folderOf = async (cwd: string | undefined) => {
|
|
65
|
-
const folder = cwd ?? (await workTree())
|
|
66
|
-
return folder === undefined ? {} : { cwd: folder }
|
|
67
|
-
}
|
|
68
|
-
const overrides: Pick<Mod<State>, 'process' | 'fs' | 'http' | 'dependencies'> = {
|
|
69
|
-
process: {
|
|
70
|
-
async run(argv, init) {
|
|
71
|
-
const folder = await folderOf(init?.cwd)
|
|
72
|
-
const timeoutMs = Math.min(init?.timeoutMs ?? deadline.ms, deadline.longestMs ?? deadline.ms)
|
|
73
|
-
return beforeDeadline(claude, { ...deadline, ms: timeoutMs }, 'mod.process.run', mod.process.run(argv, { ...init, ...folder, timeoutMs }))
|
|
74
|
-
},
|
|
75
|
-
spawn: (argv, init) => spawnWithin(claude, deadline, folderOf(init?.cwd).then((folder) => mod.process.spawn(argv, { ...init, ...folder }))),
|
|
76
|
-
},
|
|
77
|
-
fs: {
|
|
78
|
-
read: (path) => within('mod.fs.read', mod.fs.read(path)),
|
|
79
|
-
write: (path, text) => within('mod.fs.write', mod.fs.write(path, text)),
|
|
80
|
-
list: (path) => within('mod.fs.list', mod.fs.list(path)),
|
|
81
|
-
exists: (path) => within('mod.fs.exists', mod.fs.exists(path)),
|
|
82
|
-
stat: (path, options) => within('mod.fs.stat', mod.fs.stat(path, options)),
|
|
83
|
-
find: (glob) => within('mod.fs.find', mod.fs.find(glob)),
|
|
84
|
-
},
|
|
85
|
-
http: { fetch: (url, init) => within('mod.http.fetch', mod.http.fetch(url, init)) },
|
|
86
|
-
dependencies: dependencyCalls(claude, within),
|
|
87
|
-
}
|
|
88
|
-
return Object.assign(Object.create(mod) as Mod<State>, overrides)
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
function spawnWithin(claude: Claude, deadline: Deadline, started: Promise<Stream>): Stream {
|
|
92
|
-
async function* pieces(): AsyncGenerator<ProcessSpawnChunk, ProcessSpawnResult> {
|
|
93
|
-
const stream: AsyncIterator<ProcessSpawnChunk, ProcessSpawnResult> = await started
|
|
94
|
-
let finish: () => void = () => undefined
|
|
95
|
-
const running = beforeDeadline(claude, deadline, 'mod.process.spawn', new Promise<void>((resolve) => (finish = resolve)))
|
|
96
|
-
const passed = running.then(() => new Promise<never>(() => undefined))
|
|
97
|
-
try {
|
|
98
|
-
for (;;) {
|
|
99
|
-
const piece = await Promise.race([stream.next(), passed])
|
|
100
|
-
if (piece.done === true) return piece.value
|
|
101
|
-
yield piece.value
|
|
102
|
-
}
|
|
103
|
-
} finally {
|
|
104
|
-
finish()
|
|
105
|
-
void stream.return?.()
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
const result = started.then((stream) => stream.result)
|
|
109
|
-
result.catch(() => undefined)
|
|
110
|
-
return Object.assign(pieces(), { result })
|
|
51
|
+
export function withinDeadline<Value>(mod: object, deadline: Deadline, subject: string, run: () => Value | Promise<Value>): Promise<Value> {
|
|
52
|
+
return beforeDeadline(engineOf(mod).claude, deadline, subject, Promise.resolve().then(run))
|
|
111
53
|
}
|
|
112
54
|
|
|
113
55
|
export function targetWords(target: Target): string {
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
import { strictness } from '../../runtime/hooks.js'
|
|
2
2
|
import { messageOf } from '../../utils/text.js'
|
|
3
|
-
import { callBaseOf, callEffects, type CallEffects, type
|
|
3
|
+
import { callBaseOf, callEffects, type CallEffects, type Call } from '../../utils/call-effects.js'
|
|
4
4
|
import type { Workspace } from './find-project-scope.js'
|
|
5
5
|
import { folderInScope, matchTarget, targetOf, type MatchedCall, type Target, type TargetCalls, type TargetKey, type TargetOf } from './match-target.js'
|
|
6
6
|
import { resolve } from '../../vendor.js'
|
|
7
|
+
import { inFolder } from '../context.js'
|
|
7
8
|
|
|
8
9
|
export type Rule<Mod> = {
|
|
9
10
|
[Key in TargetKey]: TargetOf<Key> & {
|
|
10
|
-
when?: (call: TargetCalls[Key], mod: Mod) => boolean | Promise<boolean>
|
|
11
|
+
when?: (call: TargetCalls[Key] & { readonly folder: string }, mod: Mod) => boolean | Promise<boolean>
|
|
11
12
|
reason?: string
|
|
12
13
|
}
|
|
13
14
|
}[TargetKey]
|
|
14
|
-
type WhenOf<Mod> = { when?(call:
|
|
15
|
+
type WhenOf<Mod> = { when?(call: Call & { readonly folder: string }, mod: Mod): boolean | Promise<boolean> }
|
|
15
16
|
export type PermissionRules<Mod> = { deny?: Rule<Mod>[]; ask?: Rule<Mod>[] }
|
|
16
17
|
export type Decision = 'allow' | 'ask' | 'deny'
|
|
17
18
|
export type Verdict = { decision: Decision; reason?: string }
|
|
@@ -22,12 +23,12 @@ export function stricterVerdict<Result extends Verdict>(first: Result, second: R
|
|
|
22
23
|
return strictness.indexOf(second.decision) > strictness.indexOf(first.decision) ? second : first
|
|
23
24
|
}
|
|
24
25
|
|
|
25
|
-
export async function decidePermission<Mod>(rules: PermissionRules<Mod>, use:
|
|
26
|
+
export async function decidePermission<Mod>(rules: PermissionRules<Mod>, use: Call, workspace: Workspace, mod: Mod, within: (run: () => boolean | Promise<boolean>) => Promise<boolean>): Promise<Verdict | undefined> {
|
|
26
27
|
try {
|
|
27
28
|
const effects = callEffects(use, workspace)
|
|
28
29
|
for (const decision of ['deny', 'ask'] as const) {
|
|
29
30
|
for (const rule of rules[decision] ?? []) {
|
|
30
|
-
const outcome = await ruleOutcome(rule, use, effects, workspace,
|
|
31
|
+
const outcome = await ruleOutcome(rule, use, effects, workspace, mod, within)
|
|
31
32
|
if (outcome === undefined) continue
|
|
32
33
|
const reason = [rule.reason, outcome.failure === undefined ? undefined : `Its when check failed: ${outcome.failure}`].filter((part) => part !== undefined).join(' ')
|
|
33
34
|
return reason === '' ? { decision } : { decision, reason }
|
|
@@ -39,7 +40,7 @@ export async function decidePermission<Mod>(rules: PermissionRules<Mod>, use: To
|
|
|
39
40
|
}
|
|
40
41
|
}
|
|
41
42
|
|
|
42
|
-
async function ruleOutcome<Mod>(rule: Rule<Mod>, use:
|
|
43
|
+
async function ruleOutcome<Mod>(rule: Rule<Mod>, use: Call, effects: CallEffects, workspace: Workspace, mod: Mod, within: (run: () => boolean | Promise<boolean>) => Promise<boolean>): Promise<{ failure: string | undefined } | undefined> {
|
|
43
44
|
const matched = await matchTarget(rule, use, effects, workspace)
|
|
44
45
|
const calls = matched.length > 0 ? matched : await unparsedMatches(rule, use, effects, workspace)
|
|
45
46
|
if (calls.length === 0) return undefined
|
|
@@ -48,7 +49,8 @@ async function ruleOutcome<Mod>(rule: Rule<Mod>, use: ToolCall, effects: CallEff
|
|
|
48
49
|
for (const { call, access, folder } of calls) {
|
|
49
50
|
const fullCall = access?.contents === undefined ? call : { ...call, ...(await access.contents()) }
|
|
50
51
|
try {
|
|
51
|
-
|
|
52
|
+
const placed = await inFolder(fullCall, folder, workspace)
|
|
53
|
+
if (await within(() => when(placed, mod))) return { failure: undefined }
|
|
52
54
|
} catch (error) {
|
|
53
55
|
return { failure: messageOf(error) }
|
|
54
56
|
}
|
|
@@ -56,7 +58,7 @@ async function ruleOutcome<Mod>(rule: Rule<Mod>, use: ToolCall, effects: CallEff
|
|
|
56
58
|
return undefined
|
|
57
59
|
}
|
|
58
60
|
|
|
59
|
-
async function unparsedMatches(target: Target, use:
|
|
61
|
+
async function unparsedMatches(target: Target, use: Call, effects: CallEffects, workspace: Workspace): Promise<MatchedCall[]> {
|
|
60
62
|
const shell = effects.shell
|
|
61
63
|
if (shell === undefined || shell.isFullyParsed) return []
|
|
62
64
|
const { key, patterns } = targetOf(target)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { ifMissing, type FileSystem } from '../../utils/paths.js'
|
|
2
2
|
import { basename, dirname, resolve } from '../../vendor.js'
|
|
3
3
|
|
|
4
4
|
export type ProjectScope = { workTreeOf: (path: string) => Promise<string | undefined> }
|
|
@@ -33,19 +33,13 @@ export async function findProjectScope(pluginRoot: string, home: string, fs: Fil
|
|
|
33
33
|
|
|
34
34
|
async function readRepository(workTree: string, fs: FileSystem): Promise<string | undefined> {
|
|
35
35
|
const gitPath = resolve(workTree, '.git')
|
|
36
|
-
const git = await fs.stat(gitPath).catch((
|
|
36
|
+
const git = await fs.stat(gitPath).catch(ifMissing(undefined))
|
|
37
37
|
if (git === undefined) return undefined
|
|
38
38
|
if (git.kind === 'dir') return git.realPath ?? gitPath
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
() => linkedDirectory,
|
|
46
|
-
)
|
|
47
|
-
return (await fs.stat(commonDirectory)).realPath ?? commonDirectory
|
|
48
|
-
} catch {
|
|
49
|
-
return workTree
|
|
50
|
-
}
|
|
39
|
+
const gitDirectory = /^gitdir:\s*(.+)$/m.exec(await fs.read(gitPath))?.[1]?.trim()
|
|
40
|
+
if (gitDirectory === undefined) return workTree
|
|
41
|
+
const linkedDirectory = resolve(workTree, gitDirectory)
|
|
42
|
+
const commonDirectory = await fs.read(resolve(linkedDirectory, 'commondir')).then((text) => resolve(linkedDirectory, text.trim()), ifMissing(linkedDirectory))
|
|
43
|
+
const common = await fs.stat(commonDirectory).catch(ifMissing(undefined))
|
|
44
|
+
return common === undefined ? workTree : (common.realPath ?? commonDirectory)
|
|
51
45
|
}
|