claude-threads 1.26.0 → 1.28.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.
@@ -47754,7 +47754,11 @@ function truncateWithEllipsis(str, maxLength) {
47754
47754
  return str.substring(0, maxLength) + "...";
47755
47755
  }
47756
47756
  function escapeCodeBlockContent(content) {
47757
- return content.replace(/```/g, "` ``");
47757
+ let result = content;
47758
+ while (result.includes("```")) {
47759
+ result = result.replace(/```/g, "` ``");
47760
+ }
47761
+ return result;
47758
47762
  }
47759
47763
  // src/operations/tool-formatters/registry.ts
47760
47764
  class ToolFormatterRegistry {
@@ -48553,6 +48557,15 @@ var fileToolsFormatter = {
48553
48557
  }
48554
48558
  };
48555
48559
  // src/operations/tool-formatters/bash-tools.ts
48560
+ var PERMISSION_COMMAND_MAX = 1500;
48561
+ function truncateAtCodePoint(text, max) {
48562
+ if (text.length <= max)
48563
+ return { text, truncated: false };
48564
+ const points = Array.from(text);
48565
+ if (points.length <= max)
48566
+ return { text, truncated: false };
48567
+ return { text: points.slice(0, max).join(""), truncated: true };
48568
+ }
48556
48569
  var bashToolFormatter = {
48557
48570
  toolNames: ["Bash"],
48558
48571
  format(toolName, input, options) {
@@ -48565,9 +48578,13 @@ var bashToolFormatter = {
48565
48578
  }
48566
48579
  const truncated = cmd.length > maxCommandLength;
48567
48580
  const displayCmd = cmd.substring(0, maxCommandLength);
48581
+ const permission = truncateAtCodePoint(cmd, PERMISSION_COMMAND_MAX);
48582
+ const permissionCmd = escapeCodeBlockContent(permission.text) + (permission.truncated ? `
48583
+ [... truncated]` : "");
48568
48584
  return {
48569
48585
  display: `\uD83D\uDCBB ${formatter.formatBold("Bash")} ${formatter.formatCode(displayCmd + (truncated ? "..." : ""))}`,
48570
- permissionText: `\uD83D\uDCBB ${formatter.formatBold("Bash")} ${formatter.formatCode(cmd.substring(0, 100) + (cmd.length >= 100 ? "..." : ""))}`,
48586
+ permissionText: `\uD83D\uDCBB ${formatter.formatBold("Bash")}
48587
+ ${formatter.formatCodeBlock(permissionCmd, "bash")}`,
48571
48588
  isDestructive: true
48572
48589
  };
48573
48590
  }
@@ -49632,6 +49649,13 @@ function convertMarkdownTablesToSlack(content) {
49632
49649
  `);
49633
49650
  });
49634
49651
  }
49652
+ var DCM_THREAD_PREFIX = "dcm:";
49653
+ function isDcmThreadId(threadId) {
49654
+ return !!threadId && threadId.startsWith(DCM_THREAD_PREFIX);
49655
+ }
49656
+ function resolvePostThreadId(threadId) {
49657
+ return isDcmThreadId(threadId) ? undefined : threadId;
49658
+ }
49635
49659
 
49636
49660
  // src/version.ts
49637
49661
  import { readFileSync, existsSync } from "fs";
@@ -50748,6 +50772,144 @@ class SystemExecutor extends BaseExecutor {
50748
50772
  }
50749
50773
  // src/operations/executors/question-approval.ts
50750
50774
  init_emoji();
50775
+
50776
+ // src/persistence/audit-log.ts
50777
+ import { chmodSync, closeSync, constants as fsConstants, fchmodSync, lstatSync, mkdirSync, openSync, writeSync } from "fs";
50778
+ import { join as join2 } from "path";
50779
+ import { homedir } from "os";
50780
+
50781
+ // src/utils/logger.ts
50782
+ var globalLogHandler = null;
50783
+ var COMPONENT_WIDTH = 10;
50784
+ function createLogger(component, useStderr = false, sessionId) {
50785
+ const isDebug = () => process.env.DEBUG === "1";
50786
+ const consoleLog = useStderr ? console.error : console.log;
50787
+ const paddedComponent = component.length > COMPONENT_WIDTH ? component.substring(0, COMPONENT_WIDTH) : component.padEnd(COMPONENT_WIDTH);
50788
+ const formatMessage = (msg, args) => {
50789
+ if (args.length === 0)
50790
+ return msg;
50791
+ return `${msg} ${args.map((a) => typeof a === "object" ? JSON.stringify(a) : String(a)).join(" ")}`;
50792
+ };
50793
+ const DEFAULT_JSON_MAX_LEN = 60;
50794
+ return {
50795
+ debug: (msg, ...args) => {
50796
+ if (isDebug()) {
50797
+ const fullMsg = formatMessage(msg, args);
50798
+ if (globalLogHandler) {
50799
+ globalLogHandler("debug", paddedComponent, fullMsg, sessionId);
50800
+ } else {
50801
+ consoleLog(`[${paddedComponent}] ${fullMsg}`);
50802
+ }
50803
+ }
50804
+ },
50805
+ debugJson: (label, data, maxLen = DEFAULT_JSON_MAX_LEN) => {
50806
+ if (isDebug()) {
50807
+ const json2 = JSON.stringify(data);
50808
+ const truncated = json2.length > maxLen ? `${json2.substring(0, maxLen)}…` : json2;
50809
+ const fullMsg = `${label}: ${truncated}`;
50810
+ if (globalLogHandler) {
50811
+ globalLogHandler("debug", paddedComponent, fullMsg, sessionId);
50812
+ } else {
50813
+ consoleLog(`[${paddedComponent}] ${fullMsg}`);
50814
+ }
50815
+ }
50816
+ },
50817
+ info: (msg, ...args) => {
50818
+ const fullMsg = formatMessage(msg, args);
50819
+ if (globalLogHandler) {
50820
+ globalLogHandler("info", paddedComponent, fullMsg, sessionId);
50821
+ } else {
50822
+ consoleLog(`[${paddedComponent}] ${fullMsg}`);
50823
+ }
50824
+ },
50825
+ warn: (msg, ...args) => {
50826
+ const fullMsg = formatMessage(msg, args);
50827
+ if (globalLogHandler) {
50828
+ globalLogHandler("warn", paddedComponent, fullMsg, sessionId);
50829
+ } else {
50830
+ console.warn(`[${paddedComponent}] ⚠️ ${fullMsg}`);
50831
+ }
50832
+ },
50833
+ error: (msg, err) => {
50834
+ const fullMsg = err && isDebug() ? `${msg}
50835
+ ${err.stack || err.message}` : msg;
50836
+ if (globalLogHandler) {
50837
+ globalLogHandler("error", paddedComponent, fullMsg, sessionId);
50838
+ } else {
50839
+ console.error(`[${paddedComponent}] ❌ ${msg}`);
50840
+ if (err && isDebug()) {
50841
+ console.error(err);
50842
+ }
50843
+ }
50844
+ },
50845
+ forSession: (sid) => createLogger(component, useStderr, sid)
50846
+ };
50847
+ }
50848
+ var mcpLogger = createLogger("MCP", true);
50849
+ var wsLogger = createLogger("ws", false);
50850
+
50851
+ // src/persistence/audit-log.ts
50852
+ var log = createLogger("audit");
50853
+ var DETAIL_MAX = 500;
50854
+ var enabledPlatforms = new Set;
50855
+ var preparedDirs = new Set;
50856
+ var openFds = new Map;
50857
+ function auditDir() {
50858
+ return process.env.CLAUDE_THREADS_AUDIT_DIR || join2(homedir(), ".claude-threads", "audit");
50859
+ }
50860
+ function openAuditFd(platformId) {
50861
+ const cached3 = openFds.get(platformId);
50862
+ if (cached3 !== undefined)
50863
+ return cached3;
50864
+ const dir = auditDir();
50865
+ if (!preparedDirs.has(dir)) {
50866
+ mkdirSync(dir, { recursive: true, mode: 448 });
50867
+ chmodSync(dir, 448);
50868
+ preparedDirs.add(dir);
50869
+ }
50870
+ const file2 = join2(dir, `${encodeURIComponent(platformId)}.jsonl`);
50871
+ try {
50872
+ const st = lstatSync(file2);
50873
+ if (st.isSymbolicLink() || !st.isFile()) {
50874
+ throw new Error(`audit path exists but is not a regular file: ${file2}`);
50875
+ }
50876
+ } catch (err) {
50877
+ if (err.code !== "ENOENT")
50878
+ throw err;
50879
+ }
50880
+ const noFollow = typeof fsConstants.O_NOFOLLOW === "number" ? fsConstants.O_NOFOLLOW : 0;
50881
+ const fd = openSync(file2, fsConstants.O_WRONLY | fsConstants.O_APPEND | fsConstants.O_CREAT | noFollow, 384);
50882
+ try {
50883
+ fchmodSync(fd, 384);
50884
+ } catch {}
50885
+ openFds.set(platformId, fd);
50886
+ return fd;
50887
+ }
50888
+ function auditLog(platformId, entry) {
50889
+ if (!enabledPlatforms.has(platformId))
50890
+ return;
50891
+ try {
50892
+ const full = {
50893
+ ts: new Date().toISOString(),
50894
+ platformId,
50895
+ ...entry,
50896
+ ...entry.detail !== undefined ? { detail: entry.detail.slice(0, DETAIL_MAX) } : {}
50897
+ };
50898
+ writeSync(openAuditFd(platformId), JSON.stringify(full) + `
50899
+ `);
50900
+ } catch (err) {
50901
+ const fd = openFds.get(platformId);
50902
+ if (fd !== undefined) {
50903
+ openFds.delete(platformId);
50904
+ try {
50905
+ closeSync(fd);
50906
+ } catch {}
50907
+ }
50908
+ log.warn(`audit write failed for ${platformId}: ${err}`);
50909
+ }
50910
+ }
50911
+
50912
+ // src/operations/executors/question-approval.ts
50751
50913
  class QuestionApprovalExecutor extends BaseExecutor {
50752
50914
  constructor(options) {
50753
50915
  super(options, QuestionApprovalExecutor.createInitialState());
@@ -50962,14 +51124,29 @@ class QuestionApprovalExecutor extends BaseExecutor {
50962
51124
  return false;
50963
51125
  }
50964
51126
  if (this.state.pendingApproval?.postId === postId) {
51127
+ const approvalType = this.state.pendingApproval.type;
51128
+ const auditDecision = (approved) => {
51129
+ if (approvalType !== "plan")
51130
+ return;
51131
+ auditLog(ctx.platform.platformId, {
51132
+ threadId: ctx.threadId,
51133
+ sessionId: ctx.sessionId,
51134
+ actor: user,
51135
+ kind: "plan_approval",
51136
+ approved,
51137
+ detail: "via reaction"
51138
+ });
51139
+ };
50965
51140
  if (isApprovalEmoji(emoji4)) {
50966
51141
  ctx.logger.debug(`Approval reaction from @${user}: approved`);
51142
+ auditDecision(true);
50967
51143
  const handled = await this.handleApprovalResponse(postId, true, ctx);
50968
51144
  ctx.logger.debug(`QuestionApprovalExecutor: approval outcome=approved, handled=${handled}`);
50969
51145
  return handled;
50970
51146
  }
50971
51147
  if (isDenialEmoji(emoji4)) {
50972
51148
  ctx.logger.debug(`Approval reaction from @${user}: denied`);
51149
+ auditDecision(false);
50973
51150
  const handled = await this.handleApprovalResponse(postId, false, ctx);
50974
51151
  ctx.logger.debug(`QuestionApprovalExecutor: approval outcome=denied, handled=${handled}`);
50975
51152
  return handled;
@@ -51426,79 +51603,7 @@ class BugReportExecutor extends BaseExecutor {
51426
51603
  }
51427
51604
  // src/operations/executors/worktree-prompt.ts
51428
51605
  init_emoji();
51429
-
51430
- // src/utils/logger.ts
51431
- var globalLogHandler = null;
51432
- var COMPONENT_WIDTH = 10;
51433
- function createLogger(component, useStderr = false, sessionId) {
51434
- const isDebug = () => process.env.DEBUG === "1";
51435
- const consoleLog = useStderr ? console.error : console.log;
51436
- const paddedComponent = component.length > COMPONENT_WIDTH ? component.substring(0, COMPONENT_WIDTH) : component.padEnd(COMPONENT_WIDTH);
51437
- const formatMessage = (msg, args) => {
51438
- if (args.length === 0)
51439
- return msg;
51440
- return `${msg} ${args.map((a) => typeof a === "object" ? JSON.stringify(a) : String(a)).join(" ")}`;
51441
- };
51442
- const DEFAULT_JSON_MAX_LEN = 60;
51443
- return {
51444
- debug: (msg, ...args) => {
51445
- if (isDebug()) {
51446
- const fullMsg = formatMessage(msg, args);
51447
- if (globalLogHandler) {
51448
- globalLogHandler("debug", paddedComponent, fullMsg, sessionId);
51449
- } else {
51450
- consoleLog(`[${paddedComponent}] ${fullMsg}`);
51451
- }
51452
- }
51453
- },
51454
- debugJson: (label, data, maxLen = DEFAULT_JSON_MAX_LEN) => {
51455
- if (isDebug()) {
51456
- const json2 = JSON.stringify(data);
51457
- const truncated = json2.length > maxLen ? `${json2.substring(0, maxLen)}…` : json2;
51458
- const fullMsg = `${label}: ${truncated}`;
51459
- if (globalLogHandler) {
51460
- globalLogHandler("debug", paddedComponent, fullMsg, sessionId);
51461
- } else {
51462
- consoleLog(`[${paddedComponent}] ${fullMsg}`);
51463
- }
51464
- }
51465
- },
51466
- info: (msg, ...args) => {
51467
- const fullMsg = formatMessage(msg, args);
51468
- if (globalLogHandler) {
51469
- globalLogHandler("info", paddedComponent, fullMsg, sessionId);
51470
- } else {
51471
- consoleLog(`[${paddedComponent}] ${fullMsg}`);
51472
- }
51473
- },
51474
- warn: (msg, ...args) => {
51475
- const fullMsg = formatMessage(msg, args);
51476
- if (globalLogHandler) {
51477
- globalLogHandler("warn", paddedComponent, fullMsg, sessionId);
51478
- } else {
51479
- console.warn(`[${paddedComponent}] ⚠️ ${fullMsg}`);
51480
- }
51481
- },
51482
- error: (msg, err) => {
51483
- const fullMsg = err && isDebug() ? `${msg}
51484
- ${err.stack || err.message}` : msg;
51485
- if (globalLogHandler) {
51486
- globalLogHandler("error", paddedComponent, fullMsg, sessionId);
51487
- } else {
51488
- console.error(`[${paddedComponent}] ❌ ${msg}`);
51489
- if (err && isDebug()) {
51490
- console.error(err);
51491
- }
51492
- }
51493
- },
51494
- forSession: (sid) => createLogger(component, useStderr, sid)
51495
- };
51496
- }
51497
- var mcpLogger = createLogger("MCP", true);
51498
- var wsLogger = createLogger("ws", false);
51499
-
51500
- // src/operations/executors/worktree-prompt.ts
51501
- var log = createLogger("wt-prompt");
51606
+ var log2 = createLogger("wt-prompt");
51502
51607
  // src/operations/message-manager-events.ts
51503
51608
  import { EventEmitter } from "events";
51504
51609
 
@@ -51547,7 +51652,7 @@ function formatBytes(bytes) {
51547
51652
  }
51548
51653
 
51549
51654
  // src/operations/streaming/handler.ts
51550
- var log2 = createLogger("streaming");
51655
+ var log3 = createLogger("streaming");
51551
51656
  async function postSkippedFilesFeedback(platform, threadId, skipped) {
51552
51657
  if (skipped.length === 0)
51553
51658
  return;
@@ -51615,7 +51720,7 @@ function formatRelativeTime(date8) {
51615
51720
  return `${diffMin} min ago`;
51616
51721
  }
51617
51722
  // src/operations/message-manager.ts
51618
- var log3 = createLogger("msg-mgr");
51723
+ var log4 = createLogger("msg-mgr");
51619
51724
 
51620
51725
  class MessageManager {
51621
51726
  platform;
@@ -51708,7 +51813,7 @@ class MessageManager {
51708
51813
  });
51709
51814
  }
51710
51815
  async handleEvent(event) {
51711
- const logger = log3.forSession(this.sessionId);
51816
+ const logger = log4.forSession(this.sessionId);
51712
51817
  const transformCtx = {
51713
51818
  sessionId: this.sessionId,
51714
51819
  formatter: this.platform.getFormatter(),
@@ -51762,7 +51867,7 @@ class MessageManager {
51762
51867
  }
51763
51868
  }
51764
51869
  async executeOperation(op) {
51765
- const logger = log3.forSession(this.sessionId);
51870
+ const logger = log4.forSession(this.sessionId);
51766
51871
  const ctx = this.getExecutorContext();
51767
51872
  try {
51768
51873
  if (isContentOp(op)) {
@@ -51830,7 +51935,7 @@ class MessageManager {
51830
51935
  threadId: this.threadId,
51831
51936
  platform: this.platform,
51832
51937
  formatter: this.platform.getFormatter(),
51833
- logger: log3.forSession(this.sessionId),
51938
+ logger: log4.forSession(this.sessionId),
51834
51939
  postTracker: this.postTracker,
51835
51940
  contentBreaker: this.contentBreaker,
51836
51941
  threadLogger: this.session.threadLogger,
@@ -52050,13 +52155,13 @@ class MessageManager {
52050
52155
  return this.systemExecutor.postSuccess(message, this.getExecutorContext());
52051
52156
  }
52052
52157
  async prepareForUserMessage() {
52053
- const logger = log3.forSession(this.sessionId);
52158
+ const logger = log4.forSession(this.sessionId);
52054
52159
  logger.debug("Preparing for new user message");
52055
52160
  await this.closeCurrentPost();
52056
52161
  await this.bumpTaskList();
52057
52162
  }
52058
52163
  async handleUserMessage(message, files, username, displayName) {
52059
- const logger = log3.forSession(this.sessionId);
52164
+ const logger = log4.forSession(this.sessionId);
52060
52165
  if (!this.session.claude.isRunning()) {
52061
52166
  logger.debug("Claude not running, ignoring user message");
52062
52167
  return false;
@@ -52099,7 +52204,7 @@ class MessageManager {
52099
52204
  ];
52100
52205
  }
52101
52206
  async handleReaction(postId, emoji4, user, action) {
52102
- const logger = log3.forSession(this.sessionId);
52207
+ const logger = log4.forSession(this.sessionId);
52103
52208
  const ctx = this.getExecutorContext();
52104
52209
  logger.debug(`Routing reaction: postId=${postId}, emoji=${emoji4}, user=${user}, action=${action}`);
52105
52210
  for (const { name, executor } of this.reactionDispatchList()) {
@@ -52196,7 +52301,7 @@ class MessageManager {
52196
52301
  }
52197
52302
  }
52198
52303
  // src/session/lifecycle-fsm.ts
52199
- var log4 = createLogger("fsm");
52304
+ var log5 = createLogger("fsm");
52200
52305
  var ALLOWED_TRANSITIONS = {
52201
52306
  starting: new Set(["active", "paused", "interrupted", "cancelling", "restarting"]),
52202
52307
  active: new Set([
@@ -52223,7 +52328,7 @@ var ALLOWED_TRANSITIONS = {
52223
52328
  };
52224
52329
  // src/config/index.ts
52225
52330
  import { resolve as resolve2, dirname as dirname2 } from "path";
52226
- import { homedir } from "os";
52331
+ import { homedir as homedir2 } from "os";
52227
52332
 
52228
52333
  // node_modules/js-yaml/dist/js-yaml.mjs
52229
52334
  function getDefaultExportFromCjs(x) {
@@ -55335,7 +55440,7 @@ var jsYamlExports = requireJsYaml();
55335
55440
  var yaml = /* @__PURE__ */ getDefaultExportFromCjs(jsYamlExports);
55336
55441
 
55337
55442
  // src/config/index.ts
55338
- var CONFIG_PATH = resolve2(homedir(), ".config", "claude-threads", "config.yaml");
55443
+ var CONFIG_PATH = resolve2(homedir2(), ".config", "claude-threads", "config.yaml");
55339
55444
 
55340
55445
  // src/utils/battery.ts
55341
55446
  import { exec } from "child_process";
@@ -55440,7 +55545,7 @@ function formatReleaseNotes(notes, formatter) {
55440
55545
 
55441
55546
  // src/utils/keep-alive.ts
55442
55547
  import { spawn } from "child_process";
55443
- var log5 = createLogger("keepalive");
55548
+ var log6 = createLogger("keepalive");
55444
55549
  function keepAliveSpawnSpec(platform, parentPid) {
55445
55550
  switch (platform) {
55446
55551
  case "darwin":
@@ -55496,7 +55601,7 @@ class KeepAliveManager {
55496
55601
  if (!enabled && this.keepAliveProcess) {
55497
55602
  this.stopKeepAlive();
55498
55603
  }
55499
- log5.debug(`Keep-alive ${enabled ? "enabled" : "disabled"}`);
55604
+ log6.debug(`Keep-alive ${enabled ? "enabled" : "disabled"}`);
55500
55605
  }
55501
55606
  isEnabled() {
55502
55607
  return this.enabled;
@@ -55506,7 +55611,7 @@ class KeepAliveManager {
55506
55611
  }
55507
55612
  sessionStarted() {
55508
55613
  this.activeSessionCount++;
55509
- log5.debug(`Session started (${this.activeSessionCount} active)`);
55614
+ log6.debug(`Session started (${this.activeSessionCount} active)`);
55510
55615
  if (this.activeSessionCount === 1) {
55511
55616
  this.startKeepAlive();
55512
55617
  }
@@ -55515,7 +55620,7 @@ class KeepAliveManager {
55515
55620
  if (this.activeSessionCount > 0) {
55516
55621
  this.activeSessionCount--;
55517
55622
  }
55518
- log5.debug(`Session ended (${this.activeSessionCount} active)`);
55623
+ log6.debug(`Session ended (${this.activeSessionCount} active)`);
55519
55624
  if (this.activeSessionCount === 0) {
55520
55625
  this.stopKeepAlive();
55521
55626
  }
@@ -55529,11 +55634,11 @@ class KeepAliveManager {
55529
55634
  }
55530
55635
  startKeepAlive() {
55531
55636
  if (!this.enabled) {
55532
- log5.debug("Keep-alive disabled, skipping");
55637
+ log6.debug("Keep-alive disabled, skipping");
55533
55638
  return;
55534
55639
  }
55535
55640
  if (this.keepAliveProcess) {
55536
- log5.debug("Keep-alive already running");
55641
+ log6.debug("Keep-alive already running");
55537
55642
  return;
55538
55643
  }
55539
55644
  switch (this.platform) {
@@ -55547,12 +55652,12 @@ class KeepAliveManager {
55547
55652
  this.startWindowsKeepAlive();
55548
55653
  break;
55549
55654
  default:
55550
- log5.warn(`Keep-alive not supported on ${this.platform}`);
55655
+ log6.warn(`Keep-alive not supported on ${this.platform}`);
55551
55656
  }
55552
55657
  }
55553
55658
  stopKeepAlive() {
55554
55659
  if (this.keepAliveProcess) {
55555
- log5.debug("Stopping keep-alive");
55660
+ log6.debug("Stopping keep-alive");
55556
55661
  this.keepAliveProcess.kill();
55557
55662
  this.keepAliveProcess = null;
55558
55663
  }
@@ -55567,18 +55672,18 @@ class KeepAliveManager {
55567
55672
  detached: false
55568
55673
  });
55569
55674
  this.keepAliveProcess.on("error", (err) => {
55570
- log5.error(`Failed to start caffeinate: ${err.message}`);
55675
+ log6.error(`Failed to start caffeinate: ${err.message}`);
55571
55676
  this.keepAliveProcess = null;
55572
55677
  });
55573
55678
  this.keepAliveProcess.on("exit", (code) => {
55574
55679
  if (code !== null && code !== 0 && this.activeSessionCount > 0) {
55575
- log5.debug(`caffeinate exited with code ${code}`);
55680
+ log6.debug(`caffeinate exited with code ${code}`);
55576
55681
  }
55577
55682
  this.keepAliveProcess = null;
55578
55683
  });
55579
- log5.info("Sleep prevention active (caffeinate)");
55684
+ log6.info("Sleep prevention active (caffeinate)");
55580
55685
  } catch (err) {
55581
- log5.error(`Failed to start caffeinate: ${err}`);
55686
+ log6.error(`Failed to start caffeinate: ${err}`);
55582
55687
  }
55583
55688
  }
55584
55689
  startLinuxKeepAlive() {
@@ -55591,19 +55696,19 @@ class KeepAliveManager {
55591
55696
  detached: false
55592
55697
  });
55593
55698
  this.keepAliveProcess.on("error", (err) => {
55594
- log5.debug(`systemd-inhibit not available: ${err.message}`);
55699
+ log6.debug(`systemd-inhibit not available: ${err.message}`);
55595
55700
  this.keepAliveProcess = null;
55596
55701
  this.startLinuxKeepAliveFallback();
55597
55702
  });
55598
55703
  this.keepAliveProcess.on("exit", (code) => {
55599
55704
  if (code !== null && code !== 0 && this.activeSessionCount > 0) {
55600
- log5.debug(`systemd-inhibit exited with code ${code}`);
55705
+ log6.debug(`systemd-inhibit exited with code ${code}`);
55601
55706
  }
55602
55707
  this.keepAliveProcess = null;
55603
55708
  });
55604
- log5.info("Sleep prevention active (systemd-inhibit)");
55709
+ log6.info("Sleep prevention active (systemd-inhibit)");
55605
55710
  } catch (err) {
55606
- log5.debug(`Failed to start systemd-inhibit: ${err}`);
55711
+ log6.debug(`Failed to start systemd-inhibit: ${err}`);
55607
55712
  this.startLinuxKeepAliveFallback();
55608
55713
  }
55609
55714
  }
@@ -55614,15 +55719,15 @@ class KeepAliveManager {
55614
55719
  detached: false
55615
55720
  });
55616
55721
  this.keepAliveProcess.on("error", (err) => {
55617
- log5.warn(`Linux keep-alive fallback not available: ${err.message}`);
55722
+ log6.warn(`Linux keep-alive fallback not available: ${err.message}`);
55618
55723
  this.keepAliveProcess = null;
55619
55724
  });
55620
55725
  this.keepAliveProcess.on("exit", () => {
55621
55726
  this.keepAliveProcess = null;
55622
55727
  });
55623
- log5.info("Sleep prevention active (xdg-screensaver)");
55728
+ log6.info("Sleep prevention active (xdg-screensaver)");
55624
55729
  } catch (err) {
55625
- log5.warn(`Linux keep-alive not available: ${err}`);
55730
+ log6.warn(`Linux keep-alive not available: ${err}`);
55626
55731
  }
55627
55732
  }
55628
55733
  startWindowsKeepAlive() {
@@ -55634,18 +55739,18 @@ class KeepAliveManager {
55634
55739
  windowsHide: true
55635
55740
  });
55636
55741
  this.keepAliveProcess.on("error", (err) => {
55637
- log5.warn(`Windows keep-alive not available: ${err.message}`);
55742
+ log6.warn(`Windows keep-alive not available: ${err.message}`);
55638
55743
  this.keepAliveProcess = null;
55639
55744
  });
55640
55745
  this.keepAliveProcess.on("exit", (code) => {
55641
55746
  if (code !== null && code !== 0 && this.activeSessionCount > 0) {
55642
- log5.debug(`PowerShell keep-alive exited with code ${code}`);
55747
+ log6.debug(`PowerShell keep-alive exited with code ${code}`);
55643
55748
  }
55644
55749
  this.keepAliveProcess = null;
55645
55750
  });
55646
- log5.info("Sleep prevention active (SetThreadExecutionState)");
55751
+ log6.info("Sleep prevention active (SetThreadExecutionState)");
55647
55752
  } catch (err) {
55648
- log5.warn(`Windows keep-alive not available: ${err}`);
55753
+ log6.warn(`Windows keep-alive not available: ${err}`);
55649
55754
  }
55650
55755
  }
55651
55756
  }
@@ -55659,7 +55764,7 @@ function formatSponsorFooter(formatter) {
55659
55764
  }
55660
55765
 
55661
55766
  // src/operations/sticky-message/handler.ts
55662
- var log6 = createLogger("sticky");
55767
+ var log7 = createLogger("sticky");
55663
55768
  var botStartedAt = new Date;
55664
55769
  var stickyPostIds = new Map;
55665
55770
  var needsBump = new Map;
@@ -55898,10 +56003,10 @@ class Redactor {
55898
56003
  }
55899
56004
 
55900
56005
  // src/persistence/thread-logger.ts
55901
- import { homedir as homedir2 } from "os";
55902
- import { join as join2, dirname as dirname4 } from "path";
55903
- var log7 = createLogger("thread-log");
55904
- var LOGS_BASE_DIR = join2(homedir2(), ".claude-threads", "logs");
56006
+ import { homedir as homedir3 } from "os";
56007
+ import { join as join3, dirname as dirname4 } from "path";
56008
+ var log8 = createLogger("thread-log");
56009
+ var LOGS_BASE_DIR = join3(homedir3(), ".claude-threads", "logs");
55905
56010
 
55906
56011
  // src/operations/bug-report/handler.ts
55907
56012
  var piiRedactor = new Redactor({ aggressive: true });
@@ -55924,7 +56029,7 @@ class UsernameAnonymizer {
55924
56029
  // src/mcp/decision-bridge.ts
55925
56030
  import { createServer, createConnection } from "node:net";
55926
56031
  import { tmpdir } from "node:os";
55927
- import { join as join3 } from "node:path";
56032
+ import { join as join4 } from "node:path";
55928
56033
  import { randomUUID } from "node:crypto";
55929
56034
  import { mkdtempSync } from "node:fs";
55930
56035
  import { rm } from "node:fs/promises";
@@ -55935,8 +56040,8 @@ function bridgeSocketPath() {
55935
56040
  if (process.platform === "win32") {
55936
56041
  return `\\\\.\\pipe\\ctb-${randomUUID()}`;
55937
56042
  }
55938
- const dir = mkdtempSync(join3(tmpdir(), "ctb-"));
55939
- return join3(dir, "b.sock");
56043
+ const dir = mkdtempSync(join4(tmpdir(), "ctb-"));
56044
+ return join4(dir, "b.sock");
55940
56045
  }
55941
56046
 
55942
56047
  class DecisionBridgeServer {
@@ -56006,7 +56111,7 @@ class DecisionBridgeServer {
56006
56111
  });
56007
56112
  } catch (err) {
56008
56113
  if (process.platform !== "win32") {
56009
- await rm(join3(path, ".."), { recursive: true, force: true }).catch(() => {});
56114
+ await rm(join4(path, ".."), { recursive: true, force: true }).catch(() => {});
56010
56115
  }
56011
56116
  throw err;
56012
56117
  }
@@ -56019,7 +56124,7 @@ class DecisionBridgeServer {
56019
56124
  socket.destroy();
56020
56125
  await new Promise((resolve4) => this.server.close(() => resolve4()));
56021
56126
  if (process.platform !== "win32") {
56022
- await rm(join3(this.path, ".."), { recursive: true, force: true }).catch(() => {});
56127
+ await rm(join4(this.path, ".."), { recursive: true, force: true }).catch(() => {});
56023
56128
  }
56024
56129
  }
56025
56130
  }
@@ -56082,7 +56187,7 @@ import { resolve as resolve4, dirname as dirname5 } from "path";
56082
56187
  import { fileURLToPath as fileURLToPath3 } from "url";
56083
56188
  import { existsSync as existsSync4, readFileSync as readFileSync3, watchFile, unwatchFile, unlinkSync, statSync, readdirSync, writeFileSync } from "fs";
56084
56189
  import { tmpdir as tmpdir2 } from "os";
56085
- import { join as join4 } from "path";
56190
+ import { join as join5 } from "path";
56086
56191
 
56087
56192
  // src/mcp/outbound-env.ts
56088
56193
  var OUTBOUND_ENV = {
@@ -56173,25 +56278,25 @@ function parseRateLimitEvent(event, now = Date.now()) {
56173
56278
  }
56174
56279
 
56175
56280
  // src/claude/cli.ts
56176
- var log8 = createLogger("claude");
56281
+ var log9 = createLogger("claude");
56177
56282
  function cleanupBrowserBridgeSockets() {
56178
56283
  try {
56179
56284
  const tempDir = tmpdir2();
56180
56285
  const files = readdirSync(tempDir);
56181
56286
  for (const file2 of files) {
56182
56287
  if (file2.startsWith("claude-mcp-browser-bridge-")) {
56183
- const filePath = join4(tempDir, file2);
56288
+ const filePath = join5(tempDir, file2);
56184
56289
  try {
56185
56290
  const stats = statSync(filePath);
56186
56291
  if (stats.isSocket()) {
56187
56292
  unlinkSync(filePath);
56188
- log8.debug(`Removed stale browser bridge socket: ${file2}`);
56293
+ log9.debug(`Removed stale browser bridge socket: ${file2}`);
56189
56294
  }
56190
56295
  } catch {}
56191
56296
  }
56192
56297
  }
56193
56298
  } catch (err) {
56194
- log8.debug(`Browser bridge cleanup failed: ${err}`);
56299
+ log9.debug(`Browser bridge cleanup failed: ${err}`);
56195
56300
  }
56196
56301
  }
56197
56302
  function buildClaudeChildEnv(parentEnv, account, opts) {
@@ -56250,7 +56355,7 @@ function materializeMcpConfig(config3, sessionId, opts = {}) {
56250
56355
  return { mode: "inline", value: JSON.stringify(config3) };
56251
56356
  }
56252
56357
  const dir = opts.tmpDirOverride ?? tmpdir2();
56253
- const path = join4(dir, `claude-threads-mcp-${sessionId ?? process.pid}-${Date.now()}.json`);
56358
+ const path = join5(dir, `claude-threads-mcp-${sessionId ?? process.pid}-${Date.now()}.json`);
56254
56359
  writeFileSync(path, JSON.stringify(config3), { mode: 384 });
56255
56360
  return { mode: "file", path };
56256
56361
  }
@@ -56433,7 +56538,7 @@ class ClaudeCli extends EventEmitter2 {
56433
56538
  }
56434
56539
  let statusLineCommand;
56435
56540
  if (this.options.sessionId) {
56436
- this.statusFilePath = join4(tmpdir2(), `claude-threads-status-${this.options.sessionId}.json`);
56541
+ this.statusFilePath = join5(tmpdir2(), `claude-threads-status-${this.options.sessionId}.json`);
56437
56542
  const statusLineWriterPath = this.getStatusLineWriterPath();
56438
56543
  const runtime = runtimeForScriptPath(statusLineWriterPath);
56439
56544
  statusLineCommand = `${runtime} ${statusLineWriterPath} ${this.options.sessionId}`;
@@ -57355,7 +57460,7 @@ handlers.set("compact", createPassthroughHandler("compact"));
57355
57460
  handlers.set("model", createPassthroughHandler("model"));
57356
57461
  handlers.set("effort", createPassthroughHandler("effort"));
57357
57462
  // src/commands/system-prompt-generator.ts
57358
- var log9 = createLogger("system-prompt");
57463
+ var log10 = createLogger("system-prompt");
57359
57464
  function formatUserCommand(cmd) {
57360
57465
  const cmdStr = cmd.args ? `\`!${cmd.command} ${cmd.args}\`` : `\`!${cmd.command}\``;
57361
57466
  const description = cmd.description;
@@ -57440,7 +57545,7 @@ ${avoidCommands.map((c) => `- \`!${c.command}\` - ${c.reason}`).join(`
57440
57545
  `.trim();
57441
57546
  }
57442
57547
  // src/utils/error-handler/index.ts
57443
- var log10 = createLogger("error");
57548
+ var log11 = createLogger("error");
57444
57549
 
57445
57550
  // src/utils/session-log.ts
57446
57551
  function createSessionLog(baseLog) {
@@ -57457,45 +57562,45 @@ init_emoji();
57457
57562
 
57458
57563
  // src/git/worktree.ts
57459
57564
  import * as path from "path";
57460
- import { homedir as homedir3 } from "os";
57461
- var log11 = createLogger("git-wt");
57462
- var WORKTREES_DIR = path.join(homedir3(), ".claude-threads", "worktrees");
57463
- var METADATA_STORE_PATH = path.join(homedir3(), ".claude-threads", "worktree-metadata.json");
57565
+ import { homedir as homedir4 } from "os";
57566
+ var log12 = createLogger("git-wt");
57567
+ var WORKTREES_DIR = path.join(homedir4(), ".claude-threads", "worktrees");
57568
+ var METADATA_STORE_PATH = path.join(homedir4(), ".claude-threads", "worktree-metadata.json");
57464
57569
 
57465
57570
  // src/operations/post-helpers/index.ts
57466
- var log12 = createLogger("helpers");
57467
- var sessionLog = createSessionLog(log12);
57571
+ var log13 = createLogger("helpers");
57572
+ var sessionLog = createSessionLog(log13);
57468
57573
 
57469
57574
  // src/claude/quick-query.ts
57470
- var log13 = createLogger("query");
57575
+ var log14 = createLogger("query");
57471
57576
 
57472
57577
  // src/operations/suggestions/title.ts
57473
- var log14 = createLogger("title");
57578
+ var log15 = createLogger("title");
57474
57579
 
57475
57580
  // src/operations/suggestions/tag.ts
57476
- var log15 = createLogger("tags");
57581
+ var log16 = createLogger("tags");
57477
57582
 
57478
57583
  // src/operations/context-prompt/handler.ts
57479
57584
  init_emoji();
57480
- var log16 = createLogger("context");
57481
- var sessionLog2 = createSessionLog(log16);
57585
+ var log17 = createLogger("context");
57586
+ var sessionLog2 = createSessionLog(log17);
57482
57587
  var contextPromptTimeouts = new Map;
57483
57588
  var contextPromptFiles = new Map;
57484
57589
  // src/memory/store.ts
57485
57590
  import { createHash } from "crypto";
57486
57591
  import {
57487
- chmodSync,
57592
+ chmodSync as chmodSync2,
57488
57593
  existsSync as existsSync5,
57489
- mkdirSync,
57594
+ mkdirSync as mkdirSync2,
57490
57595
  readFileSync as readFileSync4,
57491
57596
  renameSync,
57492
57597
  realpathSync,
57493
57598
  writeFileSync as writeFileSync2
57494
57599
  } from "fs";
57495
- import { homedir as homedir4 } from "os";
57496
- import { basename as basename3, dirname as dirname7, join as join6, sep as sep2 } from "path";
57497
- var log17 = createLogger("memory");
57498
- var DEFAULT_ROOT = join6(homedir4(), ".config", "claude-threads", "memory");
57600
+ import { homedir as homedir5 } from "os";
57601
+ import { basename as basename3, dirname as dirname7, join as join7, sep as sep2 } from "path";
57602
+ var log18 = createLogger("memory");
57603
+ var DEFAULT_ROOT = join7(homedir5(), ".config", "claude-threads", "memory");
57499
57604
  var CHANNEL_BLOCK_MAX_LINES = 200;
57500
57605
  var CHANNEL_BLOCK_MAX_BYTES = 25 * 1024;
57501
57606
  var CHANNEL_FILE_MAX_ENTRIES = 400;
@@ -57538,10 +57643,10 @@ class MemoryStore {
57538
57643
  return this.root;
57539
57644
  }
57540
57645
  channelMemoryPath(platformId) {
57541
- return join6(this.root, platformSegment(platformId), "channel", "MEMORY.md");
57646
+ return join7(this.root, platformSegment(platformId), "channel", "MEMORY.md");
57542
57647
  }
57543
57648
  repoMemoryDir(platformId, repoKey) {
57544
- const dir = join6(this.root, platformSegment(platformId), "repos", repoKey);
57649
+ const dir = join7(this.root, platformSegment(platformId), "repos", repoKey);
57545
57650
  this.ensureDir(dir);
57546
57651
  return dir;
57547
57652
  }
@@ -57588,7 +57693,7 @@ class MemoryStore {
57588
57693
  if (result.added.length > 0) {
57589
57694
  this.enforceFileCap(lines);
57590
57695
  this.writeLines(platformId, lines);
57591
- log17.debug(`Channel memory for ${platformId}: +${result.added.length} entries` + (result.duplicates.length ? ` (${result.duplicates.length} duplicates skipped)` : ""));
57696
+ log18.debug(`Channel memory for ${platformId}: +${result.added.length} entries` + (result.duplicates.length ? ` (${result.duplicates.length} duplicates skipped)` : ""));
57592
57697
  }
57593
57698
  return result;
57594
57699
  });
@@ -57627,14 +57732,14 @@ class MemoryStore {
57627
57732
  }
57628
57733
  lines.splice(target.lineIndex, 1);
57629
57734
  this.writeLines(platformId, lines);
57630
- log17.debug(`Channel memory for ${platformId}: removed one entry`);
57735
+ log18.debug(`Channel memory for ${platformId}: removed one entry`);
57631
57736
  return { ok: true, removed: target.entry };
57632
57737
  });
57633
57738
  }
57634
57739
  clearChannel(platformId) {
57635
57740
  return this.runExclusive(platformId, () => {
57636
57741
  this.writeLines(platformId, []);
57637
- log17.debug(`Channel memory for ${platformId}: cleared`);
57742
+ log18.debug(`Channel memory for ${platformId}: cleared`);
57638
57743
  });
57639
57744
  }
57640
57745
  buildChannelMemoryBlock(platformId) {
@@ -57642,7 +57747,7 @@ class MemoryStore {
57642
57747
  try {
57643
57748
  lines = this.loadLines(platformId);
57644
57749
  } catch (err) {
57645
- log17.warn(`Failed to read channel memory for ${platformId}: ${err.message}`);
57750
+ log18.warn(`Failed to read channel memory for ${platformId}: ${err.message}`);
57646
57751
  return null;
57647
57752
  }
57648
57753
  if (lines.length === 0)
@@ -57717,21 +57822,22 @@ _(older entries omitted — \`!memory\` shows all)_` : rendered;
57717
57822
  const tempFile = `${file2}.tmp`;
57718
57823
  writeFileSync2(tempFile, content, { encoding: "utf-8", mode: 384 });
57719
57824
  renameSync(tempFile, file2);
57720
- chmodSync(file2, 384);
57825
+ chmodSync2(file2, 384);
57721
57826
  }
57722
57827
  ensureDir(dir) {
57723
57828
  if (!existsSync5(dir)) {
57724
- mkdirSync(dir, { recursive: true, mode: 448 });
57829
+ mkdirSync2(dir, { recursive: true, mode: 448 });
57725
57830
  }
57726
57831
  }
57727
57832
  }
57728
57833
 
57729
57834
  // src/memory/distiller.ts
57730
- var log18 = createLogger("memory");
57835
+ var log19 = createLogger("memory");
57731
57836
 
57732
57837
  // src/session/lifecycle.ts
57733
- var log19 = createLogger("lifecycle");
57734
- var sessionLog3 = createSessionLog(log19);
57838
+ var log20 = createLogger("lifecycle");
57839
+ var sessionLog3 = createSessionLog(log20);
57840
+ var _inFlightSessionStarts = new Map;
57735
57841
  var CHAT_PLATFORM_PROMPT = generateChatPlatformPrompt();
57736
57842
  // src/update-notifier.ts
57737
57843
  var import_semver2 = __toESM(require_semver2(), 1);
@@ -57740,20 +57846,20 @@ var import_semver2 = __toESM(require_semver2(), 1);
57740
57846
  init_emoji();
57741
57847
 
57742
57848
  // src/persistence/github-emails-store.ts
57743
- import { homedir as homedir5 } from "os";
57744
- import { join as join7 } from "path";
57745
- var log20 = createLogger("gh-emails");
57746
- var DEFAULT_CONFIG_DIR = join7(homedir5(), ".config", "claude-threads");
57747
- var DEFAULT_FILE = join7(DEFAULT_CONFIG_DIR, "github-emails.yaml");
57748
-
57749
- // src/persistence/routines-store.ts
57750
- import { existsSync as existsSync6, mkdirSync as mkdirSync2, readFileSync as readFileSync5 } from "fs";
57751
57849
  import { homedir as homedir6 } from "os";
57752
57850
  import { join as join8 } from "path";
57851
+ var log21 = createLogger("gh-emails");
57852
+ var DEFAULT_CONFIG_DIR = join8(homedir6(), ".config", "claude-threads");
57853
+ var DEFAULT_FILE = join8(DEFAULT_CONFIG_DIR, "github-emails.yaml");
57854
+
57855
+ // src/persistence/routines-store.ts
57856
+ import { existsSync as existsSync6, mkdirSync as mkdirSync3, readFileSync as readFileSync5 } from "fs";
57857
+ import { homedir as homedir7 } from "os";
57858
+ import { join as join9 } from "path";
57753
57859
  import { randomUUID as randomUUID2 } from "crypto";
57754
57860
 
57755
57861
  // src/persistence/atomic-file.ts
57756
- import { chmodSync as chmodSync2, renameSync as renameSync2, writeFileSync as writeFileSync3 } from "fs";
57862
+ import { chmodSync as chmodSync3, renameSync as renameSync2, writeFileSync as writeFileSync3 } from "fs";
57757
57863
 
57758
57864
  class SerialQueue {
57759
57865
  tail = Promise.resolve();
@@ -57769,13 +57875,13 @@ function writeFileAtomic(file2, content) {
57769
57875
  const tempFile = `${file2}.tmp`;
57770
57876
  writeFileSync3(tempFile, content, { encoding: "utf-8", mode: 384 });
57771
57877
  renameSync2(tempFile, file2);
57772
- chmodSync2(file2, 384);
57878
+ chmodSync3(file2, 384);
57773
57879
  }
57774
57880
 
57775
57881
  // src/persistence/routines-store.ts
57776
- var log21 = createLogger("routines");
57777
- var DEFAULT_CONFIG_DIR2 = join8(homedir6(), ".config", "claude-threads");
57778
- var DEFAULT_FILE2 = join8(DEFAULT_CONFIG_DIR2, "routines.yaml");
57882
+ var log22 = createLogger("routines");
57883
+ var DEFAULT_CONFIG_DIR2 = join9(homedir7(), ".config", "claude-threads");
57884
+ var DEFAULT_FILE2 = join9(DEFAULT_CONFIG_DIR2, "routines.yaml");
57779
57885
  var STORE_VERSION = 1;
57780
57886
  var DEFAULT_MAX_ROUTINES = 10;
57781
57887
  var SCHEDULE_PRESETS = ["hourly", "daily", "weekdays", "weekly"];
@@ -57819,13 +57925,13 @@ class RoutinesStore {
57819
57925
  const effective = filePath ?? process.env.CLAUDE_THREADS_ROUTINES_PATH;
57820
57926
  if (effective) {
57821
57927
  this.file = effective;
57822
- this.configDir = join8(effective, "..");
57928
+ this.configDir = join9(effective, "..");
57823
57929
  } else {
57824
57930
  this.file = DEFAULT_FILE2;
57825
57931
  this.configDir = DEFAULT_CONFIG_DIR2;
57826
57932
  }
57827
57933
  if (!existsSync6(this.configDir)) {
57828
- mkdirSync2(this.configDir, { recursive: true, mode: 448 });
57934
+ mkdirSync3(this.configDir, { recursive: true, mode: 448 });
57829
57935
  }
57830
57936
  }
57831
57937
  list(platformId) {
@@ -57859,7 +57965,7 @@ class RoutinesStore {
57859
57965
  };
57860
57966
  data.routines[platformId] = [...existing, full];
57861
57967
  this.writeAtomic(data);
57862
- log21.info(`Routine "${full.name}" created on ${platformId} by @${full.createdBy}`);
57968
+ log22.info(`Routine "${full.name}" created on ${platformId} by @${full.createdBy}`);
57863
57969
  return { ok: true, routine: full };
57864
57970
  });
57865
57971
  }
@@ -57886,7 +57992,7 @@ class RoutinesStore {
57886
57992
  if (routines.length === 0)
57887
57993
  delete data.routines[platformId];
57888
57994
  this.writeAtomic(data);
57889
- log21.info(`Routine "${removed.name}" removed from ${platformId}`);
57995
+ log22.info(`Routine "${removed.name}" removed from ${platformId}`);
57890
57996
  return removed;
57891
57997
  });
57892
57998
  }
@@ -57911,7 +58017,7 @@ class RoutinesStore {
57911
58017
  }
57912
58018
  return { version: parsed.version ?? STORE_VERSION, routines };
57913
58019
  } catch (err) {
57914
- log21.warn(`Failed to read ${this.file}: ${err.message} — starting empty`);
58020
+ log22.warn(`Failed to read ${this.file}: ${err.message} — starting empty`);
57915
58021
  return { version: STORE_VERSION, routines: {} };
57916
58022
  }
57917
58023
  }
@@ -57921,25 +58027,25 @@ class RoutinesStore {
57921
58027
  }
57922
58028
 
57923
58029
  // src/routines/parser.ts
57924
- var log22 = createLogger("routines");
58030
+ var log23 = createLogger("routines");
57925
58031
 
57926
58032
  // src/operations/commands/handler.ts
57927
- var log23 = createLogger("commands");
57928
- var sessionLog4 = createSessionLog(log23);
58033
+ var log24 = createLogger("commands");
58034
+ var sessionLog4 = createSessionLog(log24);
57929
58035
  // src/operations/suggestions/branch.ts
57930
58036
  import { exec as exec2 } from "child_process";
57931
58037
  import { promisify as promisify2 } from "util";
57932
58038
  var execAsync2 = promisify2(exec2);
57933
- var log24 = createLogger("branch");
58039
+ var log25 = createLogger("branch");
57934
58040
 
57935
58041
  // src/operations/worktree/handler.ts
57936
- var log25 = createLogger("worktree");
57937
- var sessionLog5 = createSessionLog(log25);
58042
+ var log26 = createLogger("worktree");
58043
+ var sessionLog5 = createSessionLog(log26);
57938
58044
  // src/operations/events/handler.ts
57939
- var log26 = createLogger("events");
57940
- var sessionLog6 = createSessionLog(log26);
58045
+ var log27 = createLogger("events");
58046
+ var sessionLog6 = createSessionLog(log27);
57941
58047
  // src/operations/monitor/handler.ts
57942
- var log27 = createLogger("monitor");
58048
+ var log28 = createLogger("monitor");
57943
58049
  var DEFAULT_INTERVAL_MS = 60 * 1000;
57944
58050
  // src/utils/websocket.ts
57945
58051
  var WS;
@@ -58021,7 +58127,7 @@ ${code}
58021
58127
 
58022
58128
  // src/platform/mattermost/upload.ts
58023
58129
  import { readFile } from "fs/promises";
58024
- var log28 = createLogger("mm-upload");
58130
+ var log29 = createLogger("mm-upload");
58025
58131
  async function uploadFileMattermost(args) {
58026
58132
  const { url: url2, token, channelId, threadId, filePath, filename, caption } = args;
58027
58133
  const buffer = await readFile(filePath);
@@ -58029,7 +58135,7 @@ async function uploadFileMattermost(args) {
58029
58135
  const arrayBuffer = buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength);
58030
58136
  const formData = new FormData;
58031
58137
  formData.append("files", new Blob([arrayBuffer]), filename);
58032
- log28.debug(`POST /files (${buffer.length} bytes, ${filename})`);
58138
+ log29.debug(`POST /files (${buffer.length} bytes, ${filename})`);
58033
58139
  const uploadResponse = await fetch(uploadUrl, {
58034
58140
  method: "POST",
58035
58141
  headers: {
@@ -58050,10 +58156,10 @@ async function uploadFileMattermost(args) {
58050
58156
  const postBody = {
58051
58157
  channel_id: channelId,
58052
58158
  message: caption ?? "",
58053
- root_id: threadId,
58159
+ root_id: resolvePostThreadId(threadId),
58054
58160
  file_ids: [fileInfo.id]
58055
58161
  };
58056
- log28.debug(`POST /posts (file_ids=[${fileInfo.id}])`);
58162
+ log29.debug(`POST /posts (file_ids=[${fileInfo.id}])`);
58057
58163
  const postResponse = await fetch(postUrl, {
58058
58164
  method: "POST",
58059
58165
  headers: {
@@ -58106,7 +58212,7 @@ async function createPost(config3, channelId, message, rootId) {
58106
58212
  return mattermostApi(config3, "POST", "/posts", {
58107
58213
  channel_id: channelId,
58108
58214
  message,
58109
- root_id: rootId
58215
+ root_id: resolvePostThreadId(rootId)
58110
58216
  });
58111
58217
  }
58112
58218
  async function updatePostRaw(config3, postId, message) {
@@ -58547,7 +58653,7 @@ ${code}
58547
58653
 
58548
58654
  // src/platform/slack/upload.ts
58549
58655
  import { readFile as readFile2 } from "fs/promises";
58550
- var log29 = createLogger("slack-upload");
58656
+ var log30 = createLogger("slack-upload");
58551
58657
  var DEFAULT_API_URL = "https://slack.com/api";
58552
58658
  async function uploadFileSlack(args) {
58553
58659
  const { botToken, channelId, threadTs, filePath, filename, caption } = args;
@@ -58555,7 +58661,7 @@ async function uploadFileSlack(args) {
58555
58661
  const buffer = await readFile2(filePath);
58556
58662
  const params = new URLSearchParams({ filename, length: String(buffer.length) });
58557
58663
  const step1Url = `${apiUrl}/files.getUploadURLExternal?${params.toString()}`;
58558
- log29.debug(`GET files.getUploadURLExternal (${buffer.length} bytes, ${filename})`);
58664
+ log30.debug(`GET files.getUploadURLExternal (${buffer.length} bytes, ${filename})`);
58559
58665
  const step1Response = await fetch(step1Url, {
58560
58666
  method: "GET",
58561
58667
  headers: {
@@ -58573,7 +58679,7 @@ async function uploadFileSlack(args) {
58573
58679
  const uploadUrl = step1Data.upload_url;
58574
58680
  const fileId = step1Data.file_id;
58575
58681
  const arrayBuffer = buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength);
58576
- log29.debug(`POST <upload_url>`);
58682
+ log30.debug(`POST <upload_url>`);
58577
58683
  const step2Response = await fetch(uploadUrl, {
58578
58684
  method: "POST",
58579
58685
  headers: {
@@ -58588,12 +58694,12 @@ async function uploadFileSlack(args) {
58588
58694
  const step3Body = {
58589
58695
  files: [{ id: fileId, title: caption ?? filename }],
58590
58696
  channel_id: channelId,
58591
- thread_ts: threadTs
58697
+ thread_ts: resolvePostThreadId(threadTs)
58592
58698
  };
58593
58699
  if (caption !== undefined) {
58594
58700
  step3Body.initial_comment = caption;
58595
58701
  }
58596
- log29.debug(`POST files.completeUploadExternal (file_id=${fileId}, thread_ts=${threadTs})`);
58702
+ log30.debug(`POST files.completeUploadExternal (file_id=${fileId}, thread_ts=${threadTs})`);
58597
58703
  const step3Response = await fetch(`${apiUrl}/files.completeUploadExternal`, {
58598
58704
  method: "POST",
58599
58705
  headers: {
@@ -58611,7 +58717,7 @@ async function uploadFileSlack(args) {
58611
58717
  throw new Error(`Slack completeUploadExternal error: ${step3Data.error || "unknown"}`);
58612
58718
  }
58613
58719
  if (!step3Data.ts) {
58614
- log29.warn(`Slack completeUploadExternal returned no ts; using fileId ${fileId} as postId. ` + `Do not use this id for updatePost/addReaction.`);
58720
+ log30.warn(`Slack completeUploadExternal returned no ts; using fileId ${fileId} as postId. ` + `Do not use this id for updatePost/addReaction.`);
58615
58721
  }
58616
58722
  return { fileId, postId: step3Data.ts ?? fileId };
58617
58723
  }
@@ -58687,7 +58793,7 @@ class SlackMcpPlatformApi {
58687
58793
  const response = await slackApi("chat.postMessage", this.config.botToken, {
58688
58794
  channel: this.config.channelId,
58689
58795
  text: message,
58690
- thread_ts: threadTs || this.config.threadTs,
58796
+ thread_ts: resolvePostThreadId(threadTs || this.config.threadTs),
58691
58797
  mrkdwn: true
58692
58798
  });
58693
58799
  const messageTs = response.ts;
@@ -59631,6 +59737,12 @@ async function resolveLatestThreadPost(cfg) {
59631
59737
  if (!cfg.sessionThreadId) {
59632
59738
  return { ok: false, reason: "no session thread to react in — pass a permalink URL instead" };
59633
59739
  }
59740
+ if (isDcmThreadId(cfg.sessionThreadId)) {
59741
+ return {
59742
+ ok: false,
59743
+ reason: "this session runs in direct channel mode (no thread of its own) — pass a permalink URL to the target message instead"
59744
+ };
59745
+ }
59634
59746
  let thread;
59635
59747
  try {
59636
59748
  thread = await cfg.api.readThread(cfg.sessionThreadId);
@@ -59732,6 +59844,12 @@ async function handleListThreadWith(args, cfg) {
59732
59844
  reason: "no session thread to read — pass a permalink URL instead"
59733
59845
  };
59734
59846
  }
59847
+ if (isDcmThreadId(cfg.sessionThreadId)) {
59848
+ return {
59849
+ ok: false,
59850
+ reason: "this session runs in direct channel mode (no thread of its own) — use read_channel_history, or pass a permalink URL"
59851
+ };
59852
+ }
59735
59853
  rootId = cfg.sessionThreadId;
59736
59854
  }
59737
59855
  const limit = clampThreadLimit(args.max_messages);