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.
- package/CHANGELOG.md +9 -0
- package/README.md +9 -0
- package/dist/index.js +752 -467
- package/dist/mcp/mcp-server.js +110 -88
- package/docs/CONFIGURATION.md +33 -0
- package/docs/audio-transcription-spec.md +151 -0
- package/package.json +1 -1
package/dist/mcp/mcp-server.js
CHANGED
|
@@ -14699,12 +14699,12 @@ var init_spawn = __esm(() => {
|
|
|
14699
14699
|
});
|
|
14700
14700
|
|
|
14701
14701
|
// src/claude/quick-query.ts
|
|
14702
|
-
var
|
|
14702
|
+
var log16;
|
|
14703
14703
|
var init_quick_query = __esm(() => {
|
|
14704
14704
|
init_spawn();
|
|
14705
14705
|
init_version_check();
|
|
14706
14706
|
init_logger();
|
|
14707
|
-
|
|
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
|
|
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
|
|
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 =
|
|
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 =
|
|
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:
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
56284
|
+
log8.debug("Keep-alive disabled, skipping");
|
|
56263
56285
|
return;
|
|
56264
56286
|
}
|
|
56265
56287
|
if (this.keepAliveProcess) {
|
|
56266
|
-
|
|
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
|
-
|
|
56302
|
+
log8.warn(`Keep-alive not supported on ${this.platform}`);
|
|
56281
56303
|
}
|
|
56282
56304
|
}
|
|
56283
56305
|
stopKeepAlive() {
|
|
56284
56306
|
if (this.keepAliveProcess) {
|
|
56285
|
-
|
|
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
|
-
|
|
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
|
-
|
|
56327
|
+
log8.debug(`caffeinate exited with code ${code}`);
|
|
56306
56328
|
}
|
|
56307
56329
|
this.keepAliveProcess = null;
|
|
56308
56330
|
});
|
|
56309
|
-
|
|
56331
|
+
log8.info("Sleep prevention active (caffeinate)");
|
|
56310
56332
|
} catch (err) {
|
|
56311
|
-
|
|
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
|
-
|
|
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
|
-
|
|
56352
|
+
log8.debug(`systemd-inhibit exited with code ${code}`);
|
|
56331
56353
|
}
|
|
56332
56354
|
this.keepAliveProcess = null;
|
|
56333
56355
|
});
|
|
56334
|
-
|
|
56356
|
+
log8.info("Sleep prevention active (systemd-inhibit)");
|
|
56335
56357
|
} catch (err) {
|
|
56336
|
-
|
|
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
|
-
|
|
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
|
-
|
|
56375
|
+
log8.info("Sleep prevention active (xdg-screensaver)");
|
|
56354
56376
|
} catch (err) {
|
|
56355
|
-
|
|
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
|
-
|
|
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
|
-
|
|
56394
|
+
log8.debug(`PowerShell keep-alive exited with code ${code}`);
|
|
56373
56395
|
}
|
|
56374
56396
|
this.keepAliveProcess = null;
|
|
56375
56397
|
});
|
|
56376
|
-
|
|
56398
|
+
log8.info("Sleep prevention active (SetThreadExecutionState)");
|
|
56377
56399
|
} catch (err) {
|
|
56378
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
56950
|
+
log11.debug(`Removed stale browser bridge socket: ${file2}`);
|
|
56929
56951
|
}
|
|
56930
56952
|
} catch {}
|
|
56931
56953
|
}
|
|
56932
56954
|
}
|
|
56933
56955
|
} catch (err) {
|
|
56934
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
58286
|
-
var sessionLog = createSessionLog(
|
|
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
|
|
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
|
|
58318
|
+
var log18 = createLogger("tags");
|
|
58297
58319
|
|
|
58298
58320
|
// src/session/metadata-suggestions.ts
|
|
58299
58321
|
init_logger();
|
|
58300
|
-
var
|
|
58301
|
-
var sessionLog2 = createSessionLog(
|
|
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
|
|
58307
|
-
var sessionLog3 = createSessionLog(
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
58856
|
+
var log26 = createLogger("watches");
|
|
58835
58857
|
|
|
58836
58858
|
// src/operations/commands/guards.ts
|
|
58837
58859
|
init_logger();
|
|
58838
|
-
var
|
|
58839
|
-
var sessionLog4 = createSessionLog(
|
|
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
|
|
58844
|
-
var sessionLog5 = createSessionLog(
|
|
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
|
|
58849
|
-
var sessionLog6 = createSessionLog(
|
|
58870
|
+
var log29 = createLogger("agent-actions");
|
|
58871
|
+
var sessionLog6 = createSessionLog(log29);
|
|
58850
58872
|
|
|
58851
58873
|
// src/session/lifecycle.ts
|
|
58852
|
-
var
|
|
58853
|
-
var sessionLog7 = createSessionLog(
|
|
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
|
|
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
|
|
58875
|
-
var sessionLog8 = createSessionLog(
|
|
58896
|
+
var log32 = createLogger("commands");
|
|
58897
|
+
var sessionLog8 = createSessionLog(log32);
|
|
58876
58898
|
// src/operations/commands/memory.ts
|
|
58877
58899
|
init_logger();
|
|
58878
|
-
var
|
|
58879
|
-
var sessionLog9 = createSessionLog(
|
|
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
|
|
58908
|
+
var log34 = createLogger("branch");
|
|
58887
58909
|
|
|
58888
58910
|
// src/operations/worktree/handler.ts
|
|
58889
58911
|
init_logger();
|
|
58890
|
-
var
|
|
58891
|
-
var sessionLog10 = createSessionLog(
|
|
58912
|
+
var log35 = createLogger("worktree");
|
|
58913
|
+
var sessionLog10 = createSessionLog(log35);
|
|
58892
58914
|
// src/operations/events/handler.ts
|
|
58893
58915
|
init_logger();
|
|
58894
|
-
var
|
|
58895
|
-
var sessionLog11 = createSessionLog(
|
|
58916
|
+
var log36 = createLogger("events");
|
|
58917
|
+
var sessionLog11 = createSessionLog(log36);
|
|
58896
58918
|
// src/operations/monitor/handler.ts
|
|
58897
58919
|
init_logger();
|
|
58898
|
-
var
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
}
|
package/docs/CONFIGURATION.md
CHANGED
|
@@ -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
|