opencode-gateway 0.3.1 → 0.3.2

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.
@@ -7,11 +7,15 @@ export type TextDeliverySession = {
7
7
  preview(text: string): Promise<void>;
8
8
  finish(finalText: string | null): Promise<boolean>;
9
9
  };
10
+ export type TextDeliveryOptions = {
11
+ progressiveRefreshIntervalMs?: number;
12
+ };
10
13
  export declare class GatewayTextDelivery {
11
14
  private readonly transport;
12
15
  private readonly store;
13
16
  private readonly telegramSupport;
14
- constructor(transport: GatewayTransportHost, store: SqliteStore, telegramSupport: TelegramProgressiveSupport);
17
+ private readonly options;
18
+ constructor(transport: GatewayTransportHost, store: SqliteStore, telegramSupport: TelegramProgressiveSupport, options?: TextDeliveryOptions);
15
19
  open(target: BindingDeliveryTarget, preference: DeliveryModePreference): Promise<TextDeliverySession>;
16
20
  openMany(targets: BindingDeliveryTarget[], preference: DeliveryModePreference): Promise<TextDeliverySession[]>;
17
21
  sendTest(target: BindingDeliveryTarget, text: string, preference: DeliveryModePreference): Promise<{
package/dist/index.js CHANGED
@@ -17219,14 +17219,18 @@ function createDraftId() {
17219
17219
  }
17220
17220
 
17221
17221
  // src/delivery/text.ts
17222
+ var DEFAULT_PROGRESSIVE_REFRESH_INTERVAL_MS = 3000;
17223
+
17222
17224
  class GatewayTextDelivery {
17223
17225
  transport;
17224
17226
  store;
17225
17227
  telegramSupport;
17226
- constructor(transport, store, telegramSupport) {
17228
+ options;
17229
+ constructor(transport, store, telegramSupport, options = {}) {
17227
17230
  this.transport = transport;
17228
17231
  this.store = store;
17229
17232
  this.telegramSupport = telegramSupport;
17233
+ this.options = options;
17230
17234
  }
17231
17235
  async open(target, preference) {
17232
17236
  const [session] = await this.openMany([target], preference);
@@ -17240,7 +17244,7 @@ class GatewayTextDelivery {
17240
17244
  const sessions = await Promise.all(uniqueTargets.map(async (target) => {
17241
17245
  const mode = await this.telegramSupport.resolveMode(target, preference);
17242
17246
  if (mode === "progressive") {
17243
- const session = new ProgressiveTextDeliverySession(target, this.transport, this.telegramSupport, this.store);
17247
+ const session = new ProgressiveTextDeliverySession(target, this.transport, this.telegramSupport, this.store, this.options.progressiveRefreshIntervalMs ?? DEFAULT_PROGRESSIVE_REFRESH_INTERVAL_MS);
17244
17248
  session.start();
17245
17249
  return session;
17246
17250
  }
@@ -17320,37 +17324,86 @@ class ProgressiveTextDeliverySession {
17320
17324
  transport;
17321
17325
  telegramSupport;
17322
17326
  store;
17327
+ refreshIntervalMs;
17323
17328
  mode = "progressive";
17324
17329
  previewFailed = false;
17325
17330
  previewDelivered = false;
17326
- closed = false;
17331
+ acceptingPreviews = true;
17332
+ finished = false;
17333
+ latestPreviewText = null;
17327
17334
  pendingPreviewCount = 0;
17328
17335
  pendingPreview = Promise.resolve();
17336
+ keepaliveTimer = null;
17329
17337
  draftId = createDraftId();
17330
- constructor(target, transport, telegramSupport, store) {
17338
+ constructor(target, transport, telegramSupport, store, refreshIntervalMs) {
17331
17339
  this.target = target;
17332
17340
  this.transport = transport;
17333
17341
  this.telegramSupport = telegramSupport;
17334
17342
  this.store = store;
17343
+ this.refreshIntervalMs = refreshIntervalMs;
17335
17344
  }
17336
17345
  start() {
17337
17346
  this.telegramSupport.startTyping(this.target);
17338
17347
  }
17339
17348
  async preview(text) {
17340
- if (this.previewFailed || this.closed || text.trim().length === 0) {
17349
+ if (this.previewFailed || !this.acceptingPreviews || this.finished || text.trim().length === 0) {
17341
17350
  return;
17342
17351
  }
17352
+ this.latestPreviewText = text;
17353
+ await this.enqueueDraftSend(() => this.latestPreviewText, true);
17354
+ if (!this.previewFailed && this.previewDelivered) {
17355
+ this.ensureKeepalive();
17356
+ }
17357
+ }
17358
+ async finish(finalText) {
17359
+ this.acceptingPreviews = false;
17360
+ this.stopKeepalive();
17361
+ await this.awaitPendingPreview();
17362
+ const normalizedFinalText = finalText?.trim() ?? "";
17363
+ if (normalizedFinalText.length === 0) {
17364
+ this.finished = true;
17365
+ return false;
17366
+ }
17367
+ if (!this.previewDelivered && !this.previewFailed) {
17368
+ recordTelegramStreamFallback(this.store, "preview_not_established", Date.now());
17369
+ }
17370
+ if (this.previewDelivered && !this.previewFailed && this.latestPreviewText !== normalizedFinalText) {
17371
+ this.latestPreviewText = normalizedFinalText;
17372
+ await this.enqueueDraftSend(() => this.latestPreviewText, false);
17373
+ }
17374
+ try {
17375
+ const ack = await this.transport.sendMessage({
17376
+ deliveryTarget: this.target,
17377
+ body: normalizedFinalText
17378
+ });
17379
+ if (ack.errorMessage !== null) {
17380
+ throw new Error(ack.errorMessage);
17381
+ }
17382
+ return true;
17383
+ } finally {
17384
+ this.finished = true;
17385
+ this.stopKeepalive();
17386
+ }
17387
+ }
17388
+ async enqueueDraftSend(getText, recordEmit) {
17343
17389
  const runPreview = async () => {
17344
17390
  try {
17345
- if (this.previewFailed || this.closed) {
17391
+ if (this.finished || this.previewFailed) {
17392
+ return;
17393
+ }
17394
+ const text = getText();
17395
+ if (text === null || text.trim().length === 0) {
17346
17396
  return;
17347
17397
  }
17348
17398
  try {
17349
- recordTelegramPreviewEmit(this.store, Date.now());
17399
+ if (recordEmit) {
17400
+ recordTelegramPreviewEmit(this.store, Date.now());
17401
+ }
17350
17402
  await this.telegramSupport.sendDraft(this.target, this.draftId, text);
17351
17403
  this.previewDelivered = true;
17352
17404
  } catch {
17353
17405
  this.previewFailed = true;
17406
+ this.stopKeepalive();
17354
17407
  }
17355
17408
  } finally {
17356
17409
  this.pendingPreviewCount = Math.max(0, this.pendingPreviewCount - 1);
@@ -17360,25 +17413,37 @@ class ProgressiveTextDeliverySession {
17360
17413
  this.pendingPreview = this.pendingPreview.then(runPreview, runPreview);
17361
17414
  await this.pendingPreview;
17362
17415
  }
17363
- async finish(finalText) {
17364
- this.closed = true;
17416
+ async awaitPendingPreview() {
17365
17417
  if (this.pendingPreviewCount > 0) {
17366
17418
  await this.pendingPreview;
17367
17419
  }
17368
- if (finalText === null || finalText.trim().length === 0) {
17369
- return false;
17370
- }
17371
- if (!this.previewDelivered && !this.previewFailed) {
17372
- recordTelegramStreamFallback(this.store, "preview_not_established", Date.now());
17420
+ }
17421
+ ensureKeepalive() {
17422
+ if (!this.shouldKeepalive() || this.keepaliveTimer !== null) {
17423
+ return;
17373
17424
  }
17374
- const ack = await this.transport.sendMessage({
17375
- deliveryTarget: this.target,
17376
- body: finalText
17377
- });
17378
- if (ack.errorMessage !== null) {
17379
- throw new Error(ack.errorMessage);
17425
+ this.keepaliveTimer = setTimeout(() => {
17426
+ this.keepaliveTimer = null;
17427
+ if (!this.shouldKeepalive()) {
17428
+ return;
17429
+ }
17430
+ this.telegramSupport.startTyping(this.target);
17431
+ this.enqueueDraftSend(() => this.latestPreviewText, false).finally(() => {
17432
+ if (this.shouldKeepalive()) {
17433
+ this.ensureKeepalive();
17434
+ }
17435
+ });
17436
+ }, this.refreshIntervalMs);
17437
+ }
17438
+ stopKeepalive() {
17439
+ if (this.keepaliveTimer === null) {
17440
+ return;
17380
17441
  }
17381
- return true;
17442
+ clearTimeout(this.keepaliveTimer);
17443
+ this.keepaliveTimer = null;
17444
+ }
17445
+ shouldKeepalive() {
17446
+ return this.acceptingPreviews && !this.finished && !this.previewFailed && this.previewDelivered && this.latestPreviewText !== null;
17382
17447
  }
17383
17448
  }
17384
17449
  function dedupeTargets(targets) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-gateway",
3
- "version": "0.3.1",
3
+ "version": "0.3.2",
4
4
  "description": "Gateway plugin for OpenCode",
5
5
  "license": "MIT",
6
6
  "type": "module",