@mukulaggarwal/pacman 0.1.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/README.md +39 -0
- package/dist/chunk-3QNXXON5.js +330 -0
- package/dist/chunk-3QNXXON5.js.map +1 -0
- package/dist/chunk-43PUZDIZ.js +148 -0
- package/dist/chunk-43PUZDIZ.js.map +1 -0
- package/dist/chunk-7D4SUZUM.js +38 -0
- package/dist/chunk-7D4SUZUM.js.map +1 -0
- package/dist/chunk-AYFIQNZ5.js +807 -0
- package/dist/chunk-AYFIQNZ5.js.map +1 -0
- package/dist/chunk-FH6ZHWGR.js +37 -0
- package/dist/chunk-FH6ZHWGR.js.map +1 -0
- package/dist/chunk-O6T35A4O.js +137 -0
- package/dist/chunk-O6T35A4O.js.map +1 -0
- package/dist/chunk-TRQIZP6Z.js +451 -0
- package/dist/chunk-TRQIZP6Z.js.map +1 -0
- package/dist/chunk-UWT6AFJB.js +471 -0
- package/dist/chunk-UWT6AFJB.js.map +1 -0
- package/dist/chunk-ZKKMIDRK.js +3923 -0
- package/dist/chunk-ZKKMIDRK.js.map +1 -0
- package/dist/daemon.d.ts +3 -0
- package/dist/daemon.js +141 -0
- package/dist/daemon.js.map +1 -0
- package/dist/dist-3PIJOFZ4.js +91 -0
- package/dist/dist-3PIJOFZ4.js.map +1 -0
- package/dist/dist-L76NGFFH.js +102 -0
- package/dist/dist-L76NGFFH.js.map +1 -0
- package/dist/dist-NV2YVVHI.js +178 -0
- package/dist/dist-NV2YVVHI.js.map +1 -0
- package/dist/dist-RMYCRZIU.js +41 -0
- package/dist/dist-RMYCRZIU.js.map +1 -0
- package/dist/dist-THLCZNOZ.js +14 -0
- package/dist/dist-THLCZNOZ.js.map +1 -0
- package/dist/dist-TWNHTXYH.js +95 -0
- package/dist/dist-TWNHTXYH.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +452 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp-compat.d.ts +1 -0
- package/dist/mcp-compat.js +78 -0
- package/dist/mcp-compat.js.map +1 -0
- package/dist/onboarding-server.d.ts +3 -0
- package/dist/onboarding-server.js +1172 -0
- package/dist/onboarding-server.js.map +1 -0
- package/dist/provider-runtime.d.ts +11 -0
- package/dist/provider-runtime.js +10 -0
- package/dist/provider-runtime.js.map +1 -0
- package/dist/slack-listener.d.ts +49 -0
- package/dist/slack-listener.js +888 -0
- package/dist/slack-listener.js.map +1 -0
- package/dist/storage.d.ts +8 -0
- package/dist/storage.js +9 -0
- package/dist/storage.js.map +1 -0
- package/package.json +75 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/slack-listener.ts"],"sourcesContent":["import { google } from 'googleapis';\nimport { createContextManager } from '@personal-assistant/context-manager';\nimport {\n createSlackConnector,\n openSocketModeConnection,\n type SlackEventPayload,\n} from '@personal-assistant/integrations-slack';\nimport { WORKSPACE_PATHS as PATHS } from '@personal-assistant/core-types';\nimport type {\n AppConfig,\n DraftOutput,\n IntegrationConfig,\n LlmProvider,\n ReplyInput,\n ReplyInputEvidence,\n SlackChannelMapping,\n SlackRuntimeConfig,\n SlackThreadSnapshot,\n StorageBackend,\n} from '@personal-assistant/core-types';\nimport { generateDraft } from './provider-runtime.js';\nimport { resolveConfiguredStorage } from './storage.js';\n\nconst RECONNECT_DELAY_MS = 5000;\nconst RECENT_EVENT_TTL_MS = 5 * 60 * 1000;\nconst PROJECT_RESOLUTION_MIN_SCORE = 0.45;\nconst PROJECT_RESOLUTION_MIN_MARGIN = 0.08;\nconst recentEventKeys = new Map<string, number>();\nconst RESOLUTION_STOPWORDS = new Set([\n 'a', 'about', 'after', 'again', 'all', 'also', 'an', 'and', 'any', 'are', 'as', 'at',\n 'back', 'be', 'been', 'before', 'being', 'between', 'both', 'but', 'by', 'can', 'could',\n 'date', 'did', 'do', 'does', 'effective', 'for', 'from', 'had', 'has', 'have', 'help',\n 'here', 'how', 'i', 'if', 'in', 'into', 'is', 'it', 'its', 'just', 'latest', 'me', 'more',\n 'most', 'my', 'need', 'of', 'on', 'only', 'or', 'other', 'our', 'out', 'over', 'same',\n 'share', 'should', 'show', 'tell', 'than', 'that', 'the', 'their', 'them', 'there',\n 'these', 'they', 'this', 'those', 'through', 'to', 'under', 'update', 'us', 'using', 'want',\n 'was', 'we', 'what', 'when', 'where', 'which', 'while', 'who', 'why', 'with', 'would',\n 'you', 'your',\n]);\n\ntype RuntimeDeps = {\n config: AppConfig;\n storage: StorageBackend;\n slackIntegration: IntegrationConfig;\n slackRuntime: SlackRuntimeConfig;\n};\n\ntype ProjectResolutionSource = {\n projectName: string;\n latestSummary: string;\n contextText: string;\n};\n\ntype ProjectResolutionCandidate = {\n projectName: string;\n normalizedProject: string;\n latestSummary: string;\n matchedNameTokens: string[];\n matchedContextTokens: string[];\n matchedAliasTokens: string[];\n cosineSimilarity: number;\n coverageScore: number;\n aliasScore: number;\n phraseScore: number;\n score: number;\n};\n\ntype ProjectResolutionDebug = {\n threadText: string;\n normalizedText: string;\n queryTokens: string[];\n candidates: ProjectResolutionCandidate[];\n selectedProject?: string;\n};\n\ntype ProjectResolutionProfile = {\n source: ProjectResolutionSource;\n normalizedProject: string;\n nameTokens: string[];\n summaryTokens: string[];\n contextTokens: string[];\n aliasTokens: string[];\n documentTokens: string[];\n};\n\nexport async function startSlackListener(workspacePath: string): Promise<void> {\n const { config, storage } = await resolveConfiguredStorage(workspacePath);\n const slackRuntime = config.slackRuntime;\n if (!slackRuntime?.enabled) {\n throw new Error('Slack runtime is not enabled in the saved configuration');\n }\n if (slackRuntime.transport !== 'socket_mode') {\n throw new Error(`Slack transport \"${slackRuntime.transport}\" is not supported yet. Use Socket Mode for v1.`);\n }\n\n const slackIntegration = config.integrations.find((integration) => integration.type === 'slack' && integration.enabled);\n if (!slackIntegration?.credentials?.botToken) {\n throw new Error('Slack integration is enabled but the bot token is missing');\n }\n\n if (!slackRuntime.appToken) {\n throw new Error('Slack runtime app token is missing');\n }\n\n const deps: RuntimeDeps = {\n config,\n storage,\n slackIntegration,\n slackRuntime,\n };\n\n const connector = createSlackConnector();\n await connector.authenticate(slackIntegration);\n\n console.log('Starting real-time Slack listener...');\n console.log(`Transport: ${slackRuntime.transport}`);\n console.log(`Review mode: ${slackRuntime.reviewMode}`);\n console.log(`Generation enabled: ${slackRuntime.generationEnabled ? 'yes' : 'no'}`);\n if (slackRuntime.channelMappings.length > 0) {\n console.log(`Mapped channels: ${slackRuntime.channelMappings.map((mapping) => mapping.channelName ?? mapping.channelId).join(', ')}`);\n } else {\n console.log('Monitored channels: all Slack channels/private groups where the bot is present');\n }\n console.log(`Escalation owner: ${config.user.name}`);\n\n while (true) {\n try {\n const session = await openSocketModeConnection(slackRuntime.appToken, {\n onEvent: (event) => {\n void handleSlackEvent(event, deps).catch((err) => {\n console.error('Slack event handling failed:', err);\n });\n },\n onError: (err) => {\n console.error('Slack Socket Mode error:', err.message);\n },\n });\n\n await session.closed;\n console.warn(`Slack Socket Mode disconnected. Reconnecting in ${RECONNECT_DELAY_MS}ms...`);\n } catch (err) {\n console.error('Slack listener connection failed:', err);\n }\n\n await sleep(RECONNECT_DELAY_MS);\n }\n}\n\nexport async function handleSlackEvent(event: SlackEventPayload, deps: RuntimeDeps): Promise<void> {\n if (!shouldHandleSlackEvent(event) || !event.channel || !event.ts) {\n console.log(`[slack] Ignored unsupported event type=${event.type} subtype=${event.subtype ?? 'none'}`);\n return;\n }\n\n const eventKey = `${event.channel}:${event.ts}`;\n if (hasSeenRecentEvent(eventKey)) {\n console.log(`[slack] Ignored duplicate event ${eventKey}`);\n return;\n }\n markRecentEvent(eventKey);\n\n const mapping = createRuntimeChannelMapping(event.channel, deps.slackRuntime.channelMappings, deps.config.user.name);\n\n if (!isReplyCandidate(event, deps.config.user.assistantName)) {\n console.log(`[slack] Ignored non-request in #${mapping.channelName ?? event.channel}: ${summarizeText(event.text)}`);\n return;\n }\n\n console.log(`[slack] Processing candidate in #${mapping.channelName ?? event.channel}: ${summarizeText(event.text)}`);\n\n const connector = createSlackConnector();\n await connector.authenticate(deps.slackIntegration);\n\n const threadTs = event.thread_ts ?? event.ts;\n const thread = await connector.fetchThread(event.channel, threadTs, mapping.channelName);\n const threadMapping: SlackChannelMapping = {\n ...mapping,\n channelName: thread.channelName ?? mapping.channelName,\n };\n const resolution = await resolveProjectName(deps.storage, thread);\n logProjectResolution(resolution);\n const projectName = resolution.selectedProject;\n if (!projectName) {\n console.log('[slack] Could not resolve a project from the thread; falling back to abstain');\n } else {\n console.log(`[slack] Resolved project: ${projectName}`);\n logSelectedProjectSummary(resolution, projectName);\n }\n\n await writeArtifact(\n deps.storage,\n `${PATHS.context.raw.slack}/${artifactKey(event.channel, threadTs)}.json`,\n {\n receivedAt: new Date().toISOString(),\n event,\n thread,\n },\n );\n\n const replyInput = await buildReplyInput(deps.config, deps.storage, threadMapping, thread, projectName);\n logEvidenceSummary(replyInput.evidence);\n await writeArtifact(\n deps.storage,\n `${PATHS.context.derived.slack.replyInputs}/${artifactKey(event.channel, threadTs)}.json`,\n replyInput,\n );\n\n const draft = await buildDraftOutput(deps.config, replyInput, threadMapping);\n console.log(`[slack] Draft outcome for ${artifactKey(event.channel, threadTs)}: ${draft.outcome}`);\n logDraftPreview(draft);\n if (draft.citations.length > 0) {\n console.log(`[slack] Draft citations: ${draft.citations.join(' | ')}`);\n }\n if (draft.missingFacts.length > 0) {\n console.log(`[slack] Draft missing facts: ${draft.missingFacts.join(' | ')}`);\n }\n await writeArtifact(\n deps.storage,\n `${PATHS.context.derived.slack.drafts}/${artifactKey(event.channel, threadTs)}.json`,\n draft,\n );\n\n let delivery: Record<string, unknown>;\n try {\n delivery = await deliverDraft(connector, deps.slackRuntime, threadMapping, thread, draft, replyInput.projectName);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n console.error(`[slack] Delivery failed for ${artifactKey(event.channel, threadTs)}: ${message}`);\n delivery = {\n mode: deps.slackRuntime.reviewMode,\n deliveredAt: new Date().toISOString(),\n channelId: thread.channelId,\n threadTs: thread.threadTs,\n reviewerUserId: threadMapping.reviewerUserId,\n outcome: 'delivery_error',\n error: message,\n };\n }\n await writeArtifact(\n deps.storage,\n `${PATHS.context.derived.slack.deliveries}/${artifactKey(event.channel, threadTs)}.json`,\n delivery,\n );\n if (delivery.mode === 'human_review') {\n console.log(`[slack] Delivery mode: human_review (ephemeral draft only, visible to reviewer ${threadMapping.reviewerDisplayName ?? threadMapping.reviewerUserId})`);\n console.log(`[slack] Reviewer target: ${threadMapping.reviewerDisplayName ?? 'unknown'} (${threadMapping.reviewerUserId})`);\n } else if (delivery.mode === 'auto_send') {\n console.log('[slack] Delivery mode: auto_send (public thread reply posted)');\n console.log(`[slack] Public reply channel: #${threadMapping.channelName ?? thread.channelId} thread=${thread.threadTs}`);\n }\n console.log(`[slack] Delivery recorded for ${artifactKey(event.channel, threadTs)} (${String(delivery.outcome ?? 'unknown')})`);\n}\n\nexport function shouldHandleSlackEvent(event: SlackEventPayload): boolean {\n if (event.type !== 'message' && event.type !== 'app_mention') return false;\n if (!event.channel || !event.ts) return false;\n if (event.bot_id) return false;\n if (event.type === 'message' && event.subtype && event.subtype !== 'thread_broadcast') return false;\n return true;\n}\n\nexport function isReplyCandidate(event: SlackEventPayload, assistantName?: string): boolean {\n if (!shouldHandleSlackEvent(event)) return false;\n if (event.type === 'app_mention') return true;\n\n const text = event.text?.trim();\n if (!text) return false;\n\n if (assistantName?.trim()) {\n const assistantPattern = new RegExp(`\\\\b${escapeRegExp(assistantName.trim())}\\\\b`, 'i');\n if (assistantPattern.test(text)) return true;\n }\n\n // Keep channel-triggered drafts narrow in v1 so Atlas responds to requests,\n // not to general project chatter.\n return /[?]$/.test(text)\n || /\\b(status|owner|blocked|blocker|eta|when|who|what|where|which|why|how|help|update|decision)\\b/i.test(text)\n || /\\b(tell|show|give)\\s+me\\b/i.test(text)\n || /\\b(can|could|would|should)\\s+you\\b/i.test(text);\n}\n\nexport function resolveChannelMapping(\n channelId: string,\n mappings: SlackChannelMapping[],\n): SlackChannelMapping | undefined {\n return mappings.find((mapping) => mapping.channelId === channelId);\n}\n\nfunction createRuntimeChannelMapping(\n channelId: string,\n mappings: SlackChannelMapping[],\n ownerName: string,\n): SlackChannelMapping {\n return resolveChannelMapping(channelId, mappings) ?? {\n channelId,\n channelName: channelId,\n reviewerUserId: 'config-owner',\n reviewerDisplayName: ownerName || 'Configured user',\n };\n}\n\nexport function extractGitHubResources(text: string): Array<{ repo: string; kind: 'issues' | 'pull'; number: string }> {\n const matches = [...text.matchAll(/github\\.com\\/([^/\\s]+\\/[^/\\s]+)\\/(issues|pull)\\/(\\d+)/g)];\n return matches.map((match) => ({\n repo: match[1],\n kind: match[2] as 'issues' | 'pull',\n number: match[3],\n }));\n}\n\nexport function extractGoogleDocIds(text: string): string[] {\n return [...text.matchAll(/docs\\.google\\.com\\/document\\/d\\/([A-Za-z0-9_-]+)/g)].map((match) => match[1]);\n}\n\nasync function buildReplyInput(\n config: AppConfig,\n storage: StorageBackend,\n mapping: SlackChannelMapping,\n thread: SlackThreadSnapshot,\n projectName?: string,\n): Promise<ReplyInput> {\n const contextManager = createContextManager(storage);\n const projectContext = await contextManager.getProjectContext(projectName ?? '');\n const evidence: ReplyInputEvidence[] = [];\n\n for (const file of projectContext.canonicalFiles) {\n evidence.push({\n source: 'project',\n reference: file.path,\n content: truncate(file.content, 2000),\n });\n }\n\n for (const file of projectContext.derivedFiles) {\n evidence.push({\n source: 'project',\n reference: file.path,\n content: truncate(file.content, 1500),\n });\n }\n\n for (const file of projectContext.rawFiles) {\n evidence.push({\n source: 'raw',\n reference: file.path,\n content: truncate(file.content, 1500),\n });\n }\n\n evidence.push(...await collectGitHubEvidence(config, mapping, thread));\n evidence.push(...await collectGoogleDriveEvidence(config, mapping, thread));\n\n return {\n projectName: projectName ?? '',\n thread,\n evidence,\n reviewMode: config.slackRuntime?.reviewMode ?? 'auto_send',\n provider: config.slackRuntime?.defaultProvider,\n model: config.slackRuntime?.defaultModel,\n };\n}\n\nasync function buildDraftOutput(\n config: AppConfig,\n replyInput: ReplyInput,\n mapping: SlackChannelMapping,\n): Promise<DraftOutput> {\n if (!replyInput.projectName) {\n return {\n outcome: 'abstain',\n draftText: '',\n citations: [],\n missingFacts: ['Could not determine which project the Slack thread is asking about.'],\n escalationOwner: mapping.reviewerDisplayName ?? mapping.reviewerUserId,\n confidence: 'low',\n };\n }\n\n const provider = config.slackRuntime?.defaultProvider;\n const model = config.slackRuntime?.defaultModel;\n\n if (!config.slackRuntime?.generationEnabled || !provider || !model) {\n return {\n outcome: 'abstain',\n draftText: '',\n citations: replyInput.evidence.map((item) => item.reference).slice(0, 5),\n missingFacts: ['Generation is disabled or provider/model is not configured.'],\n escalationOwner: mapping.reviewerDisplayName ?? mapping.reviewerUserId,\n confidence: 'low',\n };\n }\n\n try {\n return await generateDraft(provider as LlmProvider, model, config.providers, replyInput);\n } catch (err) {\n return {\n outcome: 'abstain',\n draftText: '',\n citations: replyInput.evidence.map((item) => item.reference).slice(0, 5),\n missingFacts: [err instanceof Error ? err.message : String(err)],\n escalationOwner: mapping.reviewerDisplayName ?? mapping.reviewerUserId,\n confidence: 'low',\n };\n }\n}\n\nasync function deliverDraft(\n connector: ReturnType<typeof createSlackConnector>,\n slackRuntime: SlackRuntimeConfig,\n mapping: SlackChannelMapping,\n thread: SlackThreadSnapshot,\n draft: DraftOutput,\n projectName?: string,\n): Promise<Record<string, unknown>> {\n if (slackRuntime.reviewMode === 'auto_send') {\n const threadReply = renderAutoSendMessage(draft, projectName);\n const ts = await connector.postThreadReply(thread.channelId, thread.threadTs, threadReply);\n return {\n mode: 'auto_send',\n deliveredAt: new Date().toISOString(),\n channelId: thread.channelId,\n threadTs: thread.threadTs,\n messageTs: ts,\n outcome: draft.outcome,\n postedText: threadReply,\n };\n }\n\n // Human-review delivery is kept in the runtime for future reintroduction,\n // but onboarding defaults to auto_send and no longer exposes it in the UI.\n const reviewText = renderReviewMessage(mapping, draft, projectName);\n await connector.postEphemeral(thread.channelId, mapping.reviewerUserId, reviewText, thread.threadTs);\n return {\n mode: 'human_review',\n deliveredAt: new Date().toISOString(),\n channelId: thread.channelId,\n threadTs: thread.threadTs,\n reviewerUserId: mapping.reviewerUserId,\n outcome: draft.outcome,\n };\n}\n\nasync function collectGitHubEvidence(\n config: AppConfig,\n _mapping: SlackChannelMapping,\n thread: SlackThreadSnapshot,\n): Promise<ReplyInputEvidence[]> {\n const githubIntegration = config.integrations.find((integration) => integration.type === 'github' && integration.enabled);\n const token = githubIntegration?.credentials?.token;\n if (!token) {\n return [];\n }\n\n const linkedResources = extractGitHubResources(thread.messages.map((message) => message.text).join('\\n'))\n .slice(0, 3);\n if (linkedResources.length === 0) {\n return [];\n }\n\n const evidence: ReplyInputEvidence[] = [];\n for (const resource of linkedResources) {\n const endpoint = resource.kind === 'pull'\n ? `https://api.github.com/repos/${resource.repo}/pulls/${resource.number}`\n : `https://api.github.com/repos/${resource.repo}/issues/${resource.number}`;\n const response = await fetch(endpoint, {\n headers: {\n Authorization: `token ${token}`,\n Accept: 'application/vnd.github+json',\n 'User-Agent': 'personal-assistant',\n },\n });\n if (!response.ok) continue;\n\n const data = await response.json() as {\n html_url?: string;\n title?: string;\n body?: string;\n state?: string;\n };\n\n evidence.push({\n source: 'github',\n reference: data.html_url ?? `${resource.repo}#${resource.number}`,\n content: truncate(`${data.title ?? 'Untitled'}\\nState: ${data.state ?? 'unknown'}\\n${data.body ?? ''}`, 1500),\n });\n }\n\n return evidence;\n}\n\nasync function collectGoogleDriveEvidence(\n config: AppConfig,\n _mapping: SlackChannelMapping,\n thread: SlackThreadSnapshot,\n): Promise<ReplyInputEvidence[]> {\n const gdriveIntegration = config.integrations.find((integration) => integration.type === 'gdrive' && integration.enabled);\n const credentials = gdriveIntegration?.credentials;\n if (!credentials?.clientId || !credentials?.clientSecret || !credentials?.refreshToken) {\n return [];\n }\n\n const linkedDocIds = extractGoogleDocIds(thread.messages.map((message) => message.text).join('\\n'))\n .slice(0, 3);\n if (linkedDocIds.length === 0) {\n return [];\n }\n\n const oauth2Client = new google.auth.OAuth2(credentials.clientId, credentials.clientSecret);\n oauth2Client.setCredentials({ refresh_token: credentials.refreshToken });\n const drive = google.drive({ version: 'v3', auth: oauth2Client });\n\n const evidence: ReplyInputEvidence[] = [];\n for (const docId of linkedDocIds) {\n try {\n const meta = await drive.files.get({\n fileId: docId,\n fields: 'name,webViewLink',\n });\n const exported = await drive.files.export({\n fileId: docId,\n mimeType: 'text/plain',\n });\n\n evidence.push({\n source: 'gdrive',\n reference: meta.data.webViewLink ?? docId,\n content: truncate(`${meta.data.name ?? docId}\\n${String(exported.data)}`, 1500),\n });\n } catch {\n // Ignore individual doc failures so a missing doc does not break the Slack reply loop.\n }\n }\n\n return evidence;\n}\n\nfunction renderReviewMessage(mapping: SlackChannelMapping, draft: DraftOutput, projectName?: string): string {\n const lines = [\n `*Atlas draft for ${projectName || 'unknown project'}*`,\n draft.outcome === 'draft'\n ? (draft.draftText || '_No draft text was returned._')\n : '_Atlas abstained because the available context was insufficient._',\n ];\n\n if (draft.citations.length > 0) {\n lines.push(`*Citations*\\n• ${draft.citations.join('\\n• ')}`);\n }\n\n if (draft.missingFacts.length > 0) {\n lines.push(`*Missing facts*\\n• ${draft.missingFacts.join('\\n• ')}`);\n }\n\n if (draft.escalationOwner) {\n lines.push(`*Escalation owner*\\n${draft.escalationOwner}`);\n }\n\n return truncate(lines.join('\\n\\n'), 3500);\n}\n\nfunction renderAutoSendMessage(draft: DraftOutput, projectName?: string): string {\n if (draft.outcome === 'draft' && draft.draftText.trim()) {\n return truncate(draft.draftText.trim(), 3500);\n }\n\n const lines = [\n `I can't answer confidently from the current context${projectName ? ` for ${projectName}` : ''}.`,\n ];\n\n if (draft.missingFacts.length > 0) {\n lines.push(`Missing context: ${draft.missingFacts.join('; ')}`);\n }\n\n if (draft.escalationOwner) {\n lines.push(`Best escalation path: ${draft.escalationOwner}.`);\n }\n\n return truncate(lines.join('\\n\\n'), 3500);\n}\n\nfunction artifactKey(channelId: string, threadTs: string): string {\n return `${channelId}-${threadTs.replace(/[^\\dA-Za-z_-]/g, '_')}`;\n}\n\nasync function writeArtifact(storage: StorageBackend, filePath: string, data: unknown): Promise<void> {\n await storage.write(filePath, JSON.stringify(data, null, 2));\n}\n\nfunction truncate(value: string, maxLength: number): string {\n if (value.length <= maxLength) return value;\n return `${value.slice(0, maxLength - 3)}...`;\n}\n\nfunction summarizeText(text: string | undefined, maxLength = 100): string {\n if (!text?.trim()) return '<no text>';\n return truncate(text.replace(/\\s+/g, ' ').trim(), maxLength);\n}\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\nasync function resolveProjectName(\n storage: StorageBackend,\n thread: SlackThreadSnapshot,\n): Promise<ProjectResolutionDebug> {\n const contextManager = createContextManager(storage);\n const projectNames = await contextManager.listProjects().catch(() => []);\n const threadText = thread.messages.map((message) => message.text).join(' ');\n const sources = await loadProjectResolutionSources(storage, projectNames);\n return inspectProjectResolution(sources, threadText);\n}\n\nexport function resolveProjectFromText(projectNames: string[], text: string): string | undefined {\n const sources = projectNames.map((projectName) => ({\n projectName,\n latestSummary: '',\n contextText: '',\n }));\n return inspectProjectResolution(sources, text).selectedProject;\n}\n\nexport function inspectProjectResolution(sources: ProjectResolutionSource[], text: string): ProjectResolutionDebug {\n const normalizedText = normalizeForMatching(text);\n const queryTokens = uniqueTokens(tokenizeResolutionText(text));\n if (sources.length === 0) {\n return {\n threadText: text,\n normalizedText,\n queryTokens,\n candidates: [],\n selectedProject: undefined,\n };\n }\n\n if (!normalizedText) {\n return {\n threadText: text,\n normalizedText,\n queryTokens,\n candidates: sources.map((source) => ({\n projectName: source.projectName,\n normalizedProject: normalizeForMatching(source.projectName),\n latestSummary: source.latestSummary,\n matchedNameTokens: [],\n matchedContextTokens: [],\n matchedAliasTokens: [],\n cosineSimilarity: 0,\n coverageScore: 0,\n aliasScore: 0,\n phraseScore: 0,\n score: 0,\n })),\n selectedProject: undefined,\n };\n }\n\n const profiles = sources.map((source) => createProjectResolutionProfile(source));\n const idf = buildInverseDocumentFrequencies(profiles);\n const candidates = profiles.map((profile) => scoreProjectMatch(profile, normalizedText, queryTokens, idf));\n candidates.sort((a, b) => b.score - a.score || a.projectName.localeCompare(b.projectName));\n\n if (sources.length === 1) {\n return {\n threadText: text,\n normalizedText,\n queryTokens,\n candidates,\n selectedProject: candidates[0]?.projectName,\n };\n }\n\n const [best, second] = candidates;\n const selectedProject = best\n && best.score >= PROJECT_RESOLUTION_MIN_SCORE\n && best.score - (second?.score ?? 0) >= PROJECT_RESOLUTION_MIN_MARGIN\n ? best.projectName\n : undefined;\n\n return {\n threadText: text,\n normalizedText,\n queryTokens,\n candidates,\n selectedProject,\n };\n}\n\nfunction scoreProjectMatch(\n profile: ProjectResolutionProfile,\n haystack: string,\n queryTokens: string[],\n idf: Map<string, number>,\n): ProjectResolutionCandidate {\n const { source, normalizedProject } = profile;\n if (!normalizedProject) {\n return {\n projectName: source.projectName,\n normalizedProject,\n latestSummary: source.latestSummary,\n matchedNameTokens: [],\n matchedContextTokens: [],\n matchedAliasTokens: [],\n cosineSimilarity: 0,\n coverageScore: 0,\n aliasScore: 0,\n phraseScore: 0,\n score: 0,\n };\n }\n\n const nameTokenSet = new Set(profile.nameTokens);\n const contextTokenSet = new Set([...profile.summaryTokens, ...profile.contextTokens]);\n const aliasTokenSet = new Set(profile.aliasTokens);\n const documentTokenSet = new Set(profile.documentTokens);\n const queryTokenSet = new Set(queryTokens);\n const fallbackIdf = Math.log((idf.size + 2) / 0.5) + 1;\n\n const matchedNameTokens = queryTokens.filter((token) => nameTokenSet.has(token));\n const matchedAliasTokens = queryTokens.filter((token) => aliasTokenSet.has(token));\n const matchedContextTokens = queryTokens.filter((token) =>\n contextTokenSet.has(token) && !nameTokenSet.has(token) && !aliasTokenSet.has(token));\n\n const queryVector = buildWeightedTokenMap(queryTokens, idf, fallbackIdf, 1);\n const documentVector = new Map<string, number>();\n accumulateTokenWeights(documentVector, profile.nameTokens, idf, fallbackIdf, 3.5);\n accumulateTokenWeights(documentVector, profile.summaryTokens, idf, fallbackIdf, 2.5);\n accumulateTokenWeights(documentVector, profile.contextTokens, idf, fallbackIdf, 1.2);\n accumulateTokenWeights(documentVector, profile.aliasTokens, idf, fallbackIdf, 3);\n\n const totalQueryWeight = sumWeights(queryVector) || 1;\n const matchedQueryWeight = [...queryTokenSet]\n .filter((token) => documentTokenSet.has(token))\n .reduce((sum, token) => sum + (queryVector.get(token) ?? 0), 0);\n const matchedAliasWeight = [...queryTokenSet]\n .filter((token) => aliasTokenSet.has(token))\n .reduce((sum, token) => sum + (queryVector.get(token) ?? 0), 0);\n\n const coverageScore = matchedQueryWeight / totalQueryWeight;\n const aliasScore = matchedAliasWeight / totalQueryWeight;\n const cosineSimilarity = computeCosineSimilarity(queryVector, documentVector);\n const phraseScore = haystack.includes(normalizedProject) ? 1 : 0;\n const score =\n (phraseScore * 1.5)\n + (cosineSimilarity * 1.2)\n + (coverageScore * 1)\n + (aliasScore * 0.8);\n\n return {\n projectName: source.projectName,\n normalizedProject,\n latestSummary: source.latestSummary,\n matchedNameTokens,\n matchedContextTokens,\n matchedAliasTokens,\n cosineSimilarity,\n coverageScore,\n aliasScore,\n phraseScore,\n score,\n };\n}\n\nfunction logProjectResolution(debug: ProjectResolutionDebug): void {\n console.log('[slack] Project resolution strategy: weighted TF-IDF similarity over project name, latest project summary, and recent project context, with stemming, stopword removal, and acronym alias extraction; require unique best score >= 0.45 with margin >= 0.08 or abstain');\n console.log(`[slack] Registered projects: ${debug.candidates.length > 0 ? debug.candidates.map((candidate) => candidate.projectName).join(', ') : 'none'}`);\n console.log(`[slack] Resolution text: ${summarizeText(debug.threadText, 180)}`);\n console.log(`[slack] Normalized text: ${debug.normalizedText || '<empty>'}`);\n console.log(`[slack] Query tokens: ${debug.queryTokens.length > 0 ? debug.queryTokens.join(', ') : 'none'}`);\n\n if (debug.candidates.length === 0) {\n return;\n }\n\n console.log(\n `[slack] Project candidate scores: ${debug.candidates.map((candidate) => `${candidate.projectName}=total:${formatScore(candidate.score)},cosine:${formatScore(candidate.cosineSimilarity)},coverage:${formatScore(candidate.coverageScore)},alias:${formatScore(candidate.aliasScore)},phrase:${formatScore(candidate.phraseScore)}${candidate.matchedNameTokens.length > 0 ? `,name:[${candidate.matchedNameTokens.join(', ')}]` : ''}${candidate.matchedContextTokens.length > 0 ? `,context:[${candidate.matchedContextTokens.join(', ')}]` : ''}${candidate.matchedAliasTokens.length > 0 ? `,aliases:[${candidate.matchedAliasTokens.join(', ')}]` : ''},summary:${JSON.stringify(summarizeText(candidate.latestSummary, 100))}`).join(' | ')}`,\n );\n}\n\nfunction logSelectedProjectSummary(debug: ProjectResolutionDebug, projectName: string): void {\n const selected = debug.candidates.find((candidate) => candidate.projectName === projectName);\n if (!selected?.latestSummary) {\n console.log('[slack] Selected project summary: <empty>');\n return;\n }\n\n console.log('[slack] Selected project summary begin');\n for (const line of selected.latestSummary.split('\\n')) {\n console.log(`[slack] > ${line}`);\n }\n console.log('[slack] Selected project summary end');\n}\n\nfunction logEvidenceSummary(evidence: ReplyInputEvidence[]): void {\n const counts = new Map<string, number>();\n for (const item of evidence) {\n counts.set(item.source, (counts.get(item.source) ?? 0) + 1);\n }\n\n console.log(`[slack] Evidence counts: ${[...counts.entries()].map(([source, count]) => `${source}=${count}`).join(' | ') || 'none'}`);\n\n const rawRefs = evidence\n .filter((item) => item.source === 'raw')\n .map((item) => item.reference);\n if (rawRefs.length > 0) {\n console.log(`[slack] Raw context references: ${rawRefs.join(' | ')}`);\n }\n}\n\nfunction logDraftPreview(draft: DraftOutput): void {\n if (!draft.draftText?.trim()) {\n console.log('[slack] Draft text: <empty>');\n return;\n }\n\n console.log('[slack] Draft text begin');\n for (const line of draft.draftText.trim().split('\\n')) {\n console.log(`[slack] | ${line}`);\n }\n console.log('[slack] Draft text end');\n}\n\nfunction normalizeForMatching(value: string): string {\n return value\n .replace(/<@[A-Z0-9]+>/gi, ' ')\n .replace(/([a-z0-9])([A-Z])/g, '$1 $2')\n .replace(/[_-]+/g, ' ')\n .toLowerCase()\n .replace(/[^a-z0-9\\s]+/g, ' ')\n .replace(/\\s+/g, ' ')\n .trim();\n}\n\nasync function loadProjectResolutionSources(\n storage: StorageBackend,\n projectNames: string[],\n): Promise<ProjectResolutionSource[]> {\n return Promise.all(projectNames.map(async (projectName) => {\n const filePath = `${PATHS.context.canonical.projects}/${projectName}.md`;\n let content = '';\n try {\n content = await storage.read(filePath);\n } catch {\n // Ignore missing project file and fall back to name-only matching.\n }\n\n return {\n projectName,\n latestSummary: extractLatestProjectSummary(content),\n contextText: extractRecentProjectContext(content),\n };\n }));\n}\n\nfunction extractLatestProjectSummary(content: string): string {\n const normalized = content.trim();\n if (!normalized) return '';\n\n const noteSections = normalized.split(/\\n## Note - [^\\n]+\\n+/).map((section) => section.trim()).filter(Boolean);\n if (noteSections.length > 0) {\n return truncate(noteSections[noteSections.length - 1], 800);\n }\n\n return truncate(normalized, 800);\n}\n\nfunction extractRecentProjectContext(content: string): string {\n const normalized = content.trim();\n if (!normalized) return '';\n return truncate(normalized.slice(-2500), 2500);\n}\n\nfunction tokenizeResolutionText(value: string): string[] {\n if (!value) return [];\n\n return normalizeForMatching(value)\n .split(' ')\n .map((token) => stemResolutionToken(token.trim()))\n .filter((token) => token.length > 2 && !RESOLUTION_STOPWORDS.has(token));\n}\n\nfunction stemResolutionToken(token: string): string {\n if (!token) return '';\n\n let stemmed = token.toLowerCase();\n if (stemmed.endsWith(\"'s\")) {\n stemmed = stemmed.slice(0, -2);\n }\n\n if (stemmed.length > 4 && stemmed.endsWith('ies')) {\n return `${stemmed.slice(0, -3)}y`;\n }\n if (stemmed.length > 5 && stemmed.endsWith('ing')) {\n stemmed = stemmed.slice(0, -3);\n } else if (stemmed.length > 4 && stemmed.endsWith('ed')) {\n stemmed = stemmed.slice(0, -2);\n }\n\n if (stemmed.length > 4 && stemmed.endsWith('es')) {\n stemmed = stemmed.slice(0, -2);\n } else if (stemmed.length > 3 && stemmed.endsWith('s') && !stemmed.endsWith('ss')) {\n stemmed = stemmed.slice(0, -1);\n }\n\n return stemmed;\n}\n\nfunction createProjectResolutionProfile(source: ProjectResolutionSource): ProjectResolutionProfile {\n const nameTokens = tokenizeResolutionText(source.projectName);\n const summaryTokens = tokenizeResolutionText(source.latestSummary);\n const contextTokens = tokenizeResolutionText(source.contextText);\n const aliasTokens = uniqueTokens([\n ...extractAcronymTokens(source.projectName),\n ...extractAcronymTokens(source.latestSummary),\n ...extractAcronymTokens(source.contextText),\n ]);\n\n return {\n source,\n normalizedProject: normalizeForMatching(source.projectName),\n nameTokens,\n summaryTokens,\n contextTokens,\n aliasTokens,\n documentTokens: uniqueTokens([...nameTokens, ...summaryTokens, ...contextTokens, ...aliasTokens]),\n };\n}\n\nfunction extractAcronymTokens(value: string): string[] {\n if (!value) return [];\n\n const aliases = new Set<string>();\n\n for (const match of value.matchAll(/\\b(?:[A-Z][a-z0-9]+){2,}\\b/g)) {\n const acronym = (match[0].match(/[A-Z]/g) ?? []).join('').toLowerCase();\n if (acronym.length >= 2) {\n aliases.add(acronym);\n }\n }\n\n for (const match of value.matchAll(/\\b[A-Z][A-Za-z0-9]+(?:[\\s_-]+[A-Z][A-Za-z0-9]+){1,4}\\b/g)) {\n const words = match[0].split(/[\\s_-]+/).filter(Boolean);\n const acronym = words.map((word) => word[0]?.toLowerCase() ?? '').join('');\n if (acronym.length >= 2) {\n aliases.add(acronym);\n }\n }\n\n const separatorParts = value\n .split(/[\\s_-]+/)\n .map((part) => part.replace(/[^A-Za-z0-9]/g, ''))\n .filter(Boolean);\n if (separatorParts.length >= 2 && separatorParts.length <= 5) {\n const acronym = separatorParts.map((part) => part[0]?.toLowerCase() ?? '').join('');\n if (acronym.length >= 2) {\n aliases.add(acronym);\n }\n }\n\n return [...aliases].map((token) => stemResolutionToken(token)).filter((token) => token.length > 1);\n}\n\nfunction uniqueTokens(tokens: string[]): string[] {\n return [...new Set(tokens.filter(Boolean))];\n}\n\nfunction buildInverseDocumentFrequencies(profiles: ProjectResolutionProfile[]): Map<string, number> {\n const frequencies = new Map<string, number>();\n\n for (const profile of profiles) {\n for (const token of new Set(profile.documentTokens)) {\n frequencies.set(token, (frequencies.get(token) ?? 0) + 1);\n }\n }\n\n const totalDocuments = Math.max(profiles.length, 1);\n const idf = new Map<string, number>();\n for (const [token, frequency] of frequencies.entries()) {\n idf.set(token, Math.log((totalDocuments + 1) / (frequency + 0.5)) + 1);\n }\n return idf;\n}\n\nfunction buildWeightedTokenMap(\n tokens: string[],\n idf: Map<string, number>,\n fallbackIdf: number,\n multiplier: number,\n): Map<string, number> {\n const weights = new Map<string, number>();\n accumulateTokenWeights(weights, tokens, idf, fallbackIdf, multiplier);\n return weights;\n}\n\nfunction accumulateTokenWeights(\n weights: Map<string, number>,\n tokens: string[],\n idf: Map<string, number>,\n fallbackIdf: number,\n multiplier: number,\n): void {\n for (const token of tokens) {\n const idfWeight = idf.get(token) ?? fallbackIdf;\n weights.set(token, (weights.get(token) ?? 0) + (idfWeight * multiplier));\n }\n}\n\nfunction sumWeights(weights: Map<string, number>): number {\n let total = 0;\n for (const value of weights.values()) {\n total += value;\n }\n return total;\n}\n\nfunction computeCosineSimilarity(left: Map<string, number>, right: Map<string, number>): number {\n let dot = 0;\n let leftNorm = 0;\n let rightNorm = 0;\n\n for (const value of left.values()) {\n leftNorm += value * value;\n }\n\n for (const value of right.values()) {\n rightNorm += value * value;\n }\n\n for (const [token, leftValue] of left.entries()) {\n dot += leftValue * (right.get(token) ?? 0);\n }\n\n if (leftNorm === 0 || rightNorm === 0) {\n return 0;\n }\n\n return dot / (Math.sqrt(leftNorm) * Math.sqrt(rightNorm));\n}\n\nfunction formatScore(value: number): string {\n return value.toFixed(3);\n}\n\nfunction hasSeenRecentEvent(eventKey: string): boolean {\n const seenAt = recentEventKeys.get(eventKey);\n if (!seenAt) return false;\n if (Date.now() - seenAt > RECENT_EVENT_TTL_MS) {\n recentEventKeys.delete(eventKey);\n return false;\n }\n return true;\n}\n\nfunction markRecentEvent(eventKey: string): void {\n pruneRecentEvents();\n recentEventKeys.set(eventKey, Date.now());\n}\n\nfunction pruneRecentEvents(): void {\n const now = Date.now();\n for (const [eventKey, seenAt] of recentEventKeys.entries()) {\n if (now - seenAt > RECENT_EVENT_TTL_MS) {\n recentEventKeys.delete(eventKey);\n }\n }\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n"],"mappings":"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","names":[]}
|
package/dist/storage.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@mukulaggarwal/pacman",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Privacy-first personal assistant context manager with MCP, onboarding, and Slack runtime",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"pacman": "dist/index.js",
|
|
8
|
+
"personal-assistant": "dist/index.js",
|
|
9
|
+
"personal-assistant-mcp": "dist/mcp-compat.js"
|
|
10
|
+
},
|
|
11
|
+
"main": "dist/index.js",
|
|
12
|
+
"types": "dist/index.d.ts",
|
|
13
|
+
"files": [
|
|
14
|
+
"dist/**/*.js",
|
|
15
|
+
"dist/**/*.d.ts",
|
|
16
|
+
"dist/**/*.map",
|
|
17
|
+
"README.md"
|
|
18
|
+
],
|
|
19
|
+
"homepage": "https://github.com/mukulaggarwal/personal-assistant-with-context",
|
|
20
|
+
"bugs": {
|
|
21
|
+
"url": "https://github.com/mukulaggarwal/personal-assistant-with-context/issues"
|
|
22
|
+
},
|
|
23
|
+
"repository": {
|
|
24
|
+
"type": "git",
|
|
25
|
+
"url": "git+https://github.com/mukulaggarwal/personal-assistant-with-context.git"
|
|
26
|
+
},
|
|
27
|
+
"keywords": [
|
|
28
|
+
"assistant",
|
|
29
|
+
"mcp",
|
|
30
|
+
"slack",
|
|
31
|
+
"claude",
|
|
32
|
+
"codex",
|
|
33
|
+
"context",
|
|
34
|
+
"privacy"
|
|
35
|
+
],
|
|
36
|
+
"license": "Apache-2.0",
|
|
37
|
+
"publishConfig": {
|
|
38
|
+
"access": "public"
|
|
39
|
+
},
|
|
40
|
+
"scripts": {
|
|
41
|
+
"build": "tsup --config tsup.config.ts",
|
|
42
|
+
"dev": "tsup --config tsup.config.ts --watch",
|
|
43
|
+
"test": "vitest run",
|
|
44
|
+
"lint": "eslint src/",
|
|
45
|
+
"clean": "rm -rf dist"
|
|
46
|
+
},
|
|
47
|
+
"dependencies": {
|
|
48
|
+
"@modelcontextprotocol/sdk": "^1.12.0",
|
|
49
|
+
"commander": "^13.0.0",
|
|
50
|
+
"express": "^5.0.0",
|
|
51
|
+
"googleapis": "^144.0.0",
|
|
52
|
+
"open": "^10.1.0",
|
|
53
|
+
"zod": "^3.24.0"
|
|
54
|
+
},
|
|
55
|
+
"devDependencies": {
|
|
56
|
+
"@personal-assistant/claude-installer": "workspace:*",
|
|
57
|
+
"@personal-assistant/codex-installer": "workspace:*",
|
|
58
|
+
"@personal-assistant/config-manager": "workspace:*",
|
|
59
|
+
"@personal-assistant/context-manager": "workspace:*",
|
|
60
|
+
"@personal-assistant/core-types": "workspace:*",
|
|
61
|
+
"@personal-assistant/event-client": "workspace:*",
|
|
62
|
+
"@personal-assistant/integration-runtime": "workspace:*",
|
|
63
|
+
"@personal-assistant/indexer": "workspace:*",
|
|
64
|
+
"@personal-assistant/integrations-gchat": "workspace:*",
|
|
65
|
+
"@personal-assistant/integrations-gdrive": "workspace:*",
|
|
66
|
+
"@personal-assistant/integrations-github": "workspace:*",
|
|
67
|
+
"@personal-assistant/integrations-gitlab": "workspace:*",
|
|
68
|
+
"@personal-assistant/integrations-gmail": "workspace:*",
|
|
69
|
+
"@personal-assistant/integrations-slack": "workspace:*",
|
|
70
|
+
"@personal-assistant/storage-gdrive": "workspace:*",
|
|
71
|
+
"@personal-assistant/storage-local": "workspace:*",
|
|
72
|
+
"@personal-assistant/template-engine": "workspace:*",
|
|
73
|
+
"@types/express": "^5.0.0"
|
|
74
|
+
}
|
|
75
|
+
}
|