mirror of
https://github.com/getcompanion-ai/co-mono.git
synced 2026-04-15 17:00:59 +00:00
mom: fix attachment downloads - pass store to SlackBot, process files, use absolute paths
This commit is contained in:
parent
d277d739b3
commit
e3576fe016
4 changed files with 246 additions and 107 deletions
|
|
@ -842,6 +842,23 @@ export const MODELS = {
|
|||
contextWindow: 200000,
|
||||
maxTokens: 100000,
|
||||
} satisfies Model<"openai-responses">,
|
||||
"gpt-5.2-pro": {
|
||||
id: "gpt-5.2-pro",
|
||||
name: "GPT-5.2 Pro",
|
||||
api: "openai-responses",
|
||||
provider: "openai",
|
||||
baseUrl: "https://api.openai.com/v1",
|
||||
reasoning: true,
|
||||
input: ["text", "image"],
|
||||
cost: {
|
||||
input: 21,
|
||||
output: 168,
|
||||
cacheRead: 0,
|
||||
cacheWrite: 0,
|
||||
},
|
||||
contextWindow: 400000,
|
||||
maxTokens: 128000,
|
||||
} satisfies Model<"openai-responses">,
|
||||
"gpt-4-turbo": {
|
||||
id: "gpt-4-turbo",
|
||||
name: "GPT-4 Turbo",
|
||||
|
|
@ -893,6 +910,23 @@ export const MODELS = {
|
|||
contextWindow: 200000,
|
||||
maxTokens: 100000,
|
||||
} satisfies Model<"openai-responses">,
|
||||
"gpt-5.2-chat-latest": {
|
||||
id: "gpt-5.2-chat-latest",
|
||||
name: "GPT-5.2 Chat",
|
||||
api: "openai-responses",
|
||||
provider: "openai",
|
||||
baseUrl: "https://api.openai.com/v1",
|
||||
reasoning: true,
|
||||
input: ["text", "image"],
|
||||
cost: {
|
||||
input: 1.75,
|
||||
output: 14,
|
||||
cacheRead: 0.175,
|
||||
cacheWrite: 0,
|
||||
},
|
||||
contextWindow: 128000,
|
||||
maxTokens: 16384,
|
||||
} satisfies Model<"openai-responses">,
|
||||
"gpt-5.1": {
|
||||
id: "gpt-5.1",
|
||||
name: "GPT-5.1",
|
||||
|
|
@ -1182,6 +1216,23 @@ export const MODELS = {
|
|||
contextWindow: 400000,
|
||||
maxTokens: 272000,
|
||||
} satisfies Model<"openai-responses">,
|
||||
"gpt-5.2": {
|
||||
id: "gpt-5.2",
|
||||
name: "GPT-5.2",
|
||||
api: "openai-responses",
|
||||
provider: "openai",
|
||||
baseUrl: "https://api.openai.com/v1",
|
||||
reasoning: true,
|
||||
input: ["text", "image"],
|
||||
cost: {
|
||||
input: 1.75,
|
||||
output: 14,
|
||||
cacheRead: 0.175,
|
||||
cacheWrite: 0,
|
||||
},
|
||||
contextWindow: 400000,
|
||||
maxTokens: 128000,
|
||||
} satisfies Model<"openai-responses">,
|
||||
"gpt-5.1-chat-latest": {
|
||||
id: "gpt-5.1-chat-latest",
|
||||
name: "GPT-5.1 Chat",
|
||||
|
|
@ -2093,6 +2144,23 @@ export const MODELS = {
|
|||
contextWindow: 128000,
|
||||
maxTokens: 128000,
|
||||
} satisfies Model<"openai-completions">,
|
||||
"mistral-small-2506": {
|
||||
id: "mistral-small-2506",
|
||||
name: "Mistral Small 3.2",
|
||||
api: "openai-completions",
|
||||
provider: "mistral",
|
||||
baseUrl: "https://api.mistral.ai/v1",
|
||||
reasoning: false,
|
||||
input: ["text", "image"],
|
||||
cost: {
|
||||
input: 0.1,
|
||||
output: 0.3,
|
||||
cacheRead: 0,
|
||||
cacheWrite: 0,
|
||||
},
|
||||
contextWindow: 128000,
|
||||
maxTokens: 16384,
|
||||
} satisfies Model<"openai-completions">,
|
||||
"ministral-3b-latest": {
|
||||
id: "ministral-3b-latest",
|
||||
name: "Ministral 3B",
|
||||
|
|
@ -2401,6 +2469,57 @@ export const MODELS = {
|
|||
} satisfies Model<"openai-completions">,
|
||||
},
|
||||
openrouter: {
|
||||
"openai/gpt-5.2-chat": {
|
||||
id: "openai/gpt-5.2-chat",
|
||||
name: "OpenAI: GPT-5.2 Chat",
|
||||
api: "openai-completions",
|
||||
provider: "openrouter",
|
||||
baseUrl: "https://openrouter.ai/api/v1",
|
||||
reasoning: false,
|
||||
input: ["text", "image"],
|
||||
cost: {
|
||||
input: 1.75,
|
||||
output: 14,
|
||||
cacheRead: 0.175,
|
||||
cacheWrite: 0,
|
||||
},
|
||||
contextWindow: 128000,
|
||||
maxTokens: 16384,
|
||||
} satisfies Model<"openai-completions">,
|
||||
"openai/gpt-5.2-pro": {
|
||||
id: "openai/gpt-5.2-pro",
|
||||
name: "OpenAI: GPT-5.2 Pro",
|
||||
api: "openai-completions",
|
||||
provider: "openrouter",
|
||||
baseUrl: "https://openrouter.ai/api/v1",
|
||||
reasoning: true,
|
||||
input: ["text", "image"],
|
||||
cost: {
|
||||
input: 21,
|
||||
output: 168,
|
||||
cacheRead: 0,
|
||||
cacheWrite: 0,
|
||||
},
|
||||
contextWindow: 400000,
|
||||
maxTokens: 128000,
|
||||
} satisfies Model<"openai-completions">,
|
||||
"openai/gpt-5.2": {
|
||||
id: "openai/gpt-5.2",
|
||||
name: "OpenAI: GPT-5.2",
|
||||
api: "openai-completions",
|
||||
provider: "openrouter",
|
||||
baseUrl: "https://openrouter.ai/api/v1",
|
||||
reasoning: true,
|
||||
input: ["text", "image"],
|
||||
cost: {
|
||||
input: 1.75,
|
||||
output: 14,
|
||||
cacheRead: 0.175,
|
||||
cacheWrite: 0,
|
||||
},
|
||||
contextWindow: 400000,
|
||||
maxTokens: 128000,
|
||||
} satisfies Model<"openai-completions">,
|
||||
"mistralai/devstral-2512:free": {
|
||||
id: "mistralai/devstral-2512:free",
|
||||
name: "Mistral: Devstral 2 2512 (free)",
|
||||
|
|
@ -2475,7 +2594,7 @@ export const MODELS = {
|
|||
api: "openai-completions",
|
||||
provider: "openrouter",
|
||||
baseUrl: "https://openrouter.ai/api/v1",
|
||||
reasoning: true,
|
||||
reasoning: false,
|
||||
input: ["text"],
|
||||
cost: {
|
||||
input: 0,
|
||||
|
|
@ -2648,9 +2767,9 @@ export const MODELS = {
|
|||
reasoning: true,
|
||||
input: ["text"],
|
||||
cost: {
|
||||
input: 0.26,
|
||||
output: 0.39,
|
||||
cacheRead: 0.19999999999999998,
|
||||
input: 0.25,
|
||||
output: 0.38,
|
||||
cacheRead: 0.19,
|
||||
cacheWrite: 0,
|
||||
},
|
||||
contextWindow: 163840,
|
||||
|
|
@ -3192,13 +3311,13 @@ export const MODELS = {
|
|||
reasoning: true,
|
||||
input: ["text"],
|
||||
cost: {
|
||||
input: 0.43,
|
||||
output: 1.75,
|
||||
cacheRead: 0.0799999993,
|
||||
input: 0.44,
|
||||
output: 1.76,
|
||||
cacheRead: 0,
|
||||
cacheWrite: 0,
|
||||
},
|
||||
contextWindow: 202752,
|
||||
maxTokens: 4096,
|
||||
contextWindow: 204800,
|
||||
maxTokens: 131072,
|
||||
} satisfies Model<"openai-completions">,
|
||||
"anthropic/claude-sonnet-4.5": {
|
||||
id: "anthropic/claude-sonnet-4.5",
|
||||
|
|
@ -5512,23 +5631,6 @@ export const MODELS = {
|
|||
contextWindow: 200000,
|
||||
maxTokens: 8192,
|
||||
} satisfies Model<"openai-completions">,
|
||||
"mistralai/ministral-3b": {
|
||||
id: "mistralai/ministral-3b",
|
||||
name: "Mistral: Ministral 3B",
|
||||
api: "openai-completions",
|
||||
provider: "openrouter",
|
||||
baseUrl: "https://openrouter.ai/api/v1",
|
||||
reasoning: false,
|
||||
input: ["text"],
|
||||
cost: {
|
||||
input: 0.04,
|
||||
output: 0.04,
|
||||
cacheRead: 0,
|
||||
cacheWrite: 0,
|
||||
},
|
||||
contextWindow: 131072,
|
||||
maxTokens: 4096,
|
||||
} satisfies Model<"openai-completions">,
|
||||
"mistralai/ministral-8b": {
|
||||
id: "mistralai/ministral-8b",
|
||||
name: "Mistral: Ministral 8B",
|
||||
|
|
@ -5546,6 +5648,23 @@ export const MODELS = {
|
|||
contextWindow: 131072,
|
||||
maxTokens: 4096,
|
||||
} satisfies Model<"openai-completions">,
|
||||
"mistralai/ministral-3b": {
|
||||
id: "mistralai/ministral-3b",
|
||||
name: "Mistral: Ministral 3B",
|
||||
api: "openai-completions",
|
||||
provider: "openrouter",
|
||||
baseUrl: "https://openrouter.ai/api/v1",
|
||||
reasoning: false,
|
||||
input: ["text"],
|
||||
cost: {
|
||||
input: 0.04,
|
||||
output: 0.04,
|
||||
cacheRead: 0,
|
||||
cacheWrite: 0,
|
||||
},
|
||||
contextWindow: 131072,
|
||||
maxTokens: 4096,
|
||||
} satisfies Model<"openai-completions">,
|
||||
"nvidia/llama-3.1-nemotron-70b-instruct": {
|
||||
id: "nvidia/llama-3.1-nemotron-70b-instruct",
|
||||
name: "NVIDIA: Llama 3.1 Nemotron 70B Instruct",
|
||||
|
|
@ -5716,22 +5835,22 @@ export const MODELS = {
|
|||
contextWindow: 128000,
|
||||
maxTokens: 16384,
|
||||
} satisfies Model<"openai-completions">,
|
||||
"meta-llama/llama-3.1-70b-instruct": {
|
||||
id: "meta-llama/llama-3.1-70b-instruct",
|
||||
name: "Meta: Llama 3.1 70B Instruct",
|
||||
"meta-llama/llama-3.1-8b-instruct": {
|
||||
id: "meta-llama/llama-3.1-8b-instruct",
|
||||
name: "Meta: Llama 3.1 8B Instruct",
|
||||
api: "openai-completions",
|
||||
provider: "openrouter",
|
||||
baseUrl: "https://openrouter.ai/api/v1",
|
||||
reasoning: false,
|
||||
input: ["text"],
|
||||
cost: {
|
||||
input: 0.39999999999999997,
|
||||
output: 0.39999999999999997,
|
||||
input: 0.02,
|
||||
output: 0.03,
|
||||
cacheRead: 0,
|
||||
cacheWrite: 0,
|
||||
},
|
||||
contextWindow: 131072,
|
||||
maxTokens: 4096,
|
||||
maxTokens: 16384,
|
||||
} satisfies Model<"openai-completions">,
|
||||
"meta-llama/llama-3.1-405b-instruct": {
|
||||
id: "meta-llama/llama-3.1-405b-instruct",
|
||||
|
|
@ -5750,22 +5869,22 @@ export const MODELS = {
|
|||
contextWindow: 130815,
|
||||
maxTokens: 4096,
|
||||
} satisfies Model<"openai-completions">,
|
||||
"meta-llama/llama-3.1-8b-instruct": {
|
||||
id: "meta-llama/llama-3.1-8b-instruct",
|
||||
name: "Meta: Llama 3.1 8B Instruct",
|
||||
"meta-llama/llama-3.1-70b-instruct": {
|
||||
id: "meta-llama/llama-3.1-70b-instruct",
|
||||
name: "Meta: Llama 3.1 70B Instruct",
|
||||
api: "openai-completions",
|
||||
provider: "openrouter",
|
||||
baseUrl: "https://openrouter.ai/api/v1",
|
||||
reasoning: false,
|
||||
input: ["text"],
|
||||
cost: {
|
||||
input: 0.02,
|
||||
output: 0.03,
|
||||
input: 0.39999999999999997,
|
||||
output: 0.39999999999999997,
|
||||
cacheRead: 0,
|
||||
cacheWrite: 0,
|
||||
},
|
||||
contextWindow: 131072,
|
||||
maxTokens: 16384,
|
||||
maxTokens: 4096,
|
||||
} satisfies Model<"openai-completions">,
|
||||
"mistralai/mistral-nemo": {
|
||||
id: "mistralai/mistral-nemo",
|
||||
|
|
@ -5903,6 +6022,23 @@ export const MODELS = {
|
|||
contextWindow: 128000,
|
||||
maxTokens: 4096,
|
||||
} satisfies Model<"openai-completions">,
|
||||
"openai/gpt-4o-2024-05-13": {
|
||||
id: "openai/gpt-4o-2024-05-13",
|
||||
name: "OpenAI: GPT-4o (2024-05-13)",
|
||||
api: "openai-completions",
|
||||
provider: "openrouter",
|
||||
baseUrl: "https://openrouter.ai/api/v1",
|
||||
reasoning: false,
|
||||
input: ["text", "image"],
|
||||
cost: {
|
||||
input: 5,
|
||||
output: 15,
|
||||
cacheRead: 0,
|
||||
cacheWrite: 0,
|
||||
},
|
||||
contextWindow: 128000,
|
||||
maxTokens: 4096,
|
||||
} satisfies Model<"openai-completions">,
|
||||
"openai/gpt-4o": {
|
||||
id: "openai/gpt-4o",
|
||||
name: "OpenAI: GPT-4o",
|
||||
|
|
@ -5937,22 +6073,22 @@ export const MODELS = {
|
|||
contextWindow: 128000,
|
||||
maxTokens: 64000,
|
||||
} satisfies Model<"openai-completions">,
|
||||
"openai/gpt-4o-2024-05-13": {
|
||||
id: "openai/gpt-4o-2024-05-13",
|
||||
name: "OpenAI: GPT-4o (2024-05-13)",
|
||||
"meta-llama/llama-3-70b-instruct": {
|
||||
id: "meta-llama/llama-3-70b-instruct",
|
||||
name: "Meta: Llama 3 70B Instruct",
|
||||
api: "openai-completions",
|
||||
provider: "openrouter",
|
||||
baseUrl: "https://openrouter.ai/api/v1",
|
||||
reasoning: false,
|
||||
input: ["text", "image"],
|
||||
input: ["text"],
|
||||
cost: {
|
||||
input: 5,
|
||||
output: 15,
|
||||
input: 0.3,
|
||||
output: 0.39999999999999997,
|
||||
cacheRead: 0,
|
||||
cacheWrite: 0,
|
||||
},
|
||||
contextWindow: 128000,
|
||||
maxTokens: 4096,
|
||||
contextWindow: 8192,
|
||||
maxTokens: 16384,
|
||||
} satisfies Model<"openai-completions">,
|
||||
"meta-llama/llama-3-8b-instruct": {
|
||||
id: "meta-llama/llama-3-8b-instruct",
|
||||
|
|
@ -5971,23 +6107,6 @@ export const MODELS = {
|
|||
contextWindow: 8192,
|
||||
maxTokens: 16384,
|
||||
} satisfies Model<"openai-completions">,
|
||||
"meta-llama/llama-3-70b-instruct": {
|
||||
id: "meta-llama/llama-3-70b-instruct",
|
||||
name: "Meta: Llama 3 70B Instruct",
|
||||
api: "openai-completions",
|
||||
provider: "openrouter",
|
||||
baseUrl: "https://openrouter.ai/api/v1",
|
||||
reasoning: false,
|
||||
input: ["text"],
|
||||
cost: {
|
||||
input: 0.3,
|
||||
output: 0.39999999999999997,
|
||||
cacheRead: 0,
|
||||
cacheWrite: 0,
|
||||
},
|
||||
contextWindow: 8192,
|
||||
maxTokens: 16384,
|
||||
} satisfies Model<"openai-completions">,
|
||||
"mistralai/mixtral-8x22b-instruct": {
|
||||
id: "mistralai/mixtral-8x22b-instruct",
|
||||
name: "Mistral: Mixtral 8x22B Instruct",
|
||||
|
|
@ -6073,23 +6192,6 @@ export const MODELS = {
|
|||
contextWindow: 128000,
|
||||
maxTokens: 4096,
|
||||
} satisfies Model<"openai-completions">,
|
||||
"openai/gpt-4-turbo-preview": {
|
||||
id: "openai/gpt-4-turbo-preview",
|
||||
name: "OpenAI: GPT-4 Turbo Preview",
|
||||
api: "openai-completions",
|
||||
provider: "openrouter",
|
||||
baseUrl: "https://openrouter.ai/api/v1",
|
||||
reasoning: false,
|
||||
input: ["text"],
|
||||
cost: {
|
||||
input: 10,
|
||||
output: 30,
|
||||
cacheRead: 0,
|
||||
cacheWrite: 0,
|
||||
},
|
||||
contextWindow: 128000,
|
||||
maxTokens: 4096,
|
||||
} satisfies Model<"openai-completions">,
|
||||
"openai/gpt-3.5-turbo-0613": {
|
||||
id: "openai/gpt-3.5-turbo-0613",
|
||||
name: "OpenAI: GPT-3.5 Turbo (older v0613)",
|
||||
|
|
@ -6107,6 +6209,23 @@ export const MODELS = {
|
|||
contextWindow: 4095,
|
||||
maxTokens: 4096,
|
||||
} satisfies Model<"openai-completions">,
|
||||
"openai/gpt-4-turbo-preview": {
|
||||
id: "openai/gpt-4-turbo-preview",
|
||||
name: "OpenAI: GPT-4 Turbo Preview",
|
||||
api: "openai-completions",
|
||||
provider: "openrouter",
|
||||
baseUrl: "https://openrouter.ai/api/v1",
|
||||
reasoning: false,
|
||||
input: ["text"],
|
||||
cost: {
|
||||
input: 10,
|
||||
output: 30,
|
||||
cacheRead: 0,
|
||||
cacheWrite: 0,
|
||||
},
|
||||
contextWindow: 128000,
|
||||
maxTokens: 4096,
|
||||
} satisfies Model<"openai-completions">,
|
||||
"mistralai/mistral-tiny": {
|
||||
id: "mistralai/mistral-tiny",
|
||||
name: "Mistral Tiny",
|
||||
|
|
@ -6175,23 +6294,6 @@ export const MODELS = {
|
|||
contextWindow: 16385,
|
||||
maxTokens: 4096,
|
||||
} satisfies Model<"openai-completions">,
|
||||
"openai/gpt-3.5-turbo": {
|
||||
id: "openai/gpt-3.5-turbo",
|
||||
name: "OpenAI: GPT-3.5 Turbo",
|
||||
api: "openai-completions",
|
||||
provider: "openrouter",
|
||||
baseUrl: "https://openrouter.ai/api/v1",
|
||||
reasoning: false,
|
||||
input: ["text"],
|
||||
cost: {
|
||||
input: 0.5,
|
||||
output: 1.5,
|
||||
cacheRead: 0,
|
||||
cacheWrite: 0,
|
||||
},
|
||||
contextWindow: 16385,
|
||||
maxTokens: 4096,
|
||||
} satisfies Model<"openai-completions">,
|
||||
"openai/gpt-4-0314": {
|
||||
id: "openai/gpt-4-0314",
|
||||
name: "OpenAI: GPT-4 (older v0314)",
|
||||
|
|
@ -6226,6 +6328,23 @@ export const MODELS = {
|
|||
contextWindow: 8191,
|
||||
maxTokens: 4096,
|
||||
} satisfies Model<"openai-completions">,
|
||||
"openai/gpt-3.5-turbo": {
|
||||
id: "openai/gpt-3.5-turbo",
|
||||
name: "OpenAI: GPT-3.5 Turbo",
|
||||
api: "openai-completions",
|
||||
provider: "openrouter",
|
||||
baseUrl: "https://openrouter.ai/api/v1",
|
||||
reasoning: false,
|
||||
input: ["text"],
|
||||
cost: {
|
||||
input: 0.5,
|
||||
output: 1.5,
|
||||
cacheRead: 0,
|
||||
cacheWrite: 0,
|
||||
},
|
||||
contextWindow: 16385,
|
||||
maxTokens: 4096,
|
||||
} satisfies Model<"openai-completions">,
|
||||
"openrouter/auto": {
|
||||
id: "openrouter/auto",
|
||||
name: "OpenRouter: Auto Router",
|
||||
|
|
|
|||
|
|
@ -576,9 +576,9 @@ function createRunner(sandboxConfig: SandboxConfig, channelId: string, channelDi
|
|||
// Format: "[username]: message" so LLM knows who's talking
|
||||
let userMessage = `[${ctx.message.userName || "unknown"}]: ${ctx.message.text}`;
|
||||
|
||||
// Add attachment paths if any
|
||||
// Add attachment paths if any (convert to absolute paths in execution environment)
|
||||
if (ctx.message.attachments && ctx.message.attachments.length > 0) {
|
||||
const attachmentPaths = ctx.message.attachments.map((a) => a.local).join("\n");
|
||||
const attachmentPaths = ctx.message.attachments.map((a) => `${workspacePath}/${a.local}`).join("\n");
|
||||
userMessage += `\n\nAttachments:\n${attachmentPaths}`;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ function createSlackContext(event: SlackEvent, slack: SlackBot, state: ChannelSt
|
|||
userName: user?.userName,
|
||||
channel: event.channel,
|
||||
ts: event.ts,
|
||||
attachments: [],
|
||||
attachments: (event.attachments || []).map((a) => ({ local: a.local })),
|
||||
},
|
||||
channelName: slack.getChannel(event.channel)?.name,
|
||||
store: state.store,
|
||||
|
|
@ -243,10 +243,14 @@ const handler: MomHandler = {
|
|||
|
||||
log.logStartup(workingDir, sandbox.type === "host" ? "host" : `docker:${sandbox.container}`);
|
||||
|
||||
// Shared store for attachment downloads (also used per-channel in getState)
|
||||
const sharedStore = new ChannelStore({ workingDir, botToken: MOM_SLACK_BOT_TOKEN! });
|
||||
|
||||
const bot = new SlackBotClass(handler, {
|
||||
appToken: MOM_SLACK_APP_TOKEN,
|
||||
botToken: MOM_SLACK_BOT_TOKEN,
|
||||
workingDir,
|
||||
store: sharedStore,
|
||||
});
|
||||
|
||||
bot.start();
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import { WebClient } from "@slack/web-api";
|
|||
import { appendFileSync, existsSync, mkdirSync, readFileSync } from "fs";
|
||||
import { basename, join } from "path";
|
||||
import * as log from "./log.js";
|
||||
import type { Attachment, ChannelStore } from "./store.js";
|
||||
|
||||
// ============================================================================
|
||||
// Types
|
||||
|
|
@ -14,7 +15,9 @@ export interface SlackEvent {
|
|||
ts: string;
|
||||
user: string;
|
||||
text: string;
|
||||
files?: Array<{ name: string; url_private_download?: string; url_private?: string }>;
|
||||
files?: Array<{ name?: string; url_private_download?: string; url_private?: string }>;
|
||||
/** Processed attachments with local paths (populated after logUserMessage) */
|
||||
attachments?: Attachment[];
|
||||
}
|
||||
|
||||
export interface SlackUser {
|
||||
|
|
@ -118,6 +121,7 @@ export class SlackBot {
|
|||
private webClient: WebClient;
|
||||
private handler: MomHandler;
|
||||
private workingDir: string;
|
||||
private store: ChannelStore;
|
||||
private botUserId: string | null = null;
|
||||
private startupTs: string | null = null; // Messages older than this are just logged, not processed
|
||||
|
||||
|
|
@ -125,9 +129,13 @@ export class SlackBot {
|
|||
private channels = new Map<string, SlackChannel>();
|
||||
private queues = new Map<string, ChannelQueue>();
|
||||
|
||||
constructor(handler: MomHandler, config: { appToken: string; botToken: string; workingDir: string }) {
|
||||
constructor(
|
||||
handler: MomHandler,
|
||||
config: { appToken: string; botToken: string; workingDir: string; store: ChannelStore },
|
||||
) {
|
||||
this.handler = handler;
|
||||
this.workingDir = config.workingDir;
|
||||
this.store = config.store;
|
||||
this.socketClient = new SocketModeClient({ appToken: config.appToken });
|
||||
this.webClient = new WebClient(config.botToken);
|
||||
}
|
||||
|
|
@ -258,7 +266,8 @@ export class SlackBot {
|
|||
};
|
||||
|
||||
// SYNC: Log to log.jsonl (ALWAYS, even for old messages)
|
||||
this.logUserMessage(slackEvent);
|
||||
// Also downloads attachments in background and stores local paths
|
||||
slackEvent.attachments = this.logUserMessage(slackEvent);
|
||||
|
||||
// Only trigger processing for messages AFTER startup (not replayed old messages)
|
||||
if (this.startupTs && e.ts < this.startupTs) {
|
||||
|
|
@ -336,7 +345,8 @@ export class SlackBot {
|
|||
};
|
||||
|
||||
// SYNC: Log to log.jsonl (ALL messages - channel chatter and DMs)
|
||||
this.logUserMessage(slackEvent);
|
||||
// Also downloads attachments in background and stores local paths
|
||||
slackEvent.attachments = this.logUserMessage(slackEvent);
|
||||
|
||||
// Only trigger processing for messages AFTER startup (not replayed old messages)
|
||||
if (this.startupTs && e.ts < this.startupTs) {
|
||||
|
|
@ -371,9 +381,12 @@ export class SlackBot {
|
|||
|
||||
/**
|
||||
* Log a user message to log.jsonl (SYNC)
|
||||
* Downloads attachments in background via store
|
||||
*/
|
||||
private logUserMessage(event: SlackEvent): void {
|
||||
private logUserMessage(event: SlackEvent): Attachment[] {
|
||||
const user = this.users.get(event.user);
|
||||
// Process attachments - queues downloads in background
|
||||
const attachments = event.files ? this.store.processAttachments(event.channel, event.files, event.ts) : [];
|
||||
this.logToFile(event.channel, {
|
||||
date: new Date(parseFloat(event.ts) * 1000).toISOString(),
|
||||
ts: event.ts,
|
||||
|
|
@ -381,9 +394,10 @@ export class SlackBot {
|
|||
userName: user?.userName,
|
||||
displayName: user?.displayName,
|
||||
text: event.text,
|
||||
attachments: event.files?.map((f) => f.name) || [],
|
||||
attachments,
|
||||
isBot: false,
|
||||
});
|
||||
return attachments;
|
||||
}
|
||||
|
||||
// ==========================================================================
|
||||
|
|
@ -464,6 +478,8 @@ export class SlackBot {
|
|||
const user = this.users.get(msg.user!);
|
||||
// Strip @mentions from text (same as live messages)
|
||||
const text = (msg.text || "").replace(/<@[A-Z0-9]+>/gi, "").trim();
|
||||
// Process attachments - queues downloads in background
|
||||
const attachments = msg.files ? this.store.processAttachments(channelId, msg.files, msg.ts!) : [];
|
||||
|
||||
this.logToFile(channelId, {
|
||||
date: new Date(parseFloat(msg.ts!) * 1000).toISOString(),
|
||||
|
|
@ -472,7 +488,7 @@ export class SlackBot {
|
|||
userName: isMomMessage ? undefined : user?.userName,
|
||||
displayName: isMomMessage ? undefined : user?.displayName,
|
||||
text,
|
||||
attachments: msg.files?.map((f) => f.name) || [],
|
||||
attachments,
|
||||
isBot: isMomMessage,
|
||||
});
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue