@agentorg/cli 0.0.7 → 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.
Files changed (33) hide show
  1. package/README.md +3 -3
  2. package/dist/node_modules/@agentorg/computer/dist/types/generated/schema.d.ts +3 -0
  3. package/dist/node_modules/@agentorg/computer/package.json +1 -1
  4. package/dist/node_modules/@agentorg/computer-connector/dist/src/provider.js +3 -3
  5. package/dist/node_modules/@agentorg/computer-connector/dist/src/unit.d.ts +1 -1
  6. package/dist/node_modules/@agentorg/computer-connector/dist/src/unit.js +34 -30
  7. package/dist/node_modules/@agentorg/computer-connector/package.json +1 -1
  8. package/dist/node_modules/@agentorg/interfaces/dist/src/index.d.ts +0 -1
  9. package/dist/node_modules/@agentorg/interfaces/dist/src/index.js +0 -1
  10. package/dist/node_modules/@agentorg/interfaces/dist/src/manager.d.ts +1 -1
  11. package/dist/node_modules/@agentorg/interfaces/dist/src/manager.js +1 -1
  12. package/dist/node_modules/@agentorg/looper/dist/src/loop.d.ts +40 -17
  13. package/dist/node_modules/@agentorg/looper/dist/src/loop.js +142 -69
  14. package/dist/node_modules/@agentorg/looper/dist/src/looper.d.ts +62 -18
  15. package/dist/node_modules/@agentorg/looper/dist/src/looper.js +588 -108
  16. package/dist/node_modules/@agentorg/looper/dist/src/main.d.ts +90 -0
  17. package/dist/node_modules/@agentorg/looper/dist/src/main.js +205 -0
  18. package/dist/node_modules/@agentorg/looper/dist/src/record.d.ts +156 -16
  19. package/dist/node_modules/@agentorg/looper/dist/src/record.js +292 -58
  20. package/dist/node_modules/@agentorg/manager/dist/src/control.d.ts +1 -1
  21. package/dist/node_modules/@agentorg/manager/dist/src/control.js +1 -1
  22. package/dist/node_modules/@agentorg/shell/dist/app.css +290 -375
  23. package/dist/node_modules/@agentorg/shell/dist/app.js +141 -144
  24. package/dist/node_modules/assistant/dist/src/chats.d.ts +14 -7
  25. package/dist/node_modules/assistant/dist/src/chats.js +24 -25
  26. package/dist/node_modules/assistant/dist/src/engine.js +11 -5
  27. package/dist/node_modules/chatgpt/dist/src/account.js +1 -1
  28. package/dist/src/gateway.js +0 -3
  29. package/package.json +1 -1
  30. package/dist/node_modules/@agentorg/interfaces/dist/src/folders.d.ts +0 -19
  31. package/dist/node_modules/@agentorg/interfaces/dist/src/folders.js +0 -25
  32. package/dist/src/folders.d.ts +0 -2
  33. package/dist/src/folders.js +0 -45
@@ -0,0 +1,90 @@
1
+ import type { Log, Model, ToolSpec } from "./types.js";
2
+ /** What the main loop is told, before who it speaks as. */
3
+ export declare const MAIN_INSTRUCTIONS = "You are the front desk. You do none of the work: you say whose a message is, answer it yourself when it needs no work, or stop a piece of work it asks to stop.\n\nYou are given the latest pieces of work, each by its id and title, whether it is in a turn or at rest, and a line on what it last said; then the conversation where a message has come in that no work owns.\n\n- Give it to a piece of work only when it points at that work explicitly: it names it, quotes it, or refers to what it is doing or just did, and exactly one piece of work fits. Call `route` with that work's id. Its worker will read it with everything it already knows, and answer where it came in. From then on everything said there goes to that work.\n- Answer it yourself, in plain text and calling nothing, only when it needs no tools and nothing you can't see here: a greeting, thanks, a question about who you are or about the work listed, or a request to stop that no one piece of work in a turn fits. Never say you will do, find, check or look into something: you can't, and saying so starts no work.\n- Stop a piece of work when the message asks to stop it and exactly one piece of work in a turn fits. Call `route` with only `stop`, set to its id, and say in a few words that you stopped it. If none fits, or more than one, stop nothing and call nothing: say what is in a turn, so they can say which.\n- Anything else is new work, also when it is on a subject like that of work there is. Call `route` with no `work`, and a `title` of a few words that says what the new work is.\n\nWhatever you write is said to the person as the reply. So when you give a message to work, old or new, write nothing: the worker answers.\n\nA wrong match stays, and a promise starts nothing: when in doubt whose it is, it is new work.";
4
+ /**
5
+ * What the main loop is told when a message was said to work that is in a turn: the worker has
6
+ * it, and the main loop may only stop that work.
7
+ */
8
+ export declare const HEARD_INSTRUCTIONS = "You are the front desk. You are given one piece of work that is in a turn, by its id and title, and then a message that was just said in a conversation that work follows. Its worker has the message and will read it: you don't answer it, and you give it to nobody.\n\nAct only if the message asks to stop that work. Then call `route` with only `stop`, set to its id, and say in a few words that you stopped it. Otherwise call nothing and write nothing: what you write is said only when you stop it.";
9
+ /** What is said where the main loop called to stop work and wrote nothing: whether a turn was cut. */
10
+ export declare const stopWord: (cut: boolean) => "Nothing was stopped." | "Stopped.";
11
+ /** The one function the main loop calls. */
12
+ export declare const ROUTE: ToolSpec;
13
+ /** A piece of work as the main loop is told of it. */
14
+ export interface Listed {
15
+ id: string;
16
+ title: string;
17
+ /** Which turn of it is running or waiting for its place, when one is. */
18
+ turn?: number | undefined;
19
+ /** The head of what it last said, if it has said anything. */
20
+ last?: string | undefined;
21
+ /** Whether its last turn failed. */
22
+ failed?: boolean | undefined;
23
+ }
24
+ /** A message of the thread, as the main loop reads it. */
25
+ export interface Said {
26
+ role: "user" | "assistant";
27
+ text: string;
28
+ }
29
+ /**
30
+ * What the main loop decided. `answer` is what it wrote. `placed` is whose what came in is: work
31
+ * it was told of, or new work by its title. `stop` is there when it called to stop work, and
32
+ * then nothing is placed: the turn to cut is the one it was told of, and none when that work was
33
+ * not told of as in a turn.
34
+ */
35
+ export interface Decided {
36
+ answer?: string;
37
+ placed?: {
38
+ work: string;
39
+ } | {
40
+ title: string;
41
+ };
42
+ stop?: {
43
+ work: string;
44
+ turn?: number;
45
+ };
46
+ }
47
+ /** A work's title: the first line of `text` that says anything, in a few words. */
48
+ export declare const titled: (text: string) => string;
49
+ /**
50
+ * How much the main loop is told, enough to place a message: the thread's newest messages and the
51
+ * start of each, the latest pieces of work with the start of what each last said, and the start
52
+ * of who it speaks as.
53
+ */
54
+ export declare const TOLD: {
55
+ messages: number;
56
+ each: number;
57
+ works: number;
58
+ last: number;
59
+ voice: number;
60
+ };
61
+ export declare function createMain(options: {
62
+ model: Model;
63
+ /**
64
+ * Read for each request: which model to ask, none meaning the model's own default, and who the
65
+ * main loop speaks as when it answers itself.
66
+ */
67
+ request(): Promise<{
68
+ model?: string | undefined;
69
+ voice?: string | undefined;
70
+ }>;
71
+ log: Log;
72
+ }): {
73
+ /**
74
+ * Decide on a thread, given what was said in it and the work there is. `written` is given its
75
+ * text as the model writes it. Nothing is said for a decision that is dropped. A request the
76
+ * model refuses rejects, as it refused.
77
+ */
78
+ decide(said: Said[], works: Listed[], written: (text: string) => void): Promise<Decided | undefined>;
79
+ /**
80
+ * Hear a message that joined a turn of `work`, which has it: the main loop may only stop
81
+ * that turn, and is not told who it speaks as. It gives what to say where the message was
82
+ * said if it says to stop it, and none if it doesn't or the request is dropped. Nothing it
83
+ * writes is said otherwise. A request the model refuses rejects, as it refused.
84
+ */
85
+ hear(text: string, work: Listed): Promise<string | undefined>;
86
+ /** Text the model writes while it answers `requestId`, if that is the request out now. */
87
+ delta(requestId: string, text: string): void;
88
+ /** Drop the request out now: it is cancelled, and it says nothing. */
89
+ cancel(): Promise<void>;
90
+ };
@@ -0,0 +1,205 @@
1
+ /**
2
+ * The main loop: one per looper. It is given a thread no piece of work follows, in which a message
3
+ * has come in, and the work there is. It says whose the message is, new work or work there is, or
4
+ * answers it itself when it needs no work, or stops a piece of work the message asks to stop. It
5
+ * is also told of a message said to work that is in a turn, which that work has: then it is given
6
+ * that work and that message, and may only stop that work. It does none of the work, and it has
7
+ * one function to call. Each time is one model request, which holds nothing of those before it
8
+ * but what it is given.
9
+ */
10
+ import { head } from "./record.js";
11
+ /** What the main loop is told, before who it speaks as. */
12
+ export const MAIN_INSTRUCTIONS = `You are the front desk. You do none of the work: you say whose a message is, answer it yourself when it needs no work, or stop a piece of work it asks to stop.
13
+
14
+ You are given the latest pieces of work, each by its id and title, whether it is in a turn or at rest, and a line on what it last said; then the conversation where a message has come in that no work owns.
15
+
16
+ - Give it to a piece of work only when it points at that work explicitly: it names it, quotes it, or refers to what it is doing or just did, and exactly one piece of work fits. Call \`route\` with that work's id. Its worker will read it with everything it already knows, and answer where it came in. From then on everything said there goes to that work.
17
+ - Answer it yourself, in plain text and calling nothing, only when it needs no tools and nothing you can't see here: a greeting, thanks, a question about who you are or about the work listed, or a request to stop that no one piece of work in a turn fits. Never say you will do, find, check or look into something: you can't, and saying so starts no work.
18
+ - Stop a piece of work when the message asks to stop it and exactly one piece of work in a turn fits. Call \`route\` with only \`stop\`, set to its id, and say in a few words that you stopped it. If none fits, or more than one, stop nothing and call nothing: say what is in a turn, so they can say which.
19
+ - Anything else is new work, also when it is on a subject like that of work there is. Call \`route\` with no \`work\`, and a \`title\` of a few words that says what the new work is.
20
+
21
+ Whatever you write is said to the person as the reply. So when you give a message to work, old or new, write nothing: the worker answers.
22
+
23
+ A wrong match stays, and a promise starts nothing: when in doubt whose it is, it is new work.`;
24
+ /**
25
+ * What the main loop is told when a message was said to work that is in a turn: the worker has
26
+ * it, and the main loop may only stop that work.
27
+ */
28
+ export const HEARD_INSTRUCTIONS = `You are the front desk. You are given one piece of work that is in a turn, by its id and title, and then a message that was just said in a conversation that work follows. Its worker has the message and will read it: you don't answer it, and you give it to nobody.
29
+
30
+ Act only if the message asks to stop that work. Then call \`route\` with only \`stop\`, set to its id, and say in a few words that you stopped it. Otherwise call nothing and write nothing: what you write is said only when you stop it.`;
31
+ /** What is said where the main loop called to stop work and wrote nothing: whether a turn was cut. */
32
+ export const stopWord = (cut) => (cut ? "Stopped." : "Nothing was stopped.");
33
+ /** How who it speaks as is told after that. */
34
+ const VOICE = "When you answer yourself, you speak as the one described below. What that one is told to do is a worker's to do, not yours:";
35
+ /** The one function the main loop calls. */
36
+ export const ROUTE = {
37
+ name: "route",
38
+ description: "Says whose what came in is: a piece of work there is, or new work. Or stops a piece of work.",
39
+ parameters: {
40
+ type: "object",
41
+ properties: {
42
+ work: {
43
+ type: "string",
44
+ description: "The id of the work that it points at. Leave it out for new work.",
45
+ },
46
+ title: {
47
+ type: "string",
48
+ description: "For new work: a few words that say what it is.",
49
+ },
50
+ stop: {
51
+ type: "string",
52
+ description: "The id of the work in a turn to stop. With it, leave the others out.",
53
+ },
54
+ },
55
+ },
56
+ };
57
+ /** A work's title: the first line of `text` that says anything, in a few words. */
58
+ export const titled = (text) => head((text.split("\n").find((line) => /\S/.test(line)) ?? "").replace(/\s+/g, " ").trim(), 80);
59
+ /**
60
+ * How much the main loop is told, enough to place a message: the thread's newest messages and the
61
+ * start of each, the latest pieces of work with the start of what each last said, and the start
62
+ * of who it speaks as.
63
+ */
64
+ export const TOLD = { messages: 8, each: 4000, works: 12, last: 200, voice: 100_000 };
65
+ /** The work there is, as the main loop is told of it. */
66
+ const listing = (works) => works.length === 0
67
+ ? "There is no work."
68
+ : [
69
+ "The work there is:",
70
+ ...works.map(({ id, title, turn, last, failed }) => {
71
+ const state = turn !== undefined ? "in a turn" : failed ? "at rest; its last turn failed" : "at rest";
72
+ return `- ${id}: ${title} (${state})${last ? `; it last said: ${last}` : ""}`;
73
+ }),
74
+ ].join("\n");
75
+ /** What the main loop's request holds: the work there is, then the thread as a conversation. */
76
+ const put = (said, works) => [
77
+ { type: "message", role: "user", content: listing(works) },
78
+ ...said.slice(-TOLD.messages).map(({ role, text }) => ({
79
+ type: "message",
80
+ role,
81
+ content: text.length > TOLD.each ? `${head(text, TOLD.each)}…` : text,
82
+ })),
83
+ ];
84
+ export function createMain(options) {
85
+ /** The request out now, whether it was dropped, and where its text goes as it is written. */
86
+ let asking;
87
+ /**
88
+ * Make one request of the model: what it wrote, and what it called `route` with. `voiced` is
89
+ * whether it is told who it speaks as. None for a request that is dropped, which the model is
90
+ * then not asked, or told to cancel; one the model refuses rejects, as it refused.
91
+ */
92
+ const ask = async (instructions, voiced, input, written) => {
93
+ let drop = () => { };
94
+ const gone = new Promise((resolve) => {
95
+ drop = () => {
96
+ mine.dropped = true;
97
+ resolve(undefined);
98
+ };
99
+ });
100
+ const mine = { drop: () => drop(), written };
101
+ asking = mine;
102
+ try {
103
+ const given = await Promise.race([options.request().then((to) => ({ to })), gone]);
104
+ if (!given || mine.dropped)
105
+ return undefined;
106
+ const { model, voice } = given.to;
107
+ mine.requestId = crypto.randomUUID();
108
+ const asked = options.model.respond({
109
+ requestId: mine.requestId,
110
+ ...(model ? { model } : {}),
111
+ instructions: voiced && voice
112
+ ? `${instructions}\n\n${VOICE}\n\n${head(voice, TOLD.voice)}`
113
+ : instructions,
114
+ input,
115
+ tools: [ROUTE],
116
+ });
117
+ // A model that never answers a request it was told to cancel holds nothing up.
118
+ asked.catch(() => { });
119
+ const reply = await Promise.race([asked, gone]);
120
+ if (!reply || mine.dropped)
121
+ return undefined;
122
+ const text = reply.output
123
+ .flatMap((item) => (item.type === "message" ? [item.content] : []))
124
+ .join("");
125
+ const call = reply.output.find((item) => item.type === "function_call" && item.name === ROUTE.name);
126
+ let routed;
127
+ if (call?.type === "function_call")
128
+ try {
129
+ routed = (JSON.parse(call.arguments) ?? {});
130
+ }
131
+ catch {
132
+ // Arguments that don't read: as a call that says nothing.
133
+ routed = {};
134
+ }
135
+ return { ...(text.trim() ? { text } : {}), routed };
136
+ }
137
+ finally {
138
+ if (asking === mine)
139
+ asking = undefined;
140
+ }
141
+ };
142
+ /** The turn of the work that `stop` names, if it was told of as in a turn. */
143
+ const turnOf = (stop, works) => works.find(({ id }) => id === stop)?.turn;
144
+ return {
145
+ /**
146
+ * Decide on a thread, given what was said in it and the work there is. `written` is given its
147
+ * text as the model writes it. Nothing is said for a decision that is dropped. A request the
148
+ * model refuses rejects, as it refused.
149
+ */
150
+ async decide(said, works, written) {
151
+ const asked = await ask(MAIN_INSTRUCTIONS, true, put(said, works), written);
152
+ if (!asked)
153
+ return undefined;
154
+ const { text, routed } = asked;
155
+ const answered = text === undefined ? {} : { answer: text };
156
+ // Text and no call: it answered, and nothing is placed.
157
+ if (!routed && text !== undefined)
158
+ return answered;
159
+ // A call that names work to stop only stops: nothing is placed.
160
+ if (typeof routed?.stop === "string" && routed.stop !== "") {
161
+ const turn = turnOf(routed.stop, works);
162
+ return {
163
+ ...answered,
164
+ stop: { work: routed.stop, ...(turn === undefined ? {} : { turn }) },
165
+ };
166
+ }
167
+ if (works.some(({ id }) => id === routed?.work))
168
+ return { ...answered, placed: { work: routed?.work } };
169
+ // Anything else starts new work, titled by what came in if the model gave no title.
170
+ if (typeof routed?.work === "string" && routed.work !== "")
171
+ options.log.warn("The main loop named work there isn't; it is new work.", {
172
+ work: head(routed.work, 128),
173
+ });
174
+ const title = titled(typeof routed?.title === "string" ? routed.title : "");
175
+ const newest = said.findLast(({ role }) => role === "user")?.text ?? "";
176
+ return { ...answered, placed: { title: title || titled(newest) } };
177
+ },
178
+ /**
179
+ * Hear a message that joined a turn of `work`, which has it: the main loop may only stop
180
+ * that turn, and is not told who it speaks as. It gives what to say where the message was
181
+ * said if it says to stop it, and none if it doesn't or the request is dropped. Nothing it
182
+ * writes is said otherwise. A request the model refuses rejects, as it refused.
183
+ */
184
+ async hear(text, work) {
185
+ const asked = await ask(HEARD_INSTRUCTIONS, false, put([{ role: "user", text }], [work]), () => { });
186
+ return asked && turnOf(asked.routed?.stop, [work]) !== undefined
187
+ ? (asked.text ?? stopWord(true))
188
+ : undefined;
189
+ },
190
+ /** Text the model writes while it answers `requestId`, if that is the request out now. */
191
+ delta(requestId, text) {
192
+ if (asking?.requestId === requestId)
193
+ asking.written(text);
194
+ },
195
+ /** Drop the request out now: it is cancelled, and it says nothing. */
196
+ async cancel() {
197
+ const cut = asking;
198
+ if (!cut)
199
+ return;
200
+ cut.drop();
201
+ if (cut.requestId)
202
+ await options.model.cancel({ requestId: cut.requestId }).catch(() => { });
203
+ },
204
+ };
205
+ }
@@ -1,7 +1,9 @@
1
1
  /**
2
- * The record a loop runs on, kept in a store: one key per message, holding the items a model reads
3
- * for it, and for a tool message the line a person sees. It is read once, then kept in memory, and
4
- * the oldest messages are deleted past a retention cap.
2
+ * What a loop runs on, kept in a store. A thread keeps its messages, one key each: the items a
3
+ * model reads for it, and for a tool message the line a person sees. A thread is read once, then
4
+ * kept in memory, and its oldest messages are deleted past a retention cap. A piece of work reads
5
+ * its context from the threads it follows: each message is kept once, in the thread where it is
6
+ * shown, and says which work it belongs to when that isn't its thread's own.
5
7
  */
6
8
  import { z } from "zod";
7
9
  import { Item, type Log, type Shown, type Store } from "./types.js";
@@ -38,6 +40,9 @@ export declare const Entry: z.ZodObject<{
38
40
  }>>;
39
41
  joined: z.ZodOptional<z.ZodLiteral<true>>;
40
42
  ahead: z.ZodOptional<z.ZodNumber>;
43
+ work: z.ZodOptional<z.ZodString>;
44
+ main: z.ZodOptional<z.ZodNumber>;
45
+ place: z.ZodOptional<z.ZodNumber>;
41
46
  }, z.core.$strip>;
42
47
  export type Entry = z.output<typeof Entry>;
43
48
  /** Where a record's messages are kept in its store. */
@@ -62,38 +67,173 @@ export declare const argumentsOf: (args: string) => string;
62
67
  export declare function messageOf(entry: Entry): Shown;
63
68
  /** Stored values read at once when what is kept is first loaded. */
64
69
  export declare const READS = 16;
65
- export declare function createRecord(store: Store, log: Log, limits?: {
70
+ /** A user message as it is kept when said. */
71
+ export declare const userEntry: (text: string) => {
72
+ role: "user";
73
+ items: {
74
+ type: "message";
75
+ role: "user";
76
+ content: string;
77
+ }[];
78
+ };
79
+ /** A message as a thread holds it. */
80
+ interface Kept {
81
+ /** Its number in its thread. */
82
+ seq: number;
83
+ key: string;
84
+ entry: Entry;
85
+ bytes: number;
86
+ /** Set while a user message is being written, or taken: the model is sent it once stored. */
87
+ writing?: boolean;
88
+ }
89
+ interface Held {
90
+ records: Kept[];
91
+ last: number;
92
+ bytes: number;
93
+ }
94
+ /** A thread's messages in a store, by their numbers. */
95
+ export declare function createThread(store: Store, log: Log, limits?: {
66
96
  keep: number;
67
97
  keepBytes: number;
68
98
  }): {
99
+ /** What it holds, read once. */
100
+ load: () => Promise<Held>;
101
+ push: (held: Held, entry: Omit<Entry, "id" | "at">, id?: string) => {
102
+ record: Kept;
103
+ stored: Promise<void>;
104
+ };
69
105
  /**
70
- * Keep a message, under `id` or its own number, and delete the oldest past the cap. A tool
71
- * message the store refuses is still kept in memory, since its call has run. `read` is given
72
- * for what came of a model request that had read the record up to that number: when a user
73
- * message was said since, it is kept as `ahead` of it.
106
+ * What was said in it, as a conversation: each message and each reply the main loop gave, in
107
+ * the order they were answered; and the number it holds up to.
74
108
  */
75
- append(entry: Omit<Entry, "id" | "at">, id?: string, read?: number): Promise<Entry>;
76
- /** Whether nothing is kept. */
77
- empty(): Promise<boolean>;
109
+ said(): Promise<{
110
+ said: {
111
+ role: "user" | "assistant";
112
+ text: string;
113
+ }[];
114
+ upTo: number;
115
+ }>;
116
+ /**
117
+ * Keep, under `id`, a reply the main loop gave after it had read up to `upTo`. `late` says
118
+ * whether a message was said after that, which this reply doesn't answer.
119
+ */
120
+ answer(text: string, upTo: number, id: string): Promise<{
121
+ entry: {
122
+ id: string;
123
+ role: "assistant" | "tool" | "user";
124
+ text?: string | undefined;
125
+ at: string;
126
+ items: ({
127
+ type: "message";
128
+ role: "assistant" | "user";
129
+ content: string;
130
+ } | {
131
+ type: "function_call";
132
+ callId: string;
133
+ name: string;
134
+ arguments: string;
135
+ } | {
136
+ type: "function_call_output";
137
+ callId: string;
138
+ output: string;
139
+ })[];
140
+ state?: "done" | "refused" | undefined;
141
+ joined?: true | undefined;
142
+ ahead?: number | undefined;
143
+ work?: string | undefined;
144
+ main?: number | undefined;
145
+ place?: number | undefined;
146
+ };
147
+ late: boolean;
148
+ }>;
149
+ /**
150
+ * Hold a message as `entry` from now on, in memory: `store` writes it as it then is, and
151
+ * `undo` puts it back as it was.
152
+ */
153
+ change(held: Held, record: Kept, entry: Entry): {
154
+ store: () => Promise<unknown>;
155
+ undo: () => void;
156
+ };
78
157
  /** Messages before `before`, oldest first, as many as fit `limit` and `PAGE_BUDGET`. */
79
158
  page(before: string | undefined, limit: number): Promise<{
80
159
  messages: Shown[];
81
160
  more: boolean;
82
161
  }>;
162
+ };
163
+ export type Thread = ReturnType<typeof createThread>;
164
+ /**
165
+ * A piece of work's record: its messages across the threads it follows, in the order it took them.
166
+ * Its id is the name of its own thread, whose messages are its unless they name another work; in
167
+ * any other thread, the messages that name it are. A message's place is where it stands in its
168
+ * own thread until the work follows a second thread, and a count kept with each message after. A
169
+ * message waiting in a thread it follows, said before the work had the thread, names no work yet:
170
+ * the work takes it, in the order it was said, before it keeps anything else there.
171
+ */
172
+ export declare function createRecord(options: {
173
+ id: string;
174
+ /** The threads it follows now, its own first. */
175
+ follows(): string[];
176
+ thread(name: string): Thread;
177
+ }): {
178
+ id: string;
179
+ /**
180
+ * Keep a message of its in `thread`, one of those it follows, after any waiting there. `read`
181
+ * is given for what came of a model request that had read it up to that place: when a user
182
+ * message was said since, or the turn was stopped by saying so, it is kept as `ahead` of
183
+ * that.
184
+ */
185
+ append: (entry: Omit<Entry, "id" | "at" | "work" | "place" | "ahead">, at: {
186
+ thread: string;
187
+ id?: string;
188
+ read?: number;
189
+ }) => Promise<{
190
+ entry: Entry;
191
+ thread: string;
192
+ }>;
193
+ /**
194
+ * Keep in `thread` what the main loop said as it stopped a turn of this work. It stands after
195
+ * all the thread holds, and like a message said in that turn, the work reads it after
196
+ * whatever the turn still writes.
197
+ */
198
+ stopLine: (text: string, thread: string) => Promise<{
199
+ entry: Entry;
200
+ thread: string;
201
+ }>;
202
+ /**
203
+ * Take the messages waiting in `thread`, which it has come to follow, as its own: `joined`,
204
+ * 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,
205
+ * where nothing needs taking, those said since it last did anything itself.
206
+ */
207
+ adopt(thread: string, joined: boolean): Promise<number>;
208
+ /**
209
+ * Whether it has had a turn that did something: it holds more than what was said to it and
210
+ * what the main loop said.
211
+ */
212
+ begun(): Promise<boolean>;
213
+ /** What it last said, if anything. */
214
+ last(): Promise<string | undefined>;
215
+ /** Whether it has no message. */
216
+ empty(): Promise<boolean>;
217
+ /** The thread it answers in now. */
218
+ where(): Promise<string>;
219
+ /** Its first user message, for a title. */
220
+ opening(): Promise<string>;
83
221
  /**
84
- * The conversation to send: the newest exchanges (each from the user message that starts a turn
222
+ * The conversation to send: the newest exchanges (each from a user message that is not `joined`
85
223
  * on) that fit the budget, and always the latest two, so "go on" after a long turn still has
86
224
  * that turn. When those two are over the budget, their oldest function arguments and outputs
87
225
  * are left out, each call still paired with an output. A message said during a turn comes after
88
- * whatever is `ahead` of it, so the model reads it as not yet answered. `read` is the number
89
- * up to which every user message was read, for `append` and `saidAfter`: one still being
90
- * written is not read yet.
226
+ * whatever is `ahead` of it, so the model reads it as not yet answered. `read` is the place up
227
+ * to which every user message was read, for `append` and `saidAfter`: one still being written
228
+ * is not read yet. `thread` is where what comes of it is kept.
91
229
  */
92
230
  input(): Promise<{
93
231
  items: Item[];
94
232
  read: number;
233
+ thread: string;
95
234
  }>;
96
- /** Whether a user message has been stored after the one numbered `read`, which `input` gave. */
235
+ /** Whether a user message of its has been stored after the place `read`, which `input` gave. */
97
236
  saidAfter(read: number): Promise<boolean>;
98
237
  };
99
238
  export type LoopRecord = ReturnType<typeof createRecord>;
239
+ export {};