@evandu/super-pi 0.1.145 → 0.1.147
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/agents/super-pi-task/core.ts +74 -2
- package/agents/super-pi-task/index.ts +7 -0
- package/dist/.super-pi-check-inputs.json +2 -2
- package/dist/client/.super-pi-client-sources.json +11 -11
- package/dist/client/assets/{CodeMirrorEditor-A9KvbIkm.js → CodeMirrorEditor-DQCjEnxG.js} +2 -2
- package/dist/client/assets/{dist-DM4Olwfx.js → dist-1Innu17E.js} +1 -1
- package/dist/client/assets/{dist-bIDce5j-.js → dist-1lynFOc5.js} +1 -1
- package/dist/client/assets/{dist-BlxwDnWr.js → dist-B1qLZVMK.js} +1 -1
- package/dist/client/assets/{dist-BTVbZigv.js → dist-B4pz_xdd.js} +1 -1
- package/dist/client/assets/{dist-UJ46aPS3.js → dist-B6KwDpeI.js} +1 -1
- package/dist/client/assets/{dist-CK2KFFtT.js → dist-BJVI1Unv.js} +1 -1
- package/dist/client/assets/{dist-CRnm1rnO.js → dist-BWvzD8Pe.js} +1 -1
- package/dist/client/assets/{dist-DSHM-PAs.js → dist-BayWssd0.js} +1 -1
- package/dist/client/assets/{dist-B9DE7sc5.js → dist-Bk_pkBVH.js} +1 -1
- package/dist/client/assets/{dist-D-o7iQ8c.js → dist-BpeClAv0.js} +1 -1
- package/dist/client/assets/{dist-CQFASxyb.js → dist-BsmJg5PX.js} +1 -1
- package/dist/client/assets/{dist-Ds5gfeAi.js → dist-Bx7s4rni.js} +1 -1
- package/dist/client/assets/{dist-UPJPMjWv.js → dist-CDBKM9tL.js} +1 -1
- package/dist/client/assets/{dist-CIgjifH-.js → dist-CGzXCzCG.js} +1 -1
- package/dist/client/assets/{dist-BAiV8I_O.js → dist-CRxCwn-Z.js} +1 -1
- package/dist/client/assets/{dist-Br-AuQUG.js → dist-CTDgUnBG.js} +1 -1
- package/dist/client/assets/{dist-4JbFTwg2.js → dist-D1VfMWmf.js} +1 -1
- package/dist/client/assets/{dist-BYOpvW02.js → dist-DTZLNEci.js} +1 -1
- package/dist/client/assets/{dist-CQV5kOCE.js → dist-DuUi29km.js} +1 -1
- package/dist/client/assets/{dist-CjszAoXk.js → dist-F3S0t1oM.js} +1 -1
- package/dist/client/assets/{dist-2boAf_pN.js → dist-QZ-FAVJV.js} +1 -1
- package/dist/client/assets/{dist-B1p4YF9C.js → dist-u0nBg0fZ.js} +1 -1
- package/dist/client/assets/index-BMpqviwU.css +1 -0
- package/dist/client/assets/index-Dzyp_7sf.js +102 -0
- package/dist/client/index.html +2 -2
- package/dist/server/active-memory.d.ts +17 -0
- package/dist/server/active-memory.js +39 -0
- package/dist/server/agents.d.ts +1 -1
- package/dist/server/agents.js +3 -1
- package/dist/server/application/conversation-service.d.ts +1 -1
- package/dist/server/application/conversation-service.js +12 -4
- package/dist/server/application/run-service.d.ts +32 -2
- package/dist/server/application/run-service.js +296 -40
- package/dist/server/application/scheduled-task-service.d.ts +14 -1
- package/dist/server/application/scheduled-task-service.js +27 -2
- package/dist/server/application/session-orchestrator-service.d.ts +114 -3
- package/dist/server/application/session-orchestrator-service.js +406 -35
- package/dist/server/application/session-watchdog.d.ts +159 -0
- package/dist/server/application/session-watchdog.js +244 -0
- package/dist/server/command-handler.js +1 -1
- package/dist/server/conversation-usage.d.ts +19 -0
- package/dist/server/conversation-usage.js +40 -0
- package/dist/server/file-diff.d.ts +3 -0
- package/dist/server/file-diff.js +4 -4
- package/dist/server/file-index.d.ts +4 -2
- package/dist/server/file-index.js +14 -9
- package/dist/server/file-name-index.d.ts +5 -2
- package/dist/server/file-name-index.js +22 -5
- package/dist/server/git.d.ts +3 -3
- package/dist/server/git.js +10 -9
- package/dist/server/http-server.js +256 -34
- package/dist/server/index.js +3 -0
- package/dist/server/knowledge-vectors.d.ts +15 -0
- package/dist/server/knowledge-vectors.js +118 -37
- package/dist/server/knowledge.d.ts +7 -8
- package/dist/server/knowledge.js +133 -55
- package/dist/server/length-continuation.d.ts +50 -0
- package/dist/server/length-continuation.js +55 -0
- package/dist/server/model-context-window.d.ts +46 -0
- package/dist/server/model-context-window.js +121 -0
- package/dist/server/pi-session-events.js +5 -1
- package/dist/server/pi-session-pool.d.ts +2 -0
- package/dist/server/pi-session-pool.js +16 -0
- package/dist/server/pi-session.d.ts +6 -0
- package/dist/server/pi-session.js +15 -1
- package/dist/server/runtime.d.ts +3 -0
- package/dist/server/runtime.js +23 -7
- package/dist/server/session-cwd.d.ts +17 -0
- package/dist/server/session-cwd.js +43 -0
- package/dist/server/session-ledger.d.ts +7 -0
- package/dist/server/session-tree-scope.d.ts +125 -0
- package/dist/server/session-tree-scope.js +337 -0
- package/dist/server/store.d.ts +35 -0
- package/dist/server/store.js +87 -2
- package/dist/server/task-tool.d.ts +2 -1
- package/dist/server/task-tool.js +4 -1
- package/dist/server/terminal.d.ts +1 -0
- package/dist/server/terminal.js +5 -3
- package/dist/server/turn-failure.d.ts +26 -0
- package/dist/server/turn-failure.js +67 -1
- package/dist/server/types.d.ts +33 -1
- package/dist/server/version.d.ts +25 -2
- package/dist/server/version.js +98 -26
- package/dist/server/ws-server.d.ts +1 -1
- package/dist/server/ws-server.js +7 -5
- package/package.json +36 -3
- package/dist/client/assets/index-BGsP8pt_.js +0 -100
- package/dist/client/assets/index-CiIc734l.css +0 -1
package/dist/client/index.html
CHANGED
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
<link rel="alternate icon" href="/favicon.ico" />
|
|
9
9
|
<link rel="apple-touch-icon" href="/favicon.svg" />
|
|
10
10
|
<title>Super Pi</title>
|
|
11
|
-
<script type="module" crossorigin src="/assets/index-
|
|
12
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
11
|
+
<script type="module" crossorigin src="/assets/index-Dzyp_7sf.js"></script>
|
|
12
|
+
<link rel="stylesheet" crossorigin href="/assets/index-BMpqviwU.css">
|
|
13
13
|
</head>
|
|
14
14
|
<body>
|
|
15
15
|
<div id="root"></div>
|
|
@@ -77,6 +77,23 @@ export declare class ActiveMemory {
|
|
|
77
77
|
score: number;
|
|
78
78
|
content: string;
|
|
79
79
|
}[];
|
|
80
|
+
/**
|
|
81
|
+
* Rebuilds one conversation's postings after a rare destructive transcript mutation (revert/delete).
|
|
82
|
+
*
|
|
83
|
+
* WHY THIS EXISTS. The index is a CACHE of the store, and `removeFromIndex` is the surgical half of
|
|
84
|
+
* that contract: the caller tells it which ids LEFT, and exactly those postings go. This is the other
|
|
85
|
+
* half - it rebuilds what is there NOW. A destructive mutation can also change a message's CONTENT
|
|
86
|
+
* (a withdrawn turn replaced by a rewritten one), and a posting that still carries the old text
|
|
87
|
+
* answers a search with a turn the transcript no longer holds. So the rare path pays a full
|
|
88
|
+
* re-tokenize of ONE conversation, and the rest of the workspace stays indexed.
|
|
89
|
+
*
|
|
90
|
+
* THE REMOVAL LOOP WALKS EVERY WORKSPACE, because a posting remembers the conversation it came from:
|
|
91
|
+
* the conversation's terms must stop answering searches wherever they were indexed, not only in the
|
|
92
|
+
* workspace it lives in. The reverse index (`termsByMessage`) is pruned in the same loop, so the two
|
|
93
|
+
* halves of the index cannot disagree about which messages are indexed - a stale entry would point
|
|
94
|
+
* the surgical removal at terms that are no longer there.
|
|
95
|
+
*/
|
|
96
|
+
syncConversation(conversation: Conversation): void;
|
|
80
97
|
private ensureIndex;
|
|
81
98
|
/**
|
|
82
99
|
* Drops exactly the given messages from the search index, leaving the rest of the workspace indexed.
|
|
@@ -135,6 +135,41 @@ export class ActiveMemory {
|
|
|
135
135
|
void id, candidates.set(value.messageId, value);
|
|
136
136
|
return [...candidates.values()].filter(m => !sessionId || m.conversationId === sessionId).map(m => ({ ...m, score: words.reduce((n, word) => n + (m.content.toLocaleLowerCase().includes(word) ? 1 : 0), 0) })).filter(m => m.score > 0).sort((a, b) => b.score - a.score).slice(0, 6).map(m => ({ ...m, content: m.content.slice(0, 1200) }));
|
|
137
137
|
}
|
|
138
|
+
/**
|
|
139
|
+
* Rebuilds one conversation's postings after a rare destructive transcript mutation (revert/delete).
|
|
140
|
+
*
|
|
141
|
+
* WHY THIS EXISTS. The index is a CACHE of the store, and `removeFromIndex` is the surgical half of
|
|
142
|
+
* that contract: the caller tells it which ids LEFT, and exactly those postings go. This is the other
|
|
143
|
+
* half - it rebuilds what is there NOW. A destructive mutation can also change a message's CONTENT
|
|
144
|
+
* (a withdrawn turn replaced by a rewritten one), and a posting that still carries the old text
|
|
145
|
+
* answers a search with a turn the transcript no longer holds. So the rare path pays a full
|
|
146
|
+
* re-tokenize of ONE conversation, and the rest of the workspace stays indexed.
|
|
147
|
+
*
|
|
148
|
+
* THE REMOVAL LOOP WALKS EVERY WORKSPACE, because a posting remembers the conversation it came from:
|
|
149
|
+
* the conversation's terms must stop answering searches wherever they were indexed, not only in the
|
|
150
|
+
* workspace it lives in. The reverse index (`termsByMessage`) is pruned in the same loop, so the two
|
|
151
|
+
* halves of the index cannot disagree about which messages are indexed - a stale entry would point
|
|
152
|
+
* the surgical removal at terms that are no longer there.
|
|
153
|
+
*/
|
|
154
|
+
syncConversation(conversation) {
|
|
155
|
+
for (const [, terms] of this.inverted) {
|
|
156
|
+
for (const [term, postings] of terms) {
|
|
157
|
+
for (const [messageId, value] of postings) {
|
|
158
|
+
if (value.conversationId === conversation.id) {
|
|
159
|
+
postings.delete(messageId);
|
|
160
|
+
this.indexedMessages.delete(messageId);
|
|
161
|
+
this.termsByMessage.delete(messageId);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
if (!postings.size)
|
|
165
|
+
terms.delete(term);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
if (!this.indexedWorkspaces.has(conversation.workspaceId))
|
|
169
|
+
return;
|
|
170
|
+
for (const message of conversation.messages)
|
|
171
|
+
this.addToIndex(conversation, message);
|
|
172
|
+
}
|
|
138
173
|
ensureIndex(workspaceId) {
|
|
139
174
|
if (this.indexedWorkspaces.has(workspaceId))
|
|
140
175
|
return;
|
|
@@ -224,6 +259,10 @@ export class ActiveMemory {
|
|
|
224
259
|
terms.set(term, bucket = new Map());
|
|
225
260
|
bucket.set(message.id, value);
|
|
226
261
|
}
|
|
262
|
+
// THE MESSAGE IS IN THE INDEX NOW, SO THE SET MUST SAY SO. `completed()` walks this set to find
|
|
263
|
+
// the messages it has never indexed, and a message that is indexed without being marked here is
|
|
264
|
+
// re-tokenized on EVERY turn end - the whole-conversation cost this file exists to avoid.
|
|
265
|
+
this.indexedMessages.add(message.id);
|
|
227
266
|
}
|
|
228
267
|
async tool(token, body) {
|
|
229
268
|
const identity = this.identity(token);
|
package/dist/server/agents.d.ts
CHANGED
|
@@ -38,7 +38,7 @@ type Frontmatter = Record<string, unknown>;
|
|
|
38
38
|
*/
|
|
39
39
|
export declare const PI_TOOL_NAMES: readonly ["read", "bash", "powershell", "edit", "write", "grep", "find", "ls", "codemode", "tool_search", "list_mcp_resources", "list_mcp_resource_templates", "read_mcp_resource"];
|
|
40
40
|
/** Tools shipped by this package. Authors must be able to explicitly deny host extras. */
|
|
41
|
-
export declare const SUPER_PI_TOOL_NAMES: readonly ["task", "todowrite", "workflow", "run_async", "scheduled_task", "question", "tool_register", "memory", "skill_manage", "session_search", "knowledge_search", "knowledge_import", "document_read", "document_write", "web_search", "web_fetch", "feishu_doc_read", "feishu_doc_write"];
|
|
41
|
+
export declare const SUPER_PI_TOOL_NAMES: readonly ["task", "todowrite", "workflow", "run_async", "scheduled_task", "question", "tool_register", "memory", "skill_manage", "session_search", "session_spawn", "session_status", "session_dispatch", "session_stop", "knowledge_search", "knowledge_import", "document_read", "document_write", "web_search", "web_fetch", "feishu_doc_read", "feishu_doc_write"];
|
|
42
42
|
/**
|
|
43
43
|
* Whether a name can be a real Pi tool. A name is real if it is one of `PI_TOOL_NAMES`, an MCP
|
|
44
44
|
* server tool, or a PATTERN.
|
package/dist/server/agents.js
CHANGED
|
@@ -39,7 +39,9 @@ export const PI_TOOL_NAMES = [
|
|
|
39
39
|
/** Tools shipped by this package. Authors must be able to explicitly deny host extras. */
|
|
40
40
|
export const SUPER_PI_TOOL_NAMES = [
|
|
41
41
|
"task", "todowrite", "workflow", "run_async", "scheduled_task", "question", "tool_register",
|
|
42
|
-
"memory", "skill_manage", "session_search",
|
|
42
|
+
"memory", "skill_manage", "session_search",
|
|
43
|
+
"session_spawn", "session_status", "session_dispatch", "session_stop",
|
|
44
|
+
"knowledge_search", "knowledge_import",
|
|
43
45
|
"document_read", "document_write", "web_search", "web_fetch", "feishu_doc_read", "feishu_doc_write",
|
|
44
46
|
];
|
|
45
47
|
const KNOWN_TOOL_NAMES = [...PI_TOOL_NAMES, ...SUPER_PI_TOOL_NAMES];
|
|
@@ -48,7 +48,7 @@ export declare class ConversationService {
|
|
|
48
48
|
createConversation(workspaceId: string, parentage?: {
|
|
49
49
|
parentConversationId?: string;
|
|
50
50
|
origin?: "user" | "orchestrator";
|
|
51
|
-
}): Promise<string>;
|
|
51
|
+
}, cwd?: string): Promise<string>;
|
|
52
52
|
/**
|
|
53
53
|
* Name a conversation from what was said in it. Returns the title; the CALLER applies it, because the
|
|
54
54
|
* rename is a second command with its own optimistic path and its own failure toast, and a service that
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { assertModelAllowed } from "../model-filter.js";
|
|
2
2
|
import { newConversationId } from "../store.js";
|
|
3
|
+
import { normalizeSessionCwd, resolveSessionCwd } from "../session-cwd.js";
|
|
3
4
|
function isMissingPrimaryAgent(error, agentId) {
|
|
4
5
|
const message = error instanceof Error ? error.message : String(error);
|
|
5
6
|
const id = JSON.stringify(agentId);
|
|
@@ -50,7 +51,7 @@ export class ConversationService {
|
|
|
50
51
|
* button and every other caller create a top-level conversation by omission, which is the same
|
|
51
52
|
* "absence means top level" rule the pre-tree state.json files read under.
|
|
52
53
|
*/
|
|
53
|
-
async createConversation(workspaceId, parentage) {
|
|
54
|
+
async createConversation(workspaceId, parentage, cwd) {
|
|
54
55
|
const workspace = this.store.workspace(workspaceId);
|
|
55
56
|
if (!workspace)
|
|
56
57
|
throw new Error("找不到这个工作区。");
|
|
@@ -126,7 +127,8 @@ export class ConversationService {
|
|
|
126
127
|
}
|
|
127
128
|
// `null` is intentional here: Store uses it to remove a workspace value that it
|
|
128
129
|
// would otherwise have copied before applying the resolved configuration.
|
|
129
|
-
const
|
|
130
|
+
const sessionCwd = await normalizeSessionCwd(workspace.path, cwd);
|
|
131
|
+
const defaults = { ...resolved, agentId: resolved.agentId ?? null, model: resolved.model ?? null, thinkingLevel: resolved.thinkingLevel ?? null, ...(sessionCwd ? { cwd: sessionCwd } : {}), ...(modelNotice ? { modelNotice } : {}), ...(agentNotice ? { agentNotice } : {}), ...(parentage ? { parentConversationId: parentage.parentConversationId, origin: parentage.origin } : {}) };
|
|
130
132
|
const created = await this.store.createConversation(workspaceId, defaults);
|
|
131
133
|
this.broadcaster.broadcastState();
|
|
132
134
|
return created.id;
|
|
@@ -422,7 +424,7 @@ export class ConversationService {
|
|
|
422
424
|
}
|
|
423
425
|
const outcome = await this.runtime.revert({
|
|
424
426
|
conversation,
|
|
425
|
-
cwd: workspace.path,
|
|
427
|
+
cwd: await resolveSessionCwd(workspace.path, conversation.cwd),
|
|
426
428
|
boundaryEntryId: plan.boundaryEntryId,
|
|
427
429
|
beforeBoundary: withdraw && Boolean(conversation.messages.find(item => item.id === messageId)?.piEntryId),
|
|
428
430
|
});
|
|
@@ -433,6 +435,12 @@ export class ConversationService {
|
|
|
433
435
|
const withdrawn = conversation.messages.find(item => item.id === messageId);
|
|
434
436
|
const withdrawnContent = withdrawn ? { content: withdrawn.content, images: withdrawn.images } : undefined;
|
|
435
437
|
const applied = await this.store.revertMessages(conversationId, messageId, withdraw);
|
|
438
|
+
// THE RECALL INDEX MUST SEE THE TRUNCATED TRANSCRIPT. `conversation` above is the DETACHED COPY
|
|
439
|
+
// that `turnContext` took BEFORE the store spliced its live array, so it still holds the withdrawn
|
|
440
|
+
// turns - re-syncing from it would put the text the person just withdrew straight back into the
|
|
441
|
+
// index, which is the exact leak this path exists to close. The store's post-revert conversation is
|
|
442
|
+
// the truth, and this rare destructive path is where one clone of it is the right price.
|
|
443
|
+
this.memory?.syncConversation(this.store.conversation(conversationId) ?? conversation);
|
|
436
444
|
// THE MEMORY HALF OF THE REWIND, and the half that used to be missing. Everything above removes the
|
|
437
445
|
// turn from Pi's file and from state.json; the memory store is a second durable copy of what the turn
|
|
438
446
|
// said, and it is spliced into every later prompt. So the model kept being told about a turn the person
|
|
@@ -480,7 +488,7 @@ export class ConversationService {
|
|
|
480
488
|
}
|
|
481
489
|
try {
|
|
482
490
|
const forkedId = newConversationId();
|
|
483
|
-
const outcome = await this.runtime.fork({ conversation, cwd: workspace.path, forkedConversationId: forkedId });
|
|
491
|
+
const outcome = await this.runtime.fork({ conversation, cwd: await resolveSessionCwd(workspace.path, conversation.cwd), forkedConversationId: forkedId });
|
|
484
492
|
const forked = await this.store.forkConversation(conversationId, forkedId);
|
|
485
493
|
console.log(`Super Pi: forked conversation ${conversation.id} into ${forked.id}: ` +
|
|
486
494
|
`${forked.messages.length} message(s) copied in state.json` +
|
|
@@ -161,6 +161,15 @@ export declare class RunService {
|
|
|
161
161
|
resultPath: string;
|
|
162
162
|
error?: string;
|
|
163
163
|
}): Promise<void>;
|
|
164
|
+
/**
|
|
165
|
+
* Dispatches a background result (exec or child session) into the conversation.
|
|
166
|
+
*
|
|
167
|
+
* IDLE: starts a fresh turn via `processWaitingMessage`.
|
|
168
|
+
* BUSY: attempts to steer the message into the running turn so it is delivered at the
|
|
169
|
+
* very next tool batch boundary rather than waiting for the entire turn to complete.
|
|
170
|
+
* INTERRUPTING: quietly leaves the message waiting; the interrupted or next turn will pick it up.
|
|
171
|
+
*/
|
|
172
|
+
private dispatchBackgroundResult;
|
|
164
173
|
/**
|
|
165
174
|
* Stops an active background task (spawned process or detached subagent) on user request.
|
|
166
175
|
*
|
|
@@ -171,6 +180,8 @@ export declare class RunService {
|
|
|
171
180
|
* updates immediately.
|
|
172
181
|
*/
|
|
173
182
|
stopBackgroundTask(taskId: string): Promise<void>;
|
|
183
|
+
hasActiveBackgroundTasks(conversationId: string): boolean;
|
|
184
|
+
settleBackgroundStatus(conversationId: string): Promise<void>;
|
|
174
185
|
/** Per-conversation command lane. All queue mutations and run claims use the same lane, so
|
|
175
186
|
* two browser tabs cannot both observe an idle conversation and start duplicate turns. */
|
|
176
187
|
private readonly conversationOps;
|
|
@@ -236,10 +247,10 @@ export declare class RunService {
|
|
|
236
247
|
/**
|
|
237
248
|
* Resolves conversation and workspace working directory for subagent dispatch.
|
|
238
249
|
*/
|
|
239
|
-
dispatchContext(conversationId: string): {
|
|
250
|
+
dispatchContext(conversationId: string): Promise<{
|
|
240
251
|
conversation: Conversation;
|
|
241
252
|
cwd: string;
|
|
242
|
-
}
|
|
253
|
+
}>;
|
|
243
254
|
/**
|
|
244
255
|
* Checks whether a conversation has an active turn running.
|
|
245
256
|
*/
|
|
@@ -379,11 +390,30 @@ export declare class RunService {
|
|
|
379
390
|
* stream it - which is why the two cases are expressed identically and cannot drift apart.
|
|
380
391
|
*/
|
|
381
392
|
runConversationTurns(conversation: Conversation, workspace: Workspace, prompt: string, controller: AbortController, firstMessageId: string, initialImages?: MessageImage[]): Promise<void>;
|
|
393
|
+
/**
|
|
394
|
+
* Refuses a turn when the selected model cannot accept image input, either because the incoming
|
|
395
|
+
* message carries images or because previous messages in the conversation contain images.
|
|
396
|
+
*/
|
|
397
|
+
private assertModelSupportsImages;
|
|
382
398
|
/** Keep admission owned through final persistence and recheck the durable queue before releasing. */
|
|
383
399
|
private runUntilDrained;
|
|
384
400
|
/**
|
|
385
401
|
* Enqueues or starts execution for a user message.
|
|
386
402
|
*/
|
|
403
|
+
/**
|
|
404
|
+
* STARTS A TURN FROM A SENDER THAT IS NOT THE READER.
|
|
405
|
+
*
|
|
406
|
+
* `enqueueAndRun` below is the person's path: it writes the words under the reader's own name, in
|
|
407
|
+
* the reader's bubble, so the reader can see that they said it. The orchestrator's path is the
|
|
408
|
+
* same machinery with a different speaker - a primary agent handing a task to a child session -
|
|
409
|
+
* and writing THAT under the reader's name was the bug the reader reported: the child's
|
|
410
|
+
* transcript showed an instruction they never typed, wearing their avatar.
|
|
411
|
+
*
|
|
412
|
+
* So the write goes through `addAgentMessage` instead, which records the words as the system's,
|
|
413
|
+
* and the turn runs on them exactly as before. `composePrompt` is what tells the model who is
|
|
414
|
+
* speaking, so the model is addressed in the same words.
|
|
415
|
+
*/
|
|
416
|
+
enqueueAndRunAsAgent(conversationId: string, content: string): Promise<void>;
|
|
387
417
|
enqueueAndRun(conversationId: string, content: string, images?: MessageImage[], attachments?: import("../types.js").MessageAttachments, clientId?: string): Promise<void>;
|
|
388
418
|
/**
|
|
389
419
|
* Steers a queued message into the in-flight turn.
|