MCPcopy Create free account
hub / github.com/dwgx/WindsurfAPI / rawGetChatMessage

Method rawGetChatMessage

src/client.js:434–501  ·  view source on GitHub ↗

* Stream chat via RawGetChatMessage. * Used for models without a string UID (enum < 280 generally). * * @param {Array} messages - OpenAI-format messages * @param {number} modelEnum - Model enum value * @param {string} [modelName] - Optional model name * @param {object} opts - { onC

(messages, modelEnum, modelName, opts = {})

Source from the content-addressed store, hash-verified

432 * @param {object} opts - { onChunk, onEnd, onError }
433 */
434 rawGetChatMessage(messages, modelEnum, modelName, opts = {}) {
435 acquireLsUseOrThrow(this.port);
436 try {
437 const { onChunk, onEnd, onError } = opts;
438 // Reuse the LS-scoped session_id instead of letting buildMetadata
439 // mint a fresh UUID on every call. A stable session per LS matches
440 // what a real Windsurf IDE instance sends (one session for the whole
441 // window's lifetime) and gives upstream fingerprinting less to latch
442 // onto. Cascade path already does this via lsEntry.sessionId; this
443 // closes the same gap for the legacy channel.
444 const lsEntry = getLsEntryByPort(this.port);
445 if (lsEntry && !lsEntry.sessionId) lsEntry.sessionId = randomUUID();
446 const sessionId = lsEntry?.sessionId;
447 const proto = buildRawGetChatMessageRequest(this.apiKey, messages, modelEnum, modelName, sessionId);
448 const body = grpcFrame(proto);
449
450 log.debug(`RawGetChatMessage: enum=${modelEnum} msgs=${messages.length}`);
451
452 return new Promise((resolve, reject) => {
453 const chunks = [];
454 // Once the promise has settled, ignore any further stream events. The
455 // LS occasionally emits an error frame followed by a trailing onEnd;
456 // without this guard the second callback re-resolves/re-rejects.
457 let done = false;
458
459 grpcStream(this.port, this.csrfToken, `${LS_SERVICE}/RawGetChatMessage`, body, {
460 onData: (payload) => {
461 if (done) return;
462 try {
463 const parsed = parseRawResponse(payload);
464 if (parsed.text) {
465 // Detect server-side errors returned as text
466 const errMatch = /^(permission_denied|failed_precondition|not_found|unauthenticated):/.test(parsed.text.trim());
467 if (parsed.isError || errMatch) {
468 const err = new Error(parsed.text.trim());
469 // Mark model-level errors so they don't count against the account
470 err.isModelError = /permission_denied|failed_precondition/.test(parsed.text);
471 if (err.isModelError) err.kind = 'model_error';
472 done = true;
473 reject(err);
474 return;
475 }
476 chunks.push(parsed);
477 onChunk?.(parsed);
478 }
479 } catch (e) {
480 log.error('RawGetChatMessage parse error:', e.message);
481 }
482 },
483 onEnd: () => {
484 if (done) return;
485 done = true;
486 onEnd?.(chunks);
487 resolve(chunks);
488 },
489 onError: (err) => {
490 if (done) return;
491 done = true;

Callers 3

_probeAccountImplFunction · 0.95
nonStreamResponseFunction · 0.45
handlerFunction · 0.45

Calls 12

getLsEntryByPortFunction · 0.90
grpcFrameFunction · 0.90
grpcStreamFunction · 0.90
parseRawResponseFunction · 0.90
endLsUseFunction · 0.90
acquireLsUseOrThrowFunction · 0.85
onChunkFunction · 0.85
onEndFunction · 0.85
pushMethod · 0.80
onErrorFunction · 0.70
errorMethod · 0.45

Tested by

no test coverage detected