@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/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;AAsCD,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,MAAM,GAAG,SAAS,GAAG,OAAO,CAwOtG"}
|
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,13 +15,22 @@ 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
35
|
const isLoading = [...entries.values()].some((entry) => entry.type === 'loading');
|
|
24
36
|
if (isLoading && spinning === undefined) {
|
|
@@ -60,18 +72,27 @@ 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);
|
|
66
78
|
if (previous !== undefined)
|
|
67
79
|
disarm(previous);
|
|
68
|
-
const
|
|
80
|
+
const reporting = hides !== undefined && previous?.hides === hides ? previous.reporting : undefined;
|
|
81
|
+
const entry = { id, type, message, options, actions, ...(hides === undefined ? {} : { hides }), isOpen: previous?.isOpen ?? false, reporting, timer: undefined };
|
|
69
82
|
if (type === 'error' && previous?.message !== message)
|
|
70
83
|
claude.ui.log(`${name}: ${message}${typeof options.description === 'string' ? `: ${options.description}` : ''}`, { to: 'debug' });
|
|
71
84
|
entries.set(id, entry);
|
|
72
85
|
changed();
|
|
73
86
|
return id;
|
|
74
87
|
};
|
|
88
|
+
const show = (type) => (message, options = {}) => put(type, message, options, options.action === undefined ? [] : [options.action]);
|
|
89
|
+
const hide = (entry) => {
|
|
90
|
+
dismiss(entry.id);
|
|
91
|
+
if (entry.hides === undefined)
|
|
92
|
+
return;
|
|
93
|
+
hidden.set(String(entry.id), entry.hides);
|
|
94
|
+
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' }));
|
|
95
|
+
};
|
|
75
96
|
const toast = Object.assign(show('default'), {
|
|
76
97
|
success: show('success'),
|
|
77
98
|
info: show('info'),
|
|
@@ -101,37 +122,104 @@ export function createToaster(claude, name) {
|
|
|
101
122
|
};
|
|
102
123
|
const press = (entry, run) => () => void Promise.resolve()
|
|
103
124
|
.then(run)
|
|
104
|
-
.catch((error) =>
|
|
125
|
+
.catch((error) => fail({ id: `press:${entry.id}`, message: `${entry.message}: the press failed`, error }));
|
|
126
|
+
const fail = ({ id, message, error, description = error === undefined ? undefined : describe(error), retry }) => {
|
|
127
|
+
const hides = `${version() ?? ''}\n${message}\n${error === undefined ? '' : describe(error)}`;
|
|
128
|
+
if (hidden.get(id) === hides)
|
|
129
|
+
return id;
|
|
130
|
+
hidden.delete(id);
|
|
131
|
+
const stack = error instanceof Error && error.stack !== undefined ? `\n\n${error.stack}` : '';
|
|
132
|
+
const details = async () => {
|
|
133
|
+
const modVersion = await claude.fs
|
|
134
|
+
.read(`${claude.plugin.root}/.claude-plugin/plugin.json`)
|
|
135
|
+
.then((text) => String(JSON.parse(text).version))
|
|
136
|
+
.catch((failure) => `unknown (${messageOf(failure)})`);
|
|
137
|
+
return `${name} ${modVersion}, @cmodjs/core ${coreVersion}\n${message}${description === undefined ? '' : `\n${description}`}${stack}`;
|
|
138
|
+
};
|
|
139
|
+
const startReporting = async () => {
|
|
140
|
+
const shown = entries.get(id);
|
|
141
|
+
if (shown === undefined)
|
|
142
|
+
return;
|
|
143
|
+
shown.reporting = { contact: await contactOf(claude), details: await details() };
|
|
144
|
+
disarm(shown);
|
|
145
|
+
changed();
|
|
146
|
+
if (bandId === undefined)
|
|
147
|
+
return;
|
|
148
|
+
const focused = await claude.ui.focus({ requestId: bandId, key: `toast:${id}:ask-claude` });
|
|
149
|
+
if ('deny' in focused)
|
|
150
|
+
claude.ui.log(`${name}: the Report choices did not take the keys: ${String(focused.deny)}`, { to: 'debug' });
|
|
151
|
+
};
|
|
152
|
+
const actions = [...(retry === undefined ? [] : [{ label: 'Retry', onClick: retry }]), { label: 'Report', onClick: startReporting }];
|
|
153
|
+
return put('error', message, { id, ...(description === undefined ? {} : { description }), duration: Infinity }, actions, hides);
|
|
154
|
+
};
|
|
105
155
|
const toggle = (entry) => () => {
|
|
106
156
|
entry.isOpen = !entry.isOpen;
|
|
107
157
|
disarm(entry);
|
|
108
158
|
changed();
|
|
109
159
|
};
|
|
110
160
|
const row = (entry) => {
|
|
111
|
-
const { description
|
|
161
|
+
const { description } = entry.options;
|
|
112
162
|
const isText = typeof description === 'string';
|
|
113
163
|
const icon = entry.type === 'loading' ? { glyph: spinner[frame % spinner.length], color: 'claude' } : icons[entry.type];
|
|
114
164
|
const message = isText ? Button({ plain: true, key: `toast:${entry.id}:open`, label: entry.message, onPress: toggle(entry) }) : Text({ children: entry.message });
|
|
115
165
|
const details = !isText ? description : Text({ dimColor: true, wrap: entry.isOpen ? 'wrap' : 'truncate-end', children: entry.isOpen ? description : firstLine(description) });
|
|
116
166
|
const fixed = (child) => Box({ flexShrink: 0, children: child });
|
|
167
|
+
const close = Button({ plain: true, dimColor: true, key: `toast:${entry.id}:close`, label: entry.hides === undefined ? '✕' : 'Hide', onPress: () => hide(entry) });
|
|
168
|
+
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) }));
|
|
169
|
+
const text = details === undefined ? [message] : [message, details];
|
|
170
|
+
const under = entry.reporting === undefined ? [Box({ gap: 2, flexWrap: 'wrap', children: [...actions, close] })] : reportChoices(entry, entry.reporting);
|
|
117
171
|
return Box({
|
|
118
172
|
gap: 2,
|
|
119
173
|
children: [
|
|
120
174
|
fixed(Text({ ...(icon.color === undefined ? {} : { color: icon.color }), children: icon.glyph })),
|
|
121
175
|
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) })),
|
|
176
|
+
Box({ flexDirection: 'column', flexGrow: 1, flexShrink: 1, children: entry.hides === undefined ? text : [...text, ...under] }),
|
|
177
|
+
...(entry.hides === undefined ? [...actions.map(fixed), fixed(close)] : []),
|
|
125
178
|
],
|
|
126
179
|
});
|
|
127
180
|
};
|
|
181
|
+
const reportChoices = (entry, { contact, details, status }) => {
|
|
182
|
+
const say = (said) => {
|
|
183
|
+
entry.reporting = { contact, details, status: said };
|
|
184
|
+
changed();
|
|
185
|
+
};
|
|
186
|
+
const back = () => {
|
|
187
|
+
entry.reporting = undefined;
|
|
188
|
+
changed();
|
|
189
|
+
};
|
|
190
|
+
const askClaude = async () => {
|
|
191
|
+
await claude.prompt.submit({ text: reportPrompt(name, contact, details), asUser: true });
|
|
192
|
+
back();
|
|
193
|
+
};
|
|
194
|
+
const copyError = async () => {
|
|
195
|
+
const copied = await claude.ui.copy({ text: details });
|
|
196
|
+
say(copied.isCopied ? 'Copied the error.' : `Could not copy it: ${copied.reason}`);
|
|
197
|
+
};
|
|
198
|
+
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)' })];
|
|
199
|
+
return [
|
|
200
|
+
Text({ dimColor: true, children: 'Claude writes up the problem and files it with your tools. You approve each step before anything is posted.' }),
|
|
201
|
+
Box({
|
|
202
|
+
gap: 2,
|
|
203
|
+
flexWrap: 'wrap',
|
|
204
|
+
children: [
|
|
205
|
+
Button({ plain: true, key: `toast:${entry.id}:ask-claude`, label: 'Ask Claude to report it', onPress: press(entry, askClaude) }),
|
|
206
|
+
...report,
|
|
207
|
+
Button({ plain: true, key: `toast:${entry.id}:copy`, label: 'Copy the error', onPress: press(entry, copyError) }),
|
|
208
|
+
Button({ plain: true, dimColor: true, key: `toast:${entry.id}:back`, label: 'Back', onPress: back }),
|
|
209
|
+
],
|
|
210
|
+
}),
|
|
211
|
+
...(status === undefined ? [] : [Text({ dimColor: true, children: status })]),
|
|
212
|
+
];
|
|
213
|
+
};
|
|
128
214
|
return {
|
|
129
215
|
toast,
|
|
130
216
|
copy,
|
|
217
|
+
fail,
|
|
131
218
|
get shown() {
|
|
132
219
|
return [...entries.values()].map(({ type, message, options }) => ({ type, message, ...(typeof options.description === 'string' ? { description: options.description } : {}) }));
|
|
133
220
|
},
|
|
134
|
-
draw(drawn, table, band) {
|
|
221
|
+
draw(drawn, table, band, drawnIn) {
|
|
222
|
+
bandId = drawnIn;
|
|
135
223
|
isHeld = band.hasSurvey === true;
|
|
136
224
|
if (isHeld || entries.size === 0)
|
|
137
225
|
return drawn;
|
|
@@ -153,18 +241,6 @@ export function createToaster(claude, name) {
|
|
|
153
241
|
},
|
|
154
242
|
};
|
|
155
243
|
}
|
|
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
244
|
function describe(error) {
|
|
169
245
|
const messages = [];
|
|
170
246
|
for (let cause = error; cause !== undefined; cause = cause instanceof Error ? cause.cause : undefined) {
|
|
@@ -174,3 +250,37 @@ function describe(error) {
|
|
|
174
250
|
}
|
|
175
251
|
return messages.join('\n');
|
|
176
252
|
}
|
|
253
|
+
async function contactOf(claude) {
|
|
254
|
+
const manifest = await claude.fs
|
|
255
|
+
.read(`${claude.plugin.root}/.claude-plugin/plugin.json`)
|
|
256
|
+
.then((text) => JSON.parse(text))
|
|
257
|
+
.catch((error) => {
|
|
258
|
+
claude.ui.log(`${claude.plugin.name}: could not read whom to report to: ${messageOf(error)}`, { to: 'debug' });
|
|
259
|
+
return {};
|
|
260
|
+
});
|
|
261
|
+
const repositoryUrl = isObject(manifest['repository']) ? manifest['repository']['url'] : manifest['repository'];
|
|
262
|
+
const repository = [manifest['supportUrl'], repositoryUrl].map((url) => (typeof url === 'string' ? githubRepository.exec(url)?.[1] : undefined)).find((found) => found !== undefined);
|
|
263
|
+
if (repository !== undefined)
|
|
264
|
+
return { kind: 'github', repository };
|
|
265
|
+
const author = manifest['author'];
|
|
266
|
+
const address = isObject(author) ? author['email'] : undefined;
|
|
267
|
+
return typeof address === 'string' && address !== '' ? { kind: 'email', address } : undefined;
|
|
268
|
+
}
|
|
269
|
+
function reportLink(contact, name, message, details) {
|
|
270
|
+
const title = `${name}: ${message}`.slice(0, 120);
|
|
271
|
+
const linkOf = (body) => contact.kind === 'github'
|
|
272
|
+
? `https://github.com/${contact.repository}/issues/new?title=${encodeURIComponent(title)}&body=${encodeURIComponent(body)}`
|
|
273
|
+
: `mailto:${contact.address}?subject=${encodeURIComponent(title)}&body=${encodeURIComponent(body)}`;
|
|
274
|
+
let body = details;
|
|
275
|
+
while (linkOf(body).length > linkLimit && body.length > 0)
|
|
276
|
+
body = `${body.slice(0, Math.floor(body.length * 0.8))}…`;
|
|
277
|
+
return linkOf(body);
|
|
278
|
+
}
|
|
279
|
+
function reportPrompt(name, contact, details) {
|
|
280
|
+
const where = contact === undefined
|
|
281
|
+
? `${name} names no place to report it, so find its author from its plugin.json or its marketplace.`
|
|
282
|
+
: contact.kind === 'github'
|
|
283
|
+
? `Report it as an issue on https://github.com/${contact.repository}.`
|
|
284
|
+
: `Email it to ${contact.address}.`;
|
|
285
|
+
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}`;
|
|
286
|
+
}
|
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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"}
|