opencode-tbot 0.1.6 → 0.1.7

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/dist/plugin.js CHANGED
@@ -216,13 +216,15 @@ function buildOpenCodeSdkConfig(options) {
216
216
  var EMPTY_RESPONSE_TEXT = "OpenCode returned empty response.";
217
217
  var PROMPT_MESSAGE_POLL_DELAYS_MS = [
218
218
  0,
219
- 150,
220
- 300,
221
- 600,
222
- 1200,
219
+ 100,
220
+ 250,
221
+ 500,
222
+ 1e3,
223
223
  2e3,
224
- 3200
224
+ 4e3,
225
+ 8e3
225
226
  ];
227
+ var PROMPT_MESSAGE_POLL_LIMIT = 20;
226
228
  var STRUCTURED_REPLY_SCHEMA = {
227
229
  type: "json_schema",
228
230
  retryCount: 2,
@@ -336,6 +338,7 @@ var OpenCodeClient = class {
336
338
  url: file.url
337
339
  }))];
338
340
  if (parts.length === 0) throw new Error("Prompt requires text or file attachments.");
341
+ const knownMessageIds = await this.captureKnownMessageIds(input.sessionId);
339
342
  const initialData = unwrapSdkData(await this.client.session.prompt({
340
343
  sessionID: input.sessionId,
341
344
  ...input.agent ? { agent: input.agent } : {},
@@ -344,25 +347,51 @@ var OpenCodeClient = class {
344
347
  ...input.variant ? { variant: input.variant } : {},
345
348
  parts
346
349
  }, SDK_OPTIONS));
347
- return buildPromptSessionResult(await this.resolvePromptResponse(input, initialData), {
350
+ return buildPromptSessionResult(await this.resolvePromptResponse(input, initialData, knownMessageIds), {
348
351
  emptyResponseText: EMPTY_RESPONSE_TEXT,
349
352
  finishedAt: Date.now(),
350
353
  startedAt,
351
354
  structured: input.structured ?? false
352
355
  });
353
356
  }
354
- async resolvePromptResponse(input, data) {
357
+ async resolvePromptResponse(input, data, knownMessageIds) {
355
358
  if (!shouldPollPromptMessage(data, input.structured ?? false)) return data;
356
359
  const messageId = data.info?.id;
357
- if (!messageId) return data;
360
+ let bestCandidate = data;
361
+ if (!messageId) return await this.findLatestPromptResponse(input.sessionId, {
362
+ initialMessageId: null,
363
+ knownMessageIds,
364
+ structured: input.structured ?? false
365
+ }) ?? data;
358
366
  for (const delayMs of PROMPT_MESSAGE_POLL_DELAYS_MS) {
359
367
  if (delayMs > 0) await delay(delayMs);
360
368
  const next = await this.fetchPromptMessage(input.sessionId, messageId);
361
- if (!next) continue;
369
+ if (!next) {
370
+ const latest = await this.findLatestPromptResponse(input.sessionId, {
371
+ initialMessageId: messageId,
372
+ knownMessageIds,
373
+ structured: input.structured ?? false
374
+ });
375
+ if (latest) {
376
+ bestCandidate = latest;
377
+ if (!shouldPollPromptMessage(bestCandidate, input.structured ?? false)) return bestCandidate;
378
+ }
379
+ continue;
380
+ }
362
381
  data = next;
382
+ bestCandidate = next;
363
383
  if (!shouldPollPromptMessage(data, input.structured ?? false)) return data;
384
+ const latest = await this.findLatestPromptResponse(input.sessionId, {
385
+ initialMessageId: messageId,
386
+ knownMessageIds,
387
+ structured: input.structured ?? false
388
+ });
389
+ if (latest) {
390
+ bestCandidate = latest;
391
+ if (!shouldPollPromptMessage(bestCandidate, input.structured ?? false)) return bestCandidate;
392
+ }
364
393
  }
365
- return data;
394
+ return bestCandidate;
366
395
  }
367
396
  async fetchPromptMessage(sessionId, messageId) {
368
397
  if (typeof this.client.session.message !== "function") return null;
@@ -375,6 +404,40 @@ var OpenCodeClient = class {
375
404
  return null;
376
405
  }
377
406
  }
407
+ async captureKnownMessageIds(sessionId) {
408
+ const messages = await this.fetchRecentPromptMessages(sessionId);
409
+ if (!messages) return /* @__PURE__ */ new Set();
410
+ return new Set(messages.map((message) => message.info?.id).filter((id) => typeof id === "string" && id.length > 0));
411
+ }
412
+ async fetchRecentPromptMessages(sessionId) {
413
+ if (typeof this.client.session.messages !== "function") return null;
414
+ try {
415
+ const data = unwrapSdkData(await this.client.session.messages({
416
+ sessionID: sessionId,
417
+ limit: PROMPT_MESSAGE_POLL_LIMIT
418
+ }, SDK_OPTIONS));
419
+ return Array.isArray(data) ? data : null;
420
+ } catch {
421
+ return null;
422
+ }
423
+ }
424
+ async findLatestPromptResponse(sessionId, options) {
425
+ const messages = await this.fetchRecentPromptMessages(sessionId);
426
+ if (!messages || messages.length === 0) return null;
427
+ const candidates = messages.filter((message) => toAssistantMessage(message.info) !== null).map((message) => {
428
+ const assistant = toAssistantMessage(message.info);
429
+ const id = assistant?.id ?? null;
430
+ return {
431
+ createdAt: typeof assistant?.time?.created === "number" && Number.isFinite(assistant.time.created) ? assistant.time.created : 0,
432
+ id,
433
+ isInitial: !!id && id === options.initialMessageId,
434
+ isNew: !!id && !options.knownMessageIds.has(id),
435
+ isUsable: !shouldPollPromptMessage(message, options.structured),
436
+ message
437
+ };
438
+ }).sort((left, right) => Number(right.isUsable) - Number(left.isUsable) || Number(right.isNew) - Number(left.isNew) || Number(right.isInitial) - Number(left.isInitial) || right.createdAt - left.createdAt);
439
+ return (candidates.find((candidate) => candidate.isUsable && (candidate.isNew || candidate.isInitial)) ?? candidates.find((candidate) => candidate.isNew || candidate.isInitial) ?? null)?.message ?? null;
440
+ }
378
441
  async loadModels() {
379
442
  const [configResponse, providersResponse] = await Promise.all([this.client.config.get(void 0, SDK_OPTIONS), this.client.config.providers(void 0, SDK_OPTIONS)]);
380
443
  const config = unwrapSdkData(configResponse);