@agentorg/cli 0.0.8 → 0.0.9
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/README.md +3 -3
- package/dist/node_modules/@agentorg/computer/dist/types/generated/schema.d.ts +3 -0
- package/dist/node_modules/@agentorg/computer/package.json +1 -1
- package/dist/node_modules/@agentorg/computer-connector/dist/src/provider.js +3 -3
- package/dist/node_modules/@agentorg/computer-connector/dist/src/unit.d.ts +1 -1
- package/dist/node_modules/@agentorg/computer-connector/dist/src/unit.js +34 -30
- package/dist/node_modules/@agentorg/computer-connector/package.json +1 -1
- package/dist/node_modules/@agentorg/interfaces/dist/src/index.d.ts +0 -1
- package/dist/node_modules/@agentorg/interfaces/dist/src/index.js +0 -1
- package/dist/node_modules/@agentorg/interfaces/dist/src/manager.d.ts +1 -1
- package/dist/node_modules/@agentorg/interfaces/dist/src/manager.js +1 -1
- package/dist/node_modules/@agentorg/looper/dist/src/loop.d.ts +17 -8
- package/dist/node_modules/@agentorg/looper/dist/src/loop.js +80 -41
- package/dist/node_modules/@agentorg/looper/dist/src/looper.d.ts +39 -5
- package/dist/node_modules/@agentorg/looper/dist/src/looper.js +290 -102
- package/dist/node_modules/@agentorg/looper/dist/src/main.d.ts +73 -17
- package/dist/node_modules/@agentorg/looper/dist/src/main.js +166 -77
- package/dist/node_modules/@agentorg/looper/dist/src/record.d.ts +76 -18
- package/dist/node_modules/@agentorg/looper/dist/src/record.js +190 -111
- package/dist/node_modules/@agentorg/shell/dist/app.css +255 -276
- package/dist/node_modules/@agentorg/shell/dist/app.js +144 -147
- package/dist/node_modules/assistant/dist/src/chats.d.ts +10 -5
- package/dist/node_modules/assistant/dist/src/chats.js +5 -4
- package/dist/node_modules/assistant/dist/src/engine.js +10 -4
- package/dist/node_modules/chatgpt/dist/src/account.js +1 -1
- package/dist/src/gateway.js +0 -3
- package/package.json +1 -1
- package/dist/node_modules/@agentorg/interfaces/dist/src/folders.d.ts +0 -19
- package/dist/node_modules/@agentorg/interfaces/dist/src/folders.js +0 -25
- package/dist/src/folders.d.ts +0 -2
- package/dist/src/folders.js +0 -45
|
@@ -17,18 +17,30 @@ export const Entry = z.object({
|
|
|
17
17
|
items: z.array(Item),
|
|
18
18
|
/** For a tool message whose call ran: how it ended. */
|
|
19
19
|
state: z.enum(["done", "refused"]).optional(),
|
|
20
|
-
/**
|
|
20
|
+
/**
|
|
21
|
+
* For a user message said while a turn was running, or while a stopped turn was still writing:
|
|
22
|
+
* it is part of that turn. Also for what the main loop said in a thread, taken with such
|
|
23
|
+
* messages or said as it stopped the turn: it stays in its place among them.
|
|
24
|
+
*/
|
|
21
25
|
joined: z.literal(true).optional(),
|
|
22
26
|
/**
|
|
23
27
|
* For what came of a model request that had read its work up to this place, when a user message
|
|
24
|
-
* was said after that
|
|
28
|
+
* was said after that, or the main loop said it stopped the turn: the model reads it ahead of
|
|
29
|
+
* those, which it doesn't answer.
|
|
25
30
|
*/
|
|
26
31
|
ahead: z.number().optional(),
|
|
27
32
|
/** The piece of work it belongs to, when that isn't its thread's own. */
|
|
28
33
|
work: z.string().optional(),
|
|
34
|
+
/**
|
|
35
|
+
* For what the main loop said itself, which no piece of work said: the number in its thread it
|
|
36
|
+
* stands after, ahead of any said after that. For a reply that is the number it had read up to;
|
|
37
|
+
* for what it said as it stopped a piece of work, all the thread held then.
|
|
38
|
+
*/
|
|
39
|
+
main: z.number().optional(),
|
|
29
40
|
/**
|
|
30
41
|
* Its place in its work's order, once that work follows more than one thread. Without it, its
|
|
31
|
-
* place is
|
|
42
|
+
* place is where it stands in its thread: its number, or for what the main loop said, right
|
|
43
|
+
* after the number that names.
|
|
32
44
|
*/
|
|
33
45
|
place: z.number().optional(),
|
|
34
46
|
});
|
|
@@ -109,6 +121,17 @@ export const userEntry = (text) => ({
|
|
|
109
121
|
role: "user",
|
|
110
122
|
items: [{ type: "message", role: "user", content: text }],
|
|
111
123
|
});
|
|
124
|
+
/** What the main loop said, as it is kept: it stands after `after`, a number in its thread. */
|
|
125
|
+
const mainEntry = (text, after) => ({
|
|
126
|
+
role: "assistant",
|
|
127
|
+
main: after,
|
|
128
|
+
items: [{ type: "message", role: "assistant", content: text }],
|
|
129
|
+
});
|
|
130
|
+
/**
|
|
131
|
+
* Where a message stands in its thread: its number, but what the main loop said stands right
|
|
132
|
+
* after the number it names, ahead of a message said while it answered.
|
|
133
|
+
*/
|
|
134
|
+
const orderOf = ({ seq, entry }) => (entry.main === undefined ? seq : entry.main + 0.5);
|
|
112
135
|
/** A thread's messages in a store, by their numbers. */
|
|
113
136
|
export function createThread(store, log, limits = { keep: KEEP, keepBytes: KEEP_BYTES }) {
|
|
114
137
|
let loaded;
|
|
@@ -154,76 +177,97 @@ export function createThread(store, log, limits = { keep: KEEP, keepBytes: KEEP_
|
|
|
154
177
|
});
|
|
155
178
|
return attempt;
|
|
156
179
|
};
|
|
180
|
+
/**
|
|
181
|
+
* Keep a message in a thread already read, at once, under `id` or its own number; `stored`
|
|
182
|
+
* settles when it is written and the oldest past the cap are deleted. A tool message the store
|
|
183
|
+
* refuses is still kept in memory, since its call has run; any other is taken out again.
|
|
184
|
+
*/
|
|
185
|
+
const push = (held, entry, id) => {
|
|
186
|
+
const seq = ++held.last;
|
|
187
|
+
const key = keyOf(seq);
|
|
188
|
+
const record = {
|
|
189
|
+
seq,
|
|
190
|
+
key,
|
|
191
|
+
entry: kept({
|
|
192
|
+
id: id ?? key.slice(MESSAGES.length),
|
|
193
|
+
at: new Date().toISOString(),
|
|
194
|
+
...entry,
|
|
195
|
+
}),
|
|
196
|
+
bytes: 0,
|
|
197
|
+
writing: entry.role === "user",
|
|
198
|
+
};
|
|
199
|
+
record.bytes = size(record.entry);
|
|
200
|
+
held.records.push(record);
|
|
201
|
+
held.bytes += record.bytes;
|
|
202
|
+
const stored = (async () => {
|
|
203
|
+
try {
|
|
204
|
+
await store.set({ key, value: record.entry });
|
|
205
|
+
record.writing = false;
|
|
206
|
+
}
|
|
207
|
+
catch (error) {
|
|
208
|
+
if (entry.role !== "tool") {
|
|
209
|
+
held.records.splice(held.records.indexOf(record), 1);
|
|
210
|
+
held.bytes -= record.bytes;
|
|
211
|
+
throw error;
|
|
212
|
+
}
|
|
213
|
+
log.error("A tool message couldn't be stored; it is kept until a restart.", {
|
|
214
|
+
error: String(error),
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
while (held.records.length > 1 &&
|
|
218
|
+
(held.records.length > limits.keep || held.bytes > limits.keepBytes)) {
|
|
219
|
+
const oldest = held.records.shift();
|
|
220
|
+
held.bytes -= oldest.bytes;
|
|
221
|
+
await store.delete({ key: oldest.key }).catch((error) => log.warn("An old message couldn't be deleted.", {
|
|
222
|
+
key: oldest.key,
|
|
223
|
+
error: String(error),
|
|
224
|
+
}));
|
|
225
|
+
}
|
|
226
|
+
})();
|
|
227
|
+
return { record, stored };
|
|
228
|
+
};
|
|
157
229
|
return {
|
|
158
230
|
/** What it holds, read once. */
|
|
159
231
|
load,
|
|
232
|
+
push,
|
|
160
233
|
/**
|
|
161
|
-
*
|
|
162
|
-
*
|
|
163
|
-
* refuses is still kept in memory, since its call has run; any other is taken out again.
|
|
234
|
+
* What was said in it, as a conversation: each message and each reply the main loop gave, in
|
|
235
|
+
* the order they were answered; and the number it holds up to.
|
|
164
236
|
*/
|
|
165
|
-
|
|
166
|
-
const
|
|
167
|
-
const
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
record
|
|
180
|
-
|
|
181
|
-
held.
|
|
182
|
-
|
|
183
|
-
try {
|
|
184
|
-
await store.set({ key, value: record.entry });
|
|
185
|
-
record.writing = false;
|
|
186
|
-
}
|
|
187
|
-
catch (error) {
|
|
188
|
-
if (entry.role !== "tool") {
|
|
189
|
-
held.records.splice(held.records.indexOf(record), 1);
|
|
190
|
-
held.bytes -= record.bytes;
|
|
191
|
-
throw error;
|
|
192
|
-
}
|
|
193
|
-
log.error("A tool message couldn't be stored; it is kept until a restart.", {
|
|
194
|
-
error: String(error),
|
|
195
|
-
});
|
|
196
|
-
}
|
|
197
|
-
while (held.records.length > 1 &&
|
|
198
|
-
(held.records.length > limits.keep || held.bytes > limits.keepBytes)) {
|
|
199
|
-
const oldest = held.records.shift();
|
|
200
|
-
held.bytes -= oldest.bytes;
|
|
201
|
-
await store.delete({ key: oldest.key }).catch((error) => log.warn("An old message couldn't be deleted.", {
|
|
202
|
-
key: oldest.key,
|
|
203
|
-
error: String(error),
|
|
204
|
-
}));
|
|
205
|
-
}
|
|
206
|
-
})();
|
|
207
|
-
return { record, stored };
|
|
237
|
+
async said() {
|
|
238
|
+
const held = await load();
|
|
239
|
+
const said = held.records
|
|
240
|
+
.filter(({ entry }) => entry.role !== "tool")
|
|
241
|
+
.sort((a, b) => orderOf(a) - orderOf(b))
|
|
242
|
+
.map(({ entry }) => ({ role: entry.role, text: textOf(entry) }));
|
|
243
|
+
return { said, upTo: held.last };
|
|
244
|
+
},
|
|
245
|
+
/**
|
|
246
|
+
* Keep, under `id`, a reply the main loop gave after it had read up to `upTo`. `late` says
|
|
247
|
+
* whether a message was said after that, which this reply doesn't answer.
|
|
248
|
+
*/
|
|
249
|
+
async answer(text, upTo, id) {
|
|
250
|
+
const held = await load();
|
|
251
|
+
const { record, stored } = push(held, mainEntry(text, upTo), id);
|
|
252
|
+
await stored;
|
|
253
|
+
const late = held.records.some(({ seq, entry }) => seq > upTo && entry.role === "user");
|
|
254
|
+
return { entry: record.entry, late };
|
|
208
255
|
},
|
|
209
256
|
/**
|
|
210
|
-
*
|
|
211
|
-
*
|
|
257
|
+
* Hold a message as `entry` from now on, in memory: `store` writes it as it then is, and
|
|
258
|
+
* `undo` puts it back as it was.
|
|
212
259
|
*/
|
|
213
|
-
|
|
260
|
+
change(held, record, entry) {
|
|
214
261
|
const was = { entry: record.entry, bytes: record.bytes };
|
|
215
262
|
const swap = (to) => {
|
|
216
263
|
held.bytes += to.bytes - record.bytes;
|
|
217
264
|
Object.assign(record, to);
|
|
218
265
|
};
|
|
219
266
|
swap({ entry, bytes: size(entry) });
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
swap(was);
|
|
225
|
-
throw error;
|
|
226
|
-
}
|
|
267
|
+
return {
|
|
268
|
+
store: () => store.set({ key: record.key, value: record.entry }),
|
|
269
|
+
undo: () => swap(was),
|
|
270
|
+
};
|
|
227
271
|
},
|
|
228
272
|
/** Messages before `before`, oldest first, as many as fit `limit` and `PAGE_BUDGET`. */
|
|
229
273
|
async page(before, limit) {
|
|
@@ -250,14 +294,14 @@ export function createThread(store, log, limits = { keep: KEEP, keepBytes: KEEP_
|
|
|
250
294
|
/**
|
|
251
295
|
* A piece of work's record: its messages across the threads it follows, in the order it took them.
|
|
252
296
|
* Its id is the name of its own thread, whose messages are its unless they name another work; in
|
|
253
|
-
* any other thread, the messages that name it are. A message's place is
|
|
254
|
-
* thread until the work follows a second thread, and a count kept with each message after. A
|
|
297
|
+
* any other thread, the messages that name it are. A message's place is where it stands in its
|
|
298
|
+
* own thread until the work follows a second thread, and a count kept with each message after. A
|
|
255
299
|
* message waiting in a thread it follows, said before the work had the thread, names no work yet:
|
|
256
300
|
* the work takes it, in the order it was said, before it keeps anything else there.
|
|
257
301
|
*/
|
|
258
302
|
export function createRecord(options) {
|
|
259
303
|
const { id } = options;
|
|
260
|
-
const placeOf = (record) => record.entry.place ?? record
|
|
304
|
+
const placeOf = (record) => record.entry.place ?? orderOf(record);
|
|
261
305
|
const mine = (thread, record) => record.entry.work === undefined ? thread === id : record.entry.work === id;
|
|
262
306
|
/** Every thread it follows, read: what each holds, as it changes. */
|
|
263
307
|
const load = async () => {
|
|
@@ -272,10 +316,7 @@ export function createRecord(options) {
|
|
|
272
316
|
*/
|
|
273
317
|
const own = (held) => {
|
|
274
318
|
const records = [...held].flatMap(([thread, { records }]) => records.flatMap((record) => (mine(thread, record) ? [{ thread, record }] : [])));
|
|
275
|
-
|
|
276
|
-
if (held.size > 1)
|
|
277
|
-
records.sort((a, b) => placeOf(a.record) - placeOf(b.record));
|
|
278
|
-
return records;
|
|
319
|
+
return records.sort((a, b) => placeOf(a.record) - placeOf(b.record));
|
|
279
320
|
};
|
|
280
321
|
/** The highest place among its messages. */
|
|
281
322
|
const topOf = (records) => {
|
|
@@ -284,63 +325,93 @@ export function createRecord(options) {
|
|
|
284
325
|
};
|
|
285
326
|
/**
|
|
286
327
|
* Take the messages waiting in `thread` as its own, after all it holds: at once in memory, and
|
|
287
|
-
* `written` settles when each is stored, or rejects with
|
|
288
|
-
* a message being written, the model is sent none of them
|
|
328
|
+
* `written` settles when each is stored, or rejects with the first that isn't, which stays
|
|
329
|
+
* waiting with those after it. Like a message being written, the model is sent none of them
|
|
330
|
+
* until that has settled.
|
|
289
331
|
*/
|
|
290
332
|
const take = (held, thread, joined) => {
|
|
291
333
|
const from = held.get(thread);
|
|
292
|
-
const waiting = thread === id
|
|
334
|
+
const waiting = thread === id
|
|
335
|
+
? []
|
|
336
|
+
: from.records.filter(({ entry }) => !entry.work).sort((a, b) => orderOf(a) - orderOf(b));
|
|
293
337
|
let top = topOf(own(held));
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
work: id,
|
|
297
|
-
place: ++top,
|
|
298
|
-
...(joined && record.entry.role === "user" ? { joined: true } : {}),
|
|
299
|
-
}));
|
|
300
|
-
for (const record of waiting)
|
|
338
|
+
// Each gets its place in the order it was said and answered: at once in memory.
|
|
339
|
+
const changes = waiting.map((record) => {
|
|
301
340
|
record.writing = true;
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
341
|
+
return options.thread(thread).change(from, record, {
|
|
342
|
+
...record.entry,
|
|
343
|
+
work: id,
|
|
344
|
+
place: ++top,
|
|
345
|
+
...(joined ? { joined: true } : {}),
|
|
346
|
+
});
|
|
308
347
|
});
|
|
348
|
+
// Stored one after another in that order, so what a crash or a refusal leaves taken is the
|
|
349
|
+
// start of them: the rest stay waiting, and are taken after it.
|
|
350
|
+
const written = (async () => {
|
|
351
|
+
try {
|
|
352
|
+
for (const [i, change] of changes.entries())
|
|
353
|
+
await change.store().catch((error) => {
|
|
354
|
+
for (const rest of changes.slice(i))
|
|
355
|
+
rest.undo();
|
|
356
|
+
throw error;
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
finally {
|
|
360
|
+
for (const record of waiting)
|
|
361
|
+
record.writing = false;
|
|
362
|
+
}
|
|
363
|
+
})();
|
|
309
364
|
return { taken: waiting.length, written };
|
|
310
365
|
};
|
|
311
|
-
/** Whether a user message of its follows the place `read
|
|
312
|
-
const saidAfter = (records, read
|
|
366
|
+
/** Whether a user message of its, stored already, follows the place `read`. */
|
|
367
|
+
const saidAfter = (records, read) => records.some(({ record }) => record.entry.role === "user" && placeOf(record) > read && !record.writing);
|
|
368
|
+
/**
|
|
369
|
+
* Whether something the model reads after what a request made stands past the place `read`,
|
|
370
|
+
* which that request had read up to: a user message, or what the main loop said as it stopped
|
|
371
|
+
* the turn.
|
|
372
|
+
*/
|
|
373
|
+
const heldBack = (records, read) => records.some(({ record }) => placeOf(record) > read && (record.entry.role === "user" || record.entry.joined === true));
|
|
313
374
|
/** The thread of its newest user message: where it answers. Its own, with none. */
|
|
314
375
|
const whereOf = (records) => records.findLast(({ record }) => record.entry.role === "user")?.thread ?? id;
|
|
376
|
+
/** Keep an entry of its in `thread`, made once nothing waits there, from what the thread holds. */
|
|
377
|
+
const keep = async (thread, make, at) => {
|
|
378
|
+
const held = await load();
|
|
379
|
+
const from = held.get(thread);
|
|
380
|
+
// What waits there is taken and stored first, so this is never kept ahead of it: it joins
|
|
381
|
+
// a turn if this does, or comes of one. If the store won't take it, nothing is kept.
|
|
382
|
+
const joins = make(from).joined === true || at.read !== undefined;
|
|
383
|
+
await take(held, thread, joins).written;
|
|
384
|
+
// From here to the push nothing waits, so its place and what is ahead of it are decided
|
|
385
|
+
// with the record as it stands.
|
|
386
|
+
const records = own(held);
|
|
387
|
+
const { record, stored } = options.thread(thread).push(from, {
|
|
388
|
+
...make(from),
|
|
389
|
+
...(thread === id ? {} : { work: id }),
|
|
390
|
+
...(held.size > 1 ? { place: topOf(records) + 1 } : {}),
|
|
391
|
+
...(at.read !== undefined && heldBack(records, at.read) ? { ahead: at.read } : {}),
|
|
392
|
+
}, at.id);
|
|
393
|
+
await stored;
|
|
394
|
+
return { entry: record.entry, thread };
|
|
395
|
+
};
|
|
315
396
|
return {
|
|
316
397
|
id,
|
|
317
398
|
/**
|
|
318
399
|
* Keep a message of its in `thread`, one of those it follows, after any waiting there. `read`
|
|
319
400
|
* is given for what came of a model request that had read it up to that place: when a user
|
|
320
|
-
* message was said since, it is kept as `ahead` of
|
|
401
|
+
* message was said since, or the turn was stopped by saying so, it is kept as `ahead` of
|
|
402
|
+
* that.
|
|
321
403
|
*/
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
// with the record as it stands.
|
|
330
|
-
const records = own(held);
|
|
331
|
-
const { record, stored } = options.thread(thread).push(held.get(thread), {
|
|
332
|
-
...entry,
|
|
333
|
-
...(thread === id ? {} : { work: id }),
|
|
334
|
-
...(held.size > 1 ? { place: topOf(records) + 1 } : {}),
|
|
335
|
-
...(at.read !== undefined && saidAfter(records, at.read) ? { ahead: at.read } : {}),
|
|
336
|
-
}, at.id);
|
|
337
|
-
await stored;
|
|
338
|
-
return { entry: record.entry, thread };
|
|
339
|
-
},
|
|
404
|
+
append: (entry, at) => keep(at.thread, () => entry, at),
|
|
405
|
+
/**
|
|
406
|
+
* Keep in `thread` what the main loop said as it stopped a turn of this work. It stands after
|
|
407
|
+
* all the thread holds, and like a message said in that turn, the work reads it after
|
|
408
|
+
* whatever the turn still writes.
|
|
409
|
+
*/
|
|
410
|
+
stopLine: (text, thread) => keep(thread, (from) => ({ ...mainEntry(text, from.last), joined: true }), {}),
|
|
340
411
|
/**
|
|
341
412
|
* Take the messages waiting in `thread`, which it has come to follow, as its own: `joined`,
|
|
342
|
-
* when a turn of its is running. It says how many there were to answer: in its own thread,
|
|
343
|
-
* where nothing needs taking, those said since it last did anything.
|
|
413
|
+
* when a turn of its is running or a stopped one is still writing. It says how many there were to answer: in its own thread,
|
|
414
|
+
* where nothing needs taking, those said since it last did anything itself.
|
|
344
415
|
*/
|
|
345
416
|
async adopt(thread, joined) {
|
|
346
417
|
const held = await load();
|
|
@@ -349,12 +420,20 @@ export function createRecord(options) {
|
|
|
349
420
|
if (thread !== id)
|
|
350
421
|
return taken;
|
|
351
422
|
const records = own(held);
|
|
352
|
-
const done = records.findLastIndex(({ record }) =>
|
|
353
|
-
return records.
|
|
423
|
+
const done = records.findLastIndex(({ record: { entry } }) => entry.role !== "user" && entry.main === undefined);
|
|
424
|
+
return records.slice(done + 1).filter(({ record }) => record.entry.role === "user").length;
|
|
354
425
|
},
|
|
355
|
-
/**
|
|
426
|
+
/**
|
|
427
|
+
* Whether it has had a turn that did something: it holds more than what was said to it and
|
|
428
|
+
* what the main loop said.
|
|
429
|
+
*/
|
|
356
430
|
async begun() {
|
|
357
|
-
return own(await load()).some(({ record }) =>
|
|
431
|
+
return own(await load()).some(({ record: { entry } }) => entry.role !== "user" && entry.main === undefined);
|
|
432
|
+
},
|
|
433
|
+
/** What it last said, if anything. */
|
|
434
|
+
async last() {
|
|
435
|
+
const said = own(await load()).findLast(({ record: { entry } }) => entry.role === "assistant" && entry.main === undefined);
|
|
436
|
+
return said ? textOf(said.record.entry) : undefined;
|
|
358
437
|
},
|
|
359
438
|
/** Whether it has no message. */
|
|
360
439
|
async empty() {
|
|
@@ -370,7 +449,7 @@ export function createRecord(options) {
|
|
|
370
449
|
return first ? textOf(first.record.entry) : "";
|
|
371
450
|
},
|
|
372
451
|
/**
|
|
373
|
-
* The conversation to send: the newest exchanges (each from
|
|
452
|
+
* The conversation to send: the newest exchanges (each from a user message that is not `joined`
|
|
374
453
|
* on) that fit the budget, and always the latest two, so "go on" after a long turn still has
|
|
375
454
|
* that turn. When those two are over the budget, their oldest function arguments and outputs
|
|
376
455
|
* are left out, each call still paired with an output. A message said during a turn comes after
|
|
@@ -427,7 +506,7 @@ export function createRecord(options) {
|
|
|
427
506
|
},
|
|
428
507
|
/** Whether a user message of its has been stored after the place `read`, which `input` gave. */
|
|
429
508
|
async saidAfter(read) {
|
|
430
|
-
return saidAfter(own(await load()), read
|
|
509
|
+
return saidAfter(own(await load()), read);
|
|
431
510
|
},
|
|
432
511
|
};
|
|
433
512
|
}
|