@cmodjs/core 1.0.0 → 1.5.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 +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 +130 -59
- 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 +158 -25
- 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 +136 -56
- package/src/runtime/metadata.ts +5 -4
- package/src/runtime/sessions.ts +316 -111
- package/src/runtime/toaster.ts +183 -45
- 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/runtime/toaster.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toaster.d.ts","sourceRoot":"","sources":["../src/runtime/toaster.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,aAAa,EAAS,MAAM,aAAa,CAAA;AACpF,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"toaster.d.ts","sourceRoot":"","sources":["../src/runtime/toaster.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,aAAa,EAAS,MAAM,aAAa,CAAA;AACpF,OAAO,KAAK,EAAE,KAAK,EAAE,OAAO,EAAgB,SAAS,EAAE,MAAM,WAAW,CAAA;AAIxE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAEzC,MAAM,MAAM,UAAU,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;AAE9G,MAAM,MAAM,OAAO,GAAG;IAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,OAAO,CAAA;CAAE,CAAA;AAEhK,MAAM,MAAM,OAAO,GAAG;IACpB,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAA;IACrB,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACjC,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAA;IAC/B,QAAQ,CAAC,KAAK,EAAE,SAAS,UAAU,EAAE,CAAA;IACrC,IAAI,CAAC,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,aAAa,CAAC,aAAa,CAAC,EAAE,MAAM,EAAE,MAAM,GAAG,aAAa,CAAA;CACnH,CAAA;AAuCD,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,MAAM,GAAG,SAAS,GAAG,OAAO,CA6PtG"}
|
package/runtime/toaster.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
import { Box, Button, drawWith, Text } from '../ui/elements.js';
|
|
2
|
-
import { coreVersion } from '../records.js';
|
|
1
|
+
import { Box, Button, drawWith, Link, Text } from '../ui/elements.js';
|
|
2
|
+
import { coreVersion, isObject } from '../records.js';
|
|
3
3
|
import { firstLine, messageOf } from '../utils/text.js';
|
|
4
|
+
const githubRepository = /^https:\/\/github\.com\/([^/]+\/[^/#?]+?)(?:\.git)?(?:\/issues)?\/?$/;
|
|
5
|
+
const linkLimit = 2048;
|
|
6
|
+
const hiddenKey = 'cmod:hidden-failures';
|
|
4
7
|
const defaultDuration = 4000;
|
|
5
8
|
const visibleToasts = 3;
|
|
6
9
|
const spinner = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
|
|
@@ -12,15 +15,24 @@ const icons = {
|
|
|
12
15
|
warning: { glyph: '⚠', color: 'warning' },
|
|
13
16
|
error: { glyph: '✗', color: 'error' },
|
|
14
17
|
};
|
|
15
|
-
export function createToaster(claude, name) {
|
|
18
|
+
export function createToaster(claude, name, version) {
|
|
16
19
|
const entries = new Map();
|
|
20
|
+
const hidden = new Map();
|
|
21
|
+
void claude.store.get(hiddenKey).then((saved) => {
|
|
22
|
+
if (typeof saved !== 'object' || saved === null)
|
|
23
|
+
return;
|
|
24
|
+
for (const [id, hides] of Object.entries(saved))
|
|
25
|
+
if (typeof hides === 'string' && !hidden.has(id))
|
|
26
|
+
hidden.set(id, hides);
|
|
27
|
+
}, (error) => claude.ui.log(`${name}: could not read the failures you hid: ${messageOf(error)}`, { to: 'debug' }));
|
|
17
28
|
let lastId = 0;
|
|
18
29
|
let frame = 0;
|
|
19
30
|
let spinning;
|
|
20
31
|
let isHeld = false;
|
|
21
32
|
let showsAll = false;
|
|
33
|
+
let bandId;
|
|
22
34
|
const changed = () => {
|
|
23
|
-
const isLoading = [...entries.values()].some((entry) => entry.type === 'loading');
|
|
35
|
+
const isLoading = [...entries.values()].some((entry) => entry.type === 'loading' || entry.trying !== undefined);
|
|
24
36
|
if (isLoading && spinning === undefined) {
|
|
25
37
|
spinning = claude.clock.every(spinnerMs, () => {
|
|
26
38
|
frame += 1;
|
|
@@ -60,18 +72,32 @@ export function createToaster(claude, name) {
|
|
|
60
72
|
}
|
|
61
73
|
changed();
|
|
62
74
|
};
|
|
63
|
-
const
|
|
75
|
+
const put = (type, message, options, actions, hides) => {
|
|
64
76
|
const id = options.id ?? (lastId += 1);
|
|
65
77
|
const previous = entries.get(id);
|
|
78
|
+
if (previous?.trying !== undefined && type === 'loading') {
|
|
79
|
+
previous.trying = options.description ?? message;
|
|
80
|
+
changed();
|
|
81
|
+
return id;
|
|
82
|
+
}
|
|
66
83
|
if (previous !== undefined)
|
|
67
84
|
disarm(previous);
|
|
68
|
-
const
|
|
85
|
+
const reporting = hides !== undefined && previous?.hides === hides ? previous.reporting : undefined;
|
|
86
|
+
const entry = { id, type, message, options, actions, ...(hides === undefined ? {} : { hides }), isOpen: previous?.isOpen ?? false, reporting, timer: undefined };
|
|
69
87
|
if (type === 'error' && previous?.message !== message)
|
|
70
88
|
claude.ui.log(`${name}: ${message}${typeof options.description === 'string' ? `: ${options.description}` : ''}`, { to: 'debug' });
|
|
71
89
|
entries.set(id, entry);
|
|
72
90
|
changed();
|
|
73
91
|
return id;
|
|
74
92
|
};
|
|
93
|
+
const show = (type) => (message, options = {}) => put(type, message, options, options.action === undefined ? [] : [options.action]);
|
|
94
|
+
const hide = (entry) => {
|
|
95
|
+
dismiss(entry.id);
|
|
96
|
+
if (entry.hides === undefined)
|
|
97
|
+
return;
|
|
98
|
+
hidden.set(String(entry.id), entry.hides);
|
|
99
|
+
void claude.store.set(hiddenKey, Object.fromEntries(hidden)).catch((error) => claude.ui.log(`${name}: could not remember the failure you hid: ${messageOf(error)}`, { to: 'debug' }));
|
|
100
|
+
};
|
|
75
101
|
const toast = Object.assign(show('default'), {
|
|
76
102
|
success: show('success'),
|
|
77
103
|
info: show('info'),
|
|
@@ -101,37 +127,122 @@ export function createToaster(claude, name) {
|
|
|
101
127
|
};
|
|
102
128
|
const press = (entry, run) => () => void Promise.resolve()
|
|
103
129
|
.then(run)
|
|
104
|
-
.catch((error) =>
|
|
130
|
+
.catch((error) => fail({ id: `press:${entry.id}`, message: `${entry.message}: the press failed`, error }));
|
|
131
|
+
const fail = ({ id, message, error, description = error === undefined ? undefined : describe(error), retry }) => {
|
|
132
|
+
const hides = `${version() ?? ''}\n${message}\n${error === undefined ? '' : describe(error)}`;
|
|
133
|
+
if (hidden.get(id) === hides)
|
|
134
|
+
return id;
|
|
135
|
+
hidden.delete(id);
|
|
136
|
+
const stack = error instanceof Error && error.stack !== undefined ? `\n\n${error.stack}` : '';
|
|
137
|
+
const details = async () => {
|
|
138
|
+
const modVersion = await claude.fs
|
|
139
|
+
.read(`${claude.plugin.root}/.claude-plugin/plugin.json`)
|
|
140
|
+
.then((text) => String(JSON.parse(text).version))
|
|
141
|
+
.catch((failure) => `unknown (${messageOf(failure)})`);
|
|
142
|
+
return `${name} ${modVersion}, @cmodjs/core ${coreVersion}\n${message}${description === undefined ? '' : `\n${description}`}${stack}`;
|
|
143
|
+
};
|
|
144
|
+
const startReporting = async () => {
|
|
145
|
+
const shown = entries.get(id);
|
|
146
|
+
if (shown === undefined)
|
|
147
|
+
return;
|
|
148
|
+
shown.reporting = { contact: await contactOf(claude), details: await details() };
|
|
149
|
+
disarm(shown);
|
|
150
|
+
changed();
|
|
151
|
+
if (bandId === undefined)
|
|
152
|
+
return;
|
|
153
|
+
const focused = await claude.ui.focus({ requestId: bandId, key: `toast:${id}:ask-claude` });
|
|
154
|
+
if ('deny' in focused)
|
|
155
|
+
claude.ui.log(`${name}: the Report choices did not take the keys: ${String(focused.deny)}`, { to: 'debug' });
|
|
156
|
+
};
|
|
157
|
+
const tryAgain = async () => {
|
|
158
|
+
const shown = entries.get(id);
|
|
159
|
+
if (shown === undefined || retry === undefined || shown.trying !== undefined)
|
|
160
|
+
return;
|
|
161
|
+
shown.trying = 'Starting';
|
|
162
|
+
changed();
|
|
163
|
+
try {
|
|
164
|
+
await retry();
|
|
165
|
+
}
|
|
166
|
+
finally {
|
|
167
|
+
if (entries.get(id) === shown) {
|
|
168
|
+
shown.trying = undefined;
|
|
169
|
+
changed();
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
const actions = [...(retry === undefined ? [] : [{ label: 'Retry', onClick: tryAgain }]), { label: 'Report', onClick: startReporting }];
|
|
174
|
+
return put('error', message, { id, ...(description === undefined ? {} : { description }), duration: Infinity }, actions, hides);
|
|
175
|
+
};
|
|
105
176
|
const toggle = (entry) => () => {
|
|
106
177
|
entry.isOpen = !entry.isOpen;
|
|
107
178
|
disarm(entry);
|
|
108
179
|
changed();
|
|
109
180
|
};
|
|
110
181
|
const row = (entry) => {
|
|
111
|
-
const { description
|
|
182
|
+
const { description } = entry.options;
|
|
112
183
|
const isText = typeof description === 'string';
|
|
113
|
-
const icon = entry.type === 'loading' ? { glyph: spinner[frame % spinner.length], color: 'claude' } : icons[entry.type];
|
|
184
|
+
const icon = entry.type === 'loading' || entry.trying !== undefined ? { glyph: spinner[frame % spinner.length], color: 'claude' } : icons[entry.type];
|
|
114
185
|
const message = isText ? Button({ plain: true, key: `toast:${entry.id}:open`, label: entry.message, onPress: toggle(entry) }) : Text({ children: entry.message });
|
|
115
186
|
const details = !isText ? description : Text({ dimColor: true, wrap: entry.isOpen ? 'wrap' : 'truncate-end', children: entry.isOpen ? description : firstLine(description) });
|
|
116
187
|
const fixed = (child) => Box({ flexShrink: 0, children: child });
|
|
188
|
+
const close = Button({ plain: true, dimColor: true, key: `toast:${entry.id}:close`, label: entry.hides === undefined ? '✕' : 'Hide', onPress: () => hide(entry) });
|
|
189
|
+
const actions = entry.actions.map((action, index) => Button({ plain: true, key: `toast:${entry.id}:${index === 0 ? 'action' : `action-${index}`}`, label: action.label, onPress: press(entry, action.onClick) }));
|
|
190
|
+
const buttons = Box({ gap: 2, flexWrap: 'wrap', children: [...actions, close] });
|
|
191
|
+
const trying = entry.trying === undefined ? undefined : Box({ gap: 1, children: [Text({ dimColor: true, children: 'Trying again:' }), typeof entry.trying === 'string' ? Text({ dimColor: true, wrap: 'truncate-end', children: entry.trying }) : entry.trying] });
|
|
192
|
+
const text = details === undefined ? [message] : [message, trying ?? details];
|
|
193
|
+
const under = trying !== undefined && details === undefined ? [trying] : entry.reporting === undefined ? [buttons] : reportChoices(entry, entry.reporting);
|
|
117
194
|
return Box({
|
|
118
195
|
gap: 2,
|
|
119
196
|
children: [
|
|
120
197
|
fixed(Text({ ...(icon.color === undefined ? {} : { color: icon.color }), children: icon.glyph })),
|
|
121
198
|
fixed(Text({ dimColor: true, children: name })),
|
|
122
|
-
Box({ flexDirection: 'column', flexGrow: 1, flexShrink: 1, children:
|
|
123
|
-
...(
|
|
124
|
-
fixed(Button({ plain: true, dimColor: true, key: `toast:${entry.id}:close`, label: '✕', onPress: () => dismiss(entry.id) })),
|
|
199
|
+
Box({ flexDirection: 'column', flexGrow: 1, flexShrink: 1, children: entry.hides === undefined ? text : [...text, ...under] }),
|
|
200
|
+
...(entry.hides === undefined ? [...actions.map(fixed), fixed(close)] : []),
|
|
125
201
|
],
|
|
126
202
|
});
|
|
127
203
|
};
|
|
204
|
+
const reportChoices = (entry, { contact, details, status }) => {
|
|
205
|
+
const say = (said) => {
|
|
206
|
+
entry.reporting = { contact, details, status: said };
|
|
207
|
+
changed();
|
|
208
|
+
};
|
|
209
|
+
const back = () => {
|
|
210
|
+
entry.reporting = undefined;
|
|
211
|
+
changed();
|
|
212
|
+
};
|
|
213
|
+
const askClaude = async () => {
|
|
214
|
+
await claude.prompt.submit({ text: reportPrompt(name, contact, details), asUser: true });
|
|
215
|
+
back();
|
|
216
|
+
};
|
|
217
|
+
const copyError = async () => {
|
|
218
|
+
const copied = await claude.ui.copy({ text: details });
|
|
219
|
+
say(copied.isCopied ? 'Copied the error.' : `Could not copy it: ${copied.reason}`);
|
|
220
|
+
};
|
|
221
|
+
const report = contact === undefined ? [] : [Link({ href: reportLink(contact, name, entry.message, details), label: contact.kind === 'github' ? 'Report it on GitHub (opens your browser)' : 'Email the author (opens your mail app)' })];
|
|
222
|
+
return [
|
|
223
|
+
Text({ dimColor: true, children: 'Claude writes up the problem and files it with your tools. You approve each step before anything is posted.' }),
|
|
224
|
+
Box({
|
|
225
|
+
gap: 2,
|
|
226
|
+
flexWrap: 'wrap',
|
|
227
|
+
children: [
|
|
228
|
+
Button({ plain: true, key: `toast:${entry.id}:ask-claude`, label: 'Ask Claude to report it', onPress: press(entry, askClaude) }),
|
|
229
|
+
...report,
|
|
230
|
+
Button({ plain: true, key: `toast:${entry.id}:copy`, label: 'Copy the error', onPress: press(entry, copyError) }),
|
|
231
|
+
Button({ plain: true, dimColor: true, key: `toast:${entry.id}:back`, label: 'Back', onPress: back }),
|
|
232
|
+
],
|
|
233
|
+
}),
|
|
234
|
+
...(status === undefined ? [] : [Text({ dimColor: true, children: status })]),
|
|
235
|
+
];
|
|
236
|
+
};
|
|
128
237
|
return {
|
|
129
238
|
toast,
|
|
130
239
|
copy,
|
|
240
|
+
fail,
|
|
131
241
|
get shown() {
|
|
132
242
|
return [...entries.values()].map(({ type, message, options }) => ({ type, message, ...(typeof options.description === 'string' ? { description: options.description } : {}) }));
|
|
133
243
|
},
|
|
134
|
-
draw(drawn, table, band) {
|
|
244
|
+
draw(drawn, table, band, drawnIn) {
|
|
245
|
+
bandId = drawnIn;
|
|
135
246
|
isHeld = band.hasSurvey === true;
|
|
136
247
|
if (isHeld || entries.size === 0)
|
|
137
248
|
return drawn;
|
|
@@ -153,18 +264,6 @@ export function createToaster(claude, name) {
|
|
|
153
264
|
},
|
|
154
265
|
};
|
|
155
266
|
}
|
|
156
|
-
export function showFailure({ name, ui, claude }, { id, message, error, description = describe(error) }) {
|
|
157
|
-
const stack = error instanceof Error && error.stack !== undefined ? `\n\n${error.stack}` : '';
|
|
158
|
-
const show = (label) => ui.toast.error(message, { id, description, duration: Infinity, action: { label, onClick: copy } });
|
|
159
|
-
const copy = async () => {
|
|
160
|
-
const modVersion = await claude.fs
|
|
161
|
-
.read(`${claude.plugin.root}/.claude-plugin/plugin.json`)
|
|
162
|
-
.then((text) => String(JSON.parse(text).version))
|
|
163
|
-
.catch((failure) => `unknown (${messageOf(failure)})`);
|
|
164
|
-
return ui.copy(`${name} ${modVersion}, @cmodjs/core ${coreVersion}\n${message}\n${description}${stack}`).then(() => show('Copied'), (failure) => show(`Copy failed: ${messageOf(failure)}`));
|
|
165
|
-
};
|
|
166
|
-
return show('Copy');
|
|
167
|
-
}
|
|
168
267
|
function describe(error) {
|
|
169
268
|
const messages = [];
|
|
170
269
|
for (let cause = error; cause !== undefined; cause = cause instanceof Error ? cause.cause : undefined) {
|
|
@@ -174,3 +273,37 @@ function describe(error) {
|
|
|
174
273
|
}
|
|
175
274
|
return messages.join('\n');
|
|
176
275
|
}
|
|
276
|
+
async function contactOf(claude) {
|
|
277
|
+
const manifest = await claude.fs
|
|
278
|
+
.read(`${claude.plugin.root}/.claude-plugin/plugin.json`)
|
|
279
|
+
.then((text) => JSON.parse(text))
|
|
280
|
+
.catch((error) => {
|
|
281
|
+
claude.ui.log(`${claude.plugin.name}: could not read whom to report to: ${messageOf(error)}`, { to: 'debug' });
|
|
282
|
+
return {};
|
|
283
|
+
});
|
|
284
|
+
const repositoryUrl = isObject(manifest['repository']) ? manifest['repository']['url'] : manifest['repository'];
|
|
285
|
+
const repository = [manifest['supportUrl'], repositoryUrl].map((url) => (typeof url === 'string' ? githubRepository.exec(url)?.[1] : undefined)).find((found) => found !== undefined);
|
|
286
|
+
if (repository !== undefined)
|
|
287
|
+
return { kind: 'github', repository };
|
|
288
|
+
const author = manifest['author'];
|
|
289
|
+
const address = isObject(author) ? author['email'] : undefined;
|
|
290
|
+
return typeof address === 'string' && address !== '' ? { kind: 'email', address } : undefined;
|
|
291
|
+
}
|
|
292
|
+
function reportLink(contact, name, message, details) {
|
|
293
|
+
const title = `${name}: ${message}`.slice(0, 120);
|
|
294
|
+
const linkOf = (body) => contact.kind === 'github'
|
|
295
|
+
? `https://github.com/${contact.repository}/issues/new?title=${encodeURIComponent(title)}&body=${encodeURIComponent(body)}`
|
|
296
|
+
: `mailto:${contact.address}?subject=${encodeURIComponent(title)}&body=${encodeURIComponent(body)}`;
|
|
297
|
+
let body = details;
|
|
298
|
+
while (linkOf(body).length > linkLimit && body.length > 0)
|
|
299
|
+
body = `${body.slice(0, Math.floor(body.length * 0.8))}…`;
|
|
300
|
+
return linkOf(body);
|
|
301
|
+
}
|
|
302
|
+
function reportPrompt(name, contact, details) {
|
|
303
|
+
const where = contact === undefined
|
|
304
|
+
? `${name} names no place to report it, so find its author from its plugin.json or its marketplace.`
|
|
305
|
+
: contact.kind === 'github'
|
|
306
|
+
? `Report it as an issue on https://github.com/${contact.repository}.`
|
|
307
|
+
: `Email it to ${contact.address}.`;
|
|
308
|
+
return `The ${name} mod failed. Report it to its author. ${where} First check whether it is reported already, and add to that report instead of filing a new one. Show me the report before you post it.\n\n${details}`;
|
|
309
|
+
}
|
package/runtime/ui.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../src/runtime/ui.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAc,GAAG,EAAc,MAAM,WAAW,CAAA;AAM5D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAgFpD,MAAM,MAAM,SAAS,CAAC,KAAK,SAAS,MAAM,IAAI;IAC5C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAA;IAC3C,QAAQ,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;IAC5C,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,CAAC,KAAK,CAAC,CAAA;CAC/B,CAAA;AAED,MAAM,MAAM,MAAM,CAAC,KAAK,SAAS,MAAM,IAAI;IACzC,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,EAAE,QAAQ,CAAC,CAAA;IAC7C,OAAO,IAAI,IAAI,CAAA;IACf,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CAC9B,CAAA;AAED,wBAAgB,QAAQ,CAAC,KAAK,SAAS,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,EAAE,SAAS,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,
|
|
1
|
+
{"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../src/runtime/ui.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAc,GAAG,EAAc,MAAM,WAAW,CAAA;AAM5D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAgFpD,MAAM,MAAM,SAAS,CAAC,KAAK,SAAS,MAAM,IAAI;IAC5C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAA;IAC3C,QAAQ,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;IAC5C,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,CAAC,KAAK,CAAC,CAAA;CAC/B,CAAA;AAED,MAAM,MAAM,MAAM,CAAC,KAAK,SAAS,MAAM,IAAI;IACzC,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,EAAE,QAAQ,CAAC,CAAA;IAC7C,OAAO,IAAI,IAAI,CAAA;IACf,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CAC9B,CAAA;AAED,wBAAgB,QAAQ,CAAC,KAAK,SAAS,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,EAAE,SAAS,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CA8OxI"}
|
package/runtime/ui.js
CHANGED
|
@@ -69,6 +69,17 @@ export function createUi({ name, claude, router, toaster, report, announce, mod
|
|
|
69
69
|
const panes = new Map();
|
|
70
70
|
const paneLogs = new Map();
|
|
71
71
|
const openPanes = new Set();
|
|
72
|
+
const paneStates = new Map();
|
|
73
|
+
const syncPanes = async () => {
|
|
74
|
+
for (const open of await claude.ui.panes()) {
|
|
75
|
+
if (!panes.has(open.id))
|
|
76
|
+
continue;
|
|
77
|
+
if (open.isPlaced)
|
|
78
|
+
openPanes.add(open.id);
|
|
79
|
+
paneStates.set(open.id, { isShown: open.isShown, isFocused: open.isFocused });
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
const readPanes = () => void syncPanes().catch((error) => claude.ui.log(`${name} keeps its panes' shown and focused state from before: ${messageOf(error)}`, { to: 'debug' }));
|
|
72
83
|
const requestedSizes = new Map();
|
|
73
84
|
const renders = new Set();
|
|
74
85
|
const markdownRenders = new Map();
|
|
@@ -160,6 +171,8 @@ export function createUi({ name, claude, router, toaster, report, announce, mod
|
|
|
160
171
|
if (pane === undefined || e.component !== 'Pane')
|
|
161
172
|
return next(e);
|
|
162
173
|
openPanes.add(pane.id);
|
|
174
|
+
paneStates.set(pane.id, { isShown: true, isFocused: e.props.isFocused });
|
|
175
|
+
readPanes();
|
|
163
176
|
const table = claude.ui.resolve(e);
|
|
164
177
|
try {
|
|
165
178
|
return drawWith(table, () => pane.render(mod(), e.props), markdownIn(table));
|
|
@@ -179,6 +192,8 @@ export function createUi({ name, claude, router, toaster, report, announce, mod
|
|
|
179
192
|
});
|
|
180
193
|
router.add('ui.close', async (e, next) => {
|
|
181
194
|
openPanes.delete(e.id);
|
|
195
|
+
paneStates.delete(e.id);
|
|
196
|
+
readPanes();
|
|
182
197
|
const closed = await next(e);
|
|
183
198
|
const pane = panes.get(e.id);
|
|
184
199
|
if (pane?.onClose !== undefined)
|
|
@@ -207,14 +222,23 @@ export function createUi({ name, claude, router, toaster, report, announce, mod
|
|
|
207
222
|
get isOpen() {
|
|
208
223
|
return openPanes.has(pane.id);
|
|
209
224
|
},
|
|
225
|
+
get isShown() {
|
|
226
|
+
return paneStates.get(pane.id)?.isShown ?? false;
|
|
227
|
+
},
|
|
228
|
+
get isFocused() {
|
|
229
|
+
return paneStates.get(pane.id)?.isFocused ?? false;
|
|
230
|
+
},
|
|
210
231
|
async open(options) {
|
|
211
232
|
const { isPlaced } = await openAt(pane, paneSize(pane, mod().state), options?.focus);
|
|
212
233
|
if (isPlaced)
|
|
213
234
|
openPanes.add(pane.id);
|
|
235
|
+
await syncPanes();
|
|
214
236
|
},
|
|
215
237
|
async close() {
|
|
216
238
|
await claude.ui.close({ id: pane.id });
|
|
217
239
|
openPanes.delete(pane.id);
|
|
240
|
+
paneStates.delete(pane.id);
|
|
241
|
+
await syncPanes();
|
|
218
242
|
},
|
|
219
243
|
toggle: (options) => (openPanes.has(pane.id) ? handle.close() : handle.open(options)),
|
|
220
244
|
};
|
|
@@ -286,12 +310,8 @@ export function createUi({ name, claude, router, toaster, report, announce, mod
|
|
|
286
310
|
});
|
|
287
311
|
},
|
|
288
312
|
async restorePanes() {
|
|
289
|
-
if (panes.size
|
|
290
|
-
|
|
291
|
-
for (const open of await claude.ui.panes()) {
|
|
292
|
-
if (open.isPlaced && panes.has(open.id))
|
|
293
|
-
openPanes.add(open.id);
|
|
294
|
-
}
|
|
313
|
+
if (panes.size > 0)
|
|
314
|
+
await syncPanes();
|
|
295
315
|
},
|
|
296
316
|
};
|
|
297
317
|
}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
+
import type { RecordPart } from '../session.js';
|
|
1
2
|
import type { Turn } from './turn/turn.js';
|
|
2
3
|
export declare const ContextStart = "contextStart";
|
|
3
4
|
export declare const ContextEnd = "contextEnd";
|
|
4
|
-
export type Context = {
|
|
5
|
+
export type Context = RecordPart & {
|
|
5
6
|
readonly number: number;
|
|
6
7
|
readonly openedAt: string;
|
|
7
8
|
readonly closedAt?: string;
|
|
9
|
+
readonly task?: string;
|
|
8
10
|
turns(): Promise<Turn[]>;
|
|
9
11
|
};
|
|
10
12
|
//# sourceMappingURL=context.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/session/context/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAA;AAE1C,eAAO,MAAM,YAAY,iBAAiB,CAAA;AAE1C,eAAO,MAAM,UAAU,eAAe,CAAA;AAEtC,MAAM,MAAM,OAAO,GAAG;
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/session/context/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAC/C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAA;AAE1C,eAAO,MAAM,YAAY,iBAAiB,CAAA;AAE1C,eAAO,MAAM,UAAU,eAAe,CAAA;AAEtC,MAAM,MAAM,OAAO,GAAG,UAAU,GAAG;IACjC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;IACtB,KAAK,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC,CAAA;CACzB,CAAA"}
|
|
@@ -48,6 +48,7 @@ export declare function rowOfAppend(append: {
|
|
|
48
48
|
};
|
|
49
49
|
}, at: string, cwd: string): Row;
|
|
50
50
|
export declare function messagesOf(row: Row, isInTask: boolean): Unplaced[];
|
|
51
|
+
export declare function withTexts(row: Row, texts: ReadonlyMap<number, string>): readonly unknown[];
|
|
51
52
|
export declare function textOf(content: unknown): string;
|
|
52
53
|
export declare function tagOf(text: string, tag: string): string | undefined;
|
|
53
54
|
export declare function searchText(message: Unplaced): string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"message.d.ts","sourceRoot":"","sources":["../../../../src/session/context/turn/message/message.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"message.d.ts","sourceRoot":"","sources":["../../../../src/session/context/turn/message/message.ts"],"names":[],"mappings":"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"}
|
|
@@ -77,7 +77,7 @@ function unplacedOf(row, isInTask) {
|
|
|
77
77
|
}
|
|
78
78
|
if (row.isSummary)
|
|
79
79
|
return [];
|
|
80
|
-
const results = row.content.filter(
|
|
80
|
+
const results = row.content.filter(isToolResultBlock);
|
|
81
81
|
if (results.length > 0)
|
|
82
82
|
return results.map((block) => ({ ...base, type: ToolResult, callId: block['tool_use_id'], text: textOf(block['content']), isError: block['is_error'] === true }));
|
|
83
83
|
if (text === '')
|
|
@@ -91,6 +91,47 @@ function unplacedOf(row, isInTask) {
|
|
|
91
91
|
const prompt = promptText(text);
|
|
92
92
|
return prompt === undefined ? [] : [{ ...base, type: Prompt, text: prompt, from: senderOf(row.origin, isInTask) }];
|
|
93
93
|
}
|
|
94
|
+
export function withTexts(row, texts) {
|
|
95
|
+
if (row.type === 'assistant') {
|
|
96
|
+
let index = -1;
|
|
97
|
+
return row.content.map((block) => {
|
|
98
|
+
if (!isObject(block))
|
|
99
|
+
return block;
|
|
100
|
+
const isText = block['type'] === 'text' && typeof block['text'] === 'string' && block['text'].trim() !== '';
|
|
101
|
+
const isCall = block['type'] === 'tool_use' && typeof block['id'] === 'string' && typeof block['name'] === 'string';
|
|
102
|
+
if (!isText && !isCall)
|
|
103
|
+
return block;
|
|
104
|
+
index += 1;
|
|
105
|
+
const text = texts.get(index);
|
|
106
|
+
return isText && text !== undefined ? { ...block, text } : block;
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
if (row.type === 'user' && row.content.some(isToolResultBlock)) {
|
|
110
|
+
let index = -1;
|
|
111
|
+
return row.content.map((block) => {
|
|
112
|
+
if (!isToolResultBlock(block))
|
|
113
|
+
return block;
|
|
114
|
+
index += 1;
|
|
115
|
+
const text = texts.get(index);
|
|
116
|
+
if (text === undefined)
|
|
117
|
+
return block;
|
|
118
|
+
return { ...block, content: Array.isArray(block['content']) ? keepingMedia(block['content'], text) : text };
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
const text = texts.get(0);
|
|
122
|
+
if (text === undefined)
|
|
123
|
+
return row.content;
|
|
124
|
+
const whole = textOf(row.content);
|
|
125
|
+
if (whole.trim().startsWith('<task-notification') && tagOf(whole, 'summary') !== undefined)
|
|
126
|
+
return keepingMedia(row.content, whole.replace(/<summary>[\s\S]*?<\/summary>/, () => `<summary>${text}</summary>`));
|
|
127
|
+
return keepingMedia(row.content, text);
|
|
128
|
+
}
|
|
129
|
+
function keepingMedia(content, text) {
|
|
130
|
+
return [{ type: 'text', text }, ...content.filter((block) => !isObject(block) || block['type'] !== 'text')];
|
|
131
|
+
}
|
|
132
|
+
function isToolResultBlock(block) {
|
|
133
|
+
return isObject(block) && block['type'] === 'tool_result' && typeof block['tool_use_id'] === 'string';
|
|
134
|
+
}
|
|
94
135
|
export function textOf(content) {
|
|
95
136
|
if (typeof content === 'string')
|
|
96
137
|
return content;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import type { RecordPart } from '../../session.js';
|
|
1
2
|
import type { Message } from './message/message.js';
|
|
2
3
|
import type { Prompt } from './message/prompt.js';
|
|
3
4
|
export declare const TurnStart = "turnStart";
|
|
4
5
|
export declare const TurnEnd = "turnEnd";
|
|
5
|
-
export type Turn = {
|
|
6
|
+
export type Turn = RecordPart & {
|
|
6
7
|
readonly prompt: Prompt;
|
|
7
8
|
readonly context: number;
|
|
8
9
|
readonly openedAt: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"turn.d.ts","sourceRoot":"","sources":["../../../src/session/context/turn/turn.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAA;AACnD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAEjD,eAAO,MAAM,SAAS,cAAc,CAAA;AAEpC,eAAO,MAAM,OAAO,YAAY,CAAA;AAEhC,MAAM,MAAM,IAAI,GAAG;
|
|
1
|
+
{"version":3,"file":"turn.d.ts","sourceRoot":"","sources":["../../../src/session/context/turn/turn.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAClD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAA;AACnD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAEjD,eAAO,MAAM,SAAS,cAAc,CAAA;AAEpC,eAAO,MAAM,OAAO,YAAY,CAAA;AAEhC,MAAM,MAAM,IAAI,GAAG,UAAU,GAAG;IAC9B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;IAC1B,QAAQ,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC,CAAA;CAC/B,CAAA"}
|
|
@@ -3,6 +3,7 @@ import { Message, type Row } from './context/turn/message/message.js';
|
|
|
3
3
|
import { TurnEnd, TurnStart, type Turn } from './context/turn/turn.js';
|
|
4
4
|
import { GoalChange, type Goal } from './goal/goal.js';
|
|
5
5
|
import { Task, TaskEnd, TaskStart } from './goal/task.js';
|
|
6
|
+
import type { UsageChange, Usage } from './session.js';
|
|
6
7
|
export type SessionData = {
|
|
7
8
|
readonly id: string;
|
|
8
9
|
readonly title: string;
|
|
@@ -13,13 +14,22 @@ export type SessionData = {
|
|
|
13
14
|
readonly lastAt: string;
|
|
14
15
|
readonly forkedFrom?: string;
|
|
15
16
|
readonly isRunning: boolean;
|
|
17
|
+
readonly agentType?: string;
|
|
16
18
|
};
|
|
17
|
-
export type ContextData =
|
|
18
|
-
export type TurnData =
|
|
19
|
-
export type TaskData =
|
|
19
|
+
export type ContextData = Pick<Context, 'number' | 'openedAt' | 'closedAt' | 'task'>;
|
|
20
|
+
export type TurnData = Pick<Turn, 'prompt' | 'context' | 'openedAt' | 'closedAt'>;
|
|
21
|
+
export type TaskData = Pick<Task, 'id' | 'title' | 'openedBy' | 'openedAt' | 'closedAt'> & {
|
|
22
|
+
readonly agentType: string;
|
|
23
|
+
readonly model?: string;
|
|
20
24
|
readonly parent?: string;
|
|
21
25
|
};
|
|
22
|
-
export type
|
|
26
|
+
export type RunningTask = TaskData & {
|
|
27
|
+
readonly context: number;
|
|
28
|
+
readonly contextOpenedAt?: string;
|
|
29
|
+
};
|
|
30
|
+
export type GoalData = Pick<Goal, 'text'> & {
|
|
31
|
+
readonly task?: string;
|
|
32
|
+
};
|
|
23
33
|
export type SessionChange = {
|
|
24
34
|
readonly type: typeof Message;
|
|
25
35
|
readonly message: Message;
|
|
@@ -31,12 +41,13 @@ export type SessionChange = {
|
|
|
31
41
|
readonly context: ContextData;
|
|
32
42
|
} | {
|
|
33
43
|
readonly type: typeof TaskStart | typeof TaskEnd;
|
|
34
|
-
readonly task:
|
|
35
|
-
readonly context: number;
|
|
36
|
-
};
|
|
44
|
+
readonly task: RunningTask;
|
|
37
45
|
} | {
|
|
38
46
|
readonly type: typeof GoalChange;
|
|
39
47
|
readonly goal: GoalData;
|
|
48
|
+
} | {
|
|
49
|
+
readonly type: typeof UsageChange;
|
|
50
|
+
readonly usage: Usage;
|
|
40
51
|
};
|
|
41
52
|
export type ConversationState = {
|
|
42
53
|
readonly session: string;
|
|
@@ -46,14 +57,12 @@ export type ConversationState = {
|
|
|
46
57
|
readonly goal?: string;
|
|
47
58
|
readonly agentCalls: readonly string[];
|
|
48
59
|
readonly endedCalls: Readonly<Record<string, string>>;
|
|
49
|
-
readonly tasks: Readonly<Record<string,
|
|
50
|
-
|
|
51
|
-
}>>;
|
|
60
|
+
readonly tasks: Readonly<Record<string, RunningTask>>;
|
|
61
|
+
readonly taskTurns: Readonly<Record<string, TurnData>>;
|
|
52
62
|
};
|
|
53
63
|
export type Conversation = {
|
|
54
64
|
add(row: Row, task?: string): SessionChange[];
|
|
55
65
|
startTask(task: TaskData): SessionChange[];
|
|
56
|
-
endContext(at: string): SessionChange[];
|
|
57
66
|
startContext(at: string): SessionChange[];
|
|
58
67
|
changeGoal(text: string): SessionChange[];
|
|
59
68
|
readonly state: ConversationState;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conversation.d.ts","sourceRoot":"","sources":["../src/session/conversation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,KAAK,OAAO,EAAE,MAAM,sBAAsB,CAAA;AAC7E,OAAO,EAAE,OAAO,EAA6B,KAAK,GAAG,EAAE,MAAM,mCAAmC,CAAA;AAKhG,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,KAAK,IAAI,EAAE,MAAM,wBAAwB,CAAA;AACtE,OAAO,EAAE,UAAU,EAAE,KAAK,IAAI,EAAE,MAAM,gBAAgB,CAAA;AACtD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;
|
|
1
|
+
{"version":3,"file":"conversation.d.ts","sourceRoot":"","sources":["../src/session/conversation.ts"],"names":[],"mappings":"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"}
|