MCPcopy
hub / github.com/coder/mux / commitPartial

Method commitPartial

src/node/services/historyService.ts:1259–1373  ·  view source on GitHub ↗

* Commit any existing partial message to chat history and delete partial.json. * * This is idempotent: * - If the partial has already been finalized in history, it is not committed again. * - After committing (or if already finalized), partial.json is deleted.

(workspaceId: string)

Source from the content-addressed store, hash-verified

1257 * - After committing (or if already finalized), partial.json is deleted.
1258 */
1259 async commitPartial(workspaceId: string): Promise<Result<void>> {
1260 try {
1261 let partial = await this.readPartial(workspaceId);
1262 if (!partial) {
1263 return Ok(undefined);
1264 }
1265
1266 const hadErrorMetadata = partial.metadata?.error != null;
1267
1268 // Strip transient error metadata, but persist accumulated content.
1269 if (partial.metadata?.error) {
1270 const { error, errorType, ...cleanMetadata } = partial.metadata;
1271 partial = { ...partial, metadata: cleanMetadata };
1272 }
1273
1274 const partialSeq = partial.metadata?.historySequence;
1275 if (partialSeq === undefined) {
1276 return Err("Partial message has no historySequence");
1277 }
1278
1279 const historyResult = await this.getHistoryFromLatestBoundary(workspaceId);
1280 if (!historyResult.success) {
1281 return Err(`Failed to read history: ${historyResult.error}`);
1282 }
1283
1284 const existingMessages = historyResult.data;
1285 const maxExistingSequence = this.getNewestHistorySequence(existingMessages);
1286
1287 const hasCommitWorthyParts = (partial.parts ?? []).some((part) => {
1288 if (part.type === "text" || part.type === "reasoning") {
1289 return part.text.trim().length > 0;
1290 }
1291
1292 if (part.type === "file") {
1293 return true;
1294 }
1295
1296 if (part.type === "dynamic-tool") {
1297 // Incomplete tool calls (input-available) are dropped during provider request
1298 // conversion. Persisting tool-only incomplete partials can brick future requests.
1299 return part.state === "output-available";
1300 }
1301
1302 return false;
1303 });
1304
1305 // Refusal errors can be durable even with zero assistant-visible parts:
1306 // finishReason lets the UI show a refusal row after error/errorType are
1307 // stripped on commit, and usage/toolModelUsages may be absent if the
1308 // provider omitted usage or metadata reads timed out.
1309 const hasDurableRefusalMetadata =
1310 hadErrorMetadata && isRefusalFinishReason(partial.metadata?.finishReason);
1311
1312 const existingMessage = existingMessages.find(
1313 (message) => message.metadata?.historySequence === partialSeq
1314 );
1315
1316 if (

Callers 9

finalizeChildReportFunction · 0.80
streamWithHistoryMethod · 0.80
streamMessageMethod · 0.80

Calls 11

readPartialMethod · 0.95
deletePartialMethod · 0.95
updateHistoryMethod · 0.95
appendToHistoryMethod · 0.95
deleteMessageMethod · 0.95
OkFunction · 0.90
ErrFunction · 0.90
isRefusalFinishReasonFunction · 0.90
getErrorMessageFunction · 0.90

Tested by 2

finalizeChildReportFunction · 0.64