switchroom 0.13.0 → 0.13.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.
@@ -47248,8 +47248,8 @@ var {
47248
47248
  } = import__.default;
47249
47249
 
47250
47250
  // src/build-info.ts
47251
- var VERSION = "0.13.0";
47252
- var COMMIT_SHA = "9b3d62f2";
47251
+ var VERSION = "0.13.2";
47252
+ var COMMIT_SHA = "afa0fbea";
47253
47253
 
47254
47254
  // src/cli/agent.ts
47255
47255
  init_source();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "switchroom",
3
- "version": "0.13.0",
3
+ "version": "0.13.2",
4
4
  "description": "Run Claude Code 24/7 on your Claude Pro/Max subscription over Telegram. Open-source alternative to OpenClaw and NanoClaw — no API keys.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -31221,6 +31221,7 @@ function createDraftStream(send, edit, config = {}) {
31221
31221
  draftId = allocateDraftId();
31222
31222
  currentChunkStartedAt = null;
31223
31223
  persistChainFires++;
31224
+ sendFires++;
31224
31225
  if (process.env.SWITCHROOM_STREAM_TRACES !== "0") {
31225
31226
  process.stderr.write(`gw-trace stream-persist chunk_chars=${chunk.length} ` + `elapsed=${elapsed} reason=${timeElapsed ? "time" : "size"} ` + `newMsgId=${newMsgId} newDraftId=${draftId} ` + `chatId=${chatId || "-"}
31226
31227
  `);
@@ -31367,6 +31368,7 @@ function createDraftStream(send, edit, config = {}) {
31367
31368
  try {
31368
31369
  messageId = await send(textToMaterialize);
31369
31370
  persistedTextLen = fullText.length;
31371
+ sendFires++;
31370
31372
  log?.(`stream \u2192 materialized tail (id: ${messageId}, ${textToMaterialize.length} chars)`);
31371
31373
  } catch (err) {
31372
31374
  warn?.(`draft-stream: materialize sendMessage failed: ${err instanceof Error ? err.message : String(err)}`);
@@ -47677,10 +47679,10 @@ function sweepStaleTurnActiveMarker(stateDir, opts) {
47677
47679
  }
47678
47680
 
47679
47681
  // ../src/build-info.ts
47680
- var VERSION = "0.13.0";
47681
- var COMMIT_SHA = "9b3d62f2";
47682
- var COMMIT_DATE = "2026-05-20T22:23:43Z";
47683
- var LATEST_PR = 1600;
47682
+ var VERSION = "0.13.2";
47683
+ var COMMIT_SHA = "afa0fbea";
47684
+ var COMMIT_DATE = "2026-05-21T00:58:22Z";
47685
+ var LATEST_PR = 1610;
47684
47686
  var COMMITS_AHEAD_OF_TAG = 0;
47685
47687
 
47686
47688
  // gateway/boot-version.ts
@@ -461,6 +461,12 @@ export function createDraftStream(
461
461
  draftId = allocateDraftId()
462
462
  currentChunkStartedAt = null
463
463
  persistChainFires++
464
+ // PR follow-up: persist-chain's bare send() bypasses
465
+ // sendViaMessage's increment, same shape as the finalize-
466
+ // materialize bug. Without this, streams that cross the
467
+ // 25s / 4000-char boundary would under-report `sends` by
468
+ // the chain count in stream-end.
469
+ sendFires++
464
470
  if (process.env.SWITCHROOM_STREAM_TRACES !== '0') {
465
471
  process.stderr.write(
466
472
  `gw-trace stream-persist chunk_chars=${chunk.length} ` +
@@ -664,6 +670,13 @@ export function createDraftStream(
664
670
  try {
665
671
  messageId = await send(textToMaterialize)
666
672
  persistedTextLen = fullText.length
673
+ // PR follow-up: bump sendFires so the stream-end trace
674
+ // reflects the finalize-materialize sendMessage call. Pre-
675
+ // this fix, the counter under-reported by 1 for every
676
+ // draft-transport stream that produced a non-empty reply:
677
+ // gw-trace stream-end showed `drafts=N sends=0` even
678
+ // though sendMessage HAD fired (visible in tg-post lines).
679
+ sendFires++
667
680
  log?.(`stream → materialized tail (id: ${messageId}, ${textToMaterialize.length} chars)`)
668
681
  } catch (err) {
669
682
  warn?.(`draft-stream: materialize sendMessage failed: ${err instanceof Error ? err.message : String(err)}`)
@@ -1202,4 +1202,83 @@ describe('createDraftStream — draft transport', () => {
1202
1202
  })
1203
1203
  })
1204
1204
 
1205
+ // ─── Follow-up: stream-end `sends` counter includes finalize-materialize ───
1206
+ describe('finalize-materialize bumps sends counter', () => {
1207
+ let captured: string[] = []
1208
+ let originalWrite: typeof process.stderr.write
1209
+
1210
+ beforeEach(() => {
1211
+ captured = []
1212
+ originalWrite = process.stderr.write
1213
+ process.stderr.write = ((chunk: string | Uint8Array) => {
1214
+ const text = typeof chunk === 'string' ? chunk : Buffer.from(chunk).toString('utf8')
1215
+ captured.push(text)
1216
+ return true
1217
+ }) as typeof process.stderr.write
1218
+ })
1219
+ afterEach(() => {
1220
+ process.stderr.write = originalWrite
1221
+ })
1222
+
1223
+ it('draft-transport stream that materializes on finalize shows sends>=1', async () => {
1224
+ // Pre-fix this showed sends=0 even though sendMessage fired
1225
+ // inside finalize. Bug was visible in production v0.13.0 traces.
1226
+ const m = makeMock()
1227
+ const sendMessageDraft = vi.fn(async () => {})
1228
+ const stream = createDraftStream(m.send, m.edit, {
1229
+ throttleMs: 50,
1230
+ previewTransport: 'draft',
1231
+ sendMessageDraft,
1232
+ chatId: 'chat-x',
1233
+ })
1234
+ void stream.update('Hello world')
1235
+ await microtaskFlush()
1236
+ vi.advanceTimersByTime(100)
1237
+ await microtaskFlush()
1238
+ await stream.finalize()
1239
+ // Real send() called inside finalize.
1240
+ expect(m.sendCalls.length).toBe(1)
1241
+ const endLine = captured.find((c) => c.includes('gw-trace stream-end'))
1242
+ expect(endLine).toBeDefined()
1243
+ // Counter now reflects reality.
1244
+ expect(endLine).toMatch(/sends=[1-9]/)
1245
+ })
1246
+
1247
+ it('persist-chain bump counts toward sends (size-trigger fires + finalize)', async () => {
1248
+ // The sibling bug at the persist-chain callsite — its bare
1249
+ // send(chunk) also bypasses sendViaMessage. Without the fix
1250
+ // a stream that crosses the size boundary would show sends=1
1251
+ // (only the finalize materialize), missing the chain fire.
1252
+ // With the fix sends counts BOTH the persist send AND the
1253
+ // finalize materialize → sends>=2.
1254
+ const m = makeMock()
1255
+ const sendMessageDraft = vi.fn(async () => {})
1256
+ const stream = createDraftStream(m.send, m.edit, {
1257
+ throttleMs: 50,
1258
+ previewTransport: 'draft',
1259
+ sendMessageDraft,
1260
+ chatId: 'chat-chain',
1261
+ persistSizeLimit: 200,
1262
+ })
1263
+ void stream.update('a'.repeat(100))
1264
+ await microtaskFlush()
1265
+ vi.advanceTimersByTime(300)
1266
+ void stream.update('a'.repeat(250)) // size trigger fires (tail=250 ≥ 200)
1267
+ await microtaskFlush()
1268
+ vi.advanceTimersByTime(300)
1269
+ await microtaskFlush()
1270
+ // Extra text after persist so finalize-materialize tail is non-empty.
1271
+ void stream.update('a'.repeat(250) + 'b'.repeat(50))
1272
+ await microtaskFlush()
1273
+ vi.advanceTimersByTime(300)
1274
+ await microtaskFlush()
1275
+ await stream.finalize()
1276
+ const endLine = captured.find((c) => c.includes('gw-trace stream-end'))
1277
+ expect(endLine).toBeDefined()
1278
+ // Persist send + finalize materialize = at least 2.
1279
+ expect(endLine).toMatch(/sends=[2-9]/)
1280
+ expect(endLine).toMatch(/persists=[1-9]/)
1281
+ })
1282
+ })
1283
+
1205
1284
  })