reasonix 0.52.0 → 0.53.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/README.zh-CN.md +1 -0
- package/dashboard/dist/app.css +1 -1
- package/dashboard/dist/app.js +13 -13
- package/dashboard/dist/app.js.map +1 -1
- package/dist/cli/{acp-NEUYWGUU.js → acp-ABNDGEYC.js} +63 -30
- package/dist/cli/acp-ABNDGEYC.js.map +1 -0
- package/dist/cli/chat-377YZV56.js +49 -0
- package/dist/cli/{chunk-FY5UERSG.js → chunk-2WZT27GR.js} +9 -9
- package/dist/cli/{chunk-B4MOGWHW.js → chunk-4EHRIP5U.js} +7 -7
- package/dist/cli/chunk-4EHRIP5U.js.map +1 -0
- package/dist/cli/{chunk-RCC73DWQ.js → chunk-4SBXAHR6.js} +4 -4
- package/dist/cli/{chunk-5YLEKX2V.js → chunk-4V4TKQMB.js} +4 -4
- package/dist/cli/{chunk-5YLEKX2V.js.map → chunk-4V4TKQMB.js.map} +1 -1
- package/dist/cli/chunk-7ZO6H6ZK.js +54 -0
- package/dist/cli/chunk-7ZO6H6ZK.js.map +1 -0
- package/dist/cli/{chunk-3OXD5CBM.js → chunk-A6GSOADP.js} +17870 -16070
- package/dist/cli/chunk-A6GSOADP.js.map +1 -0
- package/dist/cli/{chunk-Z663GVUB.js → chunk-APOSDBAU.js} +3 -3
- package/dist/cli/{chunk-CTRM32BP.js → chunk-B5JISV5I.js} +2 -2
- package/dist/cli/{chunk-HNZ4727T.js → chunk-DFHI2MRB.js} +412 -152
- package/dist/cli/chunk-DFHI2MRB.js.map +1 -0
- package/dist/cli/{chunk-CGVW5W7N.js → chunk-EPIHGOM3.js} +14 -14
- package/dist/cli/{chunk-CGVW5W7N.js.map → chunk-EPIHGOM3.js.map} +1 -1
- package/dist/cli/{chunk-77JIQ7SL.js → chunk-EQFZIHKJ.js} +8 -8
- package/dist/cli/chunk-EQFZIHKJ.js.map +1 -0
- package/dist/cli/{chunk-XNMXVL6C.js → chunk-FB27YXPX.js} +2 -2
- package/dist/cli/{chunk-ARBGTNHM.js → chunk-FK7NXDRP.js} +2 -2
- package/dist/cli/{chunk-AOYUW3HR.js → chunk-GCNBIWK7.js} +22 -2
- package/dist/cli/chunk-GCNBIWK7.js.map +1 -0
- package/dist/cli/{chunk-XBYHNZ5Z.js → chunk-GMQVINZK.js} +13 -5
- package/dist/cli/chunk-GMQVINZK.js.map +1 -0
- package/dist/cli/{chunk-MVLPXZAA.js → chunk-GOASYYZ4.js} +43 -11
- package/dist/cli/{chunk-MVLPXZAA.js.map → chunk-GOASYYZ4.js.map} +1 -1
- package/dist/cli/{chunk-WPY7AFS6.js → chunk-I4SH5Z7S.js} +2 -2
- package/dist/cli/{chunk-MW64SQUE.js → chunk-J26XOB2T.js} +2 -2
- package/dist/cli/{chunk-DLTE4GBY.js → chunk-J4MYMBJ7.js} +3 -3
- package/dist/cli/{chunk-CFJY64UA.js → chunk-LRO63VNK.js} +2 -2
- package/dist/cli/{chunk-XUZHBQSM.js → chunk-MQJR7YQ2.js} +2 -2
- package/dist/cli/{chunk-CPCUMMSR.js → chunk-NVI4XPOQ.js} +3 -3
- package/dist/cli/{chunk-RHQOGG43.js → chunk-OHSVEXFF.js} +3 -3
- package/dist/cli/chunk-OHSVEXFF.js.map +1 -0
- package/dist/cli/{chunk-AMSK3ZLB.js → chunk-P5SUHDUQ.js} +2 -2
- package/dist/cli/{chunk-GFJJEW3Z.js → chunk-QSKDP3OS.js} +55 -5
- package/dist/cli/chunk-QSKDP3OS.js.map +1 -0
- package/dist/cli/{chunk-D6WRFR6V.js → chunk-R7JMQMLD.js} +6 -5
- package/dist/cli/chunk-R7JMQMLD.js.map +1 -0
- package/dist/cli/{chunk-VVPV5HU6.js → chunk-RRZIIMAF.js} +2 -2
- package/dist/cli/{chunk-GNRKXRRE.js → chunk-S3QII236.js} +369 -359
- package/dist/cli/{chunk-GNRKXRRE.js.map → chunk-S3QII236.js.map} +1 -1
- package/dist/cli/{chunk-HI6THNAZ.js → chunk-TGP7JGHN.js} +32 -14
- package/dist/cli/chunk-TGP7JGHN.js.map +1 -0
- package/dist/cli/{chunk-CLHMV6OL.js → chunk-U7G72DHQ.js} +83 -42
- package/dist/cli/chunk-U7G72DHQ.js.map +1 -0
- package/dist/cli/{chunk-OMNRXZNA.js → chunk-URAI4YRL.js} +2 -2
- package/dist/cli/{chunk-6QBUXA73.js → chunk-V4AXMN4X.js} +2 -2
- package/dist/cli/{chunk-2W4F3RIZ.js → chunk-XHP6NYOT.js} +3 -2
- package/dist/cli/{chunk-2W4F3RIZ.js.map → chunk-XHP6NYOT.js.map} +1 -1
- package/dist/cli/{code-WN6D4VZO.js → code-JPFZJYVW.js} +34 -34
- package/dist/cli/{commands-DHETOY7O.js → commands-IUL2CLKH.js} +4 -4
- package/dist/cli/{commit-BBUYAKZV.js → commit-JT7LYBTL.js} +3 -3
- package/dist/cli/{config-KV7VV5LG.js → config-T4RWI5NG.js} +6 -2
- package/dist/cli/{desktop-LJVXWXNF.js → desktop-AUBW2SLL.js} +122 -38
- package/dist/cli/desktop-AUBW2SLL.js.map +1 -0
- package/dist/cli/devtools-O5HOMAGZ.js +3 -0
- package/dist/cli/diff-NINZHUJR.js +165 -0
- package/dist/cli/diff-NINZHUJR.js.map +1 -0
- package/dist/cli/{doctor-GI5LOEZL.js → doctor-OMAYGY4F.js} +10 -10
- package/dist/cli/{events-LBKMLFM4.js → events-5IVFJ4H3.js} +5 -5
- package/dist/cli/index.js +38 -38
- package/dist/cli/{mcp-DKEJK5ND.js → mcp-ECGJACAP.js} +3 -3
- package/dist/cli/{mcp-browse-V7KWDY32.js → mcp-browse-NGEOHVJB.js} +15 -15
- package/dist/cli/mcp-browse-NGEOHVJB.js.map +1 -0
- package/dist/cli/{mcp-inspect-MTABNHVM.js → mcp-inspect-ZIMNRG7G.js} +5 -5
- package/dist/cli/{prompt-ATI7DKHF.js → prompt-JCC3A7AA.js} +5 -5
- package/dist/cli/{prune-sessions-YQQSZTZS.js → prune-sessions-TE4BJYO2.js} +4 -4
- package/dist/cli/{replay-ZJQ4I4CJ.js → replay-2UUTCRTG.js} +29 -29
- package/dist/cli/replay-2UUTCRTG.js.map +1 -0
- package/dist/cli/{run-HFPRNWJY.js → run-ABQYOPVM.js} +22 -22
- package/dist/cli/{server-UHKO2VVM.js → server-MPCXIW2O.js} +27 -25
- package/dist/cli/{server-UHKO2VVM.js.map → server-MPCXIW2O.js.map} +1 -1
- package/dist/cli/{sessions-IQEWWUH3.js → sessions-YBPRGIAF.js} +16 -16
- package/dist/cli/{setup-5BYKCL62.js → setup-A34LF2QE.js} +42 -42
- package/dist/cli/setup-A34LF2QE.js.map +1 -0
- package/dist/cli/{stats-OFCGOQMZ.js → stats-GKG5JZQX.js} +6 -6
- package/dist/cli/stats-GKG5JZQX.js.map +1 -0
- package/dist/cli/{version-EODUFAAI.js → version-JD6QSM4X.js} +16 -16
- package/dist/index.d.ts +36 -5
- package/dist/index.js +443 -73
- package/dist/index.js.map +1 -1
- package/package.json +7 -2
- package/dist/cli/acp-NEUYWGUU.js.map +0 -1
- package/dist/cli/chat-QA6IVFJD.js +0 -49
- package/dist/cli/chunk-3OXD5CBM.js.map +0 -1
- package/dist/cli/chunk-77JIQ7SL.js.map +0 -1
- package/dist/cli/chunk-AOYUW3HR.js.map +0 -1
- package/dist/cli/chunk-B4MOGWHW.js.map +0 -1
- package/dist/cli/chunk-CLHMV6OL.js.map +0 -1
- package/dist/cli/chunk-D6WRFR6V.js.map +0 -1
- package/dist/cli/chunk-GFJJEW3Z.js.map +0 -1
- package/dist/cli/chunk-HI6THNAZ.js.map +0 -1
- package/dist/cli/chunk-HNZ4727T.js.map +0 -1
- package/dist/cli/chunk-I3NE5S63.js +0 -54
- package/dist/cli/chunk-I3NE5S63.js.map +0 -1
- package/dist/cli/chunk-RHQOGG43.js.map +0 -1
- package/dist/cli/chunk-XBYHNZ5Z.js.map +0 -1
- package/dist/cli/desktop-LJVXWXNF.js.map +0 -1
- package/dist/cli/diff-2JHMQAHI.js +0 -165
- package/dist/cli/diff-2JHMQAHI.js.map +0 -1
- package/dist/cli/mcp-browse-V7KWDY32.js.map +0 -1
- package/dist/cli/replay-ZJQ4I4CJ.js.map +0 -1
- package/dist/cli/setup-5BYKCL62.js.map +0 -1
- /package/dist/cli/{chat-QA6IVFJD.js.map → chat-377YZV56.js.map} +0 -0
- /package/dist/cli/{chunk-FY5UERSG.js.map → chunk-2WZT27GR.js.map} +0 -0
- /package/dist/cli/{chunk-RCC73DWQ.js.map → chunk-4SBXAHR6.js.map} +0 -0
- /package/dist/cli/{chunk-Z663GVUB.js.map → chunk-APOSDBAU.js.map} +0 -0
- /package/dist/cli/{chunk-CTRM32BP.js.map → chunk-B5JISV5I.js.map} +0 -0
- /package/dist/cli/{chunk-XNMXVL6C.js.map → chunk-FB27YXPX.js.map} +0 -0
- /package/dist/cli/{chunk-ARBGTNHM.js.map → chunk-FK7NXDRP.js.map} +0 -0
- /package/dist/cli/{chunk-WPY7AFS6.js.map → chunk-I4SH5Z7S.js.map} +0 -0
- /package/dist/cli/{chunk-MW64SQUE.js.map → chunk-J26XOB2T.js.map} +0 -0
- /package/dist/cli/{chunk-DLTE4GBY.js.map → chunk-J4MYMBJ7.js.map} +0 -0
- /package/dist/cli/{chunk-CFJY64UA.js.map → chunk-LRO63VNK.js.map} +0 -0
- /package/dist/cli/{chunk-XUZHBQSM.js.map → chunk-MQJR7YQ2.js.map} +0 -0
- /package/dist/cli/{chunk-CPCUMMSR.js.map → chunk-NVI4XPOQ.js.map} +0 -0
- /package/dist/cli/{chunk-AMSK3ZLB.js.map → chunk-P5SUHDUQ.js.map} +0 -0
- /package/dist/cli/{chunk-VVPV5HU6.js.map → chunk-RRZIIMAF.js.map} +0 -0
- /package/dist/cli/{chunk-OMNRXZNA.js.map → chunk-URAI4YRL.js.map} +0 -0
- /package/dist/cli/{chunk-6QBUXA73.js.map → chunk-V4AXMN4X.js.map} +0 -0
- /package/dist/cli/{code-WN6D4VZO.js.map → code-JPFZJYVW.js.map} +0 -0
- /package/dist/cli/{commands-DHETOY7O.js.map → commands-IUL2CLKH.js.map} +0 -0
- /package/dist/cli/{commit-BBUYAKZV.js.map → commit-JT7LYBTL.js.map} +0 -0
- /package/dist/cli/{config-KV7VV5LG.js.map → config-T4RWI5NG.js.map} +0 -0
- /package/dist/cli/{doctor-GI5LOEZL.js.map → devtools-O5HOMAGZ.js.map} +0 -0
- /package/dist/cli/{prompt-ATI7DKHF.js.map → doctor-OMAYGY4F.js.map} +0 -0
- /package/dist/cli/{events-LBKMLFM4.js.map → events-5IVFJ4H3.js.map} +0 -0
- /package/dist/cli/{mcp-DKEJK5ND.js.map → mcp-ECGJACAP.js.map} +0 -0
- /package/dist/cli/{mcp-inspect-MTABNHVM.js.map → mcp-inspect-ZIMNRG7G.js.map} +0 -0
- /package/dist/cli/{stats-OFCGOQMZ.js.map → prompt-JCC3A7AA.js.map} +0 -0
- /package/dist/cli/{prune-sessions-YQQSZTZS.js.map → prune-sessions-TE4BJYO2.js.map} +0 -0
- /package/dist/cli/{run-HFPRNWJY.js.map → run-ABQYOPVM.js.map} +0 -0
- /package/dist/cli/{sessions-IQEWWUH3.js.map → sessions-YBPRGIAF.js.map} +0 -0
- /package/dist/cli/{version-EODUFAAI.js.map → version-JD6QSM4X.js.map} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/transcript/log.ts","../../src/transcript/replay.ts"],"sourcesContent":["/** Transcripts are receipts (cost/usage/prefix); sessions are memory (ChatMessages). Don't conflate. */\n\nimport { type WriteStream, createWriteStream, readFileSync } from \"node:fs\";\nimport type { LoopEvent } from \"../loop.js\";\nimport type { RawUsage } from \"../types.js\";\n\nexport interface TranscriptRecord {\n /** ISO-8601 timestamp at emit time. */\n ts: string;\n /** 1-based turn number within the session. */\n turn: number;\n /** LoopEvent role — \"assistant_delta\" | \"assistant_final\" | \"tool\" | \"done\" | ... */\n role: string;\n /** For assistant events, the final (or delta) text; for tool events, the tool result. */\n content: string;\n /** Tool name (role === \"tool\"). */\n tool?: string;\n /** JSON-string args the model sent for a tool call (role === \"tool\"). Persisted so diff can explain *why* two runs made different calls. */\n args?: string;\n /** DeepSeek token-usage snapshot (role === \"assistant_final\"). */\n usage?: RawUsage;\n /** USD cost of this turn (role === \"assistant_final\"). */\n cost?: number;\n /** Model id that produced this turn. */\n model?: string;\n /** Lets diff attribute cache-hit delta to log stability vs prompt change. */\n prefixHash?: string;\n /** Optional error message (role === \"error\"). */\n error?: string;\n}\n\nexport interface TranscriptMeta {\n version: 1;\n source: string; // e.g. \"reasonix chat\", \"bench/baseline\", \"bench/reasonix\"\n model?: string;\n task?: string;\n mode?: string;\n repeat?: number;\n startedAt: string;\n}\n\ninterface MetaLine {\n role: \"_meta\";\n meta: TranscriptMeta;\n}\n\nexport interface ReadTranscriptResult {\n meta: TranscriptMeta | null;\n records: TranscriptRecord[];\n}\n\nexport function recordFromLoopEvent(\n ev: LoopEvent,\n extra: { model: string; prefixHash: string },\n): TranscriptRecord {\n const rec: TranscriptRecord = {\n ts: new Date().toISOString(),\n turn: ev.turn,\n role: ev.role,\n content: ev.content,\n };\n if (ev.toolName !== undefined) rec.tool = ev.toolName;\n if (ev.toolArgs !== undefined) rec.args = ev.toolArgs;\n if (ev.error !== undefined) rec.error = ev.error;\n if (ev.stats) {\n rec.usage = {\n prompt_tokens: ev.stats.usage.promptTokens,\n completion_tokens: ev.stats.usage.completionTokens,\n total_tokens: ev.stats.usage.totalTokens,\n prompt_cache_hit_tokens: ev.stats.usage.promptCacheHitTokens,\n prompt_cache_miss_tokens: ev.stats.usage.promptCacheMissTokens,\n };\n rec.cost = ev.stats.cost;\n rec.model = ev.stats.model;\n rec.prefixHash = extra.prefixHash;\n } else if (ev.role === \"assistant_final\") {\n // assistant_final without stats (shouldn't happen in the live loop but\n // might in test fixtures) — still persist model + prefix for continuity.\n rec.model = extra.model;\n rec.prefixHash = extra.prefixHash;\n }\n return rec;\n}\n\n/**\n * Append a record to an open write stream. Caller owns the stream lifecycle.\n */\nexport function writeRecord(stream: WriteStream, record: TranscriptRecord): void {\n stream.write(`${JSON.stringify(record)}\\n`);\n}\n\n/**\n * Write a _meta line to an open write stream. Call exactly once, at the top.\n */\nexport function writeMeta(stream: WriteStream, meta: TranscriptMeta): void {\n const line: MetaLine = { role: \"_meta\", meta };\n stream.write(`${JSON.stringify(line)}\\n`);\n}\n\n/**\n * Convenience: open a stream, write meta, return stream.\n */\nexport function openTranscriptFile(path: string, meta: TranscriptMeta): WriteStream {\n const stream = createWriteStream(path, { flags: \"a\" });\n writeMeta(stream, meta);\n return stream;\n}\n\n/** Tolerant: empty / malformed lines skipped, missing optionals OK — live chats may be mid-write. */\nexport function readTranscript(path: string): ReadTranscriptResult {\n const raw = readFileSync(path, \"utf8\");\n return parseTranscript(raw);\n}\n\nexport function parseTranscript(raw: string): ReadTranscriptResult {\n const out: ReadTranscriptResult = { meta: null, records: [] };\n for (const line of raw.split(/\\r?\\n/)) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n let obj: unknown;\n try {\n obj = JSON.parse(trimmed);\n } catch {\n continue;\n }\n if (!obj || typeof obj !== \"object\") continue;\n const rec = obj as Record<string, unknown>;\n if (rec.role === \"_meta\" && rec.meta && typeof rec.meta === \"object\") {\n out.meta = rec.meta as TranscriptMeta;\n continue;\n }\n if (\n typeof rec.ts === \"string\" &&\n typeof rec.turn === \"number\" &&\n typeof rec.role === \"string\" &&\n typeof rec.content === \"string\"\n ) {\n out.records.push(rec as unknown as TranscriptRecord);\n }\n }\n return out;\n}\n","/** Reconstruct session economics from a transcript alone — offline audit, no API key. */\n\nimport { Usage } from \"../client.js\";\nimport {\n type SessionSummary,\n type TurnStats,\n claudeEquivalentCost,\n costUsd,\n inputCostUsd,\n outputCostUsd,\n} from \"../telemetry/stats.js\";\nimport { type ReadTranscriptResult, type TranscriptRecord, readTranscript } from \"./log.js\";\n\nexport interface TurnPage {\n turn: number;\n records: TranscriptRecord[];\n}\n\nexport function groupRecordsByTurn(records: TranscriptRecord[]): TurnPage[] {\n const byTurn = new Map<number, TranscriptRecord[]>();\n for (const rec of records) {\n const list = byTurn.get(rec.turn);\n if (list) list.push(rec);\n else byTurn.set(rec.turn, [rec]);\n }\n return [...byTurn.entries()]\n .sort(([a], [b]) => a - b)\n .map(([turn, records]) => ({ turn, records }));\n}\n\nexport function computeCumulativeStats(pages: TurnPage[], upToIdx: number): ReplayStats {\n if (upToIdx < 0) return computeReplayStats([]);\n const flat: TranscriptRecord[] = [];\n for (let i = 0; i <= upToIdx && i < pages.length; i++) {\n const records = pages[i]?.records;\n if (records) flat.push(...records);\n }\n return computeReplayStats(flat);\n}\n\nexport interface ReplayStats extends SessionSummary {\n /** Per-turn stats, in turn order. Only assistant_final records contribute. */\n perTurn: TurnStats[];\n /** Unique models that appeared in the transcript's assistant_final records. */\n models: string[];\n /** Unique prefix hashes that appeared. Length > 1 means the prefix churned (cache-hostile). */\n prefixHashes: string[];\n /** Count of user-role records (user turns issued). */\n userTurns: number;\n /** Count of tool-role records (tool calls executed). */\n toolCalls: number;\n}\n\nexport function replayFromFile(path: string): { parsed: ReadTranscriptResult; stats: ReplayStats } {\n const parsed = readTranscript(path);\n return { parsed, stats: computeReplayStats(parsed.records) };\n}\n\nexport function computeReplayStats(records: TranscriptRecord[]): ReplayStats {\n const turns: TurnStats[] = [];\n const models = new Set<string>();\n const prefixHashes = new Set<string>();\n let userTurns = 0;\n let toolCalls = 0;\n\n for (const rec of records) {\n if (rec.role === \"user\") userTurns++;\n else if (rec.role === \"tool\") toolCalls++;\n else if (rec.role === \"assistant_final\") {\n if (rec.model) models.add(rec.model);\n if (rec.prefixHash) prefixHashes.add(rec.prefixHash);\n if (rec.usage && rec.model) {\n const u = new Usage(\n rec.usage.prompt_tokens ?? 0,\n rec.usage.completion_tokens ?? 0,\n rec.usage.total_tokens ?? 0,\n rec.usage.prompt_cache_hit_tokens ?? 0,\n rec.usage.prompt_cache_miss_tokens ?? 0,\n );\n turns.push({\n turn: rec.turn,\n model: rec.model,\n usage: u,\n // `rec.cost` wins when present — honors whatever the writer computed\n // even if pricing tables have since changed. Only recompute when\n // the transcript didn't record it (old format).\n cost: rec.cost ?? costUsd(rec.model, u),\n cacheHitRatio: u.cacheHitRatio,\n });\n }\n }\n }\n\n return {\n perTurn: turns,\n models: [...models],\n prefixHashes: [...prefixHashes],\n userTurns,\n toolCalls,\n ...summarizeTurns(turns),\n };\n}\n\nfunction summarizeTurns(turns: TurnStats[]): SessionSummary {\n const totalCost = turns.reduce((s, t) => s + t.cost, 0);\n const totalInput = turns.reduce((s, t) => s + inputCostUsd(t.model, t.usage), 0);\n const totalOutput = turns.reduce((s, t) => s + outputCostUsd(t.model, t.usage), 0);\n const totalClaude = turns.reduce((s, t) => s + claudeEquivalentCost(t.usage), 0);\n let hit = 0;\n let miss = 0;\n for (const t of turns) {\n hit += t.usage.promptCacheHitTokens;\n miss += t.usage.promptCacheMissTokens;\n }\n const cacheHitRatio = hit + miss > 0 ? hit / (hit + miss) : 0;\n const savingsVsClaude = totalClaude > 0 ? 1 - totalCost / totalClaude : 0;\n const lastTurn = turns[turns.length - 1];\n return {\n turns: turns.length,\n totalCostUsd: round(totalCost, 6),\n totalInputCostUsd: round(totalInput, 6),\n totalOutputCostUsd: round(totalOutput, 6),\n claudeEquivalentUsd: round(totalClaude, 6),\n savingsVsClaudePct: round(savingsVsClaude * 100, 2),\n cacheHitRatio: round(cacheHitRatio, 4),\n lastPromptTokens: lastTurn?.usage.promptTokens ?? 0,\n lastTurnCostUsd: round(lastTurn?.cost ?? 0, 6),\n };\n}\n\nfunction round(n: number, digits: number): number {\n const f = 10 ** digits;\n return Math.round(n * f) / f;\n}\n"],"mappings":"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","names":["records"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/retry.ts","../../src/client.ts"],"sourcesContent":["/** No retry on aborts or mid-stream body errors — re-billing the user for desynced output is worse than failing. */\n\nexport interface RetryOptions {\n /** Maximum total attempts (including the first). Default 4. */\n maxAttempts?: number;\n /** Initial backoff in ms. Doubles each retry, with jitter. Default 500. */\n initialBackoffMs?: number;\n /** Upper bound on any single backoff delay. Default 10000 (10s). */\n maxBackoffMs?: number;\n /** HTTP statuses to treat as retryable. Default [408, 429, 500, 502, 503, 504]. */\n retryableStatuses?: readonly number[];\n /** Abort signal; we do NOT retry once aborted. */\n signal?: AbortSignal;\n /** Telemetry hook — called before each wait. */\n onRetry?: (info: RetryInfo) => void;\n}\n\nexport interface RetryInfo {\n attempt: number;\n reason: string;\n waitMs: number;\n}\n\nconst DEFAULT_RETRYABLE_STATUSES = [408, 429, 500, 502, 503, 504] as const;\n\nexport async function fetchWithRetry(\n fetchFn: typeof fetch,\n url: string,\n init: RequestInit,\n opts: RetryOptions = {},\n): Promise<Response> {\n const maxAttempts = opts.maxAttempts ?? 4;\n const initial = opts.initialBackoffMs ?? 500;\n const cap = opts.maxBackoffMs ?? 10_000;\n const retryable = new Set(opts.retryableStatuses ?? DEFAULT_RETRYABLE_STATUSES);\n\n let lastError: unknown;\n\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n if (opts.signal?.aborted) throw new Error(\"aborted\");\n\n try {\n const resp = await fetchFn(url, init);\n\n // Success or non-retryable failure: return as-is.\n if (resp.ok || !retryable.has(resp.status)) return resp;\n\n // Retryable but out of attempts: return the last response so the caller\n // can surface the status to the user.\n if (attempt === maxAttempts - 1) return resp;\n\n // Drain the body so the connection can be reused on the next attempt.\n await resp.text().catch(() => undefined);\n\n const waitMs = computeWait(attempt, initial, cap, resp.headers.get(\"Retry-After\"));\n opts.onRetry?.({ attempt: attempt + 1, reason: `http ${resp.status}`, waitMs });\n await sleep(waitMs, opts.signal);\n } catch (err) {\n lastError = err;\n // Respect explicit aborts — do not retry.\n if (isAbortError(err) || opts.signal?.aborted) throw err;\n if (attempt === maxAttempts - 1) throw err;\n\n const waitMs = computeWait(attempt, initial, cap, null);\n opts.onRetry?.({\n attempt: attempt + 1,\n reason: `network: ${messageOf(err)}`,\n waitMs,\n });\n await sleep(waitMs, opts.signal);\n }\n }\n\n throw lastError ?? new Error(\"fetchWithRetry: loop exited unexpectedly\");\n}\n\nfunction computeWait(\n attempt: number,\n initial: number,\n cap: number,\n retryAfter: string | null,\n): number {\n if (retryAfter) {\n const seconds = Number.parseFloat(retryAfter);\n if (Number.isFinite(seconds) && seconds > 0) {\n return Math.min(seconds * 1000, cap);\n }\n }\n const exp = initial * 2 ** attempt;\n // Jitter range [75%, 125%] to spread retries out when many clients hit 429 together.\n const jitter = exp * (0.75 + Math.random() * 0.5);\n return Math.min(Math.max(jitter, 0), cap);\n}\n\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n if (ms <= 0) return Promise.resolve();\n return new Promise((resolve, reject) => {\n const timer = setTimeout(resolve, ms);\n if (signal) {\n const onAbort = () => {\n clearTimeout(timer);\n reject(new Error(\"aborted\"));\n };\n if (signal.aborted) onAbort();\n else signal.addEventListener(\"abort\", onAbort, { once: true });\n }\n });\n}\n\nfunction isAbortError(err: unknown): boolean {\n if (!err || typeof err !== \"object\") return false;\n const name = (err as { name?: unknown }).name;\n return name === \"AbortError\";\n}\n\nfunction messageOf(err: unknown): string {\n if (err instanceof Error) return err.message;\n try {\n return String(err);\n } catch {\n return \"unknown error\";\n }\n}\n","import { type EventSourceMessage, createParser } from \"eventsource-parser\";\nimport { loadRateLimit, resolveBaseUrlEnv } from \"./config.js\";\nimport { type RetryOptions, fetchWithRetry } from \"./retry.js\";\nimport type { ChatMessage, ChatRequestOptions, RawUsage, ToolCall, ToolSpec } from \"./types.js\";\n\nexport class Usage {\n constructor(\n public promptTokens = 0,\n public completionTokens = 0,\n public totalTokens = 0,\n public promptCacheHitTokens = 0,\n public promptCacheMissTokens = 0,\n ) {}\n\n get cacheHitRatio(): number {\n const denom = this.promptCacheHitTokens + this.promptCacheMissTokens;\n return denom > 0 ? this.promptCacheHitTokens / denom : 0;\n }\n\n static hasApiUsage(raw: unknown): raw is RawUsage {\n if (!raw || typeof raw !== \"object\") return false;\n const u = raw as RawUsage;\n return (\n typeof u.prompt_tokens === \"number\" ||\n typeof u.completion_tokens === \"number\" ||\n typeof u.total_tokens === \"number\" ||\n typeof u.prompt_cache_hit_tokens === \"number\" ||\n typeof u.prompt_cache_miss_tokens === \"number\" ||\n typeof u.prompt_eval_count === \"number\" ||\n typeof u.eval_count === \"number\"\n );\n }\n\n static fromApi(raw: RawUsage | undefined | null): Usage {\n const u = raw ?? {};\n const promptTokens = u.prompt_tokens ?? u.prompt_eval_count ?? 0;\n const completionTokens = u.completion_tokens ?? u.eval_count ?? 0;\n const cacheHitTokens = u.prompt_cache_hit_tokens ?? 0;\n const cacheMissTokens =\n u.prompt_cache_miss_tokens ?? Math.max(0, promptTokens - cacheHitTokens);\n return new Usage(\n promptTokens,\n completionTokens,\n u.total_tokens ?? promptTokens + completionTokens,\n cacheHitTokens,\n cacheMissTokens,\n );\n }\n}\n\nexport interface ChatResponse {\n content: string;\n reasoningContent: string | null;\n toolCalls: ToolCall[];\n usage: Usage;\n raw: unknown;\n}\n\nexport interface StreamChunk {\n contentDelta?: string;\n reasoningDelta?: string;\n toolCallDelta?: { index: number; id?: string; name?: string; argumentsDelta?: string };\n usage?: Usage;\n finishReason?: string;\n raw: any;\n}\n\nexport interface BalanceInfo {\n currency: string;\n total_balance: string;\n granted_balance?: string;\n topped_up_balance?: string;\n}\n\nexport interface UserBalance {\n is_available: boolean;\n balance_infos: BalanceInfo[];\n}\n\n/** Largest `total_balance` wins — the wallet the user actually paid for and expects to see ticking down. */\nexport function pickPrimaryBalance(infos: ReadonlyArray<BalanceInfo>): BalanceInfo | null {\n if (infos.length === 0) return null;\n let best = infos[0]!;\n for (let i = 1; i < infos.length; i++) {\n if (Number(infos[i]!.total_balance) > Number(best.total_balance)) best = infos[i]!;\n }\n return best;\n}\n\nexport interface ModelInfo {\n id: string;\n object: \"model\";\n owned_by: string;\n}\n\nexport interface ModelList {\n object: \"list\";\n data: ModelInfo[];\n}\n\nexport interface DeepSeekClientOptions {\n apiKey?: string;\n baseUrl?: string;\n timeoutMs?: number;\n fetch?: typeof fetch;\n rateLimit?: { rpm?: number };\n /** Retry configuration. Pass `{ maxAttempts: 1 }` to disable retries. */\n retry?: RetryOptions;\n}\n\nexport class DeepSeekClient {\n readonly apiKey: string;\n readonly baseUrl: string;\n readonly timeoutMs: number;\n readonly retry: RetryOptions;\n private readonly _fetch: typeof fetch;\n private readonly minChatIntervalMs: number;\n private nextChatRequestAt = 0;\n\n constructor(opts: DeepSeekClientOptions = {}) {\n const apiKey = opts.apiKey ?? process.env.DEEPSEEK_API_KEY;\n if (!apiKey) {\n throw new Error(\n \"DEEPSEEK_API_KEY is not set. Put it in .env or pass apiKey to DeepSeekClient.\",\n );\n }\n this.apiKey = apiKey;\n let url = opts.baseUrl ?? resolveBaseUrlEnv() ?? \"https://api.deepseek.com\";\n // Manual trim — `/\\/+$/` is O(n²) on slash-heavy non-matches per CodeQL js/polynomial-redos.\n while (url.endsWith(\"/\")) url = url.slice(0, -1);\n this.baseUrl = url;\n // 11 min. DeepSeek's load-balancer may keep a connection open for\n // up to 10 minutes while the request waits in queue (non-streaming\n // sends empty lines, streaming sends `:` SSE keep-alive comments —\n // both are invisible to our parsers, so neither surfaces until the\n // real response starts). Timing out at the legacy 2-min default\n // killed queued requests prematurely, burned the queue slot on\n // retry, and could loop through the whole queue repeatedly.\n // Setting 11 min lets the server's own 10-min cap close the\n // connection first (clean EOF → natural retry), and our timer\n // is a safety net for genuinely hung sockets.\n this.timeoutMs = opts.timeoutMs ?? 660_000;\n this._fetch = opts.fetch ?? globalThis.fetch.bind(globalThis);\n this.retry = opts.retry ?? {};\n const rpm = opts.rateLimit?.rpm ?? loadRateLimit()?.rpm;\n this.minChatIntervalMs = rpm ? Math.ceil(60_000 / rpm) : 0;\n }\n\n private async waitForChatRateLimit(signal?: AbortSignal): Promise<void> {\n if (this.minChatIntervalMs <= 0) return;\n const now = Date.now();\n const waitMs = Math.max(0, this.nextChatRequestAt - now);\n this.nextChatRequestAt = Math.max(now, this.nextChatRequestAt) + this.minChatIntervalMs;\n if (waitMs <= 0) return;\n await new Promise<void>((resolve, reject) => {\n const timer = setTimeout(resolve, waitMs);\n signal?.addEventListener(\n \"abort\",\n () => {\n clearTimeout(timer);\n reject(signal.reason ?? new DOMException(\"Aborted\", \"AbortError\"));\n },\n { once: true },\n );\n });\n }\n\n private buildPayload(opts: ChatRequestOptions, stream: boolean) {\n const payload: Record<string, unknown> = {\n model: opts.model,\n messages: opts.messages,\n stream,\n };\n if (opts.tools?.length) payload.tools = opts.tools;\n if (opts.temperature !== undefined) payload.temperature = opts.temperature;\n if (opts.maxTokens !== undefined) payload.max_tokens = opts.maxTokens;\n if (opts.responseFormat) payload.response_format = opts.responseFormat;\n // V4 thinking-mode toggle: lives under `extra_body.thinking.type` per\n // DeepSeek's docs. Docs also note that in thinking mode `temperature`,\n // `top_p`, `presence_penalty`, `frequency_penalty` are silently\n // ignored — we don't strip them here because the server's explicit\n // \"setting won't report an error\" contract means leaving them in is\n // safe and keeps the request payload diffable against OpenAI tooling.\n if (opts.thinking && !this._isAzureEndpoint()) {\n payload.extra_body = { thinking: { type: opts.thinking } };\n }\n if (opts.reasoningEffort) {\n payload.reasoning_effort = opts.reasoningEffort;\n }\n return payload;\n }\n\n /** Azure OpenAI-compatible endpoints do not accept DeepSeek's proprietary\n * `extra_body.thinking` field (they reject the request with 400). We still\n * send `reasoning_effort`, which Azure *does* support. */\n private _isAzureEndpoint(): boolean {\n try {\n const host = new URL(this.baseUrl).hostname;\n return host === \"azure.com\" || host.endsWith(\".azure.com\");\n } catch {\n return false;\n }\n }\n\n /** Returns null on failure so callers can degrade — session must keep working without balance UI. */\n async getBalance(opts: { signal?: AbortSignal } = {}): Promise<UserBalance | null> {\n try {\n const resp = await this._fetch(`${this.baseUrl}/user/balance`, {\n method: \"GET\",\n headers: { Authorization: `Bearer ${this.apiKey}` },\n signal: opts.signal,\n });\n if (!resp.ok) return null;\n const data = (await resp.json()) as UserBalance;\n if (!data || !Array.isArray(data.balance_infos)) return null;\n return data;\n } catch {\n return null;\n }\n }\n\n /** Returns null on failure — callers fall back to a hardcoded model hint. */\n async listModels(opts: { signal?: AbortSignal } = {}): Promise<ModelList | null> {\n try {\n const resp = await this._fetch(`${this.baseUrl}/models`, {\n method: \"GET\",\n headers: { Authorization: `Bearer ${this.apiKey}` },\n signal: opts.signal,\n });\n if (!resp.ok) return null;\n const data = (await resp.json()) as ModelList;\n if (!data || !Array.isArray(data.data)) return null;\n return data;\n } catch {\n return null;\n }\n }\n\n async chat(opts: ChatRequestOptions): Promise<ChatResponse> {\n const ctrl = new AbortController();\n const timer = setTimeout(\n () => ctrl.abort(new Error(`DeepSeek request timed out after ${this.timeoutMs}ms`)),\n this.timeoutMs,\n );\n // Combine — `opts.signal ?? ctrl.signal` orphans the timer when the\n // caller passes a signal, so timeoutMs never reaches fetch.\n const signal = opts.signal ? AbortSignal.any([opts.signal, ctrl.signal]) : ctrl.signal;\n\n try {\n await this.waitForChatRateLimit(signal);\n const resp = await fetchWithRetry(\n this._fetch,\n `${this.baseUrl}/chat/completions`,\n {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${this.apiKey}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(this.buildPayload(opts, false)),\n signal,\n },\n { ...this.retry, signal },\n );\n if (!resp.ok) {\n throw new Error(`DeepSeek ${resp.status}: ${await resp.text()}`);\n }\n const data: any = await resp.json();\n const choice = data.choices?.[0]?.message ?? {};\n return {\n content: choice.content ?? \"\",\n reasoningContent: choice.reasoning_content ?? null,\n toolCalls: choice.tool_calls ?? [],\n usage: Usage.fromApi(data.usage ?? data),\n raw: data,\n };\n } finally {\n clearTimeout(timer);\n }\n }\n\n async *stream(opts: ChatRequestOptions): AsyncGenerator<StreamChunk> {\n const ctrl = new AbortController();\n const timer = setTimeout(\n () => ctrl.abort(new Error(`DeepSeek stream timed out after ${this.timeoutMs}ms`)),\n this.timeoutMs,\n );\n // Combine — `opts.signal ?? ctrl.signal` orphans the timer when the\n // caller passes a signal, leaving a stalled SSE body to hang forever\n // on reader.read() (issue #1535).\n const signal = opts.signal ? AbortSignal.any([opts.signal, ctrl.signal]) : ctrl.signal;\n\n let resp: Response;\n try {\n await this.waitForChatRateLimit(signal);\n // Only the initial fetch is retried. Once the server has started sending\n // the stream body we do NOT retry — a mid-stream retry would re-bill and\n // desync the session context.\n resp = await fetchWithRetry(\n this._fetch,\n `${this.baseUrl}/chat/completions`,\n {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${this.apiKey}`,\n \"Content-Type\": \"application/json\",\n Accept: \"text/event-stream\",\n },\n body: JSON.stringify(this.buildPayload(opts, true)),\n signal,\n },\n { ...this.retry, signal },\n );\n } catch (err) {\n clearTimeout(timer);\n throw err;\n }\n if (!resp.ok || !resp.body) {\n clearTimeout(timer);\n throw new Error(`DeepSeek ${resp.status}: ${await resp.text().catch(() => \"\")}`);\n }\n\n const queue: StreamChunk[] = [];\n let done = false;\n const parser = createParser({\n onEvent: (ev: EventSourceMessage) => {\n if (!ev.data || ev.data === \"[DONE]\") {\n done = true;\n return;\n }\n try {\n const json = JSON.parse(ev.data);\n const delta = json.choices?.[0]?.delta ?? {};\n const finishReason = json.choices?.[0]?.finish_reason ?? undefined;\n const chunk: StreamChunk = { raw: json, finishReason };\n if (typeof delta.content === \"string\" && delta.content.length > 0) {\n chunk.contentDelta = delta.content;\n }\n if (typeof delta.reasoning_content === \"string\" && delta.reasoning_content.length > 0) {\n chunk.reasoningDelta = delta.reasoning_content;\n }\n if (Array.isArray(delta.tool_calls) && delta.tool_calls.length > 0) {\n const tc = delta.tool_calls[0];\n chunk.toolCallDelta = {\n index: tc.index ?? 0,\n id: tc.id,\n name: tc.function?.name,\n argumentsDelta: tc.function?.arguments,\n };\n }\n const rawUsage = json.usage ?? (Usage.hasApiUsage(json) ? json : undefined);\n if (rawUsage) {\n chunk.usage = Usage.fromApi(rawUsage);\n }\n queue.push(chunk);\n } catch {\n /* skip malformed sse frame */\n }\n },\n });\n\n const reader = resp.body.getReader();\n const decoder = new TextDecoder();\n try {\n while (true) {\n if (queue.length > 0) {\n yield queue.shift()!;\n continue;\n }\n if (done) break;\n const { value, done: streamDone } = await reader.read();\n if (streamDone) break;\n parser.feed(decoder.decode(value, { stream: true }));\n }\n while (queue.length > 0) yield queue.shift()!;\n } finally {\n clearTimeout(timer);\n reader.releaseLock();\n }\n }\n}\n\nexport type { ChatMessage, ToolCall, ToolSpec };\n"],"mappings":"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","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/cli/commands/doctor.ts"],"sourcesContent":["/** Plain-text (not Ink) — must work when everything else is broken. fail → exit 1; warn → exit 0. */\n\nimport { existsSync, readFileSync, statSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join, resolve } from \"node:path\";\nimport { DeepSeekClient, pickPrimaryBalance } from \"../../client.js\";\nimport {\n defaultConfigPath,\n loadEndpoint,\n loadProxyConfig,\n readConfig,\n resolveSemanticEmbeddingConfig,\n} from \"../../config.js\";\nimport { loadDotenv } from \"../../env.js\";\nimport { loadHooks } from \"../../hooks.js\";\nimport { t } from \"../../i18n/index.js\";\nimport { indexExists } from \"../../index/semantic/builder.js\";\nimport { checkOllamaStatus } from \"../../index/semantic/ollama-launcher.js\";\nimport { listSessions } from \"../../memory/session.js\";\nimport { detectProxyUrl, matchesNoProxy, resolveNoProxy } from \"../../net/proxy.js\";\nimport { resolveDataPath } from \"../../tokenizer.js\";\nimport { VERSION } from \"../../version.js\";\n\nexport type DoctorLevel = \"ok\" | \"warn\" | \"fail\";\n\nexport interface DoctorCheck {\n id: string;\n label: string;\n level: DoctorLevel;\n detail: string;\n}\n\nexport interface DoctorOptions {\n json?: boolean;\n}\n\ntype Level = DoctorLevel;\ntype Check = DoctorCheck;\n\nexport async function runDoctorChecks(projectRoot: string): Promise<DoctorCheck[]> {\n // No descriptive names for the destructured slots — CodeQL's clear-text-logging\n // heuristic taints any variable name matching `*key*`/`*auth*`/`*cred*`/etc and\n // would trip on `apiKeyCheck`. The slots map 1:1 to the Promise.all array below.\n const r = await Promise.all([\n checkApiKey(),\n checkConfig(),\n checkApiReach(),\n checkTokenizer(),\n checkSessions(),\n checkHooks(projectRoot),\n checkOllama(projectRoot),\n checkProject(projectRoot),\n ]);\n return [r[0], r[1], ...checkProxy(), r[2], r[3], r[4], r[5], r[6], r[7]];\n}\n\n/** Probe hosts used to show users what's going through the proxy vs. direct. Cheap (no I/O), purely a routing simulation against the same NO_PROXY patterns the dispatcher uses. */\nconst PROXY_PROBE_HOSTS = [\"api.deepseek.com\", \"github.com\", \"api.github.com\"] as const;\n\nfunction checkProxy(): Check[] {\n const cfg = loadProxyConfig();\n const envUrl = detectProxyUrl();\n const url = cfg.url ?? envUrl;\n if (!url) {\n return [\n {\n id: \"proxy\",\n label: \"http proxy \",\n level: \"ok\",\n detail:\n \"no proxy configured (cfg.proxy.url / HTTPS_PROXY / HTTP_PROXY / ALL_PROXY unset) — direct connection\",\n },\n ];\n }\n let redacted = url;\n try {\n const u = new URL(url);\n if (u.username || u.password) {\n u.username = \"***\";\n u.password = \"\";\n redacted = u.toString();\n }\n } catch {\n /* not a URL — leave raw */\n }\n const urlSource = cfg.url ? \"cfg.proxy.url\" : \"HTTPS_PROXY\";\n if (cfg.disabled) {\n return [\n {\n id: \"proxy\",\n label: \"http proxy \",\n level: \"ok\",\n detail: `${urlSource}=${redacted} is set but cfg.proxy.disabled — Reasonix routes direct`,\n },\n ];\n }\n const resolved = resolveNoProxy(process.env, {\n extraNoProxy: cfg.noProxy,\n bypassDeepSeekDirect: cfg.bypassDeepSeekDirect,\n });\n const total = resolved.all.length;\n const sourceSummary = [\n `defaults ${resolved.defaults.length}`,\n resolved.envSystem.length > 0 ? `env ${resolved.envSystem.length}` : null,\n resolved.envReasonix.length > 0 ? `REASONIX ${resolved.envReasonix.length}` : null,\n resolved.extra.length > 0 ? `config ${resolved.extra.length}` : null,\n ]\n .filter(Boolean)\n .join(\" + \");\n const proxyCheck: Check = {\n id: \"proxy\",\n label: \"http proxy \",\n level: \"ok\",\n detail: `routing fetch through ${redacted} via ${urlSource} (NO_PROXY: ${total} pattern${total === 1 ? \"\" : \"s\"} — ${sourceSummary})`,\n };\n const probes = PROXY_PROBE_HOSTS.map(\n (h) => `${h} → ${matchesNoProxy(h, resolved.all) ? \"direct\" : \"via proxy\"}`,\n );\n const routingCheck: Check = {\n id: \"proxy-routing\",\n label: \"proxy routing\",\n level: \"ok\",\n detail: probes.join(\", \"),\n };\n return [proxyCheck, routingCheck];\n}\n\nconst TTY = process.stdout.isTTY && process.env.TERM !== \"dumb\";\n\nfunction color(text: string, code: string): string {\n if (!TTY) return text;\n return `\\x1b[${code}m${text}\\x1b[0m`;\n}\n\nfunction badge(level: Level): string {\n if (level === \"ok\") return color(\"✓\", \"32\");\n if (level === \"warn\") return color(\"⚠\", \"33\");\n return color(\"✗\", \"31\");\n}\n\nfunction fmtBytes(n: number): string {\n if (n < 1024) return `${n} B`;\n if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)} KB`;\n return `${(n / 1024 / 1024).toFixed(1)} MB`;\n}\n\nasync function checkApiKey(): Promise<Check> {\n const fromEnv = process.env.DEEPSEEK_API_KEY;\n if (fromEnv) {\n return {\n id: \"api-key\",\n label: \"api key \",\n level: \"ok\",\n detail: \"set via env DEEPSEEK_API_KEY\",\n };\n }\n try {\n const cfg = readConfig();\n if (cfg.apiKey) {\n return {\n id: \"api-key\",\n label: \"api key \",\n level: \"ok\",\n detail: `from ${defaultConfigPath()}`,\n };\n }\n } catch {\n /* fall through */\n }\n return {\n id: \"api-key\",\n label: \"api key \",\n level: \"fail\",\n detail:\n \"not set — `reasonix setup` to save one, or export DEEPSEEK_API_KEY. Get a key at https://platform.deepseek.com/api_keys\",\n };\n}\n\nasync function checkConfig(): Promise<Check> {\n const path = defaultConfigPath();\n if (!existsSync(path)) {\n return {\n id: \"config\",\n label: \"config \",\n level: \"warn\",\n detail: \"missing — running with library defaults. `reasonix setup` writes one.\",\n };\n }\n try {\n const cfg = readConfig(path);\n const parts: string[] = [];\n if (cfg.model) parts.push(`model=${cfg.model}`);\n if (cfg.reasoningEffort) parts.push(`effort=${cfg.reasoningEffort}`);\n if (cfg.editMode) parts.push(`editMode=${cfg.editMode}`);\n if (cfg.mcp && cfg.mcp.length > 0) parts.push(`mcp=${cfg.mcp.length}`);\n return {\n id: \"config\",\n label: \"config \",\n level: \"ok\",\n detail: `${path}${parts.length ? ` (${parts.join(\", \")})` : \"\"}`,\n };\n } catch (err) {\n return {\n id: \"config\",\n label: \"config \",\n level: \"fail\",\n detail: t(\"doctorErrors.unreadable\", { path, message: (err as Error).message }),\n };\n }\n}\n\nasync function checkApiReach(): Promise<Check> {\n const key = process.env.DEEPSEEK_API_KEY ?? readConfig().apiKey;\n if (!key) {\n return {\n id: \"api-reach\",\n label: \"api reach \",\n level: \"warn\",\n detail: \"skipped — no api key to test with\",\n };\n }\n try {\n const client = new DeepSeekClient({ apiKey: key, baseUrl: loadEndpoint().baseUrl });\n const ctl = new AbortController();\n const timer = setTimeout(() => ctl.abort(), 8_000);\n let balance: Awaited<ReturnType<DeepSeekClient[\"getBalance\"]>>;\n try {\n balance = await client.getBalance({ signal: ctl.signal });\n } finally {\n clearTimeout(timer);\n }\n if (!balance) {\n return {\n id: \"api-reach\",\n label: \"api reach \",\n level: \"fail\",\n detail: \"/user/balance returned null — auth failed or network blocked\",\n };\n }\n const summary = summarizeBalances(balance.balance_infos);\n if (!balance.is_available) {\n return {\n id: \"api-reach\",\n label: \"api reach \",\n level: \"warn\",\n detail: `account flagged not-available${summary ? ` (${summary})` : \"\"} — top up or check your dashboard`,\n };\n }\n return {\n id: \"api-reach\",\n label: \"api reach \",\n level: \"ok\",\n detail: summary ? `/user/balance ok — ${summary}` : \"/user/balance ok\",\n };\n } catch (err) {\n return {\n id: \"api-reach\",\n label: \"api reach \",\n level: \"fail\",\n detail: `${(err as Error).message}`,\n };\n }\n}\n\nfunction summarizeBalances(\n infos: ReadonlyArray<{ currency: string; total_balance: string }>,\n): string {\n if (infos.length === 0) return \"\";\n const primary = pickPrimaryBalance(infos);\n if (infos.length === 1 || !primary)\n return primary ? `${primary.total_balance} ${primary.currency}` : \"\";\n const rest = infos.filter((i) => i !== primary).map((i) => `${i.total_balance} ${i.currency}`);\n return `${primary.total_balance} ${primary.currency} + ${rest.join(\" + \")}`;\n}\n\nasync function checkTokenizer(): Promise<Check> {\n // Reuse the runtime's resolver so the doctor never disagrees with what\n // the tokenizer actually loads — three candidates including a global\n // npm install probe via createRequire.\n const path = resolveDataPath();\n if (existsSync(path)) {\n try {\n const stat = statSync(path);\n return {\n id: \"tokenizer\",\n label: \"tokenizer \",\n level: \"ok\",\n detail: `${path} (${fmtBytes(stat.size)})`,\n };\n } catch {\n /* fall through to warn */\n }\n }\n return {\n id: \"tokenizer\",\n label: \"tokenizer \",\n level: \"warn\",\n detail:\n \"data/deepseek-tokenizer.json.gz not found — token counts will fall back to char heuristics\",\n };\n}\n\nasync function checkSessions(): Promise<Check> {\n try {\n const list = listSessions();\n if (list.length === 0) {\n return {\n id: \"sessions\",\n label: \"sessions \",\n level: \"ok\",\n detail: \"0 saved\",\n };\n }\n const totalBytes = list.reduce((s, e) => s + e.size, 0);\n const oldest = list[list.length - 1]!;\n const ageDays = Math.floor((Date.now() - oldest.mtime.getTime()) / (24 * 60 * 60 * 1000));\n const stale = list.filter(\n (e) => Date.now() - e.mtime.getTime() >= 90 * 24 * 60 * 60 * 1000,\n ).length;\n const detail = `${list.length} saved · ${fmtBytes(totalBytes)} · oldest ${ageDays}d`;\n if (stale > 0) {\n return {\n id: \"sessions\",\n label: \"sessions \",\n level: \"warn\",\n detail: `${detail} · ${stale} idle ≥90d (run \\`reasonix prune-sessions\\`)`,\n };\n }\n return { id: \"sessions\", label: \"sessions \", level: \"ok\", detail };\n } catch (err) {\n return {\n id: \"sessions\",\n label: \"sessions \",\n level: \"warn\",\n detail: t(\"doctorErrors.cannotList\", { message: (err as Error).message }),\n };\n }\n}\n\nasync function checkHooks(projectRoot: string): Promise<Check> {\n try {\n const all = loadHooks({ projectRoot });\n const global = all.filter((h) => h.scope === \"global\").length;\n const project = all.filter((h) => h.scope === \"project\").length;\n return {\n id: \"hooks\",\n label: \"hooks \",\n level: \"ok\",\n detail: `${global} global, ${project} project`,\n };\n } catch (err) {\n return {\n id: \"hooks\",\n label: \"hooks \",\n level: \"warn\",\n detail: t(\"doctorErrors.parseFailed\", { message: (err as Error).message }),\n };\n }\n}\n\nasync function checkOllama(projectRoot: string): Promise<Check> {\n let exists = false;\n try {\n exists = await indexExists(projectRoot);\n } catch {\n /* treat as no index */\n }\n if (!exists) {\n return {\n id: \"semantic\",\n label: \"semantic \",\n level: \"ok\",\n detail: \"not in use (no semantic index built; `reasonix index` to enable)\",\n };\n }\n const meta = readSemanticMeta(projectRoot);\n if (meta?.provider === \"openai-compat\") {\n const resolved = resolveSemanticEmbeddingConfig();\n if (resolved.provider !== \"openai-compat\") {\n return {\n id: \"semantic\",\n label: \"semantic \",\n level: \"warn\",\n detail: `index uses openai-compat/${meta.model} but current config resolves to ${resolved.provider}/${resolved.model} — rebuild before searching`,\n };\n }\n return {\n id: \"semantic\",\n label: \"semantic \",\n level: \"ok\",\n detail: `openai-compat · ${resolved.baseUrl} · model ${resolved.model} · api key configured`,\n };\n }\n try {\n const model = meta?.model || process.env.REASONIX_EMBED_MODEL || \"nomic-embed-text\";\n const status = await checkOllamaStatus(model);\n if (!status.binaryFound) {\n return {\n id: \"semantic\",\n label: \"semantic \",\n level: \"warn\",\n detail:\n \"ollama binary not on PATH — semantic_search will fail; install from https://ollama.com\",\n };\n }\n if (!status.daemonRunning) {\n return {\n id: \"semantic\",\n label: \"semantic \",\n level: \"warn\",\n detail:\n \"ollama daemon not running — `ollama serve` (or call /semantic in TUI to auto-start)\",\n };\n }\n if (!status.modelPulled) {\n return {\n id: \"semantic\",\n label: \"semantic \",\n level: \"warn\",\n detail: `model ${status.modelName} not pulled — \\`ollama pull ${status.modelName}\\``,\n };\n }\n return {\n id: \"semantic\",\n label: \"semantic \",\n level: \"ok\",\n detail: `ollama daemon up · model ${status.modelName} ready`,\n };\n } catch (err) {\n return {\n id: \"semantic\",\n label: \"semantic \",\n level: \"warn\",\n detail: t(\"doctorErrors.probeFailed\", { message: (err as Error).message }),\n };\n }\n}\n\nfunction readSemanticMeta(\n projectRoot: string,\n): { provider: \"ollama\" | \"openai-compat\"; model: string } | null {\n try {\n const raw = readFileSync(join(projectRoot, \".reasonix\", \"semantic\", \"index.meta.json\"), \"utf8\");\n const parsed = JSON.parse(raw) as { provider?: string; model?: string };\n return {\n provider: parsed.provider === \"openai-compat\" ? \"openai-compat\" : \"ollama\",\n model: typeof parsed.model === \"string\" ? parsed.model : \"\",\n };\n } catch {\n return null;\n }\n}\n\nasync function checkProject(projectRoot: string): Promise<Check> {\n // Heuristic: a \"real\" project has either .git, REASONIX.md, or\n // package.json. Lacking all three, `reasonix code` still works but\n // @-mentions and the project-memory pin won't surface much.\n const markers = [\".git\", \"REASONIX.md\", \"package.json\", \"pyproject.toml\", \"Cargo.toml\", \"go.mod\"];\n const found = markers.filter((m) => existsSync(join(projectRoot, m)));\n if (found.length === 0) {\n return {\n id: \"project\",\n label: \"project \",\n level: \"warn\",\n detail: `${projectRoot} has none of: ${markers.slice(0, 3).join(\", \")} … — \\`reasonix code\\` will still run, but @-mentions and project memory have nothing to anchor`,\n };\n }\n return {\n id: \"project\",\n label: \"project \",\n level: \"ok\",\n detail: `${projectRoot} (${found.join(\", \")})`,\n };\n}\n\nexport function formatDoctorJson(checks: DoctorCheck[], version: string): string {\n const ok = checks.filter((c) => c.level === \"ok\").length;\n const warn = checks.filter((c) => c.level === \"warn\").length;\n const fail = checks.filter((c) => c.level === \"fail\").length;\n return JSON.stringify({\n version,\n summary: { ok, warn, fail },\n checks: checks.map((c) => ({ id: c.id, status: c.level, message: c.detail })),\n });\n}\n\nexport async function doctorCommand(opts: DoctorOptions = {}): Promise<void> {\n loadDotenv();\n\n const projectRoot = resolve(process.cwd());\n const json = !!opts.json;\n\n if (!json) {\n console.log(`${color(`reasonix ${VERSION} · doctor`, \"1\")} (cwd: ${projectRoot})`);\n console.log(` home: ${homedir()}`);\n console.log(\"\");\n }\n\n // Run independent checks in parallel — saves ~5s when api-reach has\n // to time out. Each handler swallows its own throws into a `fail`\n // result so a thrown promise can't kill the whole report.\n const checks = await runDoctorChecks(projectRoot);\n\n const ok = checks.filter((c) => c.level === \"ok\").length;\n const warn = checks.filter((c) => c.level === \"warn\").length;\n const fail = checks.filter((c) => c.level === \"fail\").length;\n\n if (json) {\n console.log(formatDoctorJson(checks, VERSION));\n if (fail > 0) process.exit(1);\n return;\n }\n\n for (const c of checks) {\n console.log(` ${badge(c.level)} ${c.label} ${c.detail}`);\n }\n\n console.log(\"\");\n const summary = `${ok} ok · ${warn} warn · ${fail} fail`;\n if (fail > 0) {\n console.log(color(summary, \"31\"));\n process.exit(1);\n } else if (warn > 0) {\n console.log(color(summary, \"33\"));\n } else {\n console.log(color(summary, \"32\"));\n }\n}\n"],"mappings":"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","names":[]}
|