@tiey/synth 0.0.4 → 0.0.5
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 +71 -15
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1623,15 +1623,27 @@ function createService() {
|
|
|
1623
1623
|
}
|
|
1624
1624
|
});
|
|
1625
1625
|
}
|
|
1626
|
-
function
|
|
1627
|
-
const
|
|
1626
|
+
function muteConsole() {
|
|
1627
|
+
const originalConsole = {
|
|
1628
|
+
log: console.log,
|
|
1629
|
+
info: console.info,
|
|
1630
|
+
warn: console.warn,
|
|
1631
|
+
debug: console.debug
|
|
1632
|
+
};
|
|
1628
1633
|
console.log = () => {
|
|
1629
1634
|
};
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
+
console.info = () => {
|
|
1636
|
+
};
|
|
1637
|
+
console.warn = () => {
|
|
1638
|
+
};
|
|
1639
|
+
console.debug = () => {
|
|
1640
|
+
};
|
|
1641
|
+
return () => {
|
|
1642
|
+
console.log = originalConsole.log;
|
|
1643
|
+
console.info = originalConsole.info;
|
|
1644
|
+
console.warn = originalConsole.warn;
|
|
1645
|
+
console.debug = originalConsole.debug;
|
|
1646
|
+
};
|
|
1635
1647
|
}
|
|
1636
1648
|
function sleep(ms) {
|
|
1637
1649
|
return new Promise((resolve) => {
|
|
@@ -1641,6 +1653,7 @@ function sleep(ms) {
|
|
|
1641
1653
|
function waitForEvent(service, action, successEvents, failureEvents, mapResult) {
|
|
1642
1654
|
return new Promise((resolve, reject) => {
|
|
1643
1655
|
const handlers = {};
|
|
1656
|
+
const restoreConsole = muteConsole();
|
|
1644
1657
|
const cleanup = () => {
|
|
1645
1658
|
for (const eventName of [...successEvents, ...failureEvents]) {
|
|
1646
1659
|
const handler = handlers[eventName];
|
|
@@ -1648,6 +1661,7 @@ function waitForEvent(service, action, successEvents, failureEvents, mapResult)
|
|
|
1648
1661
|
service.removeListener(eventName, handler);
|
|
1649
1662
|
}
|
|
1650
1663
|
}
|
|
1664
|
+
restoreConsole();
|
|
1651
1665
|
};
|
|
1652
1666
|
for (const eventName of successEvents) {
|
|
1653
1667
|
handlers[eventName] = () => {
|
|
@@ -1665,7 +1679,7 @@ function waitForEvent(service, action, successEvents, failureEvents, mapResult)
|
|
|
1665
1679
|
service.on(eventName, handlers[eventName]);
|
|
1666
1680
|
}
|
|
1667
1681
|
try {
|
|
1668
|
-
|
|
1682
|
+
action();
|
|
1669
1683
|
} catch (err) {
|
|
1670
1684
|
cleanup();
|
|
1671
1685
|
reject(err);
|
|
@@ -1711,6 +1725,43 @@ ${stderr}`;
|
|
|
1711
1725
|
throw err;
|
|
1712
1726
|
}
|
|
1713
1727
|
}
|
|
1728
|
+
async function stopServiceWithSc() {
|
|
1729
|
+
try {
|
|
1730
|
+
await execFileAsync("sc.exe", ["stop", SERVICE_SYSTEM_NAME], {
|
|
1731
|
+
windowsHide: true
|
|
1732
|
+
});
|
|
1733
|
+
} catch (err) {
|
|
1734
|
+
const code = typeof err === "object" && err !== null && "code" in err ? err.code : void 0;
|
|
1735
|
+
const stdout = typeof err === "object" && err !== null && "stdout" in err ? String(err.stdout ?? "") : "";
|
|
1736
|
+
const stderr = typeof err === "object" && err !== null && "stderr" in err ? String(err.stderr ?? "") : "";
|
|
1737
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
1738
|
+
if (code === 1060 || stdout.includes("1060") || stderr.includes("1060") || message.includes("does not exist") || stdout.includes("1062") || stderr.includes("1062") || message.includes("has not been started")) {
|
|
1739
|
+
return;
|
|
1740
|
+
}
|
|
1741
|
+
throw err;
|
|
1742
|
+
}
|
|
1743
|
+
}
|
|
1744
|
+
async function waitForServiceState(expectedStates, timeoutMs = SERVICE_DELETE_TIMEOUT_MS) {
|
|
1745
|
+
const deadline = Date.now() + timeoutMs;
|
|
1746
|
+
while (true) {
|
|
1747
|
+
const query = await queryService();
|
|
1748
|
+
const status = query.installed ? {
|
|
1749
|
+
installed: true,
|
|
1750
|
+
state: normalizeState(query.rawState),
|
|
1751
|
+
rawState: query.rawState
|
|
1752
|
+
} : {
|
|
1753
|
+
installed: false,
|
|
1754
|
+
state: "not-installed"
|
|
1755
|
+
};
|
|
1756
|
+
if (expectedStates.includes(status.state)) {
|
|
1757
|
+
return status;
|
|
1758
|
+
}
|
|
1759
|
+
if (Date.now() >= deadline) {
|
|
1760
|
+
return status;
|
|
1761
|
+
}
|
|
1762
|
+
await sleep(SERVICE_DELETE_POLL_INTERVAL_MS);
|
|
1763
|
+
}
|
|
1764
|
+
}
|
|
1714
1765
|
async function deleteServiceWithSc() {
|
|
1715
1766
|
try {
|
|
1716
1767
|
await execFileAsync("sc.exe", ["delete", SERVICE_SYSTEM_NAME], {
|
|
@@ -1785,14 +1836,19 @@ async function uninstallService() {
|
|
|
1785
1836
|
if (!status.installed) {
|
|
1786
1837
|
return status;
|
|
1787
1838
|
}
|
|
1839
|
+
if (status.state !== "stopped") {
|
|
1840
|
+
await stopService();
|
|
1841
|
+
let stoppedStatus = await waitForServiceState(["stopped", "not-installed"]);
|
|
1842
|
+
if (stoppedStatus.installed && stoppedStatus.state !== "stopped") {
|
|
1843
|
+
await stopServiceWithSc();
|
|
1844
|
+
stoppedStatus = await waitForServiceState(["stopped", "not-installed"]);
|
|
1845
|
+
}
|
|
1846
|
+
if (!stoppedStatus.installed) {
|
|
1847
|
+
return stoppedStatus;
|
|
1848
|
+
}
|
|
1849
|
+
}
|
|
1788
1850
|
const service = createService();
|
|
1789
|
-
await waitForEvent(
|
|
1790
|
-
service,
|
|
1791
|
-
() => service.uninstall(),
|
|
1792
|
-
["uninstall", "alreadyuninstalled"],
|
|
1793
|
-
["error"],
|
|
1794
|
-
() => void 0
|
|
1795
|
-
);
|
|
1851
|
+
await waitForEvent(service, () => service.uninstall(), ["uninstall", "alreadyuninstalled"], ["error"], () => void 0);
|
|
1796
1852
|
let finalStatus = await waitForServiceDeletion();
|
|
1797
1853
|
if (!finalStatus.installed) {
|
|
1798
1854
|
return finalStatus;
|
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()\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\nconst SERVICE_DELETE_TIMEOUT_MS = 15000\nconst SERVICE_DELETE_POLL_INTERVAL_MS = 500\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 sleep(ms: number): Promise<void> {\n return new Promise((resolve) => {\n setTimeout(resolve, ms)\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\nasync function queryService(): Promise<{ installed: boolean; rawState?: string }> {\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 return {\n installed: true,\n rawState: match?.[1],\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 }\n }\n\n throw err\n }\n}\n\nasync function deleteServiceWithSc(): Promise<void> {\n try {\n await execFileAsync('sc.exe', ['delete', SERVICE_SYSTEM_NAME], {\n windowsHide: true,\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\n }\n\n throw err\n }\n}\n\nasync function waitForServiceDeletion(timeoutMs = SERVICE_DELETE_TIMEOUT_MS): Promise<ServiceStatus> {\n const deadline = Date.now() + timeoutMs\n\n while (true) {\n const query = await queryService()\n if (!query.installed) {\n return { installed: false, state: 'not-installed' }\n }\n\n if (Date.now() >= deadline) {\n return {\n installed: true,\n state: normalizeState(query.rawState),\n rawState: query.rawState,\n }\n }\n\n await sleep(SERVICE_DELETE_POLL_INTERVAL_MS)\n }\n}\n\nexport async function getServiceStatus(): Promise<ServiceStatus> {\n ensureWindows()\n\n const query = await queryService()\n if (!query.installed) {\n return { installed: false, state: 'not-installed' }\n }\n\n return {\n installed: true,\n state: normalizeState(query.rawState),\n rawState: query.rawState,\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 let finalStatus = await waitForServiceDeletion()\n if (!finalStatus.installed) {\n return finalStatus\n }\n\n await deleteServiceWithSc()\n finalStatus = await waitForServiceDeletion()\n return finalStatus\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\nconst SERVICE_DELETE_TIMEOUT_MS = 15000\nconst SERVICE_DELETE_POLL_INTERVAL_MS = 500\n\ntype ServiceQueryResult = {\n installed: boolean\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 muteConsole(): () => void {\n const originalConsole = {\n log: console.log,\n info: console.info,\n warn: console.warn,\n debug: console.debug,\n }\n\n console.log = () => {}\n console.info = () => {}\n console.warn = () => {}\n console.debug = () => {}\n\n return () => {\n console.log = originalConsole.log\n console.info = originalConsole.info\n console.warn = originalConsole.warn\n console.debug = originalConsole.debug\n }\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => {\n setTimeout(resolve, ms)\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 const restoreConsole = muteConsole()\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 restoreConsole()\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\nasync function queryService(): Promise<ServiceQueryResult> {\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 return {\n installed: true,\n rawState: match?.[1],\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 }\n }\n\n throw err\n }\n}\n\nasync function stopServiceWithSc(): Promise<void> {\n try {\n await execFileAsync('sc.exe', ['stop', SERVICE_SYSTEM_NAME], {\n windowsHide: true,\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 (\n code === 1060 ||\n stdout.includes('1060') ||\n stderr.includes('1060') ||\n message.includes('does not exist') ||\n stdout.includes('1062') ||\n stderr.includes('1062') ||\n message.includes('has not been started')\n ) {\n return\n }\n\n throw err\n }\n}\n\nasync function waitForServiceState(\n expectedStates: ServiceState[],\n timeoutMs = SERVICE_DELETE_TIMEOUT_MS,\n): Promise<ServiceStatus> {\n const deadline = Date.now() + timeoutMs\n\n while (true) {\n const query = await queryService()\n const status = query.installed\n ? {\n installed: true,\n state: normalizeState(query.rawState),\n rawState: query.rawState,\n }\n : {\n installed: false,\n state: 'not-installed' as const,\n }\n\n if (expectedStates.includes(status.state)) {\n return status\n }\n\n if (Date.now() >= deadline) {\n return status\n }\n\n await sleep(SERVICE_DELETE_POLL_INTERVAL_MS)\n }\n}\n\nasync function deleteServiceWithSc(): Promise<void> {\n try {\n await execFileAsync('sc.exe', ['delete', SERVICE_SYSTEM_NAME], {\n windowsHide: true,\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\n }\n\n throw err\n }\n}\n\nasync function waitForServiceDeletion(timeoutMs = SERVICE_DELETE_TIMEOUT_MS): Promise<ServiceStatus> {\n const deadline = Date.now() + timeoutMs\n\n while (true) {\n const query = await queryService()\n if (!query.installed) {\n return { installed: false, state: 'not-installed' }\n }\n\n if (Date.now() >= deadline) {\n return {\n installed: true,\n state: normalizeState(query.rawState),\n rawState: query.rawState,\n }\n }\n\n await sleep(SERVICE_DELETE_POLL_INTERVAL_MS)\n }\n}\n\nexport async function getServiceStatus(): Promise<ServiceStatus> {\n ensureWindows()\n\n const query = await queryService()\n if (!query.installed) {\n return { installed: false, state: 'not-installed' }\n }\n\n return {\n installed: true,\n state: normalizeState(query.rawState),\n rawState: query.rawState,\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 if (status.state !== 'stopped') {\n await stopService()\n let stoppedStatus = await waitForServiceState(['stopped', 'not-installed'])\n\n if (stoppedStatus.installed && stoppedStatus.state !== 'stopped') {\n await stopServiceWithSc()\n stoppedStatus = await waitForServiceState(['stopped', 'not-installed'])\n }\n\n if (!stoppedStatus.installed) {\n return stoppedStatus\n }\n }\n\n const service = createService()\n await waitForEvent(service, () => service.uninstall(), ['uninstall', 'alreadyuninstalled'], ['error'], () => undefined)\n\n let finalStatus = await waitForServiceDeletion()\n if (!finalStatus.installed) {\n return finalStatus\n }\n\n await deleteServiceWithSc()\n finalStatus = await waitForServiceDeletion()\n return finalStatus\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"]}
|