claude-threads 1.33.1 → 1.34.0

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.
@@ -14699,12 +14699,12 @@ var init_spawn = __esm(() => {
14699
14699
  });
14700
14700
 
14701
14701
  // src/claude/quick-query.ts
14702
- var log15;
14702
+ var log16;
14703
14703
  var init_quick_query = __esm(() => {
14704
14704
  init_spawn();
14705
14705
  init_version_check();
14706
14706
  init_logger();
14707
- log15 = createLogger("query");
14707
+ log16 = createLogger("query");
14708
14708
  });
14709
14709
 
14710
14710
  // node_modules/ws/lib/constants.js
@@ -52194,6 +52194,13 @@ function createMessageManagerEvents() {
52194
52194
  return new TypedEventEmitter;
52195
52195
  }
52196
52196
 
52197
+ // src/transcription/elevenlabs.ts
52198
+ init_logger();
52199
+ var log3 = createLogger("transcribe");
52200
+
52201
+ // src/transcription/types.ts
52202
+ var AUDIO_EXTENSIONS = new Set(["m4a", "mp3", "ogg", "opus", "wav", "aac", "flac", "webm"]);
52203
+ var GENERIC_MIME_TYPES = new Set(["", "application/octet-stream", "binary/octet-stream"]);
52197
52204
  // src/operations/streaming/handler.ts
52198
52205
  init_logger();
52199
52206
 
@@ -52218,7 +52225,19 @@ function formatBytes(bytes) {
52218
52225
  }
52219
52226
 
52220
52227
  // src/operations/streaming/handler.ts
52221
- var log3 = createLogger("streaming");
52228
+ var log4 = createLogger("streaming");
52229
+ async function postTranscriptFeedback(platform, threadId, transcripts) {
52230
+ if (!transcripts || transcripts.length === 0)
52231
+ return;
52232
+ const formatter = platform.getFormatter();
52233
+ for (const t of transcripts) {
52234
+ const quoted = t.text.split(`
52235
+ `).map((line) => formatter.formatBlockquote(line)).join(`
52236
+ `);
52237
+ await platform.createPost(`\uD83C\uDF99️ ${formatter.formatBold(`Transcript of ${t.name}:`)}
52238
+ ${quoted}`, threadId);
52239
+ }
52240
+ }
52222
52241
  async function postSkippedFilesFeedback(platform, threadId, skipped) {
52223
52242
  if (skipped.length === 0)
52224
52243
  return;
@@ -52286,7 +52305,7 @@ function formatRelativeTime(date8) {
52286
52305
  return `${diffMin} min ago`;
52287
52306
  }
52288
52307
  // src/operations/message-manager.ts
52289
- var log4 = createLogger("msg-mgr");
52308
+ var log5 = createLogger("msg-mgr");
52290
52309
 
52291
52310
  class MessageManager {
52292
52311
  platform;
@@ -52379,7 +52398,7 @@ class MessageManager {
52379
52398
  });
52380
52399
  }
52381
52400
  async handleEvent(event) {
52382
- const logger = log4.forSession(this.sessionId);
52401
+ const logger = log5.forSession(this.sessionId);
52383
52402
  const transformCtx = {
52384
52403
  sessionId: this.sessionId,
52385
52404
  formatter: this.platform.getFormatter(),
@@ -52433,7 +52452,7 @@ class MessageManager {
52433
52452
  }
52434
52453
  }
52435
52454
  async executeOperation(op) {
52436
- const logger = log4.forSession(this.sessionId);
52455
+ const logger = log5.forSession(this.sessionId);
52437
52456
  const ctx = this.getExecutorContext();
52438
52457
  try {
52439
52458
  if (isContentOp(op)) {
@@ -52501,7 +52520,7 @@ class MessageManager {
52501
52520
  threadId: this.threadId,
52502
52521
  platform: this.platform,
52503
52522
  formatter: this.platform.getFormatter(),
52504
- logger: log4.forSession(this.sessionId),
52523
+ logger: log5.forSession(this.sessionId),
52505
52524
  postTracker: this.postTracker,
52506
52525
  contentBreaker: this.contentBreaker,
52507
52526
  threadLogger: this.session.threadLogger,
@@ -52730,13 +52749,13 @@ class MessageManager {
52730
52749
  return this.systemExecutor.postSuccess(message, this.getExecutorContext());
52731
52750
  }
52732
52751
  async prepareForUserMessage() {
52733
- const logger = log4.forSession(this.sessionId);
52752
+ const logger = log5.forSession(this.sessionId);
52734
52753
  logger.debug("Preparing for new user message");
52735
52754
  await this.closeCurrentPost();
52736
52755
  await this.bumpTaskList();
52737
52756
  }
52738
52757
  async handleUserMessage(message, files, username, displayName) {
52739
- const logger = log4.forSession(this.sessionId);
52758
+ const logger = log5.forSession(this.sessionId);
52740
52759
  if (!this.session.claude.isRunning()) {
52741
52760
  logger.debug("Claude not running, ignoring user message");
52742
52761
  return false;
@@ -52751,13 +52770,16 @@ class MessageManager {
52751
52770
  }
52752
52771
  let content = outgoing;
52753
52772
  let skippedFiles = [];
52773
+ let transcripts;
52754
52774
  if (this.buildMessageContentCallback) {
52755
52775
  const built = await this.buildMessageContentCallback(outgoing, this.platform, files);
52756
52776
  content = built.content;
52757
52777
  skippedFiles = built.skipped;
52778
+ transcripts = built.transcripts;
52758
52779
  }
52759
52780
  this.session.claude.sendMessage(content);
52760
52781
  await postSkippedFilesFeedback(this.platform, this.threadId, skippedFiles);
52782
+ await postTranscriptFeedback(this.platform, this.threadId, transcripts);
52761
52783
  this.session.lastActivityAt = new Date;
52762
52784
  this.session.isProcessing = true;
52763
52785
  this.emitSessionUpdateCallback?.({ status: "active", isTyping: true });
@@ -52779,7 +52801,7 @@ class MessageManager {
52779
52801
  ];
52780
52802
  }
52781
52803
  async handleReaction(postId, emoji4, user, action) {
52782
- const logger = log4.forSession(this.sessionId);
52804
+ const logger = log5.forSession(this.sessionId);
52783
52805
  const ctx = this.getExecutorContext();
52784
52806
  logger.debug(`Routing reaction: postId=${postId}, emoji=${emoji4}, user=${user}, action=${action}`);
52785
52807
  for (const { name, executor } of this.reactionDispatchList()) {
@@ -52877,7 +52899,7 @@ class MessageManager {
52877
52899
  }
52878
52900
  // src/session/lifecycle-fsm.ts
52879
52901
  init_logger();
52880
- var log5 = createLogger("fsm");
52902
+ var log6 = createLogger("fsm");
52881
52903
  var ALLOWED_TRANSITIONS = {
52882
52904
  starting: new Set(["active", "paused", "interrupted", "cancelling", "restarting"]),
52883
52905
  active: new Set([
@@ -52935,7 +52957,7 @@ function formatSponsorFooter(formatter) {
52935
52957
  }
52936
52958
 
52937
52959
  // src/persistence/session-store.ts
52938
- var log6 = createLogger("persist");
52960
+ var log7 = createLogger("persist");
52939
52961
  function resolveEndReason(session) {
52940
52962
  if (!session.cleanedAt)
52941
52963
  return;
@@ -56170,7 +56192,7 @@ init_logger();
56170
56192
  // src/utils/keep-alive.ts
56171
56193
  init_logger();
56172
56194
  import { spawn } from "child_process";
56173
- var log7 = createLogger("keepalive");
56195
+ var log8 = createLogger("keepalive");
56174
56196
  function keepAliveSpawnSpec(platform, parentPid) {
56175
56197
  switch (platform) {
56176
56198
  case "darwin":
@@ -56226,7 +56248,7 @@ class KeepAliveManager {
56226
56248
  if (!enabled && this.keepAliveProcess) {
56227
56249
  this.stopKeepAlive();
56228
56250
  }
56229
- log7.debug(`Keep-alive ${enabled ? "enabled" : "disabled"}`);
56251
+ log8.debug(`Keep-alive ${enabled ? "enabled" : "disabled"}`);
56230
56252
  }
56231
56253
  isEnabled() {
56232
56254
  return this.enabled;
@@ -56236,7 +56258,7 @@ class KeepAliveManager {
56236
56258
  }
56237
56259
  sessionStarted() {
56238
56260
  this.activeSessionCount++;
56239
- log7.debug(`Session started (${this.activeSessionCount} active)`);
56261
+ log8.debug(`Session started (${this.activeSessionCount} active)`);
56240
56262
  if (this.activeSessionCount === 1) {
56241
56263
  this.startKeepAlive();
56242
56264
  }
@@ -56245,7 +56267,7 @@ class KeepAliveManager {
56245
56267
  if (this.activeSessionCount > 0) {
56246
56268
  this.activeSessionCount--;
56247
56269
  }
56248
- log7.debug(`Session ended (${this.activeSessionCount} active)`);
56270
+ log8.debug(`Session ended (${this.activeSessionCount} active)`);
56249
56271
  if (this.activeSessionCount === 0) {
56250
56272
  this.stopKeepAlive();
56251
56273
  }
@@ -56259,11 +56281,11 @@ class KeepAliveManager {
56259
56281
  }
56260
56282
  startKeepAlive() {
56261
56283
  if (!this.enabled) {
56262
- log7.debug("Keep-alive disabled, skipping");
56284
+ log8.debug("Keep-alive disabled, skipping");
56263
56285
  return;
56264
56286
  }
56265
56287
  if (this.keepAliveProcess) {
56266
- log7.debug("Keep-alive already running");
56288
+ log8.debug("Keep-alive already running");
56267
56289
  return;
56268
56290
  }
56269
56291
  switch (this.platform) {
@@ -56277,12 +56299,12 @@ class KeepAliveManager {
56277
56299
  this.startWindowsKeepAlive();
56278
56300
  break;
56279
56301
  default:
56280
- log7.warn(`Keep-alive not supported on ${this.platform}`);
56302
+ log8.warn(`Keep-alive not supported on ${this.platform}`);
56281
56303
  }
56282
56304
  }
56283
56305
  stopKeepAlive() {
56284
56306
  if (this.keepAliveProcess) {
56285
- log7.debug("Stopping keep-alive");
56307
+ log8.debug("Stopping keep-alive");
56286
56308
  this.keepAliveProcess.kill();
56287
56309
  this.keepAliveProcess = null;
56288
56310
  }
@@ -56297,18 +56319,18 @@ class KeepAliveManager {
56297
56319
  detached: false
56298
56320
  });
56299
56321
  this.keepAliveProcess.on("error", (err) => {
56300
- log7.error(`Failed to start caffeinate: ${err.message}`);
56322
+ log8.error(`Failed to start caffeinate: ${err.message}`);
56301
56323
  this.keepAliveProcess = null;
56302
56324
  });
56303
56325
  this.keepAliveProcess.on("exit", (code) => {
56304
56326
  if (code !== null && code !== 0 && this.activeSessionCount > 0) {
56305
- log7.debug(`caffeinate exited with code ${code}`);
56327
+ log8.debug(`caffeinate exited with code ${code}`);
56306
56328
  }
56307
56329
  this.keepAliveProcess = null;
56308
56330
  });
56309
- log7.info("Sleep prevention active (caffeinate)");
56331
+ log8.info("Sleep prevention active (caffeinate)");
56310
56332
  } catch (err) {
56311
- log7.error(`Failed to start caffeinate: ${err}`);
56333
+ log8.error(`Failed to start caffeinate: ${err}`);
56312
56334
  }
56313
56335
  }
56314
56336
  startLinuxKeepAlive() {
@@ -56321,19 +56343,19 @@ class KeepAliveManager {
56321
56343
  detached: false
56322
56344
  });
56323
56345
  this.keepAliveProcess.on("error", (err) => {
56324
- log7.debug(`systemd-inhibit not available: ${err.message}`);
56346
+ log8.debug(`systemd-inhibit not available: ${err.message}`);
56325
56347
  this.keepAliveProcess = null;
56326
56348
  this.startLinuxKeepAliveFallback();
56327
56349
  });
56328
56350
  this.keepAliveProcess.on("exit", (code) => {
56329
56351
  if (code !== null && code !== 0 && this.activeSessionCount > 0) {
56330
- log7.debug(`systemd-inhibit exited with code ${code}`);
56352
+ log8.debug(`systemd-inhibit exited with code ${code}`);
56331
56353
  }
56332
56354
  this.keepAliveProcess = null;
56333
56355
  });
56334
- log7.info("Sleep prevention active (systemd-inhibit)");
56356
+ log8.info("Sleep prevention active (systemd-inhibit)");
56335
56357
  } catch (err) {
56336
- log7.debug(`Failed to start systemd-inhibit: ${err}`);
56358
+ log8.debug(`Failed to start systemd-inhibit: ${err}`);
56337
56359
  this.startLinuxKeepAliveFallback();
56338
56360
  }
56339
56361
  }
@@ -56344,15 +56366,15 @@ class KeepAliveManager {
56344
56366
  detached: false
56345
56367
  });
56346
56368
  this.keepAliveProcess.on("error", (err) => {
56347
- log7.warn(`Linux keep-alive fallback not available: ${err.message}`);
56369
+ log8.warn(`Linux keep-alive fallback not available: ${err.message}`);
56348
56370
  this.keepAliveProcess = null;
56349
56371
  });
56350
56372
  this.keepAliveProcess.on("exit", () => {
56351
56373
  this.keepAliveProcess = null;
56352
56374
  });
56353
- log7.info("Sleep prevention active (xdg-screensaver)");
56375
+ log8.info("Sleep prevention active (xdg-screensaver)");
56354
56376
  } catch (err) {
56355
- log7.warn(`Linux keep-alive not available: ${err}`);
56377
+ log8.warn(`Linux keep-alive not available: ${err}`);
56356
56378
  }
56357
56379
  }
56358
56380
  startWindowsKeepAlive() {
@@ -56364,25 +56386,25 @@ class KeepAliveManager {
56364
56386
  windowsHide: true
56365
56387
  });
56366
56388
  this.keepAliveProcess.on("error", (err) => {
56367
- log7.warn(`Windows keep-alive not available: ${err.message}`);
56389
+ log8.warn(`Windows keep-alive not available: ${err.message}`);
56368
56390
  this.keepAliveProcess = null;
56369
56391
  });
56370
56392
  this.keepAliveProcess.on("exit", (code) => {
56371
56393
  if (code !== null && code !== 0 && this.activeSessionCount > 0) {
56372
- log7.debug(`PowerShell keep-alive exited with code ${code}`);
56394
+ log8.debug(`PowerShell keep-alive exited with code ${code}`);
56373
56395
  }
56374
56396
  this.keepAliveProcess = null;
56375
56397
  });
56376
- log7.info("Sleep prevention active (SetThreadExecutionState)");
56398
+ log8.info("Sleep prevention active (SetThreadExecutionState)");
56377
56399
  } catch (err) {
56378
- log7.warn(`Windows keep-alive not available: ${err}`);
56400
+ log8.warn(`Windows keep-alive not available: ${err}`);
56379
56401
  }
56380
56402
  }
56381
56403
  }
56382
56404
  var keepAlive = new KeepAliveManager;
56383
56405
 
56384
56406
  // src/operations/sticky-message/handler.ts
56385
- var log8 = createLogger("sticky");
56407
+ var log9 = createLogger("sticky");
56386
56408
  var botStartedAt = new Date;
56387
56409
  var stickyPostIds = new Map;
56388
56410
  var needsBump = new Map;
@@ -56627,7 +56649,7 @@ init_version_check();
56627
56649
  init_logger();
56628
56650
  import { homedir as homedir4 } from "os";
56629
56651
  import { join as join4, dirname as dirname4 } from "path";
56630
- var log9 = createLogger("thread-log");
56652
+ var log10 = createLogger("thread-log");
56631
56653
  var LOGS_BASE_DIR = join4(homedir4(), ".claude-threads", "logs");
56632
56654
 
56633
56655
  // src/operations/bug-report/handler.ts
@@ -56913,7 +56935,7 @@ function parseRateLimitEvent(event, now = Date.now()) {
56913
56935
  }
56914
56936
 
56915
56937
  // src/claude/cli.ts
56916
- var log10 = createLogger("claude");
56938
+ var log11 = createLogger("claude");
56917
56939
  function cleanupBrowserBridgeSockets() {
56918
56940
  try {
56919
56941
  const tempDir = tmpdir2();
@@ -56925,13 +56947,13 @@ function cleanupBrowserBridgeSockets() {
56925
56947
  const stats = statSync(filePath);
56926
56948
  if (stats.isSocket()) {
56927
56949
  unlinkSync(filePath);
56928
- log10.debug(`Removed stale browser bridge socket: ${file2}`);
56950
+ log11.debug(`Removed stale browser bridge socket: ${file2}`);
56929
56951
  }
56930
56952
  } catch {}
56931
56953
  }
56932
56954
  }
56933
56955
  } catch (err) {
56934
- log10.debug(`Browser bridge cleanup failed: ${err}`);
56956
+ log11.debug(`Browser bridge cleanup failed: ${err}`);
56935
56957
  }
56936
56958
  }
56937
56959
  function buildClaudeChildEnv(parentEnv, account, opts) {
@@ -58161,7 +58183,7 @@ handlers.set("model", createPassthroughHandler("model"));
58161
58183
  handlers.set("effort", createPassthroughHandler("effort"));
58162
58184
  // src/commands/system-prompt-generator.ts
58163
58185
  init_logger();
58164
- var log11 = createLogger("system-prompt");
58186
+ var log12 = createLogger("system-prompt");
58165
58187
  function formatUserCommand(cmd) {
58166
58188
  const cmdStr = cmd.args ? `\`!${cmd.command} ${cmd.args}\`` : `\`!${cmd.command}\``;
58167
58189
  const description = cmd.description;
@@ -58253,7 +58275,7 @@ ${avoidCommands.map((c) => `- \`!${c.command}\` - ${c.reason}`).join(`
58253
58275
  }
58254
58276
  // src/utils/error-handler/index.ts
58255
58277
  init_logger();
58256
- var log12 = createLogger("error");
58278
+ var log13 = createLogger("error");
58257
58279
 
58258
58280
  // src/session/lifecycle.ts
58259
58281
  init_logger();
@@ -58277,34 +58299,34 @@ init_spawn();
58277
58299
  import * as path from "path";
58278
58300
  init_logger();
58279
58301
  import { homedir as homedir5 } from "os";
58280
- var log13 = createLogger("git-wt");
58302
+ var log14 = createLogger("git-wt");
58281
58303
  var WORKTREES_DIR = path.join(homedir5(), ".claude-threads", "worktrees");
58282
58304
  var METADATA_STORE_PATH = path.join(homedir5(), ".claude-threads", "worktree-metadata.json");
58283
58305
 
58284
58306
  // src/operations/post-helpers/index.ts
58285
- var log14 = createLogger("helpers");
58286
- var sessionLog = createSessionLog(log14);
58307
+ var log15 = createLogger("helpers");
58308
+ var sessionLog = createSessionLog(log15);
58287
58309
 
58288
58310
  // src/operations/suggestions/title.ts
58289
58311
  init_quick_query();
58290
58312
  init_logger();
58291
- var log16 = createLogger("title");
58313
+ var log17 = createLogger("title");
58292
58314
 
58293
58315
  // src/operations/suggestions/tag.ts
58294
58316
  init_quick_query();
58295
58317
  init_logger();
58296
- var log17 = createLogger("tags");
58318
+ var log18 = createLogger("tags");
58297
58319
 
58298
58320
  // src/session/metadata-suggestions.ts
58299
58321
  init_logger();
58300
- var log18 = createLogger("session");
58301
- var sessionLog2 = createSessionLog(log18);
58322
+ var log19 = createLogger("session");
58323
+ var sessionLog2 = createSessionLog(log19);
58302
58324
 
58303
58325
  // src/operations/context-prompt/handler.ts
58304
58326
  init_emoji();
58305
58327
  init_logger();
58306
- var log19 = createLogger("context");
58307
- var sessionLog3 = createSessionLog(log19);
58328
+ var log20 = createLogger("context");
58329
+ var sessionLog3 = createSessionLog(log20);
58308
58330
  var contextPromptTimeouts = new Map;
58309
58331
  var contextPromptFiles = new Map;
58310
58332
  // src/memory/store.ts
@@ -58318,7 +58340,7 @@ import {
58318
58340
  import { homedir as homedir6 } from "os";
58319
58341
  import { basename as basename3, dirname as dirname7, join as join8, sep as sep2 } from "path";
58320
58342
  init_logger();
58321
- var log20 = createLogger("memory");
58343
+ var log21 = createLogger("memory");
58322
58344
  var DEFAULT_ROOT = join8(homedir6(), ".config", "claude-threads", "memory");
58323
58345
  var CHANNEL_BLOCK_MAX_LINES = 200;
58324
58346
  var CHANNEL_BLOCK_MAX_BYTES = 25 * 1024;
@@ -58414,7 +58436,7 @@ class MemoryStore {
58414
58436
  if (result.added.length > 0) {
58415
58437
  this.enforceFileCap(lines);
58416
58438
  this.writeLines(platformId, lines);
58417
- log20.debug(`Channel memory for ${platformId}: +${result.added.length} entries` + (result.duplicates.length ? ` (${result.duplicates.length} duplicates skipped)` : ""));
58439
+ log21.debug(`Channel memory for ${platformId}: +${result.added.length} entries` + (result.duplicates.length ? ` (${result.duplicates.length} duplicates skipped)` : ""));
58418
58440
  }
58419
58441
  return result;
58420
58442
  });
@@ -58453,14 +58475,14 @@ class MemoryStore {
58453
58475
  }
58454
58476
  lines.splice(target.lineIndex, 1);
58455
58477
  this.writeLines(platformId, lines);
58456
- log20.debug(`Channel memory for ${platformId}: removed one entry`);
58478
+ log21.debug(`Channel memory for ${platformId}: removed one entry`);
58457
58479
  return { ok: true, removed: target.entry };
58458
58480
  });
58459
58481
  }
58460
58482
  clearChannel(platformId) {
58461
58483
  return this.runExclusive(platformId, () => {
58462
58484
  this.writeLines(platformId, []);
58463
- log20.debug(`Channel memory for ${platformId}: cleared`);
58485
+ log21.debug(`Channel memory for ${platformId}: cleared`);
58464
58486
  });
58465
58487
  }
58466
58488
  buildChannelMemoryBlock(platformId) {
@@ -58468,7 +58490,7 @@ class MemoryStore {
58468
58490
  try {
58469
58491
  lines = this.loadLines(platformId);
58470
58492
  } catch (err) {
58471
- log20.warn(`Failed to read channel memory for ${platformId}: ${err.message}`);
58493
+ log21.warn(`Failed to read channel memory for ${platformId}: ${err.message}`);
58472
58494
  return null;
58473
58495
  }
58474
58496
  if (lines.length === 0)
@@ -58552,7 +58574,7 @@ _(older entries omitted — \`!memory\` shows all)_` : rendered;
58552
58574
  // src/memory/distiller.ts
58553
58575
  init_quick_query();
58554
58576
  init_logger();
58555
- var log21 = createLogger("memory");
58577
+ var log22 = createLogger("memory");
58556
58578
 
58557
58579
  // src/session/registry.ts
58558
58580
  function compositeSessionId(platformId, threadId) {
@@ -58816,41 +58838,41 @@ class PlatformListStore {
58816
58838
  }
58817
58839
 
58818
58840
  // src/persistence/routines-store.ts
58819
- var log22 = createLogger("routines");
58841
+ var log23 = createLogger("routines");
58820
58842
  var DEFAULT_FILE = join10(STORES_CONFIG_DIR, "routines.yaml");
58821
58843
 
58822
58844
  // src/routines/parser.ts
58823
58845
  init_logger();
58824
- var log23 = createLogger("routines");
58846
+ var log24 = createLogger("routines");
58825
58847
 
58826
58848
  // src/persistence/watches-store.ts
58827
58849
  import { join as join11 } from "path";
58828
58850
  init_logger();
58829
- var log24 = createLogger("watches");
58851
+ var log25 = createLogger("watches");
58830
58852
  var DEFAULT_FILE2 = join11(STORES_CONFIG_DIR, "watches.yaml");
58831
58853
 
58832
58854
  // src/watches/parser.ts
58833
58855
  init_logger();
58834
- var log25 = createLogger("watches");
58856
+ var log26 = createLogger("watches");
58835
58857
 
58836
58858
  // src/operations/commands/guards.ts
58837
58859
  init_logger();
58838
- var log26 = createLogger("commands");
58839
- var sessionLog4 = createSessionLog(log26);
58860
+ var log27 = createLogger("commands");
58861
+ var sessionLog4 = createSessionLog(log27);
58840
58862
 
58841
58863
  // src/operations/commands/automation.ts
58842
58864
  init_logger();
58843
- var log27 = createLogger("commands");
58844
- var sessionLog5 = createSessionLog(log27);
58865
+ var log28 = createLogger("commands");
58866
+ var sessionLog5 = createSessionLog(log28);
58845
58867
 
58846
58868
  // src/operations/agent-actions/handler.ts
58847
58869
  init_logger();
58848
- var log28 = createLogger("agent-actions");
58849
- var sessionLog6 = createSessionLog(log28);
58870
+ var log29 = createLogger("agent-actions");
58871
+ var sessionLog6 = createSessionLog(log29);
58850
58872
 
58851
58873
  // src/session/lifecycle.ts
58852
- var log29 = createLogger("lifecycle");
58853
- var sessionLog7 = createSessionLog(log29);
58874
+ var log30 = createLogger("lifecycle");
58875
+ var sessionLog7 = createSessionLog(log30);
58854
58876
  var _inFlightSessionStarts = new Map;
58855
58877
  var CHAT_PLATFORM_PROMPT = generateChatPlatformPrompt();
58856
58878
 
@@ -58866,36 +58888,36 @@ init_quick_query();
58866
58888
  import { homedir as homedir8 } from "os";
58867
58889
  import { join as join12 } from "path";
58868
58890
  init_logger();
58869
- var log30 = createLogger("gh-emails");
58891
+ var log31 = createLogger("gh-emails");
58870
58892
  var DEFAULT_CONFIG_DIR2 = join12(homedir8(), ".config", "claude-threads");
58871
58893
  var DEFAULT_FILE3 = join12(DEFAULT_CONFIG_DIR2, "github-emails.yaml");
58872
58894
 
58873
58895
  // src/operations/commands/handler.ts
58874
- var log31 = createLogger("commands");
58875
- var sessionLog8 = createSessionLog(log31);
58896
+ var log32 = createLogger("commands");
58897
+ var sessionLog8 = createSessionLog(log32);
58876
58898
  // src/operations/commands/memory.ts
58877
58899
  init_logger();
58878
- var log32 = createLogger("commands");
58879
- var sessionLog9 = createSessionLog(log32);
58900
+ var log33 = createLogger("commands");
58901
+ var sessionLog9 = createSessionLog(log33);
58880
58902
  // src/operations/suggestions/branch.ts
58881
58903
  init_quick_query();
58882
58904
  init_logger();
58883
58905
  import { exec as exec2 } from "child_process";
58884
58906
  import { promisify as promisify2 } from "util";
58885
58907
  var execAsync2 = promisify2(exec2);
58886
- var log33 = createLogger("branch");
58908
+ var log34 = createLogger("branch");
58887
58909
 
58888
58910
  // src/operations/worktree/handler.ts
58889
58911
  init_logger();
58890
- var log34 = createLogger("worktree");
58891
- var sessionLog10 = createSessionLog(log34);
58912
+ var log35 = createLogger("worktree");
58913
+ var sessionLog10 = createSessionLog(log35);
58892
58914
  // src/operations/events/handler.ts
58893
58915
  init_logger();
58894
- var log35 = createLogger("events");
58895
- var sessionLog11 = createSessionLog(log35);
58916
+ var log36 = createLogger("events");
58917
+ var sessionLog11 = createSessionLog(log36);
58896
58918
  // src/operations/monitor/handler.ts
58897
58919
  init_logger();
58898
- var log36 = createLogger("monitor");
58920
+ var log37 = createLogger("monitor");
58899
58921
  var DEFAULT_INTERVAL_MS = 60 * 1000;
58900
58922
  // src/mcp/mcp-server.ts
58901
58923
  init_logger();
@@ -58984,7 +59006,7 @@ init_logger();
58984
59006
  // src/platform/mattermost/upload.ts
58985
59007
  init_logger();
58986
59008
  import { readFile } from "fs/promises";
58987
- var log37 = createLogger("mm-upload");
59009
+ var log38 = createLogger("mm-upload");
58988
59010
  async function uploadFileMattermost(args) {
58989
59011
  const { url: url2, token, channelId, threadId, filePath, filename, caption } = args;
58990
59012
  const buffer = await readFile(filePath);
@@ -58992,7 +59014,7 @@ async function uploadFileMattermost(args) {
58992
59014
  const arrayBuffer = buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength);
58993
59015
  const formData = new FormData;
58994
59016
  formData.append("files", new Blob([arrayBuffer]), filename);
58995
- log37.debug(`POST /files (${buffer.length} bytes, ${filename})`);
59017
+ log38.debug(`POST /files (${buffer.length} bytes, ${filename})`);
58996
59018
  const uploadResponse = await fetch(uploadUrl, {
58997
59019
  method: "POST",
58998
59020
  headers: {
@@ -59016,7 +59038,7 @@ async function uploadFileMattermost(args) {
59016
59038
  root_id: resolvePostThreadId(threadId),
59017
59039
  file_ids: [fileInfo.id]
59018
59040
  };
59019
- log37.debug(`POST /posts (file_ids=[${fileInfo.id}])`);
59041
+ log38.debug(`POST /posts (file_ids=[${fileInfo.id}])`);
59020
59042
  const postResponse = await fetch(postUrl, {
59021
59043
  method: "POST",
59022
59044
  headers: {
@@ -59514,7 +59536,7 @@ ${code}
59514
59536
  // src/platform/slack/upload.ts
59515
59537
  init_logger();
59516
59538
  import { readFile as readFile2 } from "fs/promises";
59517
- var log38 = createLogger("slack-upload");
59539
+ var log39 = createLogger("slack-upload");
59518
59540
  var DEFAULT_API_URL = "https://slack.com/api";
59519
59541
  async function uploadFileSlack(args) {
59520
59542
  const { botToken, channelId, threadTs, filePath, filename, caption } = args;
@@ -59522,7 +59544,7 @@ async function uploadFileSlack(args) {
59522
59544
  const buffer = await readFile2(filePath);
59523
59545
  const params = new URLSearchParams({ filename, length: String(buffer.length) });
59524
59546
  const step1Url = `${apiUrl}/files.getUploadURLExternal?${params.toString()}`;
59525
- log38.debug(`GET files.getUploadURLExternal (${buffer.length} bytes, ${filename})`);
59547
+ log39.debug(`GET files.getUploadURLExternal (${buffer.length} bytes, ${filename})`);
59526
59548
  const step1Response = await fetch(step1Url, {
59527
59549
  method: "GET",
59528
59550
  headers: {
@@ -59540,7 +59562,7 @@ async function uploadFileSlack(args) {
59540
59562
  const uploadUrl = step1Data.upload_url;
59541
59563
  const fileId = step1Data.file_id;
59542
59564
  const arrayBuffer = buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength);
59543
- log38.debug(`POST <upload_url>`);
59565
+ log39.debug(`POST <upload_url>`);
59544
59566
  const step2Response = await fetch(uploadUrl, {
59545
59567
  method: "POST",
59546
59568
  headers: {
@@ -59560,7 +59582,7 @@ async function uploadFileSlack(args) {
59560
59582
  if (caption !== undefined) {
59561
59583
  step3Body.initial_comment = caption;
59562
59584
  }
59563
- log38.debug(`POST files.completeUploadExternal (file_id=${fileId}, thread_ts=${threadTs})`);
59585
+ log39.debug(`POST files.completeUploadExternal (file_id=${fileId}, thread_ts=${threadTs})`);
59564
59586
  const step3Response = await fetch(`${apiUrl}/files.completeUploadExternal`, {
59565
59587
  method: "POST",
59566
59588
  headers: {
@@ -59578,7 +59600,7 @@ async function uploadFileSlack(args) {
59578
59600
  throw new Error(`Slack completeUploadExternal error: ${step3Data.error || "unknown"}`);
59579
59601
  }
59580
59602
  if (!step3Data.ts) {
59581
- log38.warn(`Slack completeUploadExternal returned no ts; using fileId ${fileId} as postId. ` + `Do not use this id for updatePost/addReaction.`);
59603
+ log39.warn(`Slack completeUploadExternal returned no ts; using fileId ${fileId} as postId. ` + `Do not use this id for updatePost/addReaction.`);
59582
59604
  }
59583
59605
  return { fileId, postId: step3Data.ts ?? fileId };
59584
59606
  }
@@ -110,6 +110,39 @@ stickyMessage:
110
110
  | `description` | Line shown below the sticky title | none |
111
111
  | `footer` | Content shown before the default "Mention me to start a session" line | none |
112
112
 
113
+ ### Transcription (`transcription`)
114
+
115
+ Speech-to-text for inbound audio attachments, so a voice note is a message and not just a `.webm` on disk. Applies to every platform. Without this block, audio files are saved and listed like any other attachment.
116
+
117
+ ```yaml
118
+ transcription:
119
+ provider: elevenlabs
120
+ apiKey: your-elevenlabs-key
121
+ model: scribe_v2
122
+ languageCode: hrv
123
+ ```
124
+
125
+ | Setting | Description | Default |
126
+ |---------|-------------|---------|
127
+ | `provider` | Speech-to-text provider. Only `elevenlabs` (Scribe) today; the field is the seam for others. | required |
128
+ | `apiKey` | Provider API key. Keep it in this `0600` file, never in a repo. | required |
129
+ | `model` | Provider model id | `scribe_v2` |
130
+ | `languageCode` | Language hint, passed through verbatim (ElevenLabs accepts ISO-639-1 and ISO-639-3). Omit to auto-detect. | auto-detect |
131
+
132
+ Per-platform opt-out:
133
+
134
+ ```yaml
135
+ platforms:
136
+ - id: legal
137
+ transcription: false # this channel's audio never leaves the box
138
+ ```
139
+
140
+ The provider and its key are a property of the **deployment** — one vendor account per daemon — so they live at the top level. Whether a given channel's audio should be sent to that vendor is a property of the **channel**, which is what `transcription: false` answers. It gates every path that could reach the vendor, including watch evaluation.
141
+
142
+ ⚠️ **A transcript is user input, not narration.** It reaches Claude as message text and is evaluated by watches exactly as a typed message is — deliberately, so a watch on "deploy" fires when somebody says "deploy" out loud rather than only when they type it. The usual prompt-injection caution therefore applies in full: a voice note can say "ignore your instructions" as easily as a typed message can, and anyone who can post audio in the channel can attempt it. Treat the audio surface as exactly as trusted as the text one, because it is.
143
+
144
+ What happens: every `audio/*` attachment (or a file with an audio extension when the platform only reported a generic type) is transcribed after it is saved. Claude receives the usual file list **and** a `[Transcript of voice.webm (elevenlabs):]` block, and the bot posts the transcript back into the thread as a quote so everyone can see what Claude heard. A transcription failure is reported like a skipped file — the audio file itself still reaches Claude. A bad `provider` or missing `apiKey` fails the boot. Details: [`docs/audio-transcription-spec.md`](audio-transcription-spec.md).
145
+
113
146
  ## Platform Settings
114
147
 
115
148
  ### Mattermost