MCPcopy
hub / github.com/OpenCoworkAI/open-codesign / registerGenerateIpc

Function registerGenerateIpc

apps/desktop/src/main/ipc/generate.ts:314–1521  ·  view source on GitHub ↗
({ db, getMainWindow }: RegisterGenerateIpcDeps)

Source from the content-addressed store, hash-verified

312 * aborts every in-flight generation — call from the app `before-quit` hook.
313 */
314export function registerGenerateIpc({ db, getMainWindow }: RegisterGenerateIpcDeps): () => void {
315 const logIpc = getLogger('main:ipc');
316
317 // Cache of the last NormalizedProviderError seen per run, so recordFinalError
318 // can attach it to the final (non-transient) row. Without this, the row the
319 // user actually reports lacks upstream_request_id / status — those fields
320 // lived only on the hidden transient sibling row emitted by retry.ts.
321 // Implementation + LRU eviction lives in ../provider-context.ts.
322 const providerContext = createProviderContextStore(50);
323
324 const recordFinalError = (scope: string, runId: string, err: unknown): void => {
325 if (db === null) return;
326 const code = err instanceof CodesignError ? (err.code as string) : 'PROVIDER_UPSTREAM_ERROR';
327 const stack = err instanceof Error ? err.stack : undefined;
328 const message = err instanceof Error ? err.message : String(err);
329 const context = providerContext.consume(runId);
330 recordDiagnosticEvent(db, {
331 level: 'error',
332 code,
333 scope,
334 runId,
335 fingerprint: computeFingerprint({ errorCode: code, stack, message }),
336 message,
337 stack,
338 transient: false,
339 ...(context !== undefined ? { context } : {}),
340 });
341 };
342
343 /** Adapter so `core` can log step events through the same scoped electron-log
344 * sink the IPC handler uses. Keeps a single timeline per generation in the
345 * log file without forcing `core` to depend on electron-log.
346 *
347 * Only `provider.error` (retry in flight, transient=true) is persisted from
348 * this adapter; the `provider.error.final` event is NOT recorded because the
349 * outer handler's catch block calls `recordFinalError` — recording both
350 * would double-count the same failure with two distinct fingerprints. */
351 const coreLoggerFor = (id: string): CoreLogger => ({
352 info: (event, data) => logIpc.info(event, { generationId: id, ...(data ?? {}) }),
353 warn: (event, data) => {
354 logIpc.warn(event, { generationId: id, ...(data ?? {}) });
355 if (event === 'provider.error' && db !== null) {
356 const code = 'PROVIDER_UPSTREAM_ERROR';
357 const upstream =
358 data !== undefined && typeof data['upstream_message'] === 'string'
359 ? (data['upstream_message'] as string)
360 : event;
361 // Fingerprint basis: errorCode + synthetic frame containing the two
362 // fields that truly differentiate provider errors — upstream_status
363 // and upstream_code. JSON-stringifying `data` and passing it as
364 // `stack` would produce an identical 8-hex for every provider error
365 // because `extractTopFrames` requires lines starting with "at ".
366 const status =
367 typeof data?.['upstream_status'] === 'number' ? data['upstream_status'] : '?';
368 const upstreamCode =
369 typeof data?.['upstream_code'] === 'string' ? data['upstream_code'] : 'unknown';
370 const syntheticFrame = ` at provider (${status}:${upstreamCode})`;
371 if (data !== undefined) providerContext.remember(id, data);

Callers 2

registerIpcHandlersFunction · 0.90

Calls 15

getLoggerFunction · 0.90
detectProviderFromKeyFunction · 0.90
makeRuntimeVerifierFunction · 0.90
withRunFunction · 0.90
resolveActiveModelFunction · 0.90
withStableWorkspacePathFunction · 0.90
preparePromptContextFunction · 0.90
loadMemoryContextFunction · 0.90
getDesignFunction · 0.90

Tested by

no test coverage detected