@tiey/synth 0.0.2 → 0.0.3

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/dist/index.js CHANGED
@@ -1572,6 +1572,7 @@ var nodeWindows = require3("node-windows");
1572
1572
  var SERVICE_NAME = "Synth AI Work Summary Service";
1573
1573
  var SERVICE_DESCRIPTION = "Collect AI coding sessions and generate scheduled work summaries.";
1574
1574
  var SERVICE_ID = SERVICE_NAME.replace(/[^\w]/g, "").toLowerCase();
1575
+ var SERVICE_SYSTEM_NAME = `${SERVICE_ID}.exe`;
1575
1576
  function ensureWindows() {
1576
1577
  if (process.platform !== "win32") {
1577
1578
  throw new Error("Windows service management is only supported on win32");
@@ -1620,6 +1621,16 @@ function createService() {
1620
1621
  }
1621
1622
  });
1622
1623
  }
1624
+ function withSilentConsole(fn) {
1625
+ const originalLog = console.log;
1626
+ console.log = () => {
1627
+ };
1628
+ try {
1629
+ return fn();
1630
+ } finally {
1631
+ console.log = originalLog;
1632
+ }
1633
+ }
1623
1634
  function waitForEvent(service, action, successEvents, failureEvents, mapResult) {
1624
1635
  return new Promise((resolve, reject) => {
1625
1636
  const handlers = {};
@@ -1647,7 +1658,7 @@ function waitForEvent(service, action, successEvents, failureEvents, mapResult)
1647
1658
  service.on(eventName, handlers[eventName]);
1648
1659
  }
1649
1660
  try {
1650
- action();
1661
+ withSilentConsole(action);
1651
1662
  } catch (err) {
1652
1663
  cleanup();
1653
1664
  reject(err);
@@ -1673,7 +1684,7 @@ function normalizeState(rawState) {
1673
1684
  async function getServiceStatus() {
1674
1685
  ensureWindows();
1675
1686
  try {
1676
- const { stdout, stderr } = await execFileAsync("sc.exe", ["query", SERVICE_ID], {
1687
+ const { stdout, stderr } = await execFileAsync("sc.exe", ["query", SERVICE_SYSTEM_NAME], {
1677
1688
  windowsHide: true
1678
1689
  });
1679
1690
  const output = `${stdout}
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/config/loader.ts","../src/config/schema.ts","../src/runner.ts","../src/agent/prompts.ts","../src/processor/preprocessor.ts","../src/processor/chunker.ts","../src/agent/semaphore.ts","../src/logger.ts","../src/agent/summarizer.ts","../src/agent/providers/anthropic.ts","../src/agent/providers/openai-compatible.ts","../src/collector/claude-code.adapter.ts","../src/collector/codex.adapter.ts","../src/collector/qoder.adapter.ts","../src/collector/registry.ts","../src/report/html.ts","../src/report/markdown.ts","../src/store/state.ts","../src/service.ts","../src/scheduler.ts"],"sourcesContent":["import { Command } from 'commander'\nimport { initConfig, loadConfig } from './config/loader.js'\nimport { backfillHistory, run } from './runner.js'\nimport {\n getServiceStatus,\n installService,\n runServiceProcess,\n startService,\n stopService,\n uninstallService,\n} from './service.js'\n\nfunction formatServiceState(state: string): string {\n return state.replace(/-/g, ' ')\n}\n\nconst program = new Command()\n\nprogram\n .name('synth')\n .description('AI Coding work summary service')\n .version('0.1.0')\n\nprogram\n .command('run')\n .description('Collect sessions and generate a report immediately')\n .option('--since <date>', 'Specify the start time')\n .option('--date <date>', 'Generate the report for the given date')\n .action(async (options) => {\n const config = loadConfig()\n await run(config, {\n since: options.since ? new Date(options.since) : undefined,\n date: options.date,\n })\n })\n\nprogram\n .command('config')\n .description('Manage configuration')\n .option('--init', 'Create the default config file')\n .action((options) => {\n if (options.init) {\n console.log(initConfig())\n return\n }\n\n console.log(JSON.stringify(loadConfig(), null, 2))\n })\n\nprogram\n .command('backfill-history')\n .description('Clear collection state and rebuild historical reports from all sessions')\n .action(async () => {\n const config = loadConfig()\n await backfillHistory(config)\n })\n\nprogram\n .command('install')\n .description('Install and start the Windows service')\n .action(async () => {\n const status = await installService()\n console.log(`service: ${status.installed ? 'installed' : 'not installed'}`)\n console.log(`state: ${formatServiceState(status.state)}`)\n })\n\nprogram\n .command('uninstall')\n .description('Stop and remove the Windows service')\n .action(async () => {\n const status = await uninstallService()\n console.log(`service: ${status.installed ? 'installed' : 'not installed'}`)\n console.log(`state: ${formatServiceState(status.state)}`)\n })\n\nprogram\n .command('start')\n .description('Start the Windows service')\n .action(async () => {\n const status = await startService()\n console.log(`service: ${status.installed ? 'installed' : 'not installed'}`)\n console.log(`state: ${formatServiceState(status.state)}`)\n })\n\nprogram\n .command('stop')\n .description('Stop the Windows service')\n .action(async () => {\n const status = await stopService()\n console.log(`service: ${status.installed ? 'installed' : 'not installed'}`)\n console.log(`state: ${formatServiceState(status.state)}`)\n })\n\nprogram\n .command('status')\n .description('Show the Windows service status')\n .action(async () => {\n const status = await getServiceStatus()\n console.log(`service: ${status.installed ? 'installed' : 'not installed'}`)\n console.log(`state: ${formatServiceState(status.state)}`)\n if (status.rawState) {\n console.log(`rawState: ${status.rawState}`)\n }\n })\n\nprogram\n .command('service-run')\n .description('Internal service host command')\n .action(async () => {\n await runServiceProcess()\n })\n\nawait program.parseAsync()\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport os from 'node:os'\nimport { parse as parseYaml } from 'yaml'\nimport { configSchema, defaultConfigYaml, type SynthConfig } from './schema.js'\n\nexport function getSynthDir(): string {\n return path.join(os.homedir(), '.synth')\n}\n\nexport function getConfigPath(): string {\n return path.join(getSynthDir(), 'config.yaml')\n}\n\nexport function initConfig(): string {\n const configPath = getConfigPath()\n const dir = path.dirname(configPath)\n\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true })\n }\n\n if (fs.existsSync(configPath)) {\n return `配置文件已存在: ${configPath}`\n }\n\n fs.writeFileSync(configPath, defaultConfigYaml, 'utf-8')\n return `配置文件已生成: ${configPath}`\n}\n\nexport function loadConfig(): SynthConfig {\n const configPath = getConfigPath()\n\n let raw: unknown = {}\n if (fs.existsSync(configPath)) {\n const content = fs.readFileSync(configPath, 'utf-8')\n raw = parseYaml(content) ?? {}\n }\n\n return configSchema.parse(raw)\n}\n","import { z } from 'zod'\n\nexport const llmConfigSchema = z.object({\n provider: z.enum(['openai-compatible', 'anthropic', 'ollama']).default('openai-compatible'),\n baseUrl: z.string().default('https://api.openai.com/v1'),\n apiKey: z.string().default(''),\n model: z.string().default('gpt-4o'),\n contextWindow: z.number().int().positive().default(128000),\n maxTokens: z.number().int().positive().default(4096),\n maxConcurrency: z.number().int().positive().default(5),\n headers: z.record(z.string(), z.string()).default({}),\n})\n\nexport const agentConfigSchema = z.object({\n role: z.string().default(''),\n systemPrompt: z.string().default(''),\n mapPrompt: z.string().default(''),\n reducePrompt: z.string().default(''),\n reportPrompt: z.string().default(''),\n})\n\nexport const scheduleConfigSchema = z.object({\n cron: z.string().default('0 1-23 * * *'),\n})\n\nexport const collectorConfigSchema = z.object({\n adapters: z.array(z.string()).default(['claude-code', 'codex', 'qoder']),\n})\n\nexport const outputConfigSchema = z.object({\n formats: z.array(z.enum(['markdown', 'html'])).default(['markdown', 'html']),\n dir: z.string().default('~/.synth/reports'),\n})\n\nconst defaultLlmConfig = llmConfigSchema.parse({})\nconst defaultAgentConfig = agentConfigSchema.parse({})\nconst defaultScheduleConfig = scheduleConfigSchema.parse({})\nconst defaultCollectorConfig = collectorConfigSchema.parse({})\nconst defaultOutputConfig = outputConfigSchema.parse({})\n\nexport const configSchema = z.object({\n llm: llmConfigSchema.default(defaultLlmConfig),\n agent: agentConfigSchema.default(defaultAgentConfig),\n schedule: scheduleConfigSchema.default(defaultScheduleConfig),\n collector: collectorConfigSchema.default(defaultCollectorConfig),\n output: outputConfigSchema.default(defaultOutputConfig),\n})\n\nexport type SynthConfig = z.infer<typeof configSchema>\n\nexport const defaultConfigYaml = `# Synth config\n\nllm:\n provider: \"openai-compatible\"\n baseUrl: \"https://api.openai.com/v1\"\n apiKey: \"\"\n model: \"gpt-4o\"\n contextWindow: 128000\n maxTokens: 4096\n maxConcurrency: 5\n headers: {}\n\nagent:\n role: \"\"\n systemPrompt: \"\"\n mapPrompt: \"\"\n reducePrompt: \"\"\n reportPrompt: \"\"\n\nschedule:\n cron: \"0 1-23 * * *\"\n\ncollector:\n adapters:\n - claude-code\n - codex\n - qoder\n\noutput:\n formats:\n - markdown\n - html\n dir: \"~/.synth/reports\"\n`\n","import { createHash } from 'node:crypto'\nimport fs from 'node:fs'\nimport os from 'node:os'\nimport path from 'node:path'\nimport { Summarizer } from './agent/summarizer.js'\nimport type { LLMProvider, SessionSummary } from './agent/types.js'\nimport { AnthropicProvider } from './agent/providers/anthropic.js'\nimport { OpenAICompatibleProvider } from './agent/providers/openai-compatible.js'\nimport { ClaudeCodeAdapter } from './collector/claude-code.adapter.js'\nimport { CodexAdapter } from './collector/codex.adapter.js'\nimport { QoderAdapter } from './collector/qoder.adapter.js'\nimport { AdapterRegistry } from './collector/registry.js'\nimport type { Message, SessionRecord } from './collector/types.js'\nimport type { SynthConfig } from './config/schema.js'\nimport { getLogger } from './logger.js'\nimport { generateHtmlReport } from './report/html.js'\nimport { generateMarkdownReport } from './report/markdown.js'\nimport {\n clearCollectionState,\n getDailyCursor,\n hasMessageFingerprint,\n pruneMessageFingerprints,\n saveMessageFingerprints,\n setDailyCursor,\n} from './store/state.js'\n\nconst SAFETY_LAG_MS = 90 * 1000\nconst LOOKBACK_MS = 2 * 60 * 1000\n\nfunction createProvider(config: SynthConfig): LLMProvider {\n if (config.llm.provider === 'anthropic') {\n return new AnthropicProvider({\n baseUrl: config.llm.baseUrl,\n apiKey: config.llm.apiKey,\n model: config.llm.model,\n maxTokens: config.llm.maxTokens,\n })\n }\n\n return new OpenAICompatibleProvider({\n baseUrl: config.llm.baseUrl,\n apiKey: config.llm.apiKey,\n model: config.llm.model,\n maxTokens: config.llm.maxTokens,\n headers: config.llm.headers,\n })\n}\n\nfunction createRegistry(config: SynthConfig): AdapterRegistry {\n const registry = new AdapterRegistry()\n const adapters: Record<string, () => InstanceType<any>> = {\n 'claude-code': () => new ClaudeCodeAdapter(),\n codex: () => new CodexAdapter(),\n qoder: () => new QoderAdapter(),\n }\n\n for (const name of config.collector.adapters) {\n const factory = adapters[name]\n if (factory) {\n registry.register(factory())\n }\n }\n\n return registry\n}\n\nfunction formatDate(date: Date): string {\n const y = date.getFullYear()\n const m = String(date.getMonth() + 1).padStart(2, '0')\n const d = String(date.getDate()).padStart(2, '0')\n return `${y}-${m}-${d}`\n}\n\nfunction startOfDay(date: Date): Date {\n const value = new Date(date)\n value.setHours(0, 0, 0, 0)\n return value\n}\n\nfunction endOfDay(date: Date): Date {\n const value = new Date(date)\n value.setHours(23, 59, 59, 999)\n return value\n}\n\nfunction maxDate(left: Date, right: Date): Date {\n return left > right ? left : right\n}\n\nfunction getSafeUntil(now: Date): Date {\n return new Date(now.getTime() - SAFETY_LAG_MS)\n}\n\nfunction fingerprintMessage(session: SessionRecord, message: Message): string {\n const digest = createHash('sha1')\n .update(session.tool)\n .update('\\n')\n .update(session.sessionId)\n .update('\\n')\n .update(message.timestamp.toISOString())\n .update('\\n')\n .update(message.role)\n .update('\\n')\n .update(message.content)\n .digest('hex')\n\n return `${session.tool}:${session.sessionId}:${digest}`\n}\n\nfunction filterDuplicateMessages(date: string, sessions: SessionRecord[]): SessionRecord[] {\n const filtered: SessionRecord[] = []\n\n for (const session of sessions) {\n const messages = session.messages.filter((message) => !hasMessageFingerprint(date, fingerprintMessage(session, message)))\n if (messages.length === 0) continue\n\n filtered.push({\n ...session,\n startTime: messages[0].timestamp,\n endTime: messages[messages.length - 1].timestamp,\n messages,\n })\n }\n\n return filtered\n}\n\nfunction collectSessionFingerprints(session: SessionRecord): string[] {\n return session.messages.map((message) => fingerprintMessage(session, message))\n}\n\nfunction summarizeSessionsConfig(\n config: SynthConfig,\n sessions: SessionRecord[],\n provider: LLMProvider,\n): Promise<{ summaries: SessionSummary[]; fingerprints: string[]; hadFailures: boolean }> {\n const logger = getLogger()\n const summarizer = new Summarizer(provider, config)\n\n return (async () => {\n const summaries: SessionSummary[] = []\n const fingerprints: string[] = []\n let hadFailures = false\n\n for (const session of sessions) {\n try {\n const summary = await summarizer.summarizeSession(session)\n summaries.push(summary)\n fingerprints.push(...collectSessionFingerprints(session))\n logger.info(\n {\n tool: session.tool,\n workingDir: session.workingDir,\n sessionId: session.sessionId.slice(0, 8),\n startTime: session.startTime.toISOString(),\n endTime: session.endTime.toISOString(),\n messages: session.messages.length,\n },\n 'Session summarized',\n )\n } catch (err) {\n hadFailures = true\n logger.error(\n {\n sessionId: session.sessionId.slice(0, 8),\n err,\n },\n 'Session summarize failed and was skipped',\n )\n }\n }\n\n return { summaries, fingerprints, hadFailures }\n })()\n}\n\nfunction resolveOutputBaseDir(config: SynthConfig): string {\n return config.output.dir.replace(/^~/, os.homedir())\n}\n\nfunction clearHistoricalReports(config: SynthConfig): void {\n const logger = getLogger()\n const baseDir = resolveOutputBaseDir(config)\n const targets = [\n { dir: path.join(baseDir, 'markdown'), ext: '.md' },\n { dir: path.join(baseDir, 'html'), ext: '.html' },\n ]\n\n for (const target of targets) {\n if (!fs.existsSync(target.dir)) continue\n\n for (const file of fs.readdirSync(target.dir)) {\n if (!file.endsWith(target.ext)) continue\n fs.unlinkSync(path.join(target.dir, file))\n }\n\n logger.info({ dir: target.dir }, 'Historical report directory cleared')\n }\n}\n\nfunction partitionSessionsByDate(sessions: SessionRecord[]): Map<string, SessionRecord[]> {\n const groups = new Map<string, SessionRecord[]>()\n\n for (const session of sessions) {\n const dateBuckets = new Map<string, Message[]>()\n\n for (const message of session.messages) {\n const dateKey = formatDate(message.timestamp)\n const list = dateBuckets.get(dateKey) || []\n list.push(message)\n dateBuckets.set(dateKey, list)\n }\n\n for (const [dateKey, messages] of dateBuckets.entries()) {\n const sessionsForDate = groups.get(dateKey) || []\n sessionsForDate.push({\n ...session,\n sessionId: `${session.sessionId}:${dateKey}`,\n startTime: messages[0].timestamp,\n endTime: messages[messages.length - 1].timestamp,\n messages,\n })\n groups.set(dateKey, sessionsForDate)\n }\n }\n\n return groups\n}\n\nasync function renderReportsForDate(\n config: SynthConfig,\n date: string,\n summaries: SessionSummary[],\n provider: LLMProvider,\n append: boolean,\n): Promise<void> {\n const formats = config.output.formats\n\n if (!formats.includes('markdown') && !formats.includes('html')) {\n return\n }\n\n const markdownReport = await generateMarkdownReport(date, summaries, provider, config, {\n append,\n })\n\n if (formats.includes('html')) {\n generateHtmlReport(date, markdownReport.content, config)\n }\n}\n\nexport interface RunOptions {\n since?: Date\n date?: string\n}\n\nexport async function run(config: SynthConfig, options: RunOptions = {}): Promise<void> {\n const logger = getLogger()\n\n if (!config.llm.apiKey) {\n logger.error('Missing LLM apiKey. Run `synth config --init` and update ~/.synth/config.yaml')\n return\n }\n\n const now = new Date()\n let since: Date\n let until: Date\n let rawSince: Date\n let dateStr: string\n let appendReport = true\n let updateCursor = true\n let enableFingerprintDedup = false\n\n if (options.date) {\n const targetDay = new Date(`${options.date}T00:00:00`)\n since = startOfDay(targetDay)\n until = endOfDay(targetDay)\n rawSince = since\n dateStr = options.date\n appendReport = false\n updateCursor = false\n } else if (options.since) {\n rawSince = options.since\n since = options.since\n until = getSafeUntil(now)\n dateStr = formatDate(until)\n appendReport = true\n updateCursor = false\n } else {\n dateStr = formatDate(now)\n const dayStart = startOfDay(now)\n const cursor = getDailyCursor(dateStr)\n rawSince = cursor && cursor > dayStart ? cursor : dayStart\n since = maxDate(dayStart, new Date(rawSince.getTime() - LOOKBACK_MS))\n until = getSafeUntil(now)\n enableFingerprintDedup = true\n }\n\n if (formatDate(until) !== dateStr) {\n until = dateStr === formatDate(now) ? maxDate(startOfDay(now), until) : until\n }\n\n logger.info(\n {\n rawSince: rawSince.toISOString(),\n since: since.toISOString(),\n until: until.toISOString(),\n date: dateStr,\n appendReport,\n updateCursor,\n enableFingerprintDedup,\n safetyLagMs: options.date ? 0 : SAFETY_LAG_MS,\n lookbackMs: enableFingerprintDedup ? LOOKBACK_MS : 0,\n },\n 'Run started',\n )\n\n if (until <= since) {\n logger.info({ since: since.toISOString(), until: until.toISOString(), date: dateStr }, 'No new collection window')\n return\n }\n\n if (enableFingerprintDedup) {\n const keepFrom = new Date(startOfDay(now))\n keepFrom.setDate(keepFrom.getDate() - 2)\n pruneMessageFingerprints(formatDate(keepFrom))\n }\n\n const registry = createRegistry(config)\n const collectedSessions = await registry.collectAll(since, until, config.collector.adapters)\n const sessions = enableFingerprintDedup\n ? filterDuplicateMessages(dateStr, collectedSessions)\n : collectedSessions\n\n if (sessions.length === 0) {\n logger.info('No new messages collected in the requested window')\n if (updateCursor) {\n setDailyCursor(dateStr, until)\n }\n return\n }\n\n logger.info({ count: sessions.length }, 'Collection finished')\n\n const provider = createProvider(config)\n const { summaries, fingerprints, hadFailures } = await summarizeSessionsConfig(config, sessions, provider)\n\n if (summaries.length === 0) {\n logger.warn('All sessions failed during summarization')\n return\n }\n\n await renderReportsForDate(config, dateStr, summaries, provider, appendReport)\n\n if (enableFingerprintDedup && fingerprints.length > 0) {\n saveMessageFingerprints(dateStr, fingerprints)\n logger.info({ date: dateStr, fingerprints: fingerprints.length }, 'Message fingerprints saved')\n }\n\n if (updateCursor && !hadFailures) {\n setDailyCursor(dateStr, until)\n logger.info({ date: dateStr, cursor: until.toISOString() }, 'Daily cursor updated')\n } else if (updateCursor && hadFailures) {\n logger.warn({ date: dateStr }, 'Cursor not advanced because some sessions failed; next run will retry with dedup')\n }\n\n logger.info({ date: dateStr, sessions: summaries.length }, 'Run finished')\n}\n\nexport async function backfillHistory(config: SynthConfig): Promise<void> {\n const logger = getLogger()\n\n if (!config.llm.apiKey) {\n logger.error('Missing LLM apiKey. Run `synth config --init` and update ~/.synth/config.yaml')\n return\n }\n\n const now = new Date()\n const safeUntil = getSafeUntil(now)\n const today = formatDate(safeUntil)\n\n logger.info({ until: safeUntil.toISOString() }, 'History backfill started')\n\n clearCollectionState()\n clearHistoricalReports(config)\n\n const registry = createRegistry(config)\n const provider = createProvider(config)\n const sessions = await registry.collectAll(new Date(0), safeUntil, config.collector.adapters)\n\n if (sessions.length === 0) {\n logger.info('No sessions found for historical backfill')\n setDailyCursor(today, safeUntil)\n return\n }\n\n const sessionsByDate = partitionSessionsByDate(sessions)\n const sortedDates = Array.from(sessionsByDate.keys()).sort()\n const todayFingerprints: string[] = []\n\n for (const date of sortedDates) {\n const dateSessions = sessionsByDate.get(date) || []\n const { summaries, fingerprints } = await summarizeSessionsConfig(config, dateSessions, provider)\n\n if (summaries.length === 0) {\n logger.warn({ date }, 'No summaries generated for historical date')\n continue\n }\n\n await renderReportsForDate(config, date, summaries, provider, false)\n\n if (date === today) {\n todayFingerprints.push(...fingerprints)\n }\n }\n\n if (todayFingerprints.length > 0) {\n saveMessageFingerprints(today, todayFingerprints)\n }\n setDailyCursor(today, safeUntil)\n\n logger.info({ dates: sortedDates.length, until: safeUntil.toISOString() }, 'History backfill finished')\n}\n","export const defaultPrompts = {\n role: 'AI编程工作记录分析师',\n\n systemPrompt: `你是一位专业的工作内容分析师。你的任务是分析用户与AI编程助手的对话记录,\n提取关键工作内容,生成简洁准确的工作摘要。\n要求:\n- 关注实际完成的工作,而非对话过程\n- 提取修改的文件、解决的问题、实现的功能\n- 使用简洁的中文描述\n- 忽略闲聊、系统提示等无关内容`,\n\n mapPrompt: `以下是 {{tool}} 中的一段对话记录(第 {{chunkIndex}}/{{totalChunks}} 片)。\n工作目录:{{workingDir}}\n时间范围:{{startTime}} ~ {{endTime}}\n请提取本片段中的关键工作内容,以要点列表形式输出。\n---\n{{content}}`,\n\n reducePrompt: `以下是同一会话拆分后的各片段摘要,请合并为一份完整摘要,去重并按时间线组织:\n{{summaries}}`,\n\n reportPrompt: `请将以下会话摘要整合为工作日报,严格按照指定格式输出。\n日期:{{date}}\n要求格式:\n# {{date}} 工作日报\n## <工作目录>\n### <时间段>\n- <工作内容>\n合并规则:\n- 同一工作目录下的多个会话,按时间段分别列出\n- 时间段格式为 HH:MM~HH:MM\n---\n{{sessionSummaries}}`,\n}\n\nexport function renderTemplate(template: string, vars: Record<string, string>): string {\n return template.replace(/\\{\\{(\\w+)\\}\\}/g, (_, key: string) => vars[key] ?? '')\n}\n","import type { Message } from '../collector/types.js'\n\nconst BASE64_PATTERN = /data:[a-zA-Z0-9+/]+;base64,[A-Za-z0-9+/=]{100,}/g\nconst SYSTEM_REMINDER_PATTERN = /<system-reminder>[\\s\\S]*?<\\/system-reminder>/g\nconst DEFERRED_TOOLS_PATTERN = /<functions>[\\s\\S]*?<\\/functions>/g\n\nconst TOOL_RESULT_MAX_LEN = 200\n\n/**\n * Preprocess messages to reduce token count before sending to LLM.\n * Filters out thinking/signature blocks, base64, system-reminders,\n * truncates tool_result, and keeps tool_use name + key params.\n */\nexport function preprocessMessages(messages: Message[]): Message[] {\n const result: Message[] = []\n\n for (const msg of messages) {\n const cleaned = cleanContent(msg.content)\n if (!cleaned.trim()) continue\n\n result.push({\n role: msg.role,\n content: cleaned,\n timestamp: msg.timestamp,\n })\n }\n\n return result\n}\n\nfunction cleanContent(content: string): string {\n let text = content\n\n // Remove thinking blocks (including encrypted signatures)\n text = text.replace(/\\[thinking\\][^\\n]*/g, '')\n\n // Remove base64 content\n text = text.replace(BASE64_PATTERN, '[base64 content removed]')\n\n // Remove system-reminder blocks\n text = text.replace(SYSTEM_REMINDER_PATTERN, '')\n\n // Remove deferred_tools / functions blocks\n text = text.replace(DEFERRED_TOOLS_PATTERN, '')\n\n // Remove attachment blocks\n text = text.replace(/<attachment>[\\s\\S]*?<\\/attachment>/g, '')\n\n // Truncate tool_result content\n text = text.replace(/\\[tool_result\\]\\s*([\\s\\S]*?)(?=\\n\\[|$)/g, (match, resultContent: string) => {\n const trimmed = resultContent.trim()\n if (trimmed.length > TOOL_RESULT_MAX_LEN) {\n return `[tool_result] ${trimmed.slice(0, TOOL_RESULT_MAX_LEN)}...`\n }\n return `[tool_result] ${trimmed}`\n })\n\n // Simplify tool_use: keep name and trim very long input\n text = text.replace(/\\[tool_use:\\s*(\\w+)\\]\\s*([\\s\\S]*?)(?=\\n\\[|$)/g, (match, name: string, input: string) => {\n const trimmedInput = input.trim()\n if (trimmedInput.length > 500) {\n return `[tool_use: ${name}] ${trimmedInput.slice(0, 500)}...`\n }\n return `[tool_use: ${name}] ${trimmedInput}`\n })\n\n // Collapse multiple blank lines\n text = text.replace(/\\n{3,}/g, '\\n\\n')\n\n return text.trim()\n}\n","import type { Message } from '../collector/types.js'\n\nexport interface ChunkOptions {\n maxTokensPerChunk: number // default 50000\n overlapMessages: number // default 3\n}\n\nexport interface Chunk {\n messages: Message[]\n chunkIndex: number\n totalChunks: number\n startTime: Date\n endTime: Date\n}\n\nconst DEFAULT_OPTIONS: ChunkOptions = {\n maxTokensPerChunk: 50000,\n overlapMessages: 3,\n}\n\n/**\n * Estimate token count using char/3 heuristic.\n */\nexport function estimateTokens(text: string): number {\n return Math.ceil(text.length / 3)\n}\n\n/**\n * Estimate total tokens for a list of messages.\n */\nexport function estimateMessagesTokens(messages: Message[]): number {\n return messages.reduce((sum, m) => sum + estimateTokens(m.content), 0)\n}\n\n/**\n * Split messages into chunks, aligning boundaries to complete user-assistant pairs.\n */\nexport function chunkMessages(messages: Message[], options?: Partial<ChunkOptions>): Chunk[] {\n const opts = { ...DEFAULT_OPTIONS, ...options }\n\n const totalTokens = estimateMessagesTokens(messages)\n if (totalTokens <= opts.maxTokensPerChunk) {\n return [{\n messages,\n chunkIndex: 1,\n totalChunks: 1,\n startTime: messages[0].timestamp,\n endTime: messages[messages.length - 1].timestamp,\n }]\n }\n\n // Find pair boundaries: each pair starts with a user message\n const pairBoundaries: number[] = [0]\n for (let i = 1; i < messages.length; i++) {\n if (messages[i].role === 'user') {\n pairBoundaries.push(i)\n }\n }\n\n // Build chunks by accumulating pairs until token limit\n const rawChunks: Message[][] = []\n let currentChunk: Message[] = []\n let currentTokens = 0\n\n for (let p = 0; p < pairBoundaries.length; p++) {\n const pairStart = pairBoundaries[p]\n const pairEnd = p + 1 < pairBoundaries.length ? pairBoundaries[p + 1] : messages.length\n const pairMessages = messages.slice(pairStart, pairEnd)\n const pairTokens = pairMessages.reduce((sum, m) => sum + estimateTokens(m.content), 0)\n\n if (currentChunk.length > 0 && currentTokens + pairTokens > opts.maxTokensPerChunk) {\n rawChunks.push(currentChunk)\n currentChunk = []\n currentTokens = 0\n }\n\n currentChunk.push(...pairMessages)\n currentTokens += pairTokens\n }\n\n if (currentChunk.length > 0) {\n rawChunks.push(currentChunk)\n }\n\n // Apply overlap: prepend last N messages from previous chunk\n const totalChunks = rawChunks.length\n const chunks: Chunk[] = rawChunks.map((chunkMsgs, i) => {\n let finalMessages = chunkMsgs\n if (i > 0 && opts.overlapMessages > 0) {\n const prevChunk = rawChunks[i - 1]\n const overlapStart = Math.max(0, prevChunk.length - opts.overlapMessages)\n const overlap = prevChunk.slice(overlapStart)\n finalMessages = [...overlap, ...chunkMsgs]\n }\n\n return {\n messages: finalMessages,\n chunkIndex: i + 1,\n totalChunks,\n startTime: finalMessages[0].timestamp,\n endTime: finalMessages[finalMessages.length - 1].timestamp,\n }\n })\n\n return chunks\n}\n","export class Semaphore {\n private queue: (() => void)[] = []\n private running = 0\n\n constructor(private readonly max: number) {}\n\n async acquire(): Promise<void> {\n if (this.running < this.max) {\n this.running++\n return\n }\n return new Promise(resolve => this.queue.push(resolve))\n }\n\n release(): void {\n this.running--\n const next = this.queue.shift()\n if (next) {\n this.running++\n next()\n }\n }\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport { createRequire } from 'node:module'\nimport pino from 'pino'\nimport { getSynthDir } from './config/loader.js'\n\nconst require = createRequire(import.meta.url)\n\nfunction ensureLogDir(): string {\n const logDir = path.join(getSynthDir(), 'logs')\n if (!fs.existsSync(logDir)) {\n fs.mkdirSync(logDir, { recursive: true })\n }\n return logDir\n}\n\nfunction hasPinoPretty(): boolean {\n try {\n require.resolve('pino-pretty')\n return true\n } catch {\n return false\n }\n}\n\nexport function createLogger(level: string = 'info'): pino.Logger {\n const logDir = ensureLogDir()\n const logFile = path.join(logDir, 'synth.log')\n const targets: pino.TransportTargetOptions[] = [\n {\n target: 'pino/file',\n options: { destination: logFile, mkdir: true },\n level,\n },\n ]\n\n if (hasPinoPretty()) {\n targets.push({\n target: 'pino-pretty',\n options: { colorize: true },\n level,\n })\n } else {\n targets.push({\n target: 'pino/file',\n options: { destination: 1 },\n level,\n })\n }\n\n return pino({ level }, pino.transport({ targets }))\n}\n\nlet _logger: pino.Logger | undefined\n\nexport function getLogger(): pino.Logger {\n if (!_logger) {\n _logger = createLogger()\n }\n return _logger\n}\n\nexport function setLogger(logger: pino.Logger): void {\n _logger = logger\n}\n","import type { SessionRecord, Message } from '../collector/types.js'\nimport type { LLMProvider, SessionSummary } from './types.js'\nimport type { SynthConfig } from '../config/schema.js'\nimport { defaultPrompts, renderTemplate } from './prompts.js'\nimport { preprocessMessages } from '../processor/preprocessor.js'\nimport { chunkMessages, estimateMessagesTokens } from '../processor/chunker.js'\nimport { Semaphore } from './semaphore.js'\nimport { getLogger } from '../logger.js'\n\nconst MAX_RETRIES = 2\n\nfunction formatTime(date: Date): string {\n return date.toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit', hour12: false })\n}\n\nfunction getPrompt(config: SynthConfig, key: keyof typeof defaultPrompts): string {\n const custom = config.agent[key]\n return (custom && custom.trim()) ? custom : defaultPrompts[key]\n}\n\nfunction messagesToText(messages: Message[]): string {\n return messages\n .map(m => `[${m.role}] ${m.content}`)\n .join('\\n\\n')\n}\n\nexport class Summarizer {\n private provider: LLMProvider\n private config: SynthConfig\n private semaphore: Semaphore\n\n constructor(provider: LLMProvider, config: SynthConfig) {\n this.provider = provider\n this.config = config\n this.semaphore = new Semaphore(config.llm.maxConcurrency)\n }\n\n /**\n * Summarize a single session: preprocess → chunk if needed → summarize.\n */\n async summarizeSession(session: SessionRecord): Promise<SessionSummary> {\n const logger = getLogger()\n const preprocessed = preprocessMessages(session.messages)\n const totalTokens = estimateMessagesTokens(preprocessed)\n const systemPrompt = getPrompt(this.config, 'systemPrompt')\n\n // Token threshold: contextWindow minus buffer for system prompt and output\n const threshold = this.config.llm.contextWindow - this.config.llm.maxTokens - 2000\n\n logger.debug({\n sessionId: session.sessionId.slice(0, 8),\n totalTokens,\n threshold,\n messageCount: preprocessed.length,\n }, 'Session 摘要开始')\n\n let summary: string\n\n if (totalTokens <= threshold) {\n // Single-pass summarization\n summary = await this.singlePassSummarize(session, preprocessed, systemPrompt)\n } else {\n // MapReduce summarization\n summary = await this.mapReduceSummarize(session, preprocessed, systemPrompt, threshold)\n }\n\n logger.info({\n sessionId: session.sessionId.slice(0, 8),\n tool: session.tool,\n workingDir: session.workingDir,\n }, 'Session 摘要完成')\n\n return {\n sessionId: session.sessionId,\n tool: session.tool,\n workingDir: session.workingDir,\n startTime: session.startTime,\n endTime: session.endTime,\n summary,\n }\n }\n\n private async singlePassSummarize(\n session: SessionRecord,\n messages: Message[],\n systemPrompt: string,\n ): Promise<string> {\n const content = messagesToText(messages)\n const mapPrompt = renderTemplate(getPrompt(this.config, 'mapPrompt'), {\n tool: session.tool,\n workingDir: session.workingDir,\n startTime: formatTime(session.startTime),\n endTime: formatTime(session.endTime),\n chunkIndex: '1',\n totalChunks: '1',\n content,\n })\n\n return this.callWithRetry([\n { role: 'system', content: systemPrompt },\n { role: 'user', content: mapPrompt },\n ])\n }\n\n private async mapReduceSummarize(\n session: SessionRecord,\n messages: Message[],\n systemPrompt: string,\n maxTokensPerChunk: number,\n ): Promise<string> {\n const logger = getLogger()\n const chunks = chunkMessages(messages, { maxTokensPerChunk })\n\n logger.info({\n sessionId: session.sessionId.slice(0, 8),\n chunks: chunks.length,\n }, 'MapReduce 分片')\n\n // Map phase: concurrent summarization with semaphore\n const mapResults = await Promise.all(\n chunks.map(async (chunk) => {\n await this.semaphore.acquire()\n try {\n const content = messagesToText(chunk.messages)\n const mapPrompt = renderTemplate(getPrompt(this.config, 'mapPrompt'), {\n tool: session.tool,\n workingDir: session.workingDir,\n startTime: formatTime(chunk.startTime),\n endTime: formatTime(chunk.endTime),\n chunkIndex: String(chunk.chunkIndex),\n totalChunks: String(chunk.totalChunks),\n content,\n })\n\n const result = await this.callWithRetry([\n { role: 'system', content: systemPrompt },\n { role: 'user', content: mapPrompt },\n ])\n\n logger.debug({\n sessionId: session.sessionId.slice(0, 8),\n chunk: `${chunk.chunkIndex}/${chunk.totalChunks}`,\n }, 'Map 片段完成')\n\n return result\n } catch (err) {\n logger.error({\n sessionId: session.sessionId.slice(0, 8),\n chunk: `${chunk.chunkIndex}/${chunk.totalChunks}`,\n err,\n }, 'Map 片段失败,跳过')\n return null\n } finally {\n this.semaphore.release()\n }\n }),\n )\n\n const validSummaries = mapResults.filter((s): s is string => s !== null)\n\n if (validSummaries.length === 0) {\n return '(摘要生成失败)'\n }\n\n if (validSummaries.length === 1) {\n return validSummaries[0]\n }\n\n // Reduce phase: merge all chunk summaries\n const summariesText = validSummaries\n .map((s, i) => `--- 片段 ${i + 1} ---\\n${s}`)\n .join('\\n\\n')\n\n const reducePrompt = renderTemplate(getPrompt(this.config, 'reducePrompt'), {\n summaries: summariesText,\n })\n\n return this.callWithRetry([\n { role: 'system', content: systemPrompt },\n { role: 'user', content: reducePrompt },\n ])\n }\n\n private async callWithRetry(\n messages: { role: 'system' | 'user' | 'assistant'; content: string }[],\n ): Promise<string> {\n const logger = getLogger()\n let lastError: unknown\n\n for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {\n try {\n return await this.provider.chat(messages)\n } catch (err) {\n lastError = err\n if (attempt < MAX_RETRIES) {\n const delay = 1000 * (attempt + 1)\n logger.warn({ attempt: attempt + 1, err }, `LLM 调用失败,${delay}ms 后重试`)\n await new Promise(r => setTimeout(r, delay))\n }\n }\n }\n\n throw lastError\n }\n}\n","import Anthropic from '@anthropic-ai/sdk'\nimport type { ChatMessage, ChatOptions, LLMProvider } from '../types.js'\n\nexport interface AnthropicConfig {\n baseUrl: string\n apiKey: string\n model: string\n maxTokens: number\n}\n\nexport class AnthropicProvider implements LLMProvider {\n private client: Anthropic\n private model: string\n private maxTokens: number\n\n constructor(config: AnthropicConfig) {\n this.client = new Anthropic({\n baseURL: config.baseUrl,\n apiKey: config.apiKey,\n })\n this.model = config.model\n this.maxTokens = config.maxTokens\n }\n\n async chat(messages: ChatMessage[], options?: ChatOptions): Promise<string> {\n // Separate system prompt from conversation messages\n let system: string | undefined\n const conversationMessages: Array<{ role: 'user' | 'assistant'; content: string }> = []\n\n for (const msg of messages) {\n if (msg.role === 'system') {\n system = msg.content\n } else {\n conversationMessages.push({\n role: msg.role,\n content: msg.content,\n })\n }\n }\n\n const response = await this.client.messages.create({\n model: this.model,\n max_tokens: options?.maxTokens ?? this.maxTokens,\n system,\n messages: conversationMessages,\n })\n\n const textBlock = response.content.find(b => b.type === 'text')\n return textBlock?.type === 'text' ? textBlock.text : ''\n }\n}\n","import OpenAI from 'openai'\nimport type { ChatMessage, ChatOptions, LLMProvider } from '../types.js'\n\nexport interface OpenAICompatibleConfig {\n baseUrl: string\n apiKey: string\n model: string\n maxTokens: number\n headers?: Record<string, string>\n}\n\nexport class OpenAICompatibleProvider implements LLMProvider {\n private client: OpenAI\n private model: string\n private maxTokens: number\n\n constructor(config: OpenAICompatibleConfig) {\n this.client = new OpenAI({\n baseURL: config.baseUrl,\n apiKey: config.apiKey,\n defaultHeaders: config.headers,\n })\n this.model = config.model\n this.maxTokens = config.maxTokens\n }\n\n async chat(messages: ChatMessage[], options?: ChatOptions): Promise<string> {\n const response = await this.client.chat.completions.create({\n model: this.model,\n messages: messages.map(m => ({\n role: m.role,\n content: m.content,\n })),\n max_tokens: options?.maxTokens ?? this.maxTokens,\n temperature: options?.temperature ?? 0.3,\n })\n\n return response.choices[0]?.message?.content ?? ''\n }\n}\n","import fs from 'node:fs'\nimport os from 'node:os'\nimport path from 'node:path'\nimport readline from 'node:readline'\nimport { getLogger } from '../logger.js'\nimport type { Message, SessionRecord, ToolAdapter } from './types.js'\n\nfunction decodeProjectDir(encoded: string): string {\n const match = encoded.match(/^([A-Za-z])--(.*)?$/)\n if (!match) return encoded\n\n const drive = match[1].toUpperCase()\n const rest = match[2] ? match[2].replace(/-/g, '\\\\') : ''\n return rest ? `${drive}:\\\\${rest}` : `${drive}:\\\\`\n}\n\nfunction getClaudeDir(): string {\n return path.join(os.homedir(), '.claude')\n}\n\nfunction isMessageInWindow(timestamp: Date, since: Date, until: Date): boolean {\n return timestamp > since && timestamp <= until\n}\n\nexport class ClaudeCodeAdapter implements ToolAdapter {\n readonly name = 'claude-code'\n\n async detect(): Promise<boolean> {\n return fs.existsSync(path.join(getClaudeDir(), 'projects'))\n }\n\n async collectSessions(since: Date, until: Date): Promise<SessionRecord[]> {\n const logger = getLogger()\n const projectsDir = path.join(getClaudeDir(), 'projects')\n const results: SessionRecord[] = []\n const projectDirs = fs.readdirSync(projectsDir, { withFileTypes: true }).filter((d) => d.isDirectory())\n\n for (const projectDir of projectDirs) {\n const workingDir = decodeProjectDir(projectDir.name)\n const projectPath = path.join(projectsDir, projectDir.name)\n const jsonlFiles = fs.readdirSync(projectPath).filter((f) => f.endsWith('.jsonl'))\n\n for (const file of jsonlFiles) {\n const filePath = path.join(projectPath, file)\n const sessionId = path.basename(file, '.jsonl')\n const stat = fs.statSync(filePath)\n\n if (stat.mtime <= since) continue\n\n try {\n const session = await this.parseSession(filePath, sessionId, workingDir, since, until)\n if (session) {\n results.push(session)\n }\n } catch (err) {\n logger.warn({ file: filePath, err }, 'Claude Code session parse failed')\n }\n }\n }\n\n return results\n }\n\n private async parseSession(\n filePath: string,\n sessionId: string,\n workingDir: string,\n since: Date,\n until: Date,\n ): Promise<SessionRecord | null> {\n const messages: Message[] = []\n let cwd = workingDir\n const stream = fs.createReadStream(filePath, { encoding: 'utf-8' })\n const rl = readline.createInterface({ input: stream, crlfDelay: Infinity })\n\n for await (const line of rl) {\n if (!line.trim()) continue\n\n let entry: any\n try {\n entry = JSON.parse(line)\n } catch {\n continue\n }\n\n if (entry.cwd) {\n cwd = entry.cwd\n }\n\n if (entry.type !== 'user' && entry.type !== 'assistant') continue\n if (!entry.message) continue\n\n const timestamp = entry.timestamp ? new Date(entry.timestamp) : null\n if (!timestamp || !isMessageInWindow(timestamp, since, until)) continue\n\n const role = entry.message.role as 'user' | 'assistant'\n if (role !== 'user' && role !== 'assistant') continue\n\n const content = extractTextContent(entry.message.content)\n if (!content) continue\n\n messages.push({ role, content, timestamp })\n }\n\n if (messages.length === 0) return null\n\n return {\n tool: 'claude-code',\n sessionId,\n workingDir: cwd,\n startTime: messages[0].timestamp,\n endTime: messages[messages.length - 1].timestamp,\n messages,\n }\n }\n}\n\nfunction extractTextContent(content: unknown): string {\n if (typeof content === 'string') return content\n\n if (Array.isArray(content)) {\n const parts: string[] = []\n for (const block of content) {\n if (!block || typeof block !== 'object') continue\n const b = block as Record<string, any>\n\n if (b.type === 'text' && typeof b.text === 'string') {\n parts.push(b.text)\n } else if (b.type === 'tool_use') {\n const input = b.input ? JSON.stringify(b.input) : ''\n parts.push(`[tool_use: ${b.name}] ${input}`)\n } else if (b.type === 'tool_result') {\n const text = typeof b.content === 'string' ? b.content : ''\n parts.push(`[tool_result] ${text}`)\n } else if (b.type === 'thinking') {\n parts.push(`[thinking] ${b.thinking || ''}`)\n }\n }\n return parts.join('\\n')\n }\n\n return ''\n}\n","import fs from 'node:fs'\nimport os from 'node:os'\nimport path from 'node:path'\nimport readline from 'node:readline'\nimport { getLogger } from '../logger.js'\nimport type { Message, SessionRecord, ToolAdapter } from './types.js'\n\nfunction getCodexDir(): string {\n return path.join(os.homedir(), '.codex')\n}\n\nfunction isMessageInWindow(timestamp: Date, since: Date, until: Date): boolean {\n return timestamp > since && timestamp <= until\n}\n\nexport class CodexAdapter implements ToolAdapter {\n readonly name = 'codex'\n\n async detect(): Promise<boolean> {\n return fs.existsSync(path.join(getCodexDir(), 'sessions'))\n }\n\n async collectSessions(since: Date, until: Date): Promise<SessionRecord[]> {\n const logger = getLogger()\n const sessionsDir = path.join(getCodexDir(), 'sessions')\n const results: SessionRecord[] = []\n const sessionFiles = this.findSessionFiles(sessionsDir, since, until)\n\n for (const filePath of sessionFiles) {\n const sessionId = path.basename(filePath, '.jsonl')\n\n try {\n const session = await this.parseSession(filePath, sessionId, since, until)\n if (session) {\n results.push(session)\n }\n } catch (err) {\n logger.warn({ file: filePath, err }, 'Codex session parse failed')\n }\n }\n\n return results\n }\n\n private findSessionFiles(sessionsDir: string, since: Date, until: Date): string[] {\n const files: string[] = []\n if (!fs.existsSync(sessionsDir)) return files\n\n const years = fs.readdirSync(sessionsDir, { withFileTypes: true }).filter((d) => d.isDirectory() && /^\\d{4}$/.test(d.name))\n\n for (const yearDir of years) {\n const yearPath = path.join(sessionsDir, yearDir.name)\n const months = fs.readdirSync(yearPath, { withFileTypes: true }).filter((d) => d.isDirectory() && /^\\d{2}$/.test(d.name))\n\n for (const monthDir of months) {\n const monthPath = path.join(yearPath, monthDir.name)\n const days = fs.readdirSync(monthPath, { withFileTypes: true }).filter((d) => d.isDirectory() && /^\\d{2}$/.test(d.name))\n\n for (const dayDir of days) {\n const dirDate = new Date(`${yearDir.name}-${monthDir.name}-${dayDir.name}T00:00:00`)\n const dirDateEnd = new Date(dirDate)\n dirDateEnd.setDate(dirDateEnd.getDate() + 1)\n\n if (dirDateEnd <= since || dirDate > until) continue\n\n const dayPath = path.join(monthPath, dayDir.name)\n const jsonlFiles = fs.readdirSync(dayPath)\n .filter((f) => f.endsWith('.jsonl'))\n .map((f) => path.join(dayPath, f))\n\n files.push(...jsonlFiles)\n }\n }\n }\n\n return files\n }\n\n private async parseSession(\n filePath: string,\n sessionId: string,\n since: Date,\n until: Date,\n ): Promise<SessionRecord | null> {\n const messages: Message[] = []\n let cwd = ''\n const stream = fs.createReadStream(filePath, { encoding: 'utf-8' })\n const rl = readline.createInterface({ input: stream, crlfDelay: Infinity })\n\n for await (const line of rl) {\n if (!line.trim()) continue\n\n let entry: any\n try {\n entry = JSON.parse(line)\n } catch {\n continue\n }\n\n const type = entry.type\n const timestamp = entry.timestamp ? new Date(entry.timestamp) : null\n\n if (type === 'session_meta') {\n cwd = entry.payload?.cwd || ''\n continue\n }\n\n if (type === 'turn_context' && entry.payload?.cwd) {\n cwd = entry.payload.cwd\n continue\n }\n\n if (!timestamp || !isMessageInWindow(timestamp, since, until)) continue\n\n if (type === 'event_msg' && entry.payload?.type === 'user_message') {\n const text = entry.payload.message\n if (typeof text === 'string' && text.trim()) {\n messages.push({ role: 'user', content: text, timestamp })\n }\n continue\n }\n\n if (type === 'response_item') {\n const payload = entry.payload\n if (!payload) continue\n\n const role = payload.role\n const content = extractCodexContent(payload.content)\n if (!content) continue\n\n if (role === 'developer' || role === 'user') {\n messages.push({ role: 'user', content, timestamp })\n } else if (role === 'assistant') {\n messages.push({ role: 'assistant', content, timestamp })\n }\n }\n }\n\n if (messages.length === 0) return null\n\n return {\n tool: 'codex',\n sessionId,\n workingDir: cwd,\n startTime: messages[0].timestamp,\n endTime: messages[messages.length - 1].timestamp,\n messages,\n }\n }\n}\n\nfunction extractCodexContent(content: unknown): string {\n if (typeof content === 'string') return content\n\n if (Array.isArray(content)) {\n const parts: string[] = []\n for (const block of content) {\n if (!block || typeof block !== 'object') continue\n const b = block as Record<string, any>\n\n if (b.type === 'input_text' && typeof b.text === 'string') {\n parts.push(b.text)\n } else if (b.type === 'output_text' && typeof b.text === 'string') {\n parts.push(b.text)\n } else if (b.type === 'function_call') {\n parts.push(`[tool_use: ${b.name}] ${b.arguments || ''}`)\n } else if (b.type === 'function_call_output') {\n const output = typeof b.output === 'string' ? b.output : ''\n parts.push(`[tool_result] ${output}`)\n }\n }\n return parts.join('\\n')\n }\n\n return ''\n}\n","import fs from 'node:fs'\nimport os from 'node:os'\nimport path from 'node:path'\nimport readline from 'node:readline'\nimport { getLogger } from '../logger.js'\nimport type { Message, SessionRecord, ToolAdapter } from './types.js'\n\nfunction getQoderDir(): string {\n return path.join(os.homedir(), '.qoder')\n}\n\nfunction isMessageInWindow(timestamp: Date, since: Date, until: Date): boolean {\n return timestamp > since && timestamp <= until\n}\n\ninterface SessionMeta {\n id: string\n working_dir: string\n created_at: number\n updated_at: number\n}\n\nexport class QoderAdapter implements ToolAdapter {\n readonly name = 'qoder'\n\n async detect(): Promise<boolean> {\n return fs.existsSync(path.join(getQoderDir(), 'projects'))\n }\n\n async collectSessions(since: Date, until: Date): Promise<SessionRecord[]> {\n const logger = getLogger()\n const projectsDir = path.join(getQoderDir(), 'projects')\n const results: SessionRecord[] = []\n const projectDirs = fs.readdirSync(projectsDir, { withFileTypes: true }).filter((d) => d.isDirectory())\n\n for (const projectDir of projectDirs) {\n const projectPath = path.join(projectsDir, projectDir.name)\n const sessionFiles = fs.readdirSync(projectPath).filter((f) => f.endsWith('-session.json'))\n\n for (const sessionFile of sessionFiles) {\n const metaPath = path.join(projectPath, sessionFile)\n\n try {\n const raw = fs.readFileSync(metaPath, 'utf-8')\n const meta: SessionMeta = JSON.parse(raw)\n const createdAt = new Date(meta.created_at)\n const updatedAt = new Date(meta.updated_at)\n\n if (createdAt > until || updatedAt <= since) continue\n\n const jsonlFile = path.join(projectPath, `${meta.id}.jsonl`)\n if (!fs.existsSync(jsonlFile)) continue\n\n const session = await this.parseSession(jsonlFile, meta, since, until)\n if (session) {\n results.push(session)\n }\n } catch (err) {\n logger.warn({ file: metaPath, err }, 'Qoder session parse failed')\n }\n }\n }\n\n return results\n }\n\n private async parseSession(\n filePath: string,\n meta: SessionMeta,\n since: Date,\n until: Date,\n ): Promise<SessionRecord | null> {\n const messages: Message[] = []\n const stream = fs.createReadStream(filePath, { encoding: 'utf-8' })\n const rl = readline.createInterface({ input: stream, crlfDelay: Infinity })\n\n for await (const line of rl) {\n if (!line.trim()) continue\n\n let entry: any\n try {\n entry = JSON.parse(line)\n } catch {\n continue\n }\n\n if (entry.type !== 'user' && entry.type !== 'assistant') continue\n if (!entry.message) continue\n\n const timestamp = entry.timestamp ? new Date(entry.timestamp) : null\n if (!timestamp || !isMessageInWindow(timestamp, since, until)) continue\n\n const role = entry.message.role as 'user' | 'assistant'\n if (role !== 'user' && role !== 'assistant') continue\n\n const content = extractQoderContent(entry.message.content)\n if (!content) continue\n\n messages.push({ role, content, timestamp })\n }\n\n if (messages.length === 0) return null\n\n return {\n tool: 'qoder',\n sessionId: meta.id,\n workingDir: meta.working_dir,\n startTime: messages[0].timestamp,\n endTime: messages[messages.length - 1].timestamp,\n messages,\n }\n }\n}\n\nfunction extractQoderContent(content: unknown): string {\n if (typeof content === 'string') return content\n\n if (Array.isArray(content)) {\n const parts: string[] = []\n for (const block of content) {\n if (!block || typeof block !== 'object') continue\n const b = block as Record<string, any>\n\n if (b.type === 'text' && typeof b.text === 'string') {\n parts.push(b.text)\n } else if (b.type === 'tool_use') {\n const input = b.input ? JSON.stringify(b.input) : ''\n parts.push(`[tool_use: ${b.name}] ${input}`)\n } else if (b.type === 'tool_result') {\n const text = typeof b.content === 'string' ? b.content : ''\n parts.push(`[tool_result] ${text}`)\n } else if (b.type === 'thinking') {\n parts.push(`[thinking] ${b.thinking || ''}`)\n }\n }\n return parts.join('\\n')\n }\n\n return ''\n}\n","import type { ToolAdapter, SessionRecord } from './types.js'\nimport { getLogger } from '../logger.js'\n\nexport class AdapterRegistry {\n private adapters: Map<string, ToolAdapter> = new Map()\n\n register(adapter: ToolAdapter): void {\n this.adapters.set(adapter.name, adapter)\n }\n\n async collectAll(\n since: Date,\n until: Date,\n enabledAdapters?: string[],\n ): Promise<SessionRecord[]> {\n const logger = getLogger()\n const results: SessionRecord[] = []\n\n for (const [name, adapter] of this.adapters) {\n if (enabledAdapters && !enabledAdapters.includes(name)) {\n continue\n }\n\n const detected = await adapter.detect()\n if (!detected) {\n logger.debug({ adapter: name }, '未检测到数据目录,跳过')\n continue\n }\n\n try {\n const sessions = await adapter.collectSessions(since, until)\n logger.info({ adapter: name, count: sessions.length }, '采集完成')\n results.push(...sessions)\n } catch (err) {\n logger.error({ adapter: name, err }, '采集失败')\n }\n }\n\n return results\n }\n}\n","import fs from 'node:fs'\nimport os from 'node:os'\nimport path from 'node:path'\nimport { marked } from 'marked'\nimport type { SynthConfig } from '../config/schema.js'\nimport { getLogger } from '../logger.js'\n\nexport interface GeneratedHtmlReport {\n content: string\n filePath: string\n}\n\nconst CSS = `\nbody {\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif;\n max-width: 900px;\n margin: 0 auto;\n padding: 40px 20px;\n color: #333;\n line-height: 1.6;\n background: #fafafa;\n}\nh1 {\n color: #1a1a1a;\n border-bottom: 2px solid #e1e4e8;\n padding-bottom: 12px;\n font-size: 1.8em;\n}\nh2 {\n color: #24292e;\n margin-top: 32px;\n padding: 8px 12px;\n background: #f0f4f8;\n border-left: 4px solid #0366d6;\n border-radius: 4px;\n font-size: 1.2em;\n font-family: \"Cascadia Code\", \"Fira Code\", Consolas, monospace;\n}\nh3 {\n color: #586069;\n font-size: 1em;\n margin-top: 20px;\n font-weight: 600;\n}\nh4 {\n color: #333;\n font-size: 0.95em;\n margin-top: 16px;\n}\nul {\n padding-left: 24px;\n}\nli {\n margin: 6px 0;\n}\ncode {\n background: #f1f3f5;\n padding: 2px 6px;\n border-radius: 3px;\n font-size: 0.9em;\n}\nhr {\n border: none;\n border-top: 1px solid #e1e4e8;\n margin: 24px 0;\n}\n`.trim()\n\nfunction resolveOutputDir(config: SynthConfig): string {\n const dir = config.output.dir.replace(/^~/, os.homedir())\n return path.join(dir, 'html')\n}\n\nexport function generateHtmlReport(\n date: string,\n markdownContent: string,\n config: SynthConfig,\n): GeneratedHtmlReport {\n const logger = getLogger()\n const htmlBody = marked(markdownContent) as string\n const html = `<!DOCTYPE html>\n<html lang=\"zh-CN\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>${date} 工作日报</title>\n <style>${CSS}</style>\n</head>\n<body>\n${htmlBody}\n</body>\n</html>`\n\n const outputDir = resolveOutputDir(config)\n if (!fs.existsSync(outputDir)) {\n fs.mkdirSync(outputDir, { recursive: true })\n }\n\n const filePath = path.join(outputDir, `${date}.html`)\n fs.writeFileSync(filePath, html, 'utf-8')\n logger.info({ path: filePath }, 'HTML report generated')\n\n return {\n content: html,\n filePath,\n }\n}\n","import fs from 'node:fs'\nimport os from 'node:os'\nimport path from 'node:path'\nimport type { SessionSummary } from '../agent/types.js'\nimport type { SynthConfig } from '../config/schema.js'\nimport { getLogger } from '../logger.js'\n\nexport interface GeneratedMarkdownReport {\n content: string\n filePath: string\n}\n\nexport interface GenerateMarkdownReportOptions {\n append: boolean\n}\n\nfunction resolveOutputDir(config: SynthConfig): string {\n const dir = config.output.dir.replace(/^~/, os.homedir())\n return path.join(dir, 'markdown')\n}\n\nfunction formatTime(date: Date): string {\n return date.toLocaleTimeString('zh-CN', {\n hour: '2-digit',\n minute: '2-digit',\n hour12: false,\n })\n}\n\nfunction createReportHeader(date: string): string {\n return `# ${date} 工作日报\\n`\n}\n\nfunction renderBatchFragment(summaries: SessionSummary[]): string {\n const sorted = [...summaries].sort((a, b) => a.startTime.getTime() - b.startTime.getTime())\n const batchStart = sorted[0].startTime\n const batchEnd = sorted[sorted.length - 1].endTime\n const groups = new Map<string, SessionSummary[]>()\n\n for (const summary of sorted) {\n const list = groups.get(summary.workingDir) || []\n list.push(summary)\n groups.set(summary.workingDir, list)\n }\n\n const sections = [\n `## ${formatTime(batchStart)}~${formatTime(batchEnd)}`,\n ...Array.from(groups.entries()).flatMap(([workingDir, items]) => {\n const rendered = [`### ${workingDir}`]\n for (const item of items) {\n rendered.push(`#### [${item.tool}] ${formatTime(item.startTime)}~${formatTime(item.endTime)}`)\n rendered.push(item.summary.trim())\n }\n return rendered\n }),\n ]\n\n return `${sections.join('\\n\\n')}\\n`\n}\n\nexport async function generateMarkdownReport(\n date: string,\n summaries: SessionSummary[],\n _provider: unknown,\n config: SynthConfig,\n options: GenerateMarkdownReportOptions,\n): Promise<GeneratedMarkdownReport> {\n const logger = getLogger()\n const outputDir = resolveOutputDir(config)\n\n if (!fs.existsSync(outputDir)) {\n fs.mkdirSync(outputDir, { recursive: true })\n }\n\n const filePath = path.join(outputDir, `${date}.md`)\n const fragment = renderBatchFragment(summaries)\n\n if (!options.append || !fs.existsSync(filePath)) {\n const content = `${createReportHeader(date)}\\n${fragment}`.trimEnd() + '\\n'\n fs.writeFileSync(filePath, content, 'utf-8')\n } else {\n const prefix = fs.statSync(filePath).size > 0 ? '\\n' : ''\n fs.appendFileSync(filePath, `${prefix}${fragment}`, 'utf-8')\n }\n\n const content = fs.readFileSync(filePath, 'utf-8')\n logger.info({ path: filePath, append: options.append }, 'Markdown report updated')\n\n return {\n content,\n filePath,\n }\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport Database from 'better-sqlite3'\nimport { getSynthDir } from '../config/loader.js'\n\nlet _db: Database.Database | undefined\n\nfunction getDb(): Database.Database {\n if (_db) return _db\n\n const dbDir = getSynthDir()\n if (!fs.existsSync(dbDir)) {\n fs.mkdirSync(dbDir, { recursive: true })\n }\n\n const dbPath = path.join(dbDir, 'state.sqlite')\n _db = new Database(dbPath)\n\n _db.exec(`\n CREATE TABLE IF NOT EXISTS kv (\n key TEXT PRIMARY KEY,\n value TEXT NOT NULL\n );\n\n CREATE TABLE IF NOT EXISTS message_fingerprints (\n date TEXT NOT NULL,\n fingerprint TEXT NOT NULL,\n created_at TEXT NOT NULL,\n PRIMARY KEY (date, fingerprint)\n );\n `)\n\n return _db\n}\n\nfunction getValue(key: string): string | null {\n const db = getDb()\n const row = db.prepare('SELECT value FROM kv WHERE key = ?').get(key) as\n | { value: string }\n | undefined\n\n return row?.value ?? null\n}\n\nfunction setValue(key: string, value: string): void {\n const db = getDb()\n db.prepare(\n 'INSERT INTO kv (key, value) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value',\n ).run(key, value)\n}\n\nexport function getLastRunAt(): Date | null {\n const value = getValue('lastRunAt')\n return value ? new Date(value) : null\n}\n\nexport function setLastRunAt(date: Date): void {\n setValue('lastRunAt', date.toISOString())\n}\n\nfunction getDailyCursorKey(date: string): string {\n return `dailyCursor:${date}`\n}\n\nexport function getDailyCursor(date: string): Date | null {\n const value = getValue(getDailyCursorKey(date))\n return value ? new Date(value) : null\n}\n\nexport function setDailyCursor(date: string, cursor: Date): void {\n setValue(getDailyCursorKey(date), cursor.toISOString())\n}\n\nexport function hasMessageFingerprint(date: string, fingerprint: string): boolean {\n const db = getDb()\n const row = db\n .prepare('SELECT 1 FROM message_fingerprints WHERE date = ? AND fingerprint = ?')\n .get(date, fingerprint) as { 1: number } | undefined\n\n return !!row\n}\n\nexport function saveMessageFingerprints(date: string, fingerprints: string[]): void {\n if (fingerprints.length === 0) return\n\n const db = getDb()\n const now = new Date().toISOString()\n const stmt = db.prepare(\n 'INSERT OR IGNORE INTO message_fingerprints (date, fingerprint, created_at) VALUES (?, ?, ?)',\n )\n\n const tx = db.transaction((items: string[]) => {\n for (const fingerprint of items) {\n stmt.run(date, fingerprint, now)\n }\n })\n\n tx(fingerprints)\n}\n\nexport function pruneMessageFingerprints(beforeDate: string): void {\n const db = getDb()\n db.prepare('DELETE FROM message_fingerprints WHERE date < ?').run(beforeDate)\n}\n\nexport function clearCollectionState(): void {\n const db = getDb()\n db.exec(`\n DELETE FROM kv WHERE key = 'lastRunAt' OR key LIKE 'dailyCursor:%';\n DELETE FROM message_fingerprints;\n `)\n}\n\nexport function closeDb(): void {\n if (_db) {\n _db.close()\n _db = undefined\n }\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport { execFile } from 'node:child_process'\nimport { promisify } from 'node:util'\nimport { createRequire } from 'node:module'\nimport { fileURLToPath } from 'node:url'\nimport { loadConfig, getSynthDir } from './config/loader.js'\nimport { getLogger } from './logger.js'\nimport { startScheduler } from './scheduler.js'\nimport { closeDb } from './store/state.js'\n\nconst execFileAsync = promisify(execFile)\nconst require = createRequire(import.meta.url)\nconst nodeWindows = require('node-windows') as typeof import('node-windows')\n\nexport const SERVICE_NAME = 'Synth AI Work Summary Service'\nexport const SERVICE_DESCRIPTION = 'Collect AI coding sessions and generate scheduled work summaries.'\nexport const SERVICE_ID = SERVICE_NAME.replace(/[^\\w]/g, '').toLowerCase()\n\nexport type ServiceState =\n | 'not-installed'\n | 'running'\n | 'stopped'\n | 'start-pending'\n | 'stop-pending'\n | 'paused'\n | 'unknown'\n\nexport interface ServiceStatus {\n installed: boolean\n state: ServiceState\n rawState?: string\n}\n\nfunction ensureWindows(): void {\n if (process.platform !== 'win32') {\n throw new Error('Windows service management is only supported on win32')\n }\n}\n\nfunction ensureDir(dir: string): string {\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true })\n }\n return dir\n}\n\nfunction getServiceScriptPath(): string {\n const currentFile = fileURLToPath(new URL('./index.js', import.meta.url))\n if (fs.existsSync(currentFile)) {\n return currentFile\n }\n\n const distFallback = path.resolve(process.cwd(), 'dist', 'index.js')\n if (fs.existsSync(distFallback)) {\n return distFallback\n }\n\n throw new Error('Cannot locate dist/index.js. Run `npm run build` before installing the service.')\n}\n\nfunction getServiceWorkingDirectory(scriptPath: string): string {\n const dir = path.dirname(scriptPath)\n return path.basename(dir).toLowerCase() === 'dist' ? path.resolve(dir, '..') : dir\n}\n\nfunction getServiceLogDir(): string {\n return ensureDir(path.join(getSynthDir(), 'logs', 'service'))\n}\n\nfunction createService(): import('node-windows').Service {\n const script = getServiceScriptPath()\n\n return new nodeWindows.Service({\n name: SERVICE_NAME,\n description: SERVICE_DESCRIPTION,\n script,\n scriptOptions: 'service-run',\n workingDirectory: getServiceWorkingDirectory(script),\n logpath: getServiceLogDir(),\n maxRestarts: 5,\n wait: 2,\n grow: 0.25,\n stopparentfirst: true,\n env: {\n name: 'SYNTH_SERVICE',\n value: '1',\n },\n } as import('node-windows').ServiceConfig)\n}\n\nfunction waitForEvent<T>(\n service: import('node-windows').Service,\n action: () => void,\n successEvents: string[],\n failureEvents: string[],\n mapResult: (eventName: string) => T,\n): Promise<T> {\n return new Promise((resolve, reject) => {\n const handlers: Record<string, (...args: unknown[]) => void> = {}\n\n const cleanup = () => {\n for (const eventName of [...successEvents, ...failureEvents]) {\n const handler = handlers[eventName]\n if (handler) {\n service.removeListener(eventName, handler)\n }\n }\n }\n\n for (const eventName of successEvents) {\n handlers[eventName] = () => {\n cleanup()\n resolve(mapResult(eventName))\n }\n service.on(eventName, handlers[eventName]!)\n }\n\n for (const eventName of failureEvents) {\n handlers[eventName] = (...args: unknown[]) => {\n cleanup()\n const error = args[0] instanceof Error ? args[0] : new Error(String(args[0] ?? eventName))\n reject(error)\n }\n service.on(eventName, handlers[eventName]!)\n }\n\n try {\n action()\n } catch (err) {\n cleanup()\n reject(err)\n }\n })\n}\n\nfunction normalizeState(rawState?: string): ServiceState {\n switch (rawState) {\n case 'RUNNING':\n return 'running'\n case 'STOPPED':\n return 'stopped'\n case 'START_PENDING':\n return 'start-pending'\n case 'STOP_PENDING':\n return 'stop-pending'\n case 'PAUSED':\n return 'paused'\n default:\n return rawState ? 'unknown' : 'not-installed'\n }\n}\n\nexport async function getServiceStatus(): Promise<ServiceStatus> {\n ensureWindows()\n\n try {\n const { stdout, stderr } = await execFileAsync('sc.exe', ['query', SERVICE_ID], {\n windowsHide: true,\n })\n const output = `${stdout}\\n${stderr}`\n const match = output.match(/STATE\\s*:\\s*\\d+\\s+([A-Z_]+)/)\n const rawState = match?.[1]\n return {\n installed: true,\n state: normalizeState(rawState),\n rawState,\n }\n } catch (err) {\n const code = typeof err === 'object' && err !== null && 'code' in err ? (err as { code?: unknown }).code : undefined\n const stdout =\n typeof err === 'object' && err !== null && 'stdout' in err ? String((err as { stdout?: unknown }).stdout ?? '') : ''\n const stderr =\n typeof err === 'object' && err !== null && 'stderr' in err ? String((err as { stderr?: unknown }).stderr ?? '') : ''\n const message = err instanceof Error ? err.message : String(err)\n\n if (code === 1060 || stdout.includes('1060') || stderr.includes('1060') || message.includes('does not exist')) {\n return { installed: false, state: 'not-installed' }\n }\n throw err\n }\n}\n\nexport async function installService(): Promise<ServiceStatus> {\n ensureWindows()\n\n const status = await getServiceStatus()\n if (status.installed) {\n if (status.state !== 'running' && status.state !== 'start-pending') {\n await startService()\n return getServiceStatus()\n }\n return status\n }\n\n const service = createService()\n const result = await waitForEvent(\n service,\n () => service.install(),\n ['install', 'alreadyinstalled'],\n ['error', 'invalidinstallation'],\n (eventName) => eventName,\n )\n\n if (result === 'install') {\n await startService()\n }\n\n return getServiceStatus()\n}\n\nexport async function uninstallService(): Promise<ServiceStatus> {\n ensureWindows()\n\n const status = await getServiceStatus()\n if (!status.installed) {\n return status\n }\n\n const service = createService()\n await waitForEvent(\n service,\n () => service.uninstall(),\n ['uninstall', 'alreadyuninstalled'],\n ['error'],\n () => undefined,\n )\n\n return getServiceStatus()\n}\n\nexport async function startService(): Promise<ServiceStatus> {\n ensureWindows()\n\n const status = await getServiceStatus()\n if (!status.installed || status.state === 'running' || status.state === 'start-pending') {\n return status\n }\n\n const service = createService()\n await waitForEvent(service, () => service.start(), ['start'], ['error'], () => undefined)\n return getServiceStatus()\n}\n\nexport async function stopService(): Promise<ServiceStatus> {\n ensureWindows()\n\n const status = await getServiceStatus()\n if (!status.installed || status.state === 'stopped' || status.state === 'stop-pending') {\n return status\n }\n\n const service = createService()\n await waitForEvent(service, () => service.stop(), ['stop', 'alreadystopped'], ['error'], () => undefined)\n return getServiceStatus()\n}\n\nexport async function runServiceProcess(): Promise<void> {\n const logger = getLogger()\n const config = loadConfig()\n const task = startScheduler(config)\n\n logger.info({ cron: config.schedule.cron }, 'Windows service process started')\n\n let shuttingDown = false\n const shutdown = async (reason: string) => {\n if (shuttingDown) return\n shuttingDown = true\n\n logger.info({ reason }, 'Windows service process stopping')\n\n try {\n await Promise.resolve(task.stop())\n } finally {\n closeDb()\n }\n\n logger.info('Windows service process stopped')\n process.exit(0)\n }\n\n process.on('SIGINT', () => {\n void shutdown('SIGINT')\n })\n\n process.on('SIGTERM', () => {\n void shutdown('SIGTERM')\n })\n\n process.on('message', (message) => {\n if (message === 'shutdown') {\n void shutdown('shutdown')\n }\n })\n}\n","import cron, { type ScheduledTask } from 'node-cron'\nimport type { SynthConfig } from './config/schema.js'\nimport { getLogger } from './logger.js'\nimport { run } from './runner.js'\n\nfunction formatNextRun(task: ScheduledTask): string | null {\n const nextRun = task.getNextRun()\n return nextRun ? nextRun.toISOString() : null\n}\n\nexport function startScheduler(config: SynthConfig): ScheduledTask {\n const logger = getLogger()\n const expression = config.schedule.cron\n\n if (!cron.validate(expression)) {\n throw new Error(`Invalid cron expression: ${expression}`)\n }\n\n const task = cron.schedule(\n expression,\n async () => {\n const startedAt = new Date()\n logger.info(\n { cron: expression, startedAt: startedAt.toISOString() },\n 'Scheduled run started',\n )\n\n try {\n await run(config)\n logger.info(\n { cron: expression, finishedAt: new Date().toISOString(), nextRun: formatNextRun(task) },\n 'Scheduled run finished',\n )\n } catch (err) {\n logger.error(\n {\n cron: expression,\n err,\n finishedAt: new Date().toISOString(),\n nextRun: formatNextRun(task),\n },\n 'Scheduled run failed',\n )\n }\n },\n {\n name: 'synth-scheduler',\n noOverlap: true,\n },\n )\n\n task.on('execution:overlap', () => {\n logger.warn({ cron: expression }, 'Scheduled run skipped because previous execution is still running')\n })\n\n task.on('execution:missed', (context) => {\n logger.warn(\n { cron: expression, scheduledAt: context.date.toISOString(), triggeredAt: context.triggeredAt.toISOString() },\n 'Scheduled run was missed',\n )\n })\n\n task.on('execution:failed', (context) => {\n logger.error(\n {\n cron: expression,\n scheduledAt: context.date.toISOString(),\n triggeredAt: context.triggeredAt.toISOString(),\n err: context.execution?.error,\n },\n 'Scheduled execution callback failed',\n )\n })\n\n logger.info({ cron: expression, nextRun: formatNextRun(task) }, 'Scheduler started')\n return task\n}\n"],"mappings":"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","names":["fs","os","path","fs","path","require","path","fs","fs","os","path","path","os","fs","fs","os","path","readline","path","os","isMessageInWindow","fs","readline","fs","os","path","readline","path","os","isMessageInWindow","fs","readline","fs","os","path","os","path","fs","fs","os","path","resolveOutputDir","os","path","formatTime","fs","content","fs","path","fs","path","os","path","fs","fs","path","createRequire","require","createRequire","fs","path"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/config/loader.ts","../src/config/schema.ts","../src/runner.ts","../src/agent/prompts.ts","../src/processor/preprocessor.ts","../src/processor/chunker.ts","../src/agent/semaphore.ts","../src/logger.ts","../src/agent/summarizer.ts","../src/agent/providers/anthropic.ts","../src/agent/providers/openai-compatible.ts","../src/collector/claude-code.adapter.ts","../src/collector/codex.adapter.ts","../src/collector/qoder.adapter.ts","../src/collector/registry.ts","../src/report/html.ts","../src/report/markdown.ts","../src/store/state.ts","../src/service.ts","../src/scheduler.ts"],"sourcesContent":["import { Command } from 'commander'\nimport { initConfig, loadConfig } from './config/loader.js'\nimport { backfillHistory, run } from './runner.js'\nimport {\n getServiceStatus,\n installService,\n runServiceProcess,\n startService,\n stopService,\n uninstallService,\n} from './service.js'\n\nfunction formatServiceState(state: string): string {\n return state.replace(/-/g, ' ')\n}\n\nconst program = new Command()\n\nprogram\n .name('synth')\n .description('AI Coding work summary service')\n .version('0.1.0')\n\nprogram\n .command('run')\n .description('Collect sessions and generate a report immediately')\n .option('--since <date>', 'Specify the start time')\n .option('--date <date>', 'Generate the report for the given date')\n .action(async (options) => {\n const config = loadConfig()\n await run(config, {\n since: options.since ? new Date(options.since) : undefined,\n date: options.date,\n })\n })\n\nprogram\n .command('config')\n .description('Manage configuration')\n .option('--init', 'Create the default config file')\n .action((options) => {\n if (options.init) {\n console.log(initConfig())\n return\n }\n\n console.log(JSON.stringify(loadConfig(), null, 2))\n })\n\nprogram\n .command('backfill-history')\n .description('Clear collection state and rebuild historical reports from all sessions')\n .action(async () => {\n const config = loadConfig()\n await backfillHistory(config)\n })\n\nprogram\n .command('install')\n .description('Install and start the Windows service')\n .action(async () => {\n const status = await installService()\n console.log(`service: ${status.installed ? 'installed' : 'not installed'}`)\n console.log(`state: ${formatServiceState(status.state)}`)\n })\n\nprogram\n .command('uninstall')\n .description('Stop and remove the Windows service')\n .action(async () => {\n const status = await uninstallService()\n console.log(`service: ${status.installed ? 'installed' : 'not installed'}`)\n console.log(`state: ${formatServiceState(status.state)}`)\n })\n\nprogram\n .command('start')\n .description('Start the Windows service')\n .action(async () => {\n const status = await startService()\n console.log(`service: ${status.installed ? 'installed' : 'not installed'}`)\n console.log(`state: ${formatServiceState(status.state)}`)\n })\n\nprogram\n .command('stop')\n .description('Stop the Windows service')\n .action(async () => {\n const status = await stopService()\n console.log(`service: ${status.installed ? 'installed' : 'not installed'}`)\n console.log(`state: ${formatServiceState(status.state)}`)\n })\n\nprogram\n .command('status')\n .description('Show the Windows service status')\n .action(async () => {\n const status = await getServiceStatus()\n console.log(`service: ${status.installed ? 'installed' : 'not installed'}`)\n console.log(`state: ${formatServiceState(status.state)}`)\n if (status.rawState) {\n console.log(`rawState: ${status.rawState}`)\n }\n })\n\nprogram\n .command('service-run')\n .description('Internal service host command')\n .action(async () => {\n await runServiceProcess()\n })\n\nawait program.parseAsync()\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport os from 'node:os'\nimport { parse as parseYaml } from 'yaml'\nimport { configSchema, defaultConfigYaml, type SynthConfig } from './schema.js'\n\nexport function getSynthDir(): string {\n return path.join(os.homedir(), '.synth')\n}\n\nexport function getConfigPath(): string {\n return path.join(getSynthDir(), 'config.yaml')\n}\n\nexport function initConfig(): string {\n const configPath = getConfigPath()\n const dir = path.dirname(configPath)\n\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true })\n }\n\n if (fs.existsSync(configPath)) {\n return `配置文件已存在: ${configPath}`\n }\n\n fs.writeFileSync(configPath, defaultConfigYaml, 'utf-8')\n return `配置文件已生成: ${configPath}`\n}\n\nexport function loadConfig(): SynthConfig {\n const configPath = getConfigPath()\n\n let raw: unknown = {}\n if (fs.existsSync(configPath)) {\n const content = fs.readFileSync(configPath, 'utf-8')\n raw = parseYaml(content) ?? {}\n }\n\n return configSchema.parse(raw)\n}\n","import { z } from 'zod'\n\nexport const llmConfigSchema = z.object({\n provider: z.enum(['openai-compatible', 'anthropic', 'ollama']).default('openai-compatible'),\n baseUrl: z.string().default('https://api.openai.com/v1'),\n apiKey: z.string().default(''),\n model: z.string().default('gpt-4o'),\n contextWindow: z.number().int().positive().default(128000),\n maxTokens: z.number().int().positive().default(4096),\n maxConcurrency: z.number().int().positive().default(5),\n headers: z.record(z.string(), z.string()).default({}),\n})\n\nexport const agentConfigSchema = z.object({\n role: z.string().default(''),\n systemPrompt: z.string().default(''),\n mapPrompt: z.string().default(''),\n reducePrompt: z.string().default(''),\n reportPrompt: z.string().default(''),\n})\n\nexport const scheduleConfigSchema = z.object({\n cron: z.string().default('0 1-23 * * *'),\n})\n\nexport const collectorConfigSchema = z.object({\n adapters: z.array(z.string()).default(['claude-code', 'codex', 'qoder']),\n})\n\nexport const outputConfigSchema = z.object({\n formats: z.array(z.enum(['markdown', 'html'])).default(['markdown', 'html']),\n dir: z.string().default('~/.synth/reports'),\n})\n\nconst defaultLlmConfig = llmConfigSchema.parse({})\nconst defaultAgentConfig = agentConfigSchema.parse({})\nconst defaultScheduleConfig = scheduleConfigSchema.parse({})\nconst defaultCollectorConfig = collectorConfigSchema.parse({})\nconst defaultOutputConfig = outputConfigSchema.parse({})\n\nexport const configSchema = z.object({\n llm: llmConfigSchema.default(defaultLlmConfig),\n agent: agentConfigSchema.default(defaultAgentConfig),\n schedule: scheduleConfigSchema.default(defaultScheduleConfig),\n collector: collectorConfigSchema.default(defaultCollectorConfig),\n output: outputConfigSchema.default(defaultOutputConfig),\n})\n\nexport type SynthConfig = z.infer<typeof configSchema>\n\nexport const defaultConfigYaml = `# Synth config\n\nllm:\n provider: \"openai-compatible\"\n baseUrl: \"https://api.openai.com/v1\"\n apiKey: \"\"\n model: \"gpt-4o\"\n contextWindow: 128000\n maxTokens: 4096\n maxConcurrency: 5\n headers: {}\n\nagent:\n role: \"\"\n systemPrompt: \"\"\n mapPrompt: \"\"\n reducePrompt: \"\"\n reportPrompt: \"\"\n\nschedule:\n cron: \"0 1-23 * * *\"\n\ncollector:\n adapters:\n - claude-code\n - codex\n - qoder\n\noutput:\n formats:\n - markdown\n - html\n dir: \"~/.synth/reports\"\n`\n","import { createHash } from 'node:crypto'\nimport fs from 'node:fs'\nimport os from 'node:os'\nimport path from 'node:path'\nimport { Summarizer } from './agent/summarizer.js'\nimport type { LLMProvider, SessionSummary } from './agent/types.js'\nimport { AnthropicProvider } from './agent/providers/anthropic.js'\nimport { OpenAICompatibleProvider } from './agent/providers/openai-compatible.js'\nimport { ClaudeCodeAdapter } from './collector/claude-code.adapter.js'\nimport { CodexAdapter } from './collector/codex.adapter.js'\nimport { QoderAdapter } from './collector/qoder.adapter.js'\nimport { AdapterRegistry } from './collector/registry.js'\nimport type { Message, SessionRecord } from './collector/types.js'\nimport type { SynthConfig } from './config/schema.js'\nimport { getLogger } from './logger.js'\nimport { generateHtmlReport } from './report/html.js'\nimport { generateMarkdownReport } from './report/markdown.js'\nimport {\n clearCollectionState,\n getDailyCursor,\n hasMessageFingerprint,\n pruneMessageFingerprints,\n saveMessageFingerprints,\n setDailyCursor,\n} from './store/state.js'\n\nconst SAFETY_LAG_MS = 90 * 1000\nconst LOOKBACK_MS = 2 * 60 * 1000\n\nfunction createProvider(config: SynthConfig): LLMProvider {\n if (config.llm.provider === 'anthropic') {\n return new AnthropicProvider({\n baseUrl: config.llm.baseUrl,\n apiKey: config.llm.apiKey,\n model: config.llm.model,\n maxTokens: config.llm.maxTokens,\n })\n }\n\n return new OpenAICompatibleProvider({\n baseUrl: config.llm.baseUrl,\n apiKey: config.llm.apiKey,\n model: config.llm.model,\n maxTokens: config.llm.maxTokens,\n headers: config.llm.headers,\n })\n}\n\nfunction createRegistry(config: SynthConfig): AdapterRegistry {\n const registry = new AdapterRegistry()\n const adapters: Record<string, () => InstanceType<any>> = {\n 'claude-code': () => new ClaudeCodeAdapter(),\n codex: () => new CodexAdapter(),\n qoder: () => new QoderAdapter(),\n }\n\n for (const name of config.collector.adapters) {\n const factory = adapters[name]\n if (factory) {\n registry.register(factory())\n }\n }\n\n return registry\n}\n\nfunction formatDate(date: Date): string {\n const y = date.getFullYear()\n const m = String(date.getMonth() + 1).padStart(2, '0')\n const d = String(date.getDate()).padStart(2, '0')\n return `${y}-${m}-${d}`\n}\n\nfunction startOfDay(date: Date): Date {\n const value = new Date(date)\n value.setHours(0, 0, 0, 0)\n return value\n}\n\nfunction endOfDay(date: Date): Date {\n const value = new Date(date)\n value.setHours(23, 59, 59, 999)\n return value\n}\n\nfunction maxDate(left: Date, right: Date): Date {\n return left > right ? left : right\n}\n\nfunction getSafeUntil(now: Date): Date {\n return new Date(now.getTime() - SAFETY_LAG_MS)\n}\n\nfunction fingerprintMessage(session: SessionRecord, message: Message): string {\n const digest = createHash('sha1')\n .update(session.tool)\n .update('\\n')\n .update(session.sessionId)\n .update('\\n')\n .update(message.timestamp.toISOString())\n .update('\\n')\n .update(message.role)\n .update('\\n')\n .update(message.content)\n .digest('hex')\n\n return `${session.tool}:${session.sessionId}:${digest}`\n}\n\nfunction filterDuplicateMessages(date: string, sessions: SessionRecord[]): SessionRecord[] {\n const filtered: SessionRecord[] = []\n\n for (const session of sessions) {\n const messages = session.messages.filter((message) => !hasMessageFingerprint(date, fingerprintMessage(session, message)))\n if (messages.length === 0) continue\n\n filtered.push({\n ...session,\n startTime: messages[0].timestamp,\n endTime: messages[messages.length - 1].timestamp,\n messages,\n })\n }\n\n return filtered\n}\n\nfunction collectSessionFingerprints(session: SessionRecord): string[] {\n return session.messages.map((message) => fingerprintMessage(session, message))\n}\n\nfunction summarizeSessionsConfig(\n config: SynthConfig,\n sessions: SessionRecord[],\n provider: LLMProvider,\n): Promise<{ summaries: SessionSummary[]; fingerprints: string[]; hadFailures: boolean }> {\n const logger = getLogger()\n const summarizer = new Summarizer(provider, config)\n\n return (async () => {\n const summaries: SessionSummary[] = []\n const fingerprints: string[] = []\n let hadFailures = false\n\n for (const session of sessions) {\n try {\n const summary = await summarizer.summarizeSession(session)\n summaries.push(summary)\n fingerprints.push(...collectSessionFingerprints(session))\n logger.info(\n {\n tool: session.tool,\n workingDir: session.workingDir,\n sessionId: session.sessionId.slice(0, 8),\n startTime: session.startTime.toISOString(),\n endTime: session.endTime.toISOString(),\n messages: session.messages.length,\n },\n 'Session summarized',\n )\n } catch (err) {\n hadFailures = true\n logger.error(\n {\n sessionId: session.sessionId.slice(0, 8),\n err,\n },\n 'Session summarize failed and was skipped',\n )\n }\n }\n\n return { summaries, fingerprints, hadFailures }\n })()\n}\n\nfunction resolveOutputBaseDir(config: SynthConfig): string {\n return config.output.dir.replace(/^~/, os.homedir())\n}\n\nfunction clearHistoricalReports(config: SynthConfig): void {\n const logger = getLogger()\n const baseDir = resolveOutputBaseDir(config)\n const targets = [\n { dir: path.join(baseDir, 'markdown'), ext: '.md' },\n { dir: path.join(baseDir, 'html'), ext: '.html' },\n ]\n\n for (const target of targets) {\n if (!fs.existsSync(target.dir)) continue\n\n for (const file of fs.readdirSync(target.dir)) {\n if (!file.endsWith(target.ext)) continue\n fs.unlinkSync(path.join(target.dir, file))\n }\n\n logger.info({ dir: target.dir }, 'Historical report directory cleared')\n }\n}\n\nfunction partitionSessionsByDate(sessions: SessionRecord[]): Map<string, SessionRecord[]> {\n const groups = new Map<string, SessionRecord[]>()\n\n for (const session of sessions) {\n const dateBuckets = new Map<string, Message[]>()\n\n for (const message of session.messages) {\n const dateKey = formatDate(message.timestamp)\n const list = dateBuckets.get(dateKey) || []\n list.push(message)\n dateBuckets.set(dateKey, list)\n }\n\n for (const [dateKey, messages] of dateBuckets.entries()) {\n const sessionsForDate = groups.get(dateKey) || []\n sessionsForDate.push({\n ...session,\n sessionId: `${session.sessionId}:${dateKey}`,\n startTime: messages[0].timestamp,\n endTime: messages[messages.length - 1].timestamp,\n messages,\n })\n groups.set(dateKey, sessionsForDate)\n }\n }\n\n return groups\n}\n\nasync function renderReportsForDate(\n config: SynthConfig,\n date: string,\n summaries: SessionSummary[],\n provider: LLMProvider,\n append: boolean,\n): Promise<void> {\n const formats = config.output.formats\n\n if (!formats.includes('markdown') && !formats.includes('html')) {\n return\n }\n\n const markdownReport = await generateMarkdownReport(date, summaries, provider, config, {\n append,\n })\n\n if (formats.includes('html')) {\n generateHtmlReport(date, markdownReport.content, config)\n }\n}\n\nexport interface RunOptions {\n since?: Date\n date?: string\n}\n\nexport async function run(config: SynthConfig, options: RunOptions = {}): Promise<void> {\n const logger = getLogger()\n\n if (!config.llm.apiKey) {\n logger.error('Missing LLM apiKey. Run `synth config --init` and update ~/.synth/config.yaml')\n return\n }\n\n const now = new Date()\n let since: Date\n let until: Date\n let rawSince: Date\n let dateStr: string\n let appendReport = true\n let updateCursor = true\n let enableFingerprintDedup = false\n\n if (options.date) {\n const targetDay = new Date(`${options.date}T00:00:00`)\n since = startOfDay(targetDay)\n until = endOfDay(targetDay)\n rawSince = since\n dateStr = options.date\n appendReport = false\n updateCursor = false\n } else if (options.since) {\n rawSince = options.since\n since = options.since\n until = getSafeUntil(now)\n dateStr = formatDate(until)\n appendReport = true\n updateCursor = false\n } else {\n dateStr = formatDate(now)\n const dayStart = startOfDay(now)\n const cursor = getDailyCursor(dateStr)\n rawSince = cursor && cursor > dayStart ? cursor : dayStart\n since = maxDate(dayStart, new Date(rawSince.getTime() - LOOKBACK_MS))\n until = getSafeUntil(now)\n enableFingerprintDedup = true\n }\n\n if (formatDate(until) !== dateStr) {\n until = dateStr === formatDate(now) ? maxDate(startOfDay(now), until) : until\n }\n\n logger.info(\n {\n rawSince: rawSince.toISOString(),\n since: since.toISOString(),\n until: until.toISOString(),\n date: dateStr,\n appendReport,\n updateCursor,\n enableFingerprintDedup,\n safetyLagMs: options.date ? 0 : SAFETY_LAG_MS,\n lookbackMs: enableFingerprintDedup ? LOOKBACK_MS : 0,\n },\n 'Run started',\n )\n\n if (until <= since) {\n logger.info({ since: since.toISOString(), until: until.toISOString(), date: dateStr }, 'No new collection window')\n return\n }\n\n if (enableFingerprintDedup) {\n const keepFrom = new Date(startOfDay(now))\n keepFrom.setDate(keepFrom.getDate() - 2)\n pruneMessageFingerprints(formatDate(keepFrom))\n }\n\n const registry = createRegistry(config)\n const collectedSessions = await registry.collectAll(since, until, config.collector.adapters)\n const sessions = enableFingerprintDedup\n ? filterDuplicateMessages(dateStr, collectedSessions)\n : collectedSessions\n\n if (sessions.length === 0) {\n logger.info('No new messages collected in the requested window')\n if (updateCursor) {\n setDailyCursor(dateStr, until)\n }\n return\n }\n\n logger.info({ count: sessions.length }, 'Collection finished')\n\n const provider = createProvider(config)\n const { summaries, fingerprints, hadFailures } = await summarizeSessionsConfig(config, sessions, provider)\n\n if (summaries.length === 0) {\n logger.warn('All sessions failed during summarization')\n return\n }\n\n await renderReportsForDate(config, dateStr, summaries, provider, appendReport)\n\n if (enableFingerprintDedup && fingerprints.length > 0) {\n saveMessageFingerprints(dateStr, fingerprints)\n logger.info({ date: dateStr, fingerprints: fingerprints.length }, 'Message fingerprints saved')\n }\n\n if (updateCursor && !hadFailures) {\n setDailyCursor(dateStr, until)\n logger.info({ date: dateStr, cursor: until.toISOString() }, 'Daily cursor updated')\n } else if (updateCursor && hadFailures) {\n logger.warn({ date: dateStr }, 'Cursor not advanced because some sessions failed; next run will retry with dedup')\n }\n\n logger.info({ date: dateStr, sessions: summaries.length }, 'Run finished')\n}\n\nexport async function backfillHistory(config: SynthConfig): Promise<void> {\n const logger = getLogger()\n\n if (!config.llm.apiKey) {\n logger.error('Missing LLM apiKey. Run `synth config --init` and update ~/.synth/config.yaml')\n return\n }\n\n const now = new Date()\n const safeUntil = getSafeUntil(now)\n const today = formatDate(safeUntil)\n\n logger.info({ until: safeUntil.toISOString() }, 'History backfill started')\n\n clearCollectionState()\n clearHistoricalReports(config)\n\n const registry = createRegistry(config)\n const provider = createProvider(config)\n const sessions = await registry.collectAll(new Date(0), safeUntil, config.collector.adapters)\n\n if (sessions.length === 0) {\n logger.info('No sessions found for historical backfill')\n setDailyCursor(today, safeUntil)\n return\n }\n\n const sessionsByDate = partitionSessionsByDate(sessions)\n const sortedDates = Array.from(sessionsByDate.keys()).sort()\n const todayFingerprints: string[] = []\n\n for (const date of sortedDates) {\n const dateSessions = sessionsByDate.get(date) || []\n const { summaries, fingerprints } = await summarizeSessionsConfig(config, dateSessions, provider)\n\n if (summaries.length === 0) {\n logger.warn({ date }, 'No summaries generated for historical date')\n continue\n }\n\n await renderReportsForDate(config, date, summaries, provider, false)\n\n if (date === today) {\n todayFingerprints.push(...fingerprints)\n }\n }\n\n if (todayFingerprints.length > 0) {\n saveMessageFingerprints(today, todayFingerprints)\n }\n setDailyCursor(today, safeUntil)\n\n logger.info({ dates: sortedDates.length, until: safeUntil.toISOString() }, 'History backfill finished')\n}\n","export const defaultPrompts = {\n role: 'AI编程工作记录分析师',\n\n systemPrompt: `你是一位专业的工作内容分析师。你的任务是分析用户与AI编程助手的对话记录,\n提取关键工作内容,生成简洁准确的工作摘要。\n要求:\n- 关注实际完成的工作,而非对话过程\n- 提取修改的文件、解决的问题、实现的功能\n- 使用简洁的中文描述\n- 忽略闲聊、系统提示等无关内容`,\n\n mapPrompt: `以下是 {{tool}} 中的一段对话记录(第 {{chunkIndex}}/{{totalChunks}} 片)。\n工作目录:{{workingDir}}\n时间范围:{{startTime}} ~ {{endTime}}\n请提取本片段中的关键工作内容,以要点列表形式输出。\n---\n{{content}}`,\n\n reducePrompt: `以下是同一会话拆分后的各片段摘要,请合并为一份完整摘要,去重并按时间线组织:\n{{summaries}}`,\n\n reportPrompt: `请将以下会话摘要整合为工作日报,严格按照指定格式输出。\n日期:{{date}}\n要求格式:\n# {{date}} 工作日报\n## <工作目录>\n### <时间段>\n- <工作内容>\n合并规则:\n- 同一工作目录下的多个会话,按时间段分别列出\n- 时间段格式为 HH:MM~HH:MM\n---\n{{sessionSummaries}}`,\n}\n\nexport function renderTemplate(template: string, vars: Record<string, string>): string {\n return template.replace(/\\{\\{(\\w+)\\}\\}/g, (_, key: string) => vars[key] ?? '')\n}\n","import type { Message } from '../collector/types.js'\n\nconst BASE64_PATTERN = /data:[a-zA-Z0-9+/]+;base64,[A-Za-z0-9+/=]{100,}/g\nconst SYSTEM_REMINDER_PATTERN = /<system-reminder>[\\s\\S]*?<\\/system-reminder>/g\nconst DEFERRED_TOOLS_PATTERN = /<functions>[\\s\\S]*?<\\/functions>/g\n\nconst TOOL_RESULT_MAX_LEN = 200\n\n/**\n * Preprocess messages to reduce token count before sending to LLM.\n * Filters out thinking/signature blocks, base64, system-reminders,\n * truncates tool_result, and keeps tool_use name + key params.\n */\nexport function preprocessMessages(messages: Message[]): Message[] {\n const result: Message[] = []\n\n for (const msg of messages) {\n const cleaned = cleanContent(msg.content)\n if (!cleaned.trim()) continue\n\n result.push({\n role: msg.role,\n content: cleaned,\n timestamp: msg.timestamp,\n })\n }\n\n return result\n}\n\nfunction cleanContent(content: string): string {\n let text = content\n\n // Remove thinking blocks (including encrypted signatures)\n text = text.replace(/\\[thinking\\][^\\n]*/g, '')\n\n // Remove base64 content\n text = text.replace(BASE64_PATTERN, '[base64 content removed]')\n\n // Remove system-reminder blocks\n text = text.replace(SYSTEM_REMINDER_PATTERN, '')\n\n // Remove deferred_tools / functions blocks\n text = text.replace(DEFERRED_TOOLS_PATTERN, '')\n\n // Remove attachment blocks\n text = text.replace(/<attachment>[\\s\\S]*?<\\/attachment>/g, '')\n\n // Truncate tool_result content\n text = text.replace(/\\[tool_result\\]\\s*([\\s\\S]*?)(?=\\n\\[|$)/g, (match, resultContent: string) => {\n const trimmed = resultContent.trim()\n if (trimmed.length > TOOL_RESULT_MAX_LEN) {\n return `[tool_result] ${trimmed.slice(0, TOOL_RESULT_MAX_LEN)}...`\n }\n return `[tool_result] ${trimmed}`\n })\n\n // Simplify tool_use: keep name and trim very long input\n text = text.replace(/\\[tool_use:\\s*(\\w+)\\]\\s*([\\s\\S]*?)(?=\\n\\[|$)/g, (match, name: string, input: string) => {\n const trimmedInput = input.trim()\n if (trimmedInput.length > 500) {\n return `[tool_use: ${name}] ${trimmedInput.slice(0, 500)}...`\n }\n return `[tool_use: ${name}] ${trimmedInput}`\n })\n\n // Collapse multiple blank lines\n text = text.replace(/\\n{3,}/g, '\\n\\n')\n\n return text.trim()\n}\n","import type { Message } from '../collector/types.js'\n\nexport interface ChunkOptions {\n maxTokensPerChunk: number // default 50000\n overlapMessages: number // default 3\n}\n\nexport interface Chunk {\n messages: Message[]\n chunkIndex: number\n totalChunks: number\n startTime: Date\n endTime: Date\n}\n\nconst DEFAULT_OPTIONS: ChunkOptions = {\n maxTokensPerChunk: 50000,\n overlapMessages: 3,\n}\n\n/**\n * Estimate token count using char/3 heuristic.\n */\nexport function estimateTokens(text: string): number {\n return Math.ceil(text.length / 3)\n}\n\n/**\n * Estimate total tokens for a list of messages.\n */\nexport function estimateMessagesTokens(messages: Message[]): number {\n return messages.reduce((sum, m) => sum + estimateTokens(m.content), 0)\n}\n\n/**\n * Split messages into chunks, aligning boundaries to complete user-assistant pairs.\n */\nexport function chunkMessages(messages: Message[], options?: Partial<ChunkOptions>): Chunk[] {\n const opts = { ...DEFAULT_OPTIONS, ...options }\n\n const totalTokens = estimateMessagesTokens(messages)\n if (totalTokens <= opts.maxTokensPerChunk) {\n return [{\n messages,\n chunkIndex: 1,\n totalChunks: 1,\n startTime: messages[0].timestamp,\n endTime: messages[messages.length - 1].timestamp,\n }]\n }\n\n // Find pair boundaries: each pair starts with a user message\n const pairBoundaries: number[] = [0]\n for (let i = 1; i < messages.length; i++) {\n if (messages[i].role === 'user') {\n pairBoundaries.push(i)\n }\n }\n\n // Build chunks by accumulating pairs until token limit\n const rawChunks: Message[][] = []\n let currentChunk: Message[] = []\n let currentTokens = 0\n\n for (let p = 0; p < pairBoundaries.length; p++) {\n const pairStart = pairBoundaries[p]\n const pairEnd = p + 1 < pairBoundaries.length ? pairBoundaries[p + 1] : messages.length\n const pairMessages = messages.slice(pairStart, pairEnd)\n const pairTokens = pairMessages.reduce((sum, m) => sum + estimateTokens(m.content), 0)\n\n if (currentChunk.length > 0 && currentTokens + pairTokens > opts.maxTokensPerChunk) {\n rawChunks.push(currentChunk)\n currentChunk = []\n currentTokens = 0\n }\n\n currentChunk.push(...pairMessages)\n currentTokens += pairTokens\n }\n\n if (currentChunk.length > 0) {\n rawChunks.push(currentChunk)\n }\n\n // Apply overlap: prepend last N messages from previous chunk\n const totalChunks = rawChunks.length\n const chunks: Chunk[] = rawChunks.map((chunkMsgs, i) => {\n let finalMessages = chunkMsgs\n if (i > 0 && opts.overlapMessages > 0) {\n const prevChunk = rawChunks[i - 1]\n const overlapStart = Math.max(0, prevChunk.length - opts.overlapMessages)\n const overlap = prevChunk.slice(overlapStart)\n finalMessages = [...overlap, ...chunkMsgs]\n }\n\n return {\n messages: finalMessages,\n chunkIndex: i + 1,\n totalChunks,\n startTime: finalMessages[0].timestamp,\n endTime: finalMessages[finalMessages.length - 1].timestamp,\n }\n })\n\n return chunks\n}\n","export class Semaphore {\n private queue: (() => void)[] = []\n private running = 0\n\n constructor(private readonly max: number) {}\n\n async acquire(): Promise<void> {\n if (this.running < this.max) {\n this.running++\n return\n }\n return new Promise(resolve => this.queue.push(resolve))\n }\n\n release(): void {\n this.running--\n const next = this.queue.shift()\n if (next) {\n this.running++\n next()\n }\n }\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport { createRequire } from 'node:module'\nimport pino from 'pino'\nimport { getSynthDir } from './config/loader.js'\n\nconst require = createRequire(import.meta.url)\n\nfunction ensureLogDir(): string {\n const logDir = path.join(getSynthDir(), 'logs')\n if (!fs.existsSync(logDir)) {\n fs.mkdirSync(logDir, { recursive: true })\n }\n return logDir\n}\n\nfunction hasPinoPretty(): boolean {\n try {\n require.resolve('pino-pretty')\n return true\n } catch {\n return false\n }\n}\n\nexport function createLogger(level: string = 'info'): pino.Logger {\n const logDir = ensureLogDir()\n const logFile = path.join(logDir, 'synth.log')\n const targets: pino.TransportTargetOptions[] = [\n {\n target: 'pino/file',\n options: { destination: logFile, mkdir: true },\n level,\n },\n ]\n\n if (hasPinoPretty()) {\n targets.push({\n target: 'pino-pretty',\n options: { colorize: true },\n level,\n })\n } else {\n targets.push({\n target: 'pino/file',\n options: { destination: 1 },\n level,\n })\n }\n\n return pino({ level }, pino.transport({ targets }))\n}\n\nlet _logger: pino.Logger | undefined\n\nexport function getLogger(): pino.Logger {\n if (!_logger) {\n _logger = createLogger()\n }\n return _logger\n}\n\nexport function setLogger(logger: pino.Logger): void {\n _logger = logger\n}\n","import type { SessionRecord, Message } from '../collector/types.js'\nimport type { LLMProvider, SessionSummary } from './types.js'\nimport type { SynthConfig } from '../config/schema.js'\nimport { defaultPrompts, renderTemplate } from './prompts.js'\nimport { preprocessMessages } from '../processor/preprocessor.js'\nimport { chunkMessages, estimateMessagesTokens } from '../processor/chunker.js'\nimport { Semaphore } from './semaphore.js'\nimport { getLogger } from '../logger.js'\n\nconst MAX_RETRIES = 2\n\nfunction formatTime(date: Date): string {\n return date.toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit', hour12: false })\n}\n\nfunction getPrompt(config: SynthConfig, key: keyof typeof defaultPrompts): string {\n const custom = config.agent[key]\n return (custom && custom.trim()) ? custom : defaultPrompts[key]\n}\n\nfunction messagesToText(messages: Message[]): string {\n return messages\n .map(m => `[${m.role}] ${m.content}`)\n .join('\\n\\n')\n}\n\nexport class Summarizer {\n private provider: LLMProvider\n private config: SynthConfig\n private semaphore: Semaphore\n\n constructor(provider: LLMProvider, config: SynthConfig) {\n this.provider = provider\n this.config = config\n this.semaphore = new Semaphore(config.llm.maxConcurrency)\n }\n\n /**\n * Summarize a single session: preprocess → chunk if needed → summarize.\n */\n async summarizeSession(session: SessionRecord): Promise<SessionSummary> {\n const logger = getLogger()\n const preprocessed = preprocessMessages(session.messages)\n const totalTokens = estimateMessagesTokens(preprocessed)\n const systemPrompt = getPrompt(this.config, 'systemPrompt')\n\n // Token threshold: contextWindow minus buffer for system prompt and output\n const threshold = this.config.llm.contextWindow - this.config.llm.maxTokens - 2000\n\n logger.debug({\n sessionId: session.sessionId.slice(0, 8),\n totalTokens,\n threshold,\n messageCount: preprocessed.length,\n }, 'Session 摘要开始')\n\n let summary: string\n\n if (totalTokens <= threshold) {\n // Single-pass summarization\n summary = await this.singlePassSummarize(session, preprocessed, systemPrompt)\n } else {\n // MapReduce summarization\n summary = await this.mapReduceSummarize(session, preprocessed, systemPrompt, threshold)\n }\n\n logger.info({\n sessionId: session.sessionId.slice(0, 8),\n tool: session.tool,\n workingDir: session.workingDir,\n }, 'Session 摘要完成')\n\n return {\n sessionId: session.sessionId,\n tool: session.tool,\n workingDir: session.workingDir,\n startTime: session.startTime,\n endTime: session.endTime,\n summary,\n }\n }\n\n private async singlePassSummarize(\n session: SessionRecord,\n messages: Message[],\n systemPrompt: string,\n ): Promise<string> {\n const content = messagesToText(messages)\n const mapPrompt = renderTemplate(getPrompt(this.config, 'mapPrompt'), {\n tool: session.tool,\n workingDir: session.workingDir,\n startTime: formatTime(session.startTime),\n endTime: formatTime(session.endTime),\n chunkIndex: '1',\n totalChunks: '1',\n content,\n })\n\n return this.callWithRetry([\n { role: 'system', content: systemPrompt },\n { role: 'user', content: mapPrompt },\n ])\n }\n\n private async mapReduceSummarize(\n session: SessionRecord,\n messages: Message[],\n systemPrompt: string,\n maxTokensPerChunk: number,\n ): Promise<string> {\n const logger = getLogger()\n const chunks = chunkMessages(messages, { maxTokensPerChunk })\n\n logger.info({\n sessionId: session.sessionId.slice(0, 8),\n chunks: chunks.length,\n }, 'MapReduce 分片')\n\n // Map phase: concurrent summarization with semaphore\n const mapResults = await Promise.all(\n chunks.map(async (chunk) => {\n await this.semaphore.acquire()\n try {\n const content = messagesToText(chunk.messages)\n const mapPrompt = renderTemplate(getPrompt(this.config, 'mapPrompt'), {\n tool: session.tool,\n workingDir: session.workingDir,\n startTime: formatTime(chunk.startTime),\n endTime: formatTime(chunk.endTime),\n chunkIndex: String(chunk.chunkIndex),\n totalChunks: String(chunk.totalChunks),\n content,\n })\n\n const result = await this.callWithRetry([\n { role: 'system', content: systemPrompt },\n { role: 'user', content: mapPrompt },\n ])\n\n logger.debug({\n sessionId: session.sessionId.slice(0, 8),\n chunk: `${chunk.chunkIndex}/${chunk.totalChunks}`,\n }, 'Map 片段完成')\n\n return result\n } catch (err) {\n logger.error({\n sessionId: session.sessionId.slice(0, 8),\n chunk: `${chunk.chunkIndex}/${chunk.totalChunks}`,\n err,\n }, 'Map 片段失败,跳过')\n return null\n } finally {\n this.semaphore.release()\n }\n }),\n )\n\n const validSummaries = mapResults.filter((s): s is string => s !== null)\n\n if (validSummaries.length === 0) {\n return '(摘要生成失败)'\n }\n\n if (validSummaries.length === 1) {\n return validSummaries[0]\n }\n\n // Reduce phase: merge all chunk summaries\n const summariesText = validSummaries\n .map((s, i) => `--- 片段 ${i + 1} ---\\n${s}`)\n .join('\\n\\n')\n\n const reducePrompt = renderTemplate(getPrompt(this.config, 'reducePrompt'), {\n summaries: summariesText,\n })\n\n return this.callWithRetry([\n { role: 'system', content: systemPrompt },\n { role: 'user', content: reducePrompt },\n ])\n }\n\n private async callWithRetry(\n messages: { role: 'system' | 'user' | 'assistant'; content: string }[],\n ): Promise<string> {\n const logger = getLogger()\n let lastError: unknown\n\n for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {\n try {\n return await this.provider.chat(messages)\n } catch (err) {\n lastError = err\n if (attempt < MAX_RETRIES) {\n const delay = 1000 * (attempt + 1)\n logger.warn({ attempt: attempt + 1, err }, `LLM 调用失败,${delay}ms 后重试`)\n await new Promise(r => setTimeout(r, delay))\n }\n }\n }\n\n throw lastError\n }\n}\n","import Anthropic from '@anthropic-ai/sdk'\nimport type { ChatMessage, ChatOptions, LLMProvider } from '../types.js'\n\nexport interface AnthropicConfig {\n baseUrl: string\n apiKey: string\n model: string\n maxTokens: number\n}\n\nexport class AnthropicProvider implements LLMProvider {\n private client: Anthropic\n private model: string\n private maxTokens: number\n\n constructor(config: AnthropicConfig) {\n this.client = new Anthropic({\n baseURL: config.baseUrl,\n apiKey: config.apiKey,\n })\n this.model = config.model\n this.maxTokens = config.maxTokens\n }\n\n async chat(messages: ChatMessage[], options?: ChatOptions): Promise<string> {\n // Separate system prompt from conversation messages\n let system: string | undefined\n const conversationMessages: Array<{ role: 'user' | 'assistant'; content: string }> = []\n\n for (const msg of messages) {\n if (msg.role === 'system') {\n system = msg.content\n } else {\n conversationMessages.push({\n role: msg.role,\n content: msg.content,\n })\n }\n }\n\n const response = await this.client.messages.create({\n model: this.model,\n max_tokens: options?.maxTokens ?? this.maxTokens,\n system,\n messages: conversationMessages,\n })\n\n const textBlock = response.content.find(b => b.type === 'text')\n return textBlock?.type === 'text' ? textBlock.text : ''\n }\n}\n","import OpenAI from 'openai'\nimport type { ChatMessage, ChatOptions, LLMProvider } from '../types.js'\n\nexport interface OpenAICompatibleConfig {\n baseUrl: string\n apiKey: string\n model: string\n maxTokens: number\n headers?: Record<string, string>\n}\n\nexport class OpenAICompatibleProvider implements LLMProvider {\n private client: OpenAI\n private model: string\n private maxTokens: number\n\n constructor(config: OpenAICompatibleConfig) {\n this.client = new OpenAI({\n baseURL: config.baseUrl,\n apiKey: config.apiKey,\n defaultHeaders: config.headers,\n })\n this.model = config.model\n this.maxTokens = config.maxTokens\n }\n\n async chat(messages: ChatMessage[], options?: ChatOptions): Promise<string> {\n const response = await this.client.chat.completions.create({\n model: this.model,\n messages: messages.map(m => ({\n role: m.role,\n content: m.content,\n })),\n max_tokens: options?.maxTokens ?? this.maxTokens,\n temperature: options?.temperature ?? 0.3,\n })\n\n return response.choices[0]?.message?.content ?? ''\n }\n}\n","import fs from 'node:fs'\nimport os from 'node:os'\nimport path from 'node:path'\nimport readline from 'node:readline'\nimport { getLogger } from '../logger.js'\nimport type { Message, SessionRecord, ToolAdapter } from './types.js'\n\nfunction decodeProjectDir(encoded: string): string {\n const match = encoded.match(/^([A-Za-z])--(.*)?$/)\n if (!match) return encoded\n\n const drive = match[1].toUpperCase()\n const rest = match[2] ? match[2].replace(/-/g, '\\\\') : ''\n return rest ? `${drive}:\\\\${rest}` : `${drive}:\\\\`\n}\n\nfunction getClaudeDir(): string {\n return path.join(os.homedir(), '.claude')\n}\n\nfunction isMessageInWindow(timestamp: Date, since: Date, until: Date): boolean {\n return timestamp > since && timestamp <= until\n}\n\nexport class ClaudeCodeAdapter implements ToolAdapter {\n readonly name = 'claude-code'\n\n async detect(): Promise<boolean> {\n return fs.existsSync(path.join(getClaudeDir(), 'projects'))\n }\n\n async collectSessions(since: Date, until: Date): Promise<SessionRecord[]> {\n const logger = getLogger()\n const projectsDir = path.join(getClaudeDir(), 'projects')\n const results: SessionRecord[] = []\n const projectDirs = fs.readdirSync(projectsDir, { withFileTypes: true }).filter((d) => d.isDirectory())\n\n for (const projectDir of projectDirs) {\n const workingDir = decodeProjectDir(projectDir.name)\n const projectPath = path.join(projectsDir, projectDir.name)\n const jsonlFiles = fs.readdirSync(projectPath).filter((f) => f.endsWith('.jsonl'))\n\n for (const file of jsonlFiles) {\n const filePath = path.join(projectPath, file)\n const sessionId = path.basename(file, '.jsonl')\n const stat = fs.statSync(filePath)\n\n if (stat.mtime <= since) continue\n\n try {\n const session = await this.parseSession(filePath, sessionId, workingDir, since, until)\n if (session) {\n results.push(session)\n }\n } catch (err) {\n logger.warn({ file: filePath, err }, 'Claude Code session parse failed')\n }\n }\n }\n\n return results\n }\n\n private async parseSession(\n filePath: string,\n sessionId: string,\n workingDir: string,\n since: Date,\n until: Date,\n ): Promise<SessionRecord | null> {\n const messages: Message[] = []\n let cwd = workingDir\n const stream = fs.createReadStream(filePath, { encoding: 'utf-8' })\n const rl = readline.createInterface({ input: stream, crlfDelay: Infinity })\n\n for await (const line of rl) {\n if (!line.trim()) continue\n\n let entry: any\n try {\n entry = JSON.parse(line)\n } catch {\n continue\n }\n\n if (entry.cwd) {\n cwd = entry.cwd\n }\n\n if (entry.type !== 'user' && entry.type !== 'assistant') continue\n if (!entry.message) continue\n\n const timestamp = entry.timestamp ? new Date(entry.timestamp) : null\n if (!timestamp || !isMessageInWindow(timestamp, since, until)) continue\n\n const role = entry.message.role as 'user' | 'assistant'\n if (role !== 'user' && role !== 'assistant') continue\n\n const content = extractTextContent(entry.message.content)\n if (!content) continue\n\n messages.push({ role, content, timestamp })\n }\n\n if (messages.length === 0) return null\n\n return {\n tool: 'claude-code',\n sessionId,\n workingDir: cwd,\n startTime: messages[0].timestamp,\n endTime: messages[messages.length - 1].timestamp,\n messages,\n }\n }\n}\n\nfunction extractTextContent(content: unknown): string {\n if (typeof content === 'string') return content\n\n if (Array.isArray(content)) {\n const parts: string[] = []\n for (const block of content) {\n if (!block || typeof block !== 'object') continue\n const b = block as Record<string, any>\n\n if (b.type === 'text' && typeof b.text === 'string') {\n parts.push(b.text)\n } else if (b.type === 'tool_use') {\n const input = b.input ? JSON.stringify(b.input) : ''\n parts.push(`[tool_use: ${b.name}] ${input}`)\n } else if (b.type === 'tool_result') {\n const text = typeof b.content === 'string' ? b.content : ''\n parts.push(`[tool_result] ${text}`)\n } else if (b.type === 'thinking') {\n parts.push(`[thinking] ${b.thinking || ''}`)\n }\n }\n return parts.join('\\n')\n }\n\n return ''\n}\n","import fs from 'node:fs'\nimport os from 'node:os'\nimport path from 'node:path'\nimport readline from 'node:readline'\nimport { getLogger } from '../logger.js'\nimport type { Message, SessionRecord, ToolAdapter } from './types.js'\n\nfunction getCodexDir(): string {\n return path.join(os.homedir(), '.codex')\n}\n\nfunction isMessageInWindow(timestamp: Date, since: Date, until: Date): boolean {\n return timestamp > since && timestamp <= until\n}\n\nexport class CodexAdapter implements ToolAdapter {\n readonly name = 'codex'\n\n async detect(): Promise<boolean> {\n return fs.existsSync(path.join(getCodexDir(), 'sessions'))\n }\n\n async collectSessions(since: Date, until: Date): Promise<SessionRecord[]> {\n const logger = getLogger()\n const sessionsDir = path.join(getCodexDir(), 'sessions')\n const results: SessionRecord[] = []\n const sessionFiles = this.findSessionFiles(sessionsDir, since, until)\n\n for (const filePath of sessionFiles) {\n const sessionId = path.basename(filePath, '.jsonl')\n\n try {\n const session = await this.parseSession(filePath, sessionId, since, until)\n if (session) {\n results.push(session)\n }\n } catch (err) {\n logger.warn({ file: filePath, err }, 'Codex session parse failed')\n }\n }\n\n return results\n }\n\n private findSessionFiles(sessionsDir: string, since: Date, until: Date): string[] {\n const files: string[] = []\n if (!fs.existsSync(sessionsDir)) return files\n\n const years = fs.readdirSync(sessionsDir, { withFileTypes: true }).filter((d) => d.isDirectory() && /^\\d{4}$/.test(d.name))\n\n for (const yearDir of years) {\n const yearPath = path.join(sessionsDir, yearDir.name)\n const months = fs.readdirSync(yearPath, { withFileTypes: true }).filter((d) => d.isDirectory() && /^\\d{2}$/.test(d.name))\n\n for (const monthDir of months) {\n const monthPath = path.join(yearPath, monthDir.name)\n const days = fs.readdirSync(monthPath, { withFileTypes: true }).filter((d) => d.isDirectory() && /^\\d{2}$/.test(d.name))\n\n for (const dayDir of days) {\n const dirDate = new Date(`${yearDir.name}-${monthDir.name}-${dayDir.name}T00:00:00`)\n const dirDateEnd = new Date(dirDate)\n dirDateEnd.setDate(dirDateEnd.getDate() + 1)\n\n if (dirDateEnd <= since || dirDate > until) continue\n\n const dayPath = path.join(monthPath, dayDir.name)\n const jsonlFiles = fs.readdirSync(dayPath)\n .filter((f) => f.endsWith('.jsonl'))\n .map((f) => path.join(dayPath, f))\n\n files.push(...jsonlFiles)\n }\n }\n }\n\n return files\n }\n\n private async parseSession(\n filePath: string,\n sessionId: string,\n since: Date,\n until: Date,\n ): Promise<SessionRecord | null> {\n const messages: Message[] = []\n let cwd = ''\n const stream = fs.createReadStream(filePath, { encoding: 'utf-8' })\n const rl = readline.createInterface({ input: stream, crlfDelay: Infinity })\n\n for await (const line of rl) {\n if (!line.trim()) continue\n\n let entry: any\n try {\n entry = JSON.parse(line)\n } catch {\n continue\n }\n\n const type = entry.type\n const timestamp = entry.timestamp ? new Date(entry.timestamp) : null\n\n if (type === 'session_meta') {\n cwd = entry.payload?.cwd || ''\n continue\n }\n\n if (type === 'turn_context' && entry.payload?.cwd) {\n cwd = entry.payload.cwd\n continue\n }\n\n if (!timestamp || !isMessageInWindow(timestamp, since, until)) continue\n\n if (type === 'event_msg' && entry.payload?.type === 'user_message') {\n const text = entry.payload.message\n if (typeof text === 'string' && text.trim()) {\n messages.push({ role: 'user', content: text, timestamp })\n }\n continue\n }\n\n if (type === 'response_item') {\n const payload = entry.payload\n if (!payload) continue\n\n const role = payload.role\n const content = extractCodexContent(payload.content)\n if (!content) continue\n\n if (role === 'developer' || role === 'user') {\n messages.push({ role: 'user', content, timestamp })\n } else if (role === 'assistant') {\n messages.push({ role: 'assistant', content, timestamp })\n }\n }\n }\n\n if (messages.length === 0) return null\n\n return {\n tool: 'codex',\n sessionId,\n workingDir: cwd,\n startTime: messages[0].timestamp,\n endTime: messages[messages.length - 1].timestamp,\n messages,\n }\n }\n}\n\nfunction extractCodexContent(content: unknown): string {\n if (typeof content === 'string') return content\n\n if (Array.isArray(content)) {\n const parts: string[] = []\n for (const block of content) {\n if (!block || typeof block !== 'object') continue\n const b = block as Record<string, any>\n\n if (b.type === 'input_text' && typeof b.text === 'string') {\n parts.push(b.text)\n } else if (b.type === 'output_text' && typeof b.text === 'string') {\n parts.push(b.text)\n } else if (b.type === 'function_call') {\n parts.push(`[tool_use: ${b.name}] ${b.arguments || ''}`)\n } else if (b.type === 'function_call_output') {\n const output = typeof b.output === 'string' ? b.output : ''\n parts.push(`[tool_result] ${output}`)\n }\n }\n return parts.join('\\n')\n }\n\n return ''\n}\n","import fs from 'node:fs'\nimport os from 'node:os'\nimport path from 'node:path'\nimport readline from 'node:readline'\nimport { getLogger } from '../logger.js'\nimport type { Message, SessionRecord, ToolAdapter } from './types.js'\n\nfunction getQoderDir(): string {\n return path.join(os.homedir(), '.qoder')\n}\n\nfunction isMessageInWindow(timestamp: Date, since: Date, until: Date): boolean {\n return timestamp > since && timestamp <= until\n}\n\ninterface SessionMeta {\n id: string\n working_dir: string\n created_at: number\n updated_at: number\n}\n\nexport class QoderAdapter implements ToolAdapter {\n readonly name = 'qoder'\n\n async detect(): Promise<boolean> {\n return fs.existsSync(path.join(getQoderDir(), 'projects'))\n }\n\n async collectSessions(since: Date, until: Date): Promise<SessionRecord[]> {\n const logger = getLogger()\n const projectsDir = path.join(getQoderDir(), 'projects')\n const results: SessionRecord[] = []\n const projectDirs = fs.readdirSync(projectsDir, { withFileTypes: true }).filter((d) => d.isDirectory())\n\n for (const projectDir of projectDirs) {\n const projectPath = path.join(projectsDir, projectDir.name)\n const sessionFiles = fs.readdirSync(projectPath).filter((f) => f.endsWith('-session.json'))\n\n for (const sessionFile of sessionFiles) {\n const metaPath = path.join(projectPath, sessionFile)\n\n try {\n const raw = fs.readFileSync(metaPath, 'utf-8')\n const meta: SessionMeta = JSON.parse(raw)\n const createdAt = new Date(meta.created_at)\n const updatedAt = new Date(meta.updated_at)\n\n if (createdAt > until || updatedAt <= since) continue\n\n const jsonlFile = path.join(projectPath, `${meta.id}.jsonl`)\n if (!fs.existsSync(jsonlFile)) continue\n\n const session = await this.parseSession(jsonlFile, meta, since, until)\n if (session) {\n results.push(session)\n }\n } catch (err) {\n logger.warn({ file: metaPath, err }, 'Qoder session parse failed')\n }\n }\n }\n\n return results\n }\n\n private async parseSession(\n filePath: string,\n meta: SessionMeta,\n since: Date,\n until: Date,\n ): Promise<SessionRecord | null> {\n const messages: Message[] = []\n const stream = fs.createReadStream(filePath, { encoding: 'utf-8' })\n const rl = readline.createInterface({ input: stream, crlfDelay: Infinity })\n\n for await (const line of rl) {\n if (!line.trim()) continue\n\n let entry: any\n try {\n entry = JSON.parse(line)\n } catch {\n continue\n }\n\n if (entry.type !== 'user' && entry.type !== 'assistant') continue\n if (!entry.message) continue\n\n const timestamp = entry.timestamp ? new Date(entry.timestamp) : null\n if (!timestamp || !isMessageInWindow(timestamp, since, until)) continue\n\n const role = entry.message.role as 'user' | 'assistant'\n if (role !== 'user' && role !== 'assistant') continue\n\n const content = extractQoderContent(entry.message.content)\n if (!content) continue\n\n messages.push({ role, content, timestamp })\n }\n\n if (messages.length === 0) return null\n\n return {\n tool: 'qoder',\n sessionId: meta.id,\n workingDir: meta.working_dir,\n startTime: messages[0].timestamp,\n endTime: messages[messages.length - 1].timestamp,\n messages,\n }\n }\n}\n\nfunction extractQoderContent(content: unknown): string {\n if (typeof content === 'string') return content\n\n if (Array.isArray(content)) {\n const parts: string[] = []\n for (const block of content) {\n if (!block || typeof block !== 'object') continue\n const b = block as Record<string, any>\n\n if (b.type === 'text' && typeof b.text === 'string') {\n parts.push(b.text)\n } else if (b.type === 'tool_use') {\n const input = b.input ? JSON.stringify(b.input) : ''\n parts.push(`[tool_use: ${b.name}] ${input}`)\n } else if (b.type === 'tool_result') {\n const text = typeof b.content === 'string' ? b.content : ''\n parts.push(`[tool_result] ${text}`)\n } else if (b.type === 'thinking') {\n parts.push(`[thinking] ${b.thinking || ''}`)\n }\n }\n return parts.join('\\n')\n }\n\n return ''\n}\n","import type { ToolAdapter, SessionRecord } from './types.js'\nimport { getLogger } from '../logger.js'\n\nexport class AdapterRegistry {\n private adapters: Map<string, ToolAdapter> = new Map()\n\n register(adapter: ToolAdapter): void {\n this.adapters.set(adapter.name, adapter)\n }\n\n async collectAll(\n since: Date,\n until: Date,\n enabledAdapters?: string[],\n ): Promise<SessionRecord[]> {\n const logger = getLogger()\n const results: SessionRecord[] = []\n\n for (const [name, adapter] of this.adapters) {\n if (enabledAdapters && !enabledAdapters.includes(name)) {\n continue\n }\n\n const detected = await adapter.detect()\n if (!detected) {\n logger.debug({ adapter: name }, '未检测到数据目录,跳过')\n continue\n }\n\n try {\n const sessions = await adapter.collectSessions(since, until)\n logger.info({ adapter: name, count: sessions.length }, '采集完成')\n results.push(...sessions)\n } catch (err) {\n logger.error({ adapter: name, err }, '采集失败')\n }\n }\n\n return results\n }\n}\n","import fs from 'node:fs'\nimport os from 'node:os'\nimport path from 'node:path'\nimport { marked } from 'marked'\nimport type { SynthConfig } from '../config/schema.js'\nimport { getLogger } from '../logger.js'\n\nexport interface GeneratedHtmlReport {\n content: string\n filePath: string\n}\n\nconst CSS = `\nbody {\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif;\n max-width: 900px;\n margin: 0 auto;\n padding: 40px 20px;\n color: #333;\n line-height: 1.6;\n background: #fafafa;\n}\nh1 {\n color: #1a1a1a;\n border-bottom: 2px solid #e1e4e8;\n padding-bottom: 12px;\n font-size: 1.8em;\n}\nh2 {\n color: #24292e;\n margin-top: 32px;\n padding: 8px 12px;\n background: #f0f4f8;\n border-left: 4px solid #0366d6;\n border-radius: 4px;\n font-size: 1.2em;\n font-family: \"Cascadia Code\", \"Fira Code\", Consolas, monospace;\n}\nh3 {\n color: #586069;\n font-size: 1em;\n margin-top: 20px;\n font-weight: 600;\n}\nh4 {\n color: #333;\n font-size: 0.95em;\n margin-top: 16px;\n}\nul {\n padding-left: 24px;\n}\nli {\n margin: 6px 0;\n}\ncode {\n background: #f1f3f5;\n padding: 2px 6px;\n border-radius: 3px;\n font-size: 0.9em;\n}\nhr {\n border: none;\n border-top: 1px solid #e1e4e8;\n margin: 24px 0;\n}\n`.trim()\n\nfunction resolveOutputDir(config: SynthConfig): string {\n const dir = config.output.dir.replace(/^~/, os.homedir())\n return path.join(dir, 'html')\n}\n\nexport function generateHtmlReport(\n date: string,\n markdownContent: string,\n config: SynthConfig,\n): GeneratedHtmlReport {\n const logger = getLogger()\n const htmlBody = marked(markdownContent) as string\n const html = `<!DOCTYPE html>\n<html lang=\"zh-CN\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>${date} 工作日报</title>\n <style>${CSS}</style>\n</head>\n<body>\n${htmlBody}\n</body>\n</html>`\n\n const outputDir = resolveOutputDir(config)\n if (!fs.existsSync(outputDir)) {\n fs.mkdirSync(outputDir, { recursive: true })\n }\n\n const filePath = path.join(outputDir, `${date}.html`)\n fs.writeFileSync(filePath, html, 'utf-8')\n logger.info({ path: filePath }, 'HTML report generated')\n\n return {\n content: html,\n filePath,\n }\n}\n","import fs from 'node:fs'\nimport os from 'node:os'\nimport path from 'node:path'\nimport type { SessionSummary } from '../agent/types.js'\nimport type { SynthConfig } from '../config/schema.js'\nimport { getLogger } from '../logger.js'\n\nexport interface GeneratedMarkdownReport {\n content: string\n filePath: string\n}\n\nexport interface GenerateMarkdownReportOptions {\n append: boolean\n}\n\nfunction resolveOutputDir(config: SynthConfig): string {\n const dir = config.output.dir.replace(/^~/, os.homedir())\n return path.join(dir, 'markdown')\n}\n\nfunction formatTime(date: Date): string {\n return date.toLocaleTimeString('zh-CN', {\n hour: '2-digit',\n minute: '2-digit',\n hour12: false,\n })\n}\n\nfunction createReportHeader(date: string): string {\n return `# ${date} 工作日报\\n`\n}\n\nfunction renderBatchFragment(summaries: SessionSummary[]): string {\n const sorted = [...summaries].sort((a, b) => a.startTime.getTime() - b.startTime.getTime())\n const batchStart = sorted[0].startTime\n const batchEnd = sorted[sorted.length - 1].endTime\n const groups = new Map<string, SessionSummary[]>()\n\n for (const summary of sorted) {\n const list = groups.get(summary.workingDir) || []\n list.push(summary)\n groups.set(summary.workingDir, list)\n }\n\n const sections = [\n `## ${formatTime(batchStart)}~${formatTime(batchEnd)}`,\n ...Array.from(groups.entries()).flatMap(([workingDir, items]) => {\n const rendered = [`### ${workingDir}`]\n for (const item of items) {\n rendered.push(`#### [${item.tool}] ${formatTime(item.startTime)}~${formatTime(item.endTime)}`)\n rendered.push(item.summary.trim())\n }\n return rendered\n }),\n ]\n\n return `${sections.join('\\n\\n')}\\n`\n}\n\nexport async function generateMarkdownReport(\n date: string,\n summaries: SessionSummary[],\n _provider: unknown,\n config: SynthConfig,\n options: GenerateMarkdownReportOptions,\n): Promise<GeneratedMarkdownReport> {\n const logger = getLogger()\n const outputDir = resolveOutputDir(config)\n\n if (!fs.existsSync(outputDir)) {\n fs.mkdirSync(outputDir, { recursive: true })\n }\n\n const filePath = path.join(outputDir, `${date}.md`)\n const fragment = renderBatchFragment(summaries)\n\n if (!options.append || !fs.existsSync(filePath)) {\n const content = `${createReportHeader(date)}\\n${fragment}`.trimEnd() + '\\n'\n fs.writeFileSync(filePath, content, 'utf-8')\n } else {\n const prefix = fs.statSync(filePath).size > 0 ? '\\n' : ''\n fs.appendFileSync(filePath, `${prefix}${fragment}`, 'utf-8')\n }\n\n const content = fs.readFileSync(filePath, 'utf-8')\n logger.info({ path: filePath, append: options.append }, 'Markdown report updated')\n\n return {\n content,\n filePath,\n }\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport Database from 'better-sqlite3'\nimport { getSynthDir } from '../config/loader.js'\n\nlet _db: Database.Database | undefined\n\nfunction getDb(): Database.Database {\n if (_db) return _db\n\n const dbDir = getSynthDir()\n if (!fs.existsSync(dbDir)) {\n fs.mkdirSync(dbDir, { recursive: true })\n }\n\n const dbPath = path.join(dbDir, 'state.sqlite')\n _db = new Database(dbPath)\n\n _db.exec(`\n CREATE TABLE IF NOT EXISTS kv (\n key TEXT PRIMARY KEY,\n value TEXT NOT NULL\n );\n\n CREATE TABLE IF NOT EXISTS message_fingerprints (\n date TEXT NOT NULL,\n fingerprint TEXT NOT NULL,\n created_at TEXT NOT NULL,\n PRIMARY KEY (date, fingerprint)\n );\n `)\n\n return _db\n}\n\nfunction getValue(key: string): string | null {\n const db = getDb()\n const row = db.prepare('SELECT value FROM kv WHERE key = ?').get(key) as\n | { value: string }\n | undefined\n\n return row?.value ?? null\n}\n\nfunction setValue(key: string, value: string): void {\n const db = getDb()\n db.prepare(\n 'INSERT INTO kv (key, value) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value',\n ).run(key, value)\n}\n\nexport function getLastRunAt(): Date | null {\n const value = getValue('lastRunAt')\n return value ? new Date(value) : null\n}\n\nexport function setLastRunAt(date: Date): void {\n setValue('lastRunAt', date.toISOString())\n}\n\nfunction getDailyCursorKey(date: string): string {\n return `dailyCursor:${date}`\n}\n\nexport function getDailyCursor(date: string): Date | null {\n const value = getValue(getDailyCursorKey(date))\n return value ? new Date(value) : null\n}\n\nexport function setDailyCursor(date: string, cursor: Date): void {\n setValue(getDailyCursorKey(date), cursor.toISOString())\n}\n\nexport function hasMessageFingerprint(date: string, fingerprint: string): boolean {\n const db = getDb()\n const row = db\n .prepare('SELECT 1 FROM message_fingerprints WHERE date = ? AND fingerprint = ?')\n .get(date, fingerprint) as { 1: number } | undefined\n\n return !!row\n}\n\nexport function saveMessageFingerprints(date: string, fingerprints: string[]): void {\n if (fingerprints.length === 0) return\n\n const db = getDb()\n const now = new Date().toISOString()\n const stmt = db.prepare(\n 'INSERT OR IGNORE INTO message_fingerprints (date, fingerprint, created_at) VALUES (?, ?, ?)',\n )\n\n const tx = db.transaction((items: string[]) => {\n for (const fingerprint of items) {\n stmt.run(date, fingerprint, now)\n }\n })\n\n tx(fingerprints)\n}\n\nexport function pruneMessageFingerprints(beforeDate: string): void {\n const db = getDb()\n db.prepare('DELETE FROM message_fingerprints WHERE date < ?').run(beforeDate)\n}\n\nexport function clearCollectionState(): void {\n const db = getDb()\n db.exec(`\n DELETE FROM kv WHERE key = 'lastRunAt' OR key LIKE 'dailyCursor:%';\n DELETE FROM message_fingerprints;\n `)\n}\n\nexport function closeDb(): void {\n if (_db) {\n _db.close()\n _db = undefined\n }\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport { execFile } from 'node:child_process'\nimport { promisify } from 'node:util'\nimport { createRequire } from 'node:module'\nimport { fileURLToPath } from 'node:url'\nimport { loadConfig, getSynthDir } from './config/loader.js'\nimport { getLogger } from './logger.js'\nimport { startScheduler } from './scheduler.js'\nimport { closeDb } from './store/state.js'\n\nconst execFileAsync = promisify(execFile)\nconst require = createRequire(import.meta.url)\nconst nodeWindows = require('node-windows') as typeof import('node-windows')\n\nexport const SERVICE_NAME = 'Synth AI Work Summary Service'\nexport const SERVICE_DESCRIPTION = 'Collect AI coding sessions and generate scheduled work summaries.'\nexport const SERVICE_ID = SERVICE_NAME.replace(/[^\\w]/g, '').toLowerCase()\nexport const SERVICE_SYSTEM_NAME = `${SERVICE_ID}.exe`\n\nexport type ServiceState =\n | 'not-installed'\n | 'running'\n | 'stopped'\n | 'start-pending'\n | 'stop-pending'\n | 'paused'\n | 'unknown'\n\nexport interface ServiceStatus {\n installed: boolean\n state: ServiceState\n rawState?: string\n}\n\nfunction ensureWindows(): void {\n if (process.platform !== 'win32') {\n throw new Error('Windows service management is only supported on win32')\n }\n}\n\nfunction ensureDir(dir: string): string {\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true })\n }\n return dir\n}\n\nfunction getServiceScriptPath(): string {\n const currentFile = fileURLToPath(new URL('./index.js', import.meta.url))\n if (fs.existsSync(currentFile)) {\n return currentFile\n }\n\n const distFallback = path.resolve(process.cwd(), 'dist', 'index.js')\n if (fs.existsSync(distFallback)) {\n return distFallback\n }\n\n throw new Error('Cannot locate dist/index.js. Run `npm run build` before installing the service.')\n}\n\nfunction getServiceWorkingDirectory(scriptPath: string): string {\n const dir = path.dirname(scriptPath)\n return path.basename(dir).toLowerCase() === 'dist' ? path.resolve(dir, '..') : dir\n}\n\nfunction getServiceLogDir(): string {\n return ensureDir(path.join(getSynthDir(), 'logs', 'service'))\n}\n\nfunction createService(): import('node-windows').Service {\n const script = getServiceScriptPath()\n\n return new nodeWindows.Service({\n name: SERVICE_NAME,\n description: SERVICE_DESCRIPTION,\n script,\n scriptOptions: 'service-run',\n workingDirectory: getServiceWorkingDirectory(script),\n logpath: getServiceLogDir(),\n maxRestarts: 5,\n wait: 2,\n grow: 0.25,\n stopparentfirst: true,\n env: {\n name: 'SYNTH_SERVICE',\n value: '1',\n },\n } as import('node-windows').ServiceConfig)\n}\n\nfunction withSilentConsole<T>(fn: () => T): T {\n const originalLog = console.log\n console.log = () => {}\n\n try {\n return fn()\n } finally {\n console.log = originalLog\n }\n}\n\nfunction waitForEvent<T>(\n service: import('node-windows').Service,\n action: () => void,\n successEvents: string[],\n failureEvents: string[],\n mapResult: (eventName: string) => T,\n): Promise<T> {\n return new Promise((resolve, reject) => {\n const handlers: Record<string, (...args: unknown[]) => void> = {}\n\n const cleanup = () => {\n for (const eventName of [...successEvents, ...failureEvents]) {\n const handler = handlers[eventName]\n if (handler) {\n service.removeListener(eventName, handler)\n }\n }\n }\n\n for (const eventName of successEvents) {\n handlers[eventName] = () => {\n cleanup()\n resolve(mapResult(eventName))\n }\n service.on(eventName, handlers[eventName]!)\n }\n\n for (const eventName of failureEvents) {\n handlers[eventName] = (...args: unknown[]) => {\n cleanup()\n const error = args[0] instanceof Error ? args[0] : new Error(String(args[0] ?? eventName))\n reject(error)\n }\n service.on(eventName, handlers[eventName]!)\n }\n\n try {\n withSilentConsole(action)\n } catch (err) {\n cleanup()\n reject(err)\n }\n })\n}\n\nfunction normalizeState(rawState?: string): ServiceState {\n switch (rawState) {\n case 'RUNNING':\n return 'running'\n case 'STOPPED':\n return 'stopped'\n case 'START_PENDING':\n return 'start-pending'\n case 'STOP_PENDING':\n return 'stop-pending'\n case 'PAUSED':\n return 'paused'\n default:\n return rawState ? 'unknown' : 'not-installed'\n }\n}\n\nexport async function getServiceStatus(): Promise<ServiceStatus> {\n ensureWindows()\n\n try {\n const { stdout, stderr } = await execFileAsync('sc.exe', ['query', SERVICE_SYSTEM_NAME], {\n windowsHide: true,\n })\n const output = `${stdout}\\n${stderr}`\n const match = output.match(/STATE\\s*:\\s*\\d+\\s+([A-Z_]+)/)\n const rawState = match?.[1]\n return {\n installed: true,\n state: normalizeState(rawState),\n rawState,\n }\n } catch (err) {\n const code = typeof err === 'object' && err !== null && 'code' in err ? (err as { code?: unknown }).code : undefined\n const stdout =\n typeof err === 'object' && err !== null && 'stdout' in err ? String((err as { stdout?: unknown }).stdout ?? '') : ''\n const stderr =\n typeof err === 'object' && err !== null && 'stderr' in err ? String((err as { stderr?: unknown }).stderr ?? '') : ''\n const message = err instanceof Error ? err.message : String(err)\n\n if (code === 1060 || stdout.includes('1060') || stderr.includes('1060') || message.includes('does not exist')) {\n return { installed: false, state: 'not-installed' }\n }\n throw err\n }\n}\n\nexport async function installService(): Promise<ServiceStatus> {\n ensureWindows()\n\n const status = await getServiceStatus()\n if (status.installed) {\n if (status.state !== 'running' && status.state !== 'start-pending') {\n await startService()\n return getServiceStatus()\n }\n return status\n }\n\n const service = createService()\n const result = await waitForEvent(\n service,\n () => service.install(),\n ['install', 'alreadyinstalled'],\n ['error', 'invalidinstallation'],\n (eventName) => eventName,\n )\n\n if (result === 'install') {\n await startService()\n }\n\n return getServiceStatus()\n}\n\nexport async function uninstallService(): Promise<ServiceStatus> {\n ensureWindows()\n\n const status = await getServiceStatus()\n if (!status.installed) {\n return status\n }\n\n const service = createService()\n await waitForEvent(\n service,\n () => service.uninstall(),\n ['uninstall', 'alreadyuninstalled'],\n ['error'],\n () => undefined,\n )\n\n return getServiceStatus()\n}\n\nexport async function startService(): Promise<ServiceStatus> {\n ensureWindows()\n\n const status = await getServiceStatus()\n if (!status.installed || status.state === 'running' || status.state === 'start-pending') {\n return status\n }\n\n const service = createService()\n await waitForEvent(service, () => service.start(), ['start'], ['error'], () => undefined)\n return getServiceStatus()\n}\n\nexport async function stopService(): Promise<ServiceStatus> {\n ensureWindows()\n\n const status = await getServiceStatus()\n if (!status.installed || status.state === 'stopped' || status.state === 'stop-pending') {\n return status\n }\n\n const service = createService()\n await waitForEvent(service, () => service.stop(), ['stop', 'alreadystopped'], ['error'], () => undefined)\n return getServiceStatus()\n}\n\nexport async function runServiceProcess(): Promise<void> {\n const logger = getLogger()\n const config = loadConfig()\n const task = startScheduler(config)\n\n logger.info({ cron: config.schedule.cron }, 'Windows service process started')\n\n let shuttingDown = false\n const shutdown = async (reason: string) => {\n if (shuttingDown) return\n shuttingDown = true\n\n logger.info({ reason }, 'Windows service process stopping')\n\n try {\n await Promise.resolve(task.stop())\n } finally {\n closeDb()\n }\n\n logger.info('Windows service process stopped')\n process.exit(0)\n }\n\n process.on('SIGINT', () => {\n void shutdown('SIGINT')\n })\n\n process.on('SIGTERM', () => {\n void shutdown('SIGTERM')\n })\n\n process.on('message', (message) => {\n if (message === 'shutdown') {\n void shutdown('shutdown')\n }\n })\n}\n","import cron, { type ScheduledTask } from 'node-cron'\nimport type { SynthConfig } from './config/schema.js'\nimport { getLogger } from './logger.js'\nimport { run } from './runner.js'\n\nfunction formatNextRun(task: ScheduledTask): string | null {\n const nextRun = task.getNextRun()\n return nextRun ? nextRun.toISOString() : null\n}\n\nexport function startScheduler(config: SynthConfig): ScheduledTask {\n const logger = getLogger()\n const expression = config.schedule.cron\n\n if (!cron.validate(expression)) {\n throw new Error(`Invalid cron expression: ${expression}`)\n }\n\n const task = cron.schedule(\n expression,\n async () => {\n const startedAt = new Date()\n logger.info(\n { cron: expression, startedAt: startedAt.toISOString() },\n 'Scheduled run started',\n )\n\n try {\n await run(config)\n logger.info(\n { cron: expression, finishedAt: new Date().toISOString(), nextRun: formatNextRun(task) },\n 'Scheduled run finished',\n )\n } catch (err) {\n logger.error(\n {\n cron: expression,\n err,\n finishedAt: new Date().toISOString(),\n nextRun: formatNextRun(task),\n },\n 'Scheduled run failed',\n )\n }\n },\n {\n name: 'synth-scheduler',\n noOverlap: true,\n },\n )\n\n task.on('execution:overlap', () => {\n logger.warn({ cron: expression }, 'Scheduled run skipped because previous execution is still running')\n })\n\n task.on('execution:missed', (context) => {\n logger.warn(\n { cron: expression, scheduledAt: context.date.toISOString(), triggeredAt: context.triggeredAt.toISOString() },\n 'Scheduled run was missed',\n )\n })\n\n task.on('execution:failed', (context) => {\n logger.error(\n {\n cron: expression,\n scheduledAt: context.date.toISOString(),\n triggeredAt: context.triggeredAt.toISOString(),\n err: context.execution?.error,\n },\n 'Scheduled execution callback failed',\n )\n })\n\n logger.info({ cron: expression, nextRun: formatNextRun(task) }, 'Scheduler started')\n return task\n}\n"],"mappings":"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","names":["fs","os","path","fs","path","require","path","fs","fs","os","path","path","os","fs","fs","os","path","readline","path","os","isMessageInWindow","fs","readline","fs","os","path","readline","path","os","isMessageInWindow","fs","readline","fs","os","path","os","path","fs","fs","os","path","resolveOutputDir","os","path","formatTime","fs","content","fs","path","fs","path","os","path","fs","fs","path","createRequire","require","createRequire","fs","path"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tiey/synth",
3
- "version": "0.0.2",
3
+ "version": "0.0.3",
4
4
  "description": "AI coding work summary service for collecting sessions and generating scheduled daily reports.",
5
5
  "type": "module",
6
6
  "bin": {