reasonix 0.0.6 → 0.2.2
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 +34 -7
- package/dist/cli/index.js +801 -24
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +211 -2
- package/dist/index.js +446 -5
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { WriteStream } from 'node:fs';
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Retry layer for DeepSeek API calls.
|
|
3
5
|
*
|
|
@@ -436,6 +438,12 @@ interface LoopEvent {
|
|
|
436
438
|
content: string;
|
|
437
439
|
reasoningDelta?: string;
|
|
438
440
|
toolName?: string;
|
|
441
|
+
/**
|
|
442
|
+
* Raw JSON-string arguments the model sent for a tool call (role === "tool").
|
|
443
|
+
* Populated so transcripts can persist *why* a tool was called, not just
|
|
444
|
+
* what it returned. Needed by `reasonix diff` to explain divergences.
|
|
445
|
+
*/
|
|
446
|
+
toolArgs?: string;
|
|
439
447
|
stats?: TurnStats;
|
|
440
448
|
planState?: TypedPlanState;
|
|
441
449
|
repair?: RepairReport;
|
|
@@ -561,6 +569,207 @@ declare function deleteSession(name: string): boolean;
|
|
|
561
569
|
*/
|
|
562
570
|
declare function loadDotenv(path?: string): void;
|
|
563
571
|
|
|
572
|
+
/**
|
|
573
|
+
* Transcript format — the canonical "audit log" of a Reasonix session.
|
|
574
|
+
*
|
|
575
|
+
* Design split:
|
|
576
|
+
* - Session file (`~/.reasonix/sessions/<name>.jsonl`) stores only the
|
|
577
|
+
* `ChatMessage`s the model needs to resume. See session.ts.
|
|
578
|
+
* - Transcript file (this module) stores every LoopEvent with usage, cost,
|
|
579
|
+
* model, and prefix fingerprint attached where available — enough for
|
|
580
|
+
* replay and diff to reconstruct economics.
|
|
581
|
+
*
|
|
582
|
+
* The two are different contracts: sessions are the user's *memory*;
|
|
583
|
+
* transcripts are the *receipts*. Don't conflate them.
|
|
584
|
+
*
|
|
585
|
+
* Backward compatibility: all fields beyond {ts, turn, role, content} are
|
|
586
|
+
* optional on read. A v0.1 transcript (pre-usage) still parses and renders
|
|
587
|
+
* — it just shows cost/cache as n/a.
|
|
588
|
+
*/
|
|
589
|
+
|
|
590
|
+
interface TranscriptRecord {
|
|
591
|
+
/** ISO-8601 timestamp at emit time. */
|
|
592
|
+
ts: string;
|
|
593
|
+
/** 1-based turn number within the session. */
|
|
594
|
+
turn: number;
|
|
595
|
+
/** LoopEvent role — "assistant_delta" | "assistant_final" | "tool" | "done" | ... */
|
|
596
|
+
role: string;
|
|
597
|
+
/** For assistant events, the final (or delta) text; for tool events, the tool result. */
|
|
598
|
+
content: string;
|
|
599
|
+
/** Tool name (role === "tool"). */
|
|
600
|
+
tool?: string;
|
|
601
|
+
/** JSON-string args the model sent for a tool call (role === "tool"). Persisted so diff can explain *why* two runs made different calls. */
|
|
602
|
+
args?: string;
|
|
603
|
+
/** DeepSeek token-usage snapshot (role === "assistant_final"). */
|
|
604
|
+
usage?: RawUsage;
|
|
605
|
+
/** USD cost of this turn (role === "assistant_final"). */
|
|
606
|
+
cost?: number;
|
|
607
|
+
/** Model id that produced this turn. */
|
|
608
|
+
model?: string;
|
|
609
|
+
/**
|
|
610
|
+
* The ImmutablePrefix fingerprint at this turn. Lets diff prove two runs
|
|
611
|
+
* share a prefix — i.e. any cache-hit delta is attributable to log
|
|
612
|
+
* stability, not to a different system prompt.
|
|
613
|
+
*/
|
|
614
|
+
prefixHash?: string;
|
|
615
|
+
/** Optional error message (role === "error"). */
|
|
616
|
+
error?: string;
|
|
617
|
+
}
|
|
618
|
+
interface TranscriptMeta {
|
|
619
|
+
/**
|
|
620
|
+
* Optional metadata written as the first line of a transcript. Lets
|
|
621
|
+
* downstream tooling know what it's reading without guessing.
|
|
622
|
+
* Recognized by a special role "_meta".
|
|
623
|
+
*/
|
|
624
|
+
version: 1;
|
|
625
|
+
source: string;
|
|
626
|
+
model?: string;
|
|
627
|
+
task?: string;
|
|
628
|
+
mode?: string;
|
|
629
|
+
repeat?: number;
|
|
630
|
+
startedAt: string;
|
|
631
|
+
}
|
|
632
|
+
interface ReadTranscriptResult {
|
|
633
|
+
meta: TranscriptMeta | null;
|
|
634
|
+
records: TranscriptRecord[];
|
|
635
|
+
}
|
|
636
|
+
/**
|
|
637
|
+
* Build a TranscriptRecord from a LoopEvent. Extra fields (model,
|
|
638
|
+
* prefixHash) that the LoopEvent doesn't carry are passed in separately
|
|
639
|
+
* because they're session-level, not event-level.
|
|
640
|
+
*/
|
|
641
|
+
declare function recordFromLoopEvent(ev: LoopEvent, extra: {
|
|
642
|
+
model: string;
|
|
643
|
+
prefixHash: string;
|
|
644
|
+
}): TranscriptRecord;
|
|
645
|
+
/**
|
|
646
|
+
* Append a record to an open write stream. Caller owns the stream lifecycle.
|
|
647
|
+
*/
|
|
648
|
+
declare function writeRecord(stream: WriteStream, record: TranscriptRecord): void;
|
|
649
|
+
/**
|
|
650
|
+
* Write a _meta line to an open write stream. Call exactly once, at the top.
|
|
651
|
+
*/
|
|
652
|
+
declare function writeMeta(stream: WriteStream, meta: TranscriptMeta): void;
|
|
653
|
+
/**
|
|
654
|
+
* Convenience: open a stream, write meta, return stream.
|
|
655
|
+
*/
|
|
656
|
+
declare function openTranscriptFile(path: string, meta: TranscriptMeta): WriteStream;
|
|
657
|
+
/**
|
|
658
|
+
* Parse a transcript file. Returns meta (if the first line is a _meta record)
|
|
659
|
+
* and the full record list.
|
|
660
|
+
*
|
|
661
|
+
* Robustness contract:
|
|
662
|
+
* - Empty lines are skipped.
|
|
663
|
+
* - Malformed JSON lines are skipped silently (do not crash on partial
|
|
664
|
+
* files — live chats may be mid-write).
|
|
665
|
+
* - Records missing optional fields still parse — they're just rendered
|
|
666
|
+
* with n/a where the optional value would go.
|
|
667
|
+
*/
|
|
668
|
+
declare function readTranscript(path: string): ReadTranscriptResult;
|
|
669
|
+
declare function parseTranscript(raw: string): ReadTranscriptResult;
|
|
670
|
+
|
|
671
|
+
/**
|
|
672
|
+
* Replay — reconstruct session economics from a transcript file.
|
|
673
|
+
*
|
|
674
|
+
* Given a transcript written by App.tsx or the bench runner, rebuild a
|
|
675
|
+
* SessionSummary-compatible aggregate (turn count, total cost, cache-hit
|
|
676
|
+
* ratio, vs-Claude estimate) without replaying the LLM calls.
|
|
677
|
+
*
|
|
678
|
+
* The whole point is offline auditing: a reader should be able to reproduce
|
|
679
|
+
* the headline numbers from a transcript alone, without an API key.
|
|
680
|
+
*/
|
|
681
|
+
|
|
682
|
+
interface ReplayStats extends SessionSummary {
|
|
683
|
+
/** Per-turn stats, in turn order. Only assistant_final records contribute. */
|
|
684
|
+
perTurn: TurnStats[];
|
|
685
|
+
/** Unique models that appeared in the transcript's assistant_final records. */
|
|
686
|
+
models: string[];
|
|
687
|
+
/** Unique prefix hashes that appeared. Length > 1 means the prefix churned (cache-hostile). */
|
|
688
|
+
prefixHashes: string[];
|
|
689
|
+
/** Count of user-role records (user turns issued). */
|
|
690
|
+
userTurns: number;
|
|
691
|
+
/** Count of tool-role records (tool calls executed). */
|
|
692
|
+
toolCalls: number;
|
|
693
|
+
}
|
|
694
|
+
/**
|
|
695
|
+
* Parse a transcript file and compute replay stats. Throws only on I/O
|
|
696
|
+
* errors; malformed lines inside the file are skipped silently.
|
|
697
|
+
*/
|
|
698
|
+
declare function replayFromFile(path: string): {
|
|
699
|
+
parsed: ReadTranscriptResult;
|
|
700
|
+
stats: ReplayStats;
|
|
701
|
+
};
|
|
702
|
+
declare function computeReplayStats(records: TranscriptRecord[]): ReplayStats;
|
|
703
|
+
|
|
704
|
+
/**
|
|
705
|
+
* Diff — compare two transcripts and produce a summary + divergence report.
|
|
706
|
+
*
|
|
707
|
+
* Two transcripts are "comparable" when they stem from the same task (or
|
|
708
|
+
* the same user prompt). Alignment is by turn number: assistant_final #N
|
|
709
|
+
* in A pairs with assistant_final #N in B. If one side ran more turns, the
|
|
710
|
+
* extras are labeled "only in A" / "only in B".
|
|
711
|
+
*
|
|
712
|
+
* What we compute:
|
|
713
|
+
* - Aggregate deltas: turns, tool calls, cache hit, cost, token counts
|
|
714
|
+
* - First divergence: the lowest turn where A and B's tool calls or
|
|
715
|
+
* assistant text differ meaningfully
|
|
716
|
+
* - Prefix-stability story: how many unique prefix hashes each side used
|
|
717
|
+
*
|
|
718
|
+
* Non-goals (deliberately):
|
|
719
|
+
* - LLM-judge quality comparison
|
|
720
|
+
* - Per-token delta rendering — not useful at the fidelity we're at
|
|
721
|
+
* - Embedding similarity — Levenshtein ratio is cheap and good enough
|
|
722
|
+
*/
|
|
723
|
+
|
|
724
|
+
interface DiffSide {
|
|
725
|
+
label: string;
|
|
726
|
+
meta: ReadTranscriptResult["meta"];
|
|
727
|
+
records: TranscriptRecord[];
|
|
728
|
+
stats: ReplayStats;
|
|
729
|
+
}
|
|
730
|
+
interface TurnPair {
|
|
731
|
+
turn: number;
|
|
732
|
+
aAssistant?: TranscriptRecord;
|
|
733
|
+
bAssistant?: TranscriptRecord;
|
|
734
|
+
aTools: TranscriptRecord[];
|
|
735
|
+
bTools: TranscriptRecord[];
|
|
736
|
+
/**
|
|
737
|
+
* Classification of the pair:
|
|
738
|
+
* "match" — both sides present, text & tool calls within threshold
|
|
739
|
+
* "diverge" — both sides present, but text or tool calls differ
|
|
740
|
+
* "only_in_a" — assistant_final in A but not B
|
|
741
|
+
* "only_in_b" — assistant_final in B but not A
|
|
742
|
+
*/
|
|
743
|
+
kind: "match" | "diverge" | "only_in_a" | "only_in_b";
|
|
744
|
+
/** When kind === "diverge", a short one-liner pointing at what differs. */
|
|
745
|
+
divergenceNote?: string;
|
|
746
|
+
}
|
|
747
|
+
interface DiffReport {
|
|
748
|
+
a: DiffSide;
|
|
749
|
+
b: DiffSide;
|
|
750
|
+
pairs: TurnPair[];
|
|
751
|
+
firstDivergenceTurn: number | null;
|
|
752
|
+
}
|
|
753
|
+
declare function diffTranscripts(a: {
|
|
754
|
+
label: string;
|
|
755
|
+
parsed: ReadTranscriptResult;
|
|
756
|
+
}, b: {
|
|
757
|
+
label: string;
|
|
758
|
+
parsed: ReadTranscriptResult;
|
|
759
|
+
}): DiffReport;
|
|
760
|
+
/**
|
|
761
|
+
* Normalized Levenshtein similarity ratio in [0, 1]. 1 = identical.
|
|
762
|
+
* Early-exits for long strings (> 2000 chars) with a cheap token-overlap
|
|
763
|
+
* estimate to keep diff fast on chatty transcripts.
|
|
764
|
+
*/
|
|
765
|
+
declare function similarity(a: string, b: string): number;
|
|
766
|
+
interface RenderOptions {
|
|
767
|
+
/** Monochrome output (for file redirection or piping). Defaults to true. */
|
|
768
|
+
monochrome?: boolean;
|
|
769
|
+
}
|
|
770
|
+
declare function renderSummaryTable(report: DiffReport, _opts?: RenderOptions): string;
|
|
771
|
+
declare function renderMarkdown(report: DiffReport): string;
|
|
772
|
+
|
|
564
773
|
/**
|
|
565
774
|
* User-level config storage for the Reasonix CLI.
|
|
566
775
|
*
|
|
@@ -588,6 +797,6 @@ declare function redactKey(key: string): string;
|
|
|
588
797
|
|
|
589
798
|
/** Reasonix — DeepSeek-native agent framework. Library entry point. */
|
|
590
799
|
|
|
591
|
-
declare const VERSION = "0.
|
|
800
|
+
declare const VERSION = "0.2.2";
|
|
592
801
|
|
|
593
|
-
export { AppendOnlyLog, type BranchOptions, type BranchProgress, type BranchResult, type BranchSample, type BranchSelector, type BranchSummary, CacheFirstLoop, type CacheFirstLoopOptions, type ChatMessage, type ChatResponse, DeepSeekClient, type DeepSeekClientOptions, type EventRole, type FlattenDecision, type HarvestOptions, ImmutablePrefix, type ImmutablePrefixOptions, type JSONSchema, type LoopEvent, type ReasonixConfig, type ReconfigurableOptions, type RepairReport, type RetryInfo, type RetryOptions, type Role, type ScavengeOptions, type ScavengeResult, type SessionInfo, SessionStats, type SessionSummary, StormBreaker, type StreamChunk, type ToolCall, ToolCallRepair, type ToolCallRepairOptions, type ToolDefinition, type ToolFunctionSpec, ToolRegistry, type ToolSpec, type TruncationRepairResult, type TurnStats, type TypedPlanState, Usage, VERSION, VolatileScratch, aggregateBranchUsage, analyzeSchema, appendSessionMessage, claudeEquivalentCost, costUsd, defaultConfigPath, defaultSelector, deleteSession, emptyPlanState, fetchWithRetry, flattenSchema, harvest, isPlanStateEmpty, isPlausibleKey, listSessions, loadApiKey, loadDotenv, loadSessionMessages, nestArguments, readConfig, redactKey, repairTruncatedJson, runBranches, sanitizeName as sanitizeSessionName, saveApiKey, scavengeToolCalls, sessionPath, sessionsDir, writeConfig };
|
|
802
|
+
export { AppendOnlyLog, type BranchOptions, type BranchProgress, type BranchResult, type BranchSample, type BranchSelector, type BranchSummary, CacheFirstLoop, type CacheFirstLoopOptions, type ChatMessage, type ChatResponse, DeepSeekClient, type DeepSeekClientOptions, type RenderOptions as DiffRenderOptions, type DiffReport, type DiffSide, type EventRole, type FlattenDecision, type HarvestOptions, ImmutablePrefix, type ImmutablePrefixOptions, type JSONSchema, type LoopEvent, type ReadTranscriptResult, type ReasonixConfig, type ReconfigurableOptions, type RepairReport, type ReplayStats, type RetryInfo, type RetryOptions, type Role, type ScavengeOptions, type ScavengeResult, type SessionInfo, SessionStats, type SessionSummary, StormBreaker, type StreamChunk, type ToolCall, ToolCallRepair, type ToolCallRepairOptions, type ToolDefinition, type ToolFunctionSpec, ToolRegistry, type ToolSpec, type TranscriptMeta, type TranscriptRecord, type TruncationRepairResult, type TurnPair, type TurnStats, type TypedPlanState, Usage, VERSION, VolatileScratch, aggregateBranchUsage, analyzeSchema, appendSessionMessage, claudeEquivalentCost, computeReplayStats, costUsd, defaultConfigPath, defaultSelector, deleteSession, diffTranscripts, emptyPlanState, fetchWithRetry, flattenSchema, harvest, isPlanStateEmpty, isPlausibleKey, listSessions, loadApiKey, loadDotenv, loadSessionMessages, nestArguments, openTranscriptFile, parseTranscript, readConfig, readTranscript, recordFromLoopEvent, redactKey, renderMarkdown as renderDiffMarkdown, renderSummaryTable as renderDiffSummary, repairTruncatedJson, replayFromFile, runBranches, sanitizeName as sanitizeSessionName, saveApiKey, scavengeToolCalls, sessionPath, sessionsDir, similarity, writeConfig, writeMeta, writeRecord };
|