reasonix 0.5.8 → 0.5.20
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/cli/index.js +1011 -168
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +121 -7
- package/dist/index.js +157 -21
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -69,6 +69,14 @@ interface ChatMessage {
|
|
|
69
69
|
name?: string;
|
|
70
70
|
tool_call_id?: string;
|
|
71
71
|
tool_calls?: ToolCall[];
|
|
72
|
+
/**
|
|
73
|
+
* R1 `reasoning_content` captured from the assistant's thinking turn.
|
|
74
|
+
* DeepSeek's thinking mode 400s with "reasoning_content in the
|
|
75
|
+
* thinking mode must be passed back" when a tool-loop continuation
|
|
76
|
+
* omits it from the preceding assistant message. Round-tripped for
|
|
77
|
+
* deepseek-reasoner turns with tool_calls; absent for deepseek-chat.
|
|
78
|
+
*/
|
|
79
|
+
reasoning_content?: string | null;
|
|
72
80
|
}
|
|
73
81
|
interface RawUsage {
|
|
74
82
|
prompt_tokens?: number;
|
|
@@ -790,6 +798,19 @@ interface LoopEvent {
|
|
|
790
798
|
toolArgs?: string;
|
|
791
799
|
/** Cumulative arguments-string length for `role === "tool_call_delta"`. */
|
|
792
800
|
toolCallArgsChars?: number;
|
|
801
|
+
/**
|
|
802
|
+
* Zero-based index of the tool call this delta belongs to. Surfaces
|
|
803
|
+
* multi-tool turns: on a response emitting 4 write_file calls the UI
|
|
804
|
+
* can show "building call 3/?" instead of a context-free spinner.
|
|
805
|
+
*/
|
|
806
|
+
toolCallIndex?: number;
|
|
807
|
+
/**
|
|
808
|
+
* Count of prior tool calls (this turn) whose arguments have finished
|
|
809
|
+
* streaming into valid JSON. Not all ready calls have been dispatched
|
|
810
|
+
* yet — dispatch still happens post-stream — but the user gets "2
|
|
811
|
+
* ready" progress feedback while later calls keep streaming.
|
|
812
|
+
*/
|
|
813
|
+
toolCallReadyCount?: number;
|
|
793
814
|
stats?: TurnStats;
|
|
794
815
|
planState?: TypedPlanState;
|
|
795
816
|
repair?: RepairReport;
|
|
@@ -922,7 +943,7 @@ declare class CacheFirstLoop {
|
|
|
922
943
|
tokensSaved: number;
|
|
923
944
|
charsSaved: number;
|
|
924
945
|
};
|
|
925
|
-
|
|
946
|
+
appendAndPersist(message: ChatMessage): void;
|
|
926
947
|
/**
|
|
927
948
|
* Start a fresh conversation WITHOUT exiting. Drops every message
|
|
928
949
|
* in the in-memory log AND rewrites the session file to empty so
|
|
@@ -970,6 +991,15 @@ declare class CacheFirstLoop {
|
|
|
970
991
|
private forceSummaryAfterIterLimit;
|
|
971
992
|
run(userInput: string, onEvent?: (ev: LoopEvent) => void): Promise<string>;
|
|
972
993
|
private assistantMessage;
|
|
994
|
+
/**
|
|
995
|
+
* Build a synthetic assistant message we insert into the log without
|
|
996
|
+
* a real API round trip (abort notices, future system injections).
|
|
997
|
+
* Reasoner models reject follow-up requests whose assistant history
|
|
998
|
+
* is missing `reasoning_content`, so we stamp an empty-string
|
|
999
|
+
* placeholder on reasoner sessions to satisfy the validator. V3
|
|
1000
|
+
* doesn't care — field stays absent there.
|
|
1001
|
+
*/
|
|
1002
|
+
private syntheticAssistantMessage;
|
|
973
1003
|
}
|
|
974
1004
|
/**
|
|
975
1005
|
* R1 occasionally hallucinates tool-call markup as plain text when the
|
|
@@ -1085,6 +1115,22 @@ interface ListFilesOptions {
|
|
|
1085
1115
|
* - entries the walker can't read (permission errors, broken links).
|
|
1086
1116
|
*/
|
|
1087
1117
|
declare function listFilesSync(root: string, opts?: ListFilesOptions): string[];
|
|
1118
|
+
interface FileWithStats {
|
|
1119
|
+
/** Relative path with forward-slash separator. */
|
|
1120
|
+
path: string;
|
|
1121
|
+
/** Modification time (Date.getTime() / ms since epoch). 0 when stat failed. */
|
|
1122
|
+
mtimeMs: number;
|
|
1123
|
+
}
|
|
1124
|
+
/**
|
|
1125
|
+
* Same walk as {@link listFilesSync} but also statS each file for
|
|
1126
|
+
* modification time. Used by the `@` picker to surface recently-
|
|
1127
|
+
* edited files first — matches VS Code Quick Open / similar UX.
|
|
1128
|
+
*
|
|
1129
|
+
* Stat failures don't throw: the entry is kept with `mtimeMs: 0` so
|
|
1130
|
+
* it still appears in the picker (just sinks to the bottom of the
|
|
1131
|
+
* recency sort).
|
|
1132
|
+
*/
|
|
1133
|
+
declare function listFilesWithStatsSync(root: string, opts?: ListFilesOptions): FileWithStats[];
|
|
1088
1134
|
/**
|
|
1089
1135
|
* Prefix pattern used by the `@` picker to detect an IN-PROGRESS
|
|
1090
1136
|
* mention at the END of the input buffer. Captures the partial path
|
|
@@ -1106,14 +1152,36 @@ declare function detectAtPicker(input: string): {
|
|
|
1106
1152
|
query: string;
|
|
1107
1153
|
atOffset: number;
|
|
1108
1154
|
} | null;
|
|
1155
|
+
/** A candidate accepted by the picker ranker — either a bare path or a path with mtime. */
|
|
1156
|
+
type PickerCandidate = string | FileWithStats;
|
|
1157
|
+
interface RankPickerOptions {
|
|
1158
|
+
/** Upper bound on returned entries. Default 40. */
|
|
1159
|
+
limit?: number;
|
|
1160
|
+
/**
|
|
1161
|
+
* Paths the user or model has touched recently (via tool calls like
|
|
1162
|
+
* `read_file` / `edit_file`). Matching paths get a recency boost so
|
|
1163
|
+
* the picker surfaces "stuff I just looked at" near the top.
|
|
1164
|
+
*/
|
|
1165
|
+
recentlyUsed?: readonly string[];
|
|
1166
|
+
}
|
|
1109
1167
|
/**
|
|
1110
1168
|
* Filter and rank candidate files against the picker's partial query.
|
|
1111
|
-
*
|
|
1112
|
-
*
|
|
1113
|
-
*
|
|
1114
|
-
*
|
|
1169
|
+
*
|
|
1170
|
+
* Empty query:
|
|
1171
|
+
* - Sort by "recently used" bucket first (if provided), then mtime
|
|
1172
|
+
* descending (newer first), then path alpha.
|
|
1173
|
+
* - Pure-string input (no mtime data) falls back to alpha since
|
|
1174
|
+
* recency info isn't available.
|
|
1175
|
+
*
|
|
1176
|
+
* Non-empty query:
|
|
1177
|
+
* - Case-insensitive substring match, with a basename-prefix boost
|
|
1178
|
+
* so `lo` floats `loop.ts`-shaped paths to the top.
|
|
1179
|
+
* - Ties broken first by recently-used membership, then mtime.
|
|
1180
|
+
*
|
|
1181
|
+
* Back-compat: passes `string[]` through the same logic (mtime = 0,
|
|
1182
|
+
* recently-used still honored).
|
|
1115
1183
|
*/
|
|
1116
|
-
declare function rankPickerCandidates(files: readonly
|
|
1184
|
+
declare function rankPickerCandidates(files: readonly PickerCandidate[], query: string, limitOrOpts?: number | RankPickerOptions): string[];
|
|
1117
1185
|
/**
|
|
1118
1186
|
* Matches `@` at a word boundary (start-of-string or preceded by
|
|
1119
1187
|
* whitespace) followed by a path-like token. Deliberately rejects `@`
|
|
@@ -1512,6 +1580,10 @@ interface SubagentEvent {
|
|
|
1512
1580
|
kind: "start" | "progress" | "end";
|
|
1513
1581
|
/** First ~30 chars of the task prompt — used for the TUI status row. */
|
|
1514
1582
|
task: string;
|
|
1583
|
+
/** Skill that spawned this subagent, when applicable. Stamped on every event so the TUI/logger can attribute without extra plumbing. */
|
|
1584
|
+
skillName?: string;
|
|
1585
|
+
/** Model id the child loop ran on. Stamped alongside skillName. */
|
|
1586
|
+
model?: string;
|
|
1515
1587
|
/** Iteration count inside the child loop (number of tool results so far). */
|
|
1516
1588
|
iter?: number;
|
|
1517
1589
|
/** Wall-clock ms since the subagent started. */
|
|
@@ -1522,6 +1594,10 @@ interface SubagentEvent {
|
|
|
1522
1594
|
error?: string;
|
|
1523
1595
|
/** Total turns the subagent took. Set on `end`. */
|
|
1524
1596
|
turns?: number;
|
|
1597
|
+
/** Total USD spent inside the child loop. Set on `end`. */
|
|
1598
|
+
costUsd?: number;
|
|
1599
|
+
/** Aggregated child-loop Usage (sum across turns). Set on `end`. */
|
|
1600
|
+
usage?: Usage;
|
|
1525
1601
|
}
|
|
1526
1602
|
/**
|
|
1527
1603
|
* Mutable ref the registration writes through. The TUI sets `.current`
|
|
@@ -3028,6 +3104,22 @@ interface UsageRecord {
|
|
|
3028
3104
|
costUsd: number;
|
|
3029
3105
|
/** What the same turn would have cost at Claude Sonnet 4.6 rates. */
|
|
3030
3106
|
claudeEquivUsd: number;
|
|
3107
|
+
/**
|
|
3108
|
+
* Distinguishes ordinary parent-loop turns from subagent summary rows.
|
|
3109
|
+
* Absent on pre-0.5.14 records — treat as "turn" when missing.
|
|
3110
|
+
*/
|
|
3111
|
+
kind?: "turn" | "subagent";
|
|
3112
|
+
/** Present when `kind === "subagent"`. Attribution metadata for the /stats roll-up. */
|
|
3113
|
+
subagent?: {
|
|
3114
|
+
/** Skill that spawned it, when the spawn came from a `runAs: subagent` skill. */
|
|
3115
|
+
skillName?: string;
|
|
3116
|
+
/** First ~60 chars of the task prompt — enough context to recognize a run, never the full text. */
|
|
3117
|
+
taskPreview: string;
|
|
3118
|
+
/** Tool calls the child loop dispatched before returning. */
|
|
3119
|
+
toolIters: number;
|
|
3120
|
+
/** Wall-clock ms. */
|
|
3121
|
+
durationMs: number;
|
|
3122
|
+
};
|
|
3031
3123
|
}
|
|
3032
3124
|
/** Where the log lives. Tests override via `opts.path`. */
|
|
3033
3125
|
declare function defaultUsageLogPath(homeDirOverride?: string): string;
|
|
@@ -3039,6 +3131,9 @@ interface AppendUsageInput {
|
|
|
3039
3131
|
now?: number;
|
|
3040
3132
|
/** Override the log path (tests). */
|
|
3041
3133
|
path?: string;
|
|
3134
|
+
/** When appending a subagent summary row, set `kind: "subagent"` and populate `subagent`. */
|
|
3135
|
+
kind?: "turn" | "subagent";
|
|
3136
|
+
subagent?: UsageRecord["subagent"];
|
|
3042
3137
|
}
|
|
3043
3138
|
/**
|
|
3044
3139
|
* Append one record and return it. Swallows disk errors — the TUI
|
|
@@ -3093,6 +3188,25 @@ interface UsageAggregate {
|
|
|
3093
3188
|
firstSeen: number | null;
|
|
3094
3189
|
/** Latest record's ts, or `null` when the log is empty. */
|
|
3095
3190
|
lastSeen: number | null;
|
|
3191
|
+
/**
|
|
3192
|
+
* Subagent-specific rollup. Undefined when no subagent records exist
|
|
3193
|
+
* in the log so consumers can cheaply skip the section. Counts reflect
|
|
3194
|
+
* subagent SPAWNS (not internal child-loop turns) — one row per run.
|
|
3195
|
+
*/
|
|
3196
|
+
subagents?: SubagentAggregate;
|
|
3197
|
+
}
|
|
3198
|
+
/** Rolled-up view of all `kind: "subagent"` records. */
|
|
3199
|
+
interface SubagentAggregate {
|
|
3200
|
+
total: number;
|
|
3201
|
+
costUsd: number;
|
|
3202
|
+
totalDurationMs: number;
|
|
3203
|
+
/** Per-skill breakdown. Records without `skillName` (raw spawn_subagent calls) group under `"(adhoc)"`. */
|
|
3204
|
+
bySkill: Array<{
|
|
3205
|
+
skillName: string;
|
|
3206
|
+
count: number;
|
|
3207
|
+
costUsd: number;
|
|
3208
|
+
durationMs: number;
|
|
3209
|
+
}>;
|
|
3096
3210
|
}
|
|
3097
3211
|
/**
|
|
3098
3212
|
* Fold a flat record list into the dashboard shape — rolling windows
|
|
@@ -3107,4 +3221,4 @@ declare function aggregateUsage(records: UsageRecord[], opts?: AggregateOptions)
|
|
|
3107
3221
|
/** File-size helper for the stats header — "1.2 MB" etc. Returns "" if missing. */
|
|
3108
3222
|
declare function formatLogSize(path?: string): string;
|
|
3109
3223
|
|
|
3110
|
-
export { AT_MENTION_PATTERN, AT_PICKER_PREFIX, type AggregateOptions, AppendOnlyLog, type AppendUsageInput, type ApplyResult, type ApplyStatus, type AtMentionExpansion, type AtMentionOptions, type BranchOptions, type BranchProgress, type BranchResult, type BranchSample, type BranchSelector, type BranchSummary, type BridgeOptions, type BridgeResult, CODE_SYSTEM_PROMPT, CacheFirstLoop, type CacheFirstLoopOptions, type CallToolResult, type ChatMessage, type ChatResponse, DEFAULT_AT_MENTION_MAX_BYTES, DEFAULT_MAX_RESULT_CHARS, DEFAULT_MAX_RESULT_TOKENS, DEFAULT_PICKER_IGNORE_DIRS, DeepSeekClient, type DeepSeekClientOptions, type RenderOptions as DiffRenderOptions, type DiffReport, type DiffSide, type EditBlock, type EditSnapshot, type EventRole, type FilesystemToolsOptions, type FlattenDecision, type FlattenOptions, type GetLatestVersionOptions, type GetPromptResult, HOOK_EVENTS, HOOK_SETTINGS_DIRNAME, HOOK_SETTINGS_FILENAME, type HarvestOptions, type HookConfig, type HookEvent, type HookOutcome, type HookPayload, type HookReport, type HookScope, type HookSettings, type HookSpawnInput, type HookSpawnResult, type HookSpawner, ImmutablePrefix, type ImmutablePrefixOptions, type InitializeResult, type InspectionReport, type JSONSchema, type JsonRpcMessage, type JsonRpcRequest, type JsonRpcResponse, LATEST_CACHE_TTL_MS, LATEST_FETCH_TIMEOUT_MS, type ListFilesOptions, type ListPromptsResult, type ListResourcesResult, type ListToolsResult, type LoadHookSettingsOptions, type LoopEvent, MCP_PROTOCOL_VERSION, MEMORY_INDEX_FILE, MEMORY_INDEX_MAX_CHARS, McpClient, type McpClientOptions, type McpContentBlock, type McpProgressHandler, type McpProgressInfo, type McpPrompt, type McpPromptArgument, type McpPromptMessage, type McpPromptResourceBlock, type McpResource, type McpResourceContents, type McpResourceContentsBlob, type McpResourceContentsText, type McpSpec, type McpTool, type McpToolSchema, type McpTransport, type MemoryEntry, type MemoryScope, MemoryStore, type MemoryStoreOptions, type MemoryToolsOptions, type MemoryType, type WriteInput as MemoryWriteInput, NeedsConfirmationError, PROJECT_MEMORY_FILE, PROJECT_MEMORY_MAX_CHARS, type PageContent, PlanProposedError, type PlanToolOptions, type ProgressNotificationParams, type ProjectMemory, type ReadResourceResult, type ReadTranscriptResult, type ReasonixConfig, type ReconfigurableOptions, type RepairReport, type ReplayStats, type ResolvedHook, type RetryInfo, type RetryOptions, type Role, type RunCommandResult, type RunHooksOptions, type ScavengeOptions, type ScavengeResult, type SearchResult, type SectionResult, type SessionInfo, SessionStats, type SessionSummary, type ShellToolsOptions, type SseMcpSpec, SseTransport, type SseTransportOptions, type StdioMcpSpec, StdioTransport, type StdioTransportOptions, StormBreaker, type StreamChunk, type SubagentEvent, type SubagentSink, type SubagentToolOptions, type ToolCall, type ToolCallContext, ToolCallRepair, type ToolCallRepairOptions, type ToolDefinition, type ToolFunctionSpec, ToolRegistry, type ToolSpec, type TranscriptMeta, type TranscriptRecord, type TruncationRepairResult, type TurnPair, type TurnStats, type TypedPlanState, USER_MEMORY_DIR, Usage, type UsageAggregate, type UsageBucket, type UsageRecord, VERSION, VolatileScratch, type WebFetchOptions, type WebSearchOptions, type WebToolsOptions, aggregateBranchUsage, aggregateUsage, analyzeSchema, appendSessionMessage, appendUsage, applyEditBlock, applyEditBlocks, applyMemoryStack, applyProjectMemory, applyUserMemory, bridgeMcpTools, bucketCacheHitRatio, bucketSavingsFraction, claudeEquivalentCost, codeSystemPrompt, compareVersions, computeReplayStats, costUsd, decideOutcome, defaultConfigPath, defaultSelector, defaultUsageLogPath, deleteSession, detectAtPicker, detectShellOperator, diffTranscripts, emptyPlanState, expandAtMentions, fetchWithRetry, fixToolCallPairing, flattenMcpResult, flattenSchema, forkRegistryExcluding, formatCommandResult, formatHookOutcomeMessage, formatLogSize, formatLoopError, formatSearchResults, getLatestVersion, globalSettingsPath, harvest, healLoadedMessages, healLoadedMessagesByTokens, htmlToText, injectPowerShellUtf8, inputCostUsd, inspectMcpServer, isAllowed, isJsonRpcError, isNpxInstall, isPlanStateEmpty, isPlausibleKey, listFilesSync, listSessions, loadApiKey, loadDotenv, loadHooks, loadSessionMessages, matchesTool, memoryEnabled, nestArguments, openTranscriptFile, outputCostUsd, parseEditBlocks, parseMcpSpec, parseMojeekResults, parseTranscript, prepareSpawn, projectHash, projectSettingsPath, quoteForCmdExe, rankPickerCandidates, readConfig, readProjectMemory, readTranscript, readUsageLog, recordFromLoopEvent, redactKey, registerFilesystemTools, registerMemoryTools, registerPlanTool, registerShellTools, registerSubagentTool, registerWebTools, renderMarkdown as renderDiffMarkdown, renderSummaryTable as renderDiffSummary, repairTruncatedJson, replayFromFile, resolveExecutable, restoreSnapshots, runBranches, runCommand, runHooks, sanitizeMemoryName, sanitizeName as sanitizeSessionName, saveApiKey, scavengeToolCalls, sessionPath, sessionsDir, similarity, snapshotBeforeEdits, stripHallucinatedToolMarkup, tokenizeCommand, truncateForModel, truncateForModelByTokens, webFetch, webSearch, withUtf8Codepage, writeConfig, writeMeta, writeRecord };
|
|
3224
|
+
export { AT_MENTION_PATTERN, AT_PICKER_PREFIX, type AggregateOptions, AppendOnlyLog, type AppendUsageInput, type ApplyResult, type ApplyStatus, type AtMentionExpansion, type AtMentionOptions, type BranchOptions, type BranchProgress, type BranchResult, type BranchSample, type BranchSelector, type BranchSummary, type BridgeOptions, type BridgeResult, CODE_SYSTEM_PROMPT, CacheFirstLoop, type CacheFirstLoopOptions, type CallToolResult, type ChatMessage, type ChatResponse, DEFAULT_AT_MENTION_MAX_BYTES, DEFAULT_MAX_RESULT_CHARS, DEFAULT_MAX_RESULT_TOKENS, DEFAULT_PICKER_IGNORE_DIRS, DeepSeekClient, type DeepSeekClientOptions, type RenderOptions as DiffRenderOptions, type DiffReport, type DiffSide, type EditBlock, type EditSnapshot, type EventRole, type FileWithStats, type FilesystemToolsOptions, type FlattenDecision, type FlattenOptions, type GetLatestVersionOptions, type GetPromptResult, HOOK_EVENTS, HOOK_SETTINGS_DIRNAME, HOOK_SETTINGS_FILENAME, type HarvestOptions, type HookConfig, type HookEvent, type HookOutcome, type HookPayload, type HookReport, type HookScope, type HookSettings, type HookSpawnInput, type HookSpawnResult, type HookSpawner, ImmutablePrefix, type ImmutablePrefixOptions, type InitializeResult, type InspectionReport, type JSONSchema, type JsonRpcMessage, type JsonRpcRequest, type JsonRpcResponse, LATEST_CACHE_TTL_MS, LATEST_FETCH_TIMEOUT_MS, type ListFilesOptions, type ListPromptsResult, type ListResourcesResult, type ListToolsResult, type LoadHookSettingsOptions, type LoopEvent, MCP_PROTOCOL_VERSION, MEMORY_INDEX_FILE, MEMORY_INDEX_MAX_CHARS, McpClient, type McpClientOptions, type McpContentBlock, type McpProgressHandler, type McpProgressInfo, type McpPrompt, type McpPromptArgument, type McpPromptMessage, type McpPromptResourceBlock, type McpResource, type McpResourceContents, type McpResourceContentsBlob, type McpResourceContentsText, type McpSpec, type McpTool, type McpToolSchema, type McpTransport, type MemoryEntry, type MemoryScope, MemoryStore, type MemoryStoreOptions, type MemoryToolsOptions, type MemoryType, type WriteInput as MemoryWriteInput, NeedsConfirmationError, PROJECT_MEMORY_FILE, PROJECT_MEMORY_MAX_CHARS, type PageContent, type PickerCandidate, PlanProposedError, type PlanToolOptions, type ProgressNotificationParams, type ProjectMemory, type RankPickerOptions, type ReadResourceResult, type ReadTranscriptResult, type ReasonixConfig, type ReconfigurableOptions, type RepairReport, type ReplayStats, type ResolvedHook, type RetryInfo, type RetryOptions, type Role, type RunCommandResult, type RunHooksOptions, type ScavengeOptions, type ScavengeResult, type SearchResult, type SectionResult, type SessionInfo, SessionStats, type SessionSummary, type ShellToolsOptions, type SseMcpSpec, SseTransport, type SseTransportOptions, type StdioMcpSpec, StdioTransport, type StdioTransportOptions, StormBreaker, type StreamChunk, type SubagentEvent, type SubagentSink, type SubagentToolOptions, type ToolCall, type ToolCallContext, ToolCallRepair, type ToolCallRepairOptions, type ToolDefinition, type ToolFunctionSpec, ToolRegistry, type ToolSpec, type TranscriptMeta, type TranscriptRecord, type TruncationRepairResult, type TurnPair, type TurnStats, type TypedPlanState, USER_MEMORY_DIR, Usage, type UsageAggregate, type UsageBucket, type UsageRecord, VERSION, VolatileScratch, type WebFetchOptions, type WebSearchOptions, type WebToolsOptions, aggregateBranchUsage, aggregateUsage, analyzeSchema, appendSessionMessage, appendUsage, applyEditBlock, applyEditBlocks, applyMemoryStack, applyProjectMemory, applyUserMemory, bridgeMcpTools, bucketCacheHitRatio, bucketSavingsFraction, claudeEquivalentCost, codeSystemPrompt, compareVersions, computeReplayStats, costUsd, decideOutcome, defaultConfigPath, defaultSelector, defaultUsageLogPath, deleteSession, detectAtPicker, detectShellOperator, diffTranscripts, emptyPlanState, expandAtMentions, fetchWithRetry, fixToolCallPairing, flattenMcpResult, flattenSchema, forkRegistryExcluding, formatCommandResult, formatHookOutcomeMessage, formatLogSize, formatLoopError, formatSearchResults, getLatestVersion, globalSettingsPath, harvest, healLoadedMessages, healLoadedMessagesByTokens, htmlToText, injectPowerShellUtf8, inputCostUsd, inspectMcpServer, isAllowed, isJsonRpcError, isNpxInstall, isPlanStateEmpty, isPlausibleKey, listFilesSync, listFilesWithStatsSync, listSessions, loadApiKey, loadDotenv, loadHooks, loadSessionMessages, matchesTool, memoryEnabled, nestArguments, openTranscriptFile, outputCostUsd, parseEditBlocks, parseMcpSpec, parseMojeekResults, parseTranscript, prepareSpawn, projectHash, projectSettingsPath, quoteForCmdExe, rankPickerCandidates, readConfig, readProjectMemory, readTranscript, readUsageLog, recordFromLoopEvent, redactKey, registerFilesystemTools, registerMemoryTools, registerPlanTool, registerShellTools, registerSubagentTool, registerWebTools, renderMarkdown as renderDiffMarkdown, renderSummaryTable as renderDiffSummary, repairTruncatedJson, replayFromFile, resolveExecutable, restoreSnapshots, runBranches, runCommand, runHooks, sanitizeMemoryName, sanitizeName as sanitizeSessionName, saveApiKey, scavengeToolCalls, sessionPath, sessionsDir, similarity, snapshotBeforeEdits, stripHallucinatedToolMarkup, tokenizeCommand, truncateForModel, truncateForModelByTokens, webFetch, webSearch, withUtf8Codepage, writeConfig, writeMeta, writeRecord };
|
package/dist/index.js
CHANGED
|
@@ -1563,6 +1563,11 @@ function deleteSession(name) {
|
|
|
1563
1563
|
const path = sessionPath(name);
|
|
1564
1564
|
try {
|
|
1565
1565
|
unlinkSync(path);
|
|
1566
|
+
const sidecar = path.replace(/\.jsonl$/, ".pending.json");
|
|
1567
|
+
try {
|
|
1568
|
+
unlinkSync(sidecar);
|
|
1569
|
+
} catch {
|
|
1570
|
+
}
|
|
1566
1571
|
return true;
|
|
1567
1572
|
} catch {
|
|
1568
1573
|
return false;
|
|
@@ -1590,13 +1595,18 @@ function countLines(path) {
|
|
|
1590
1595
|
|
|
1591
1596
|
// src/telemetry.ts
|
|
1592
1597
|
var DEEPSEEK_PRICING = {
|
|
1593
|
-
"deepseek-
|
|
1594
|
-
"deepseek-
|
|
1598
|
+
"deepseek-v4-flash": { inputCacheHit: 0.028, inputCacheMiss: 0.139, output: 0.278 },
|
|
1599
|
+
"deepseek-v4-pro": { inputCacheHit: 0.139, inputCacheMiss: 1.667, output: 3.333 },
|
|
1600
|
+
// Compat aliases — priced as v4-flash per the deprecation notice.
|
|
1601
|
+
"deepseek-chat": { inputCacheHit: 0.028, inputCacheMiss: 0.139, output: 0.278 },
|
|
1602
|
+
"deepseek-reasoner": { inputCacheHit: 0.028, inputCacheMiss: 0.139, output: 0.278 }
|
|
1595
1603
|
};
|
|
1596
1604
|
var CLAUDE_SONNET_PRICING = { input: 3, output: 15 };
|
|
1597
1605
|
var DEEPSEEK_CONTEXT_TOKENS = {
|
|
1598
|
-
"deepseek-
|
|
1599
|
-
"deepseek-
|
|
1606
|
+
"deepseek-v4-flash": 1e6,
|
|
1607
|
+
"deepseek-v4-pro": 1e6,
|
|
1608
|
+
"deepseek-chat": 1e6,
|
|
1609
|
+
"deepseek-reasoner": 1e6
|
|
1600
1610
|
};
|
|
1601
1611
|
var DEFAULT_CONTEXT_TOKENS = 131072;
|
|
1602
1612
|
function costUsd(model, usage) {
|
|
@@ -1924,7 +1934,7 @@ var CacheFirstLoop = class {
|
|
|
1924
1934
|
content: `aborted at iter ${iter}/${this.maxToolIters} \u2014 stopped without producing a summary (press \u2191 + Enter or /retry to resume)`
|
|
1925
1935
|
};
|
|
1926
1936
|
const stoppedMsg = "[aborted by user (Esc) \u2014 no summary produced. Ask again or /retry when ready; prior tool output is still in the log.]";
|
|
1927
|
-
this.appendAndPersist(
|
|
1937
|
+
this.appendAndPersist(this.syntheticAssistantMessage(stoppedMsg));
|
|
1928
1938
|
yield {
|
|
1929
1939
|
turn: this._turn,
|
|
1930
1940
|
role: "assistant_final",
|
|
@@ -2060,6 +2070,7 @@ var CacheFirstLoop = class {
|
|
|
2060
2070
|
};
|
|
2061
2071
|
} else if (this.stream) {
|
|
2062
2072
|
const callBuf = /* @__PURE__ */ new Map();
|
|
2073
|
+
const readyIndices = /* @__PURE__ */ new Set();
|
|
2063
2074
|
for await (const chunk of this.client.stream({
|
|
2064
2075
|
model: this.model,
|
|
2065
2076
|
messages,
|
|
@@ -2095,13 +2106,18 @@ var CacheFirstLoop = class {
|
|
|
2095
2106
|
if (d.argumentsDelta)
|
|
2096
2107
|
cur.function.arguments = (cur.function.arguments ?? "") + d.argumentsDelta;
|
|
2097
2108
|
callBuf.set(d.index, cur);
|
|
2109
|
+
if (!readyIndices.has(d.index) && cur.function.name && looksLikeCompleteJson(cur.function.arguments ?? "")) {
|
|
2110
|
+
readyIndices.add(d.index);
|
|
2111
|
+
}
|
|
2098
2112
|
if (cur.function.name) {
|
|
2099
2113
|
yield {
|
|
2100
2114
|
turn: this._turn,
|
|
2101
2115
|
role: "tool_call_delta",
|
|
2102
2116
|
content: "",
|
|
2103
2117
|
toolName: cur.function.name,
|
|
2104
|
-
toolCallArgsChars: (cur.function.arguments ?? "").length
|
|
2118
|
+
toolCallArgsChars: (cur.function.arguments ?? "").length,
|
|
2119
|
+
toolCallIndex: d.index,
|
|
2120
|
+
toolCallReadyCount: readyIndices.size
|
|
2105
2121
|
};
|
|
2106
2122
|
}
|
|
2107
2123
|
}
|
|
@@ -2152,7 +2168,9 @@ var CacheFirstLoop = class {
|
|
|
2152
2168
|
reasoningContent || null,
|
|
2153
2169
|
assistantContent || null
|
|
2154
2170
|
);
|
|
2155
|
-
this.appendAndPersist(
|
|
2171
|
+
this.appendAndPersist(
|
|
2172
|
+
this.assistantMessage(assistantContent, repairedCalls, reasoningContent)
|
|
2173
|
+
);
|
|
2156
2174
|
yield {
|
|
2157
2175
|
turn: this._turn,
|
|
2158
2176
|
role: "assistant_final",
|
|
@@ -2314,7 +2332,7 @@ ${reason}`;
|
|
|
2314
2332
|
|
|
2315
2333
|
${summary}`;
|
|
2316
2334
|
const summaryStats = this.stats.record(this._turn, this.model, resp.usage ?? new Usage());
|
|
2317
|
-
this.appendAndPersist(
|
|
2335
|
+
this.appendAndPersist(this.assistantMessage(summary, [], resp.reasoningContent ?? void 0));
|
|
2318
2336
|
yield {
|
|
2319
2337
|
turn: this._turn,
|
|
2320
2338
|
role: "assistant_final",
|
|
@@ -2343,12 +2361,35 @@ ${summary}`;
|
|
|
2343
2361
|
}
|
|
2344
2362
|
return final;
|
|
2345
2363
|
}
|
|
2346
|
-
assistantMessage(content, toolCalls) {
|
|
2364
|
+
assistantMessage(content, toolCalls, reasoningContent) {
|
|
2347
2365
|
const msg = { role: "assistant", content };
|
|
2348
2366
|
if (toolCalls.length > 0) msg.tool_calls = toolCalls;
|
|
2367
|
+
if (reasoningContent && reasoningContent.length > 0) {
|
|
2368
|
+
msg.reasoning_content = reasoningContent;
|
|
2369
|
+
}
|
|
2370
|
+
return msg;
|
|
2371
|
+
}
|
|
2372
|
+
/**
|
|
2373
|
+
* Build a synthetic assistant message we insert into the log without
|
|
2374
|
+
* a real API round trip (abort notices, future system injections).
|
|
2375
|
+
* Reasoner models reject follow-up requests whose assistant history
|
|
2376
|
+
* is missing `reasoning_content`, so we stamp an empty-string
|
|
2377
|
+
* placeholder on reasoner sessions to satisfy the validator. V3
|
|
2378
|
+
* doesn't care — field stays absent there.
|
|
2379
|
+
*/
|
|
2380
|
+
syntheticAssistantMessage(content) {
|
|
2381
|
+
const msg = { role: "assistant", content };
|
|
2382
|
+
if (isThinkingModeModel(this.model)) {
|
|
2383
|
+
msg.reasoning_content = "";
|
|
2384
|
+
}
|
|
2349
2385
|
return msg;
|
|
2350
2386
|
}
|
|
2351
2387
|
};
|
|
2388
|
+
function isThinkingModeModel(model) {
|
|
2389
|
+
if (model.includes("reasoner")) return true;
|
|
2390
|
+
if (model === "deepseek-v4-flash" || model === "deepseek-v4-pro") return true;
|
|
2391
|
+
return false;
|
|
2392
|
+
}
|
|
2352
2393
|
function stripHallucinatedToolMarkup(s) {
|
|
2353
2394
|
let out = s;
|
|
2354
2395
|
out = out.replace(/<|DSML|function_calls>[\s\S]*?<\/?|DSML|function_calls>/g, "");
|
|
@@ -2364,6 +2405,15 @@ function safeParseToolArgs(raw) {
|
|
|
2364
2405
|
return raw;
|
|
2365
2406
|
}
|
|
2366
2407
|
}
|
|
2408
|
+
function looksLikeCompleteJson(s) {
|
|
2409
|
+
if (!s || !s.trim()) return false;
|
|
2410
|
+
try {
|
|
2411
|
+
JSON.parse(s);
|
|
2412
|
+
return true;
|
|
2413
|
+
} catch {
|
|
2414
|
+
return false;
|
|
2415
|
+
}
|
|
2416
|
+
}
|
|
2367
2417
|
function* hookWarnings(outcomes, turn) {
|
|
2368
2418
|
for (const o of outcomes) {
|
|
2369
2419
|
if (o.decision === "pass") continue;
|
|
@@ -2511,6 +2561,9 @@ var DEFAULT_PICKER_IGNORE_DIRS = [
|
|
|
2511
2561
|
"__pycache__"
|
|
2512
2562
|
];
|
|
2513
2563
|
function listFilesSync(root, opts = {}) {
|
|
2564
|
+
return listFilesWithStatsSync(root, opts).map((e) => e.path);
|
|
2565
|
+
}
|
|
2566
|
+
function listFilesWithStatsSync(root, opts = {}) {
|
|
2514
2567
|
const maxResults = Math.max(1, opts.maxResults ?? 500);
|
|
2515
2568
|
const ignore = new Set(opts.ignoreDirs ?? DEFAULT_PICKER_IGNORE_DIRS);
|
|
2516
2569
|
const rootAbs = resolve(root);
|
|
@@ -2531,7 +2584,12 @@ function listFilesSync(root, opts = {}) {
|
|
|
2531
2584
|
if (ent.name.startsWith(".") || ignore.has(ent.name)) continue;
|
|
2532
2585
|
walk2(join4(dirAbs, ent.name), relPath);
|
|
2533
2586
|
} else if (ent.isFile()) {
|
|
2534
|
-
|
|
2587
|
+
let mtimeMs = 0;
|
|
2588
|
+
try {
|
|
2589
|
+
mtimeMs = statSync2(join4(dirAbs, ent.name)).mtimeMs;
|
|
2590
|
+
} catch {
|
|
2591
|
+
}
|
|
2592
|
+
out.push({ path: relPath, mtimeMs });
|
|
2535
2593
|
}
|
|
2536
2594
|
}
|
|
2537
2595
|
};
|
|
@@ -2546,12 +2604,31 @@ function detectAtPicker(input) {
|
|
|
2546
2604
|
const atOffset = input.length - query.length - 1;
|
|
2547
2605
|
return { query, atOffset };
|
|
2548
2606
|
}
|
|
2549
|
-
function rankPickerCandidates(files, query,
|
|
2550
|
-
|
|
2607
|
+
function rankPickerCandidates(files, query, limitOrOpts) {
|
|
2608
|
+
const opts = typeof limitOrOpts === "number" ? { limit: limitOrOpts } : limitOrOpts ?? {};
|
|
2609
|
+
const limit = opts.limit ?? 40;
|
|
2610
|
+
const recent = new Set(opts.recentlyUsed ?? []);
|
|
2611
|
+
const entries = files.map(
|
|
2612
|
+
(f) => typeof f === "string" ? { path: f, mtimeMs: 0 } : f
|
|
2613
|
+
);
|
|
2614
|
+
if (!query) {
|
|
2615
|
+
const anyMtime = entries.some((e) => e.mtimeMs > 0);
|
|
2616
|
+
if (!anyMtime && recent.size === 0) {
|
|
2617
|
+
return entries.slice(0, limit).map((e) => e.path);
|
|
2618
|
+
}
|
|
2619
|
+
const sorted = [...entries].sort((a, b) => {
|
|
2620
|
+
const aRecent = recent.has(a.path) ? 1 : 0;
|
|
2621
|
+
const bRecent = recent.has(b.path) ? 1 : 0;
|
|
2622
|
+
if (aRecent !== bRecent) return bRecent - aRecent;
|
|
2623
|
+
if (a.mtimeMs !== b.mtimeMs) return b.mtimeMs - a.mtimeMs;
|
|
2624
|
+
return a.path.localeCompare(b.path);
|
|
2625
|
+
});
|
|
2626
|
+
return sorted.slice(0, limit).map((e) => e.path);
|
|
2627
|
+
}
|
|
2551
2628
|
const needle = query.toLowerCase();
|
|
2552
2629
|
const scored = [];
|
|
2553
|
-
for (const
|
|
2554
|
-
const lower =
|
|
2630
|
+
for (const e of entries) {
|
|
2631
|
+
const lower = e.path.toLowerCase();
|
|
2555
2632
|
const hit = lower.indexOf(needle);
|
|
2556
2633
|
if (hit < 0) continue;
|
|
2557
2634
|
const slash = lower.lastIndexOf("/");
|
|
@@ -2559,9 +2636,18 @@ function rankPickerCandidates(files, query, limit = 40) {
|
|
|
2559
2636
|
let score = 2;
|
|
2560
2637
|
if (base.startsWith(needle)) score = 0;
|
|
2561
2638
|
else if (lower.startsWith(needle)) score = 1;
|
|
2562
|
-
scored.push({
|
|
2639
|
+
scored.push({
|
|
2640
|
+
path: e.path,
|
|
2641
|
+
score: score * 1e4 + hit,
|
|
2642
|
+
mtimeMs: e.mtimeMs,
|
|
2643
|
+
recent: recent.has(e.path)
|
|
2644
|
+
});
|
|
2563
2645
|
}
|
|
2564
|
-
scored.sort((a, b) =>
|
|
2646
|
+
scored.sort((a, b) => {
|
|
2647
|
+
if (a.score !== b.score) return a.score - b.score;
|
|
2648
|
+
if (a.recent !== b.recent) return a.recent ? -1 : 1;
|
|
2649
|
+
return b.mtimeMs - a.mtimeMs;
|
|
2650
|
+
});
|
|
2565
2651
|
return scored.slice(0, limit).map((s) => s.path);
|
|
2566
2652
|
}
|
|
2567
2653
|
var AT_MENTION_PATTERN = /(?<=^|\s)@([a-zA-Z0-9_./\\-]+)/g;
|
|
@@ -3925,11 +4011,14 @@ async function spawnSubagent(opts) {
|
|
|
3925
4011
|
const maxToolIters = opts.maxToolIters ?? DEFAULT_MAX_ITERS;
|
|
3926
4012
|
const maxResultChars = opts.maxResultChars ?? DEFAULT_MAX_RESULT_CHARS2;
|
|
3927
4013
|
const sink = opts.sink;
|
|
4014
|
+
const skillName = opts.skillName;
|
|
3928
4015
|
const startedAt = Date.now();
|
|
3929
4016
|
const taskPreview = opts.task.length > 30 ? `${opts.task.slice(0, 30)}\u2026` : opts.task;
|
|
3930
4017
|
sink?.current?.({
|
|
3931
4018
|
kind: "start",
|
|
3932
4019
|
task: taskPreview,
|
|
4020
|
+
skillName,
|
|
4021
|
+
model,
|
|
3933
4022
|
iter: 0,
|
|
3934
4023
|
elapsedMs: 0
|
|
3935
4024
|
});
|
|
@@ -3959,6 +4048,8 @@ async function spawnSubagent(opts) {
|
|
|
3959
4048
|
sink?.current?.({
|
|
3960
4049
|
kind: "progress",
|
|
3961
4050
|
task: taskPreview,
|
|
4051
|
+
skillName,
|
|
4052
|
+
model,
|
|
3962
4053
|
iter: toolIter,
|
|
3963
4054
|
elapsedMs: Date.now() - startedAt
|
|
3964
4055
|
});
|
|
@@ -3981,17 +4072,22 @@ async function spawnSubagent(opts) {
|
|
|
3981
4072
|
const elapsedMs = Date.now() - startedAt;
|
|
3982
4073
|
const turns = childLoop.stats.turns.length;
|
|
3983
4074
|
const costUsd2 = childLoop.stats.totalCost;
|
|
4075
|
+
const usage = aggregateChildUsage(childLoop);
|
|
3984
4076
|
const truncated = final.length > maxResultChars ? `${final.slice(0, maxResultChars)}
|
|
3985
4077
|
|
|
3986
4078
|
[\u2026truncated ${final.length - maxResultChars} chars; ask the subagent for a tighter summary if you need more.]` : final;
|
|
3987
4079
|
sink?.current?.({
|
|
3988
4080
|
kind: "end",
|
|
3989
4081
|
task: taskPreview,
|
|
4082
|
+
skillName,
|
|
4083
|
+
model,
|
|
3990
4084
|
iter: toolIter,
|
|
3991
4085
|
elapsedMs,
|
|
3992
4086
|
summary: errorMessage ? void 0 : truncated.slice(0, 120),
|
|
3993
4087
|
error: errorMessage,
|
|
3994
|
-
turns
|
|
4088
|
+
turns,
|
|
4089
|
+
costUsd: costUsd2,
|
|
4090
|
+
usage
|
|
3995
4091
|
});
|
|
3996
4092
|
return {
|
|
3997
4093
|
success: !errorMessage,
|
|
@@ -4000,9 +4096,23 @@ async function spawnSubagent(opts) {
|
|
|
4000
4096
|
turns,
|
|
4001
4097
|
toolIters: toolIter,
|
|
4002
4098
|
elapsedMs,
|
|
4003
|
-
costUsd: costUsd2
|
|
4099
|
+
costUsd: costUsd2,
|
|
4100
|
+
model,
|
|
4101
|
+
skillName,
|
|
4102
|
+
usage
|
|
4004
4103
|
};
|
|
4005
4104
|
}
|
|
4105
|
+
function aggregateChildUsage(loop) {
|
|
4106
|
+
const agg = new Usage();
|
|
4107
|
+
for (const t of loop.stats.turns) {
|
|
4108
|
+
agg.promptTokens += t.usage.promptTokens;
|
|
4109
|
+
agg.completionTokens += t.usage.completionTokens;
|
|
4110
|
+
agg.totalTokens += t.usage.totalTokens;
|
|
4111
|
+
agg.promptCacheHitTokens += t.usage.promptCacheHitTokens;
|
|
4112
|
+
agg.promptCacheMissTokens += t.usage.promptCacheMissTokens;
|
|
4113
|
+
}
|
|
4114
|
+
return agg;
|
|
4115
|
+
}
|
|
4006
4116
|
function formatSubagentResult(r) {
|
|
4007
4117
|
if (!r.success) {
|
|
4008
4118
|
return JSON.stringify({
|
|
@@ -4045,8 +4155,8 @@ function registerSubagentTool(parentRegistry, opts) {
|
|
|
4045
4155
|
},
|
|
4046
4156
|
model: {
|
|
4047
4157
|
type: "string",
|
|
4048
|
-
enum: ["deepseek-chat", "deepseek-reasoner"],
|
|
4049
|
-
description: "Which DeepSeek model the subagent runs on. 'deepseek-
|
|
4158
|
+
enum: ["deepseek-v4-flash", "deepseek-v4-pro", "deepseek-chat", "deepseek-reasoner"],
|
|
4159
|
+
description: "Which DeepSeek model the subagent runs on. 'deepseek-v4-flash' (default; thinking mode) is fast and cheap and is what the legacy 'deepseek-chat' / 'deepseek-reasoner' aliases route to today. Use 'deepseek-v4-pro' only when the subtask needs the strongest model \u2014 roughly 12\xD7 the input cost and 12\xD7 the output cost vs flash."
|
|
4050
4160
|
}
|
|
4051
4161
|
},
|
|
4052
4162
|
required: ["task"]
|
|
@@ -6209,6 +6319,8 @@ function appendUsage(input) {
|
|
|
6209
6319
|
costUsd: costUsd(input.model, input.usage),
|
|
6210
6320
|
claudeEquivUsd: claudeEquivalentCost(input.usage)
|
|
6211
6321
|
};
|
|
6322
|
+
if (input.kind === "subagent") record.kind = "subagent";
|
|
6323
|
+
if (input.subagent) record.subagent = input.subagent;
|
|
6212
6324
|
const path = input.path ?? defaultUsageLogPath();
|
|
6213
6325
|
try {
|
|
6214
6326
|
mkdirSync6(dirname7(path), { recursive: true });
|
|
@@ -6282,6 +6394,10 @@ function aggregateUsage(records, opts = {}) {
|
|
|
6282
6394
|
const sessionCounts = /* @__PURE__ */ new Map();
|
|
6283
6395
|
let firstSeen = null;
|
|
6284
6396
|
let lastSeen = null;
|
|
6397
|
+
const skillCounts = /* @__PURE__ */ new Map();
|
|
6398
|
+
let subagentTotal = 0;
|
|
6399
|
+
let subagentCost = 0;
|
|
6400
|
+
let subagentDuration = 0;
|
|
6285
6401
|
for (const r of records) {
|
|
6286
6402
|
addToBucket(all, r);
|
|
6287
6403
|
if (r.ts >= today.since) addToBucket(today, r);
|
|
@@ -6292,15 +6408,34 @@ function aggregateUsage(records, opts = {}) {
|
|
|
6292
6408
|
sessionCounts.set(sessKey, (sessionCounts.get(sessKey) ?? 0) + 1);
|
|
6293
6409
|
if (firstSeen === null || r.ts < firstSeen) firstSeen = r.ts;
|
|
6294
6410
|
if (lastSeen === null || r.ts > lastSeen) lastSeen = r.ts;
|
|
6411
|
+
if (r.kind === "subagent") {
|
|
6412
|
+
subagentTotal += 1;
|
|
6413
|
+
subagentCost += r.costUsd;
|
|
6414
|
+
const dur = r.subagent?.durationMs ?? 0;
|
|
6415
|
+
subagentDuration += dur;
|
|
6416
|
+
const key = r.subagent?.skillName?.trim() || "(adhoc)";
|
|
6417
|
+
const prev = skillCounts.get(key) ?? { count: 0, costUsd: 0, durationMs: 0 };
|
|
6418
|
+
prev.count += 1;
|
|
6419
|
+
prev.costUsd += r.costUsd;
|
|
6420
|
+
prev.durationMs += dur;
|
|
6421
|
+
skillCounts.set(key, prev);
|
|
6422
|
+
}
|
|
6295
6423
|
}
|
|
6296
6424
|
const byModel = Array.from(modelCounts.entries()).map(([model, turns]) => ({ model, turns })).sort((a, b) => b.turns - a.turns);
|
|
6297
6425
|
const bySession = Array.from(sessionCounts.entries()).map(([session, turns]) => ({ session, turns })).sort((a, b) => b.turns - a.turns);
|
|
6426
|
+
const subagents = subagentTotal > 0 ? {
|
|
6427
|
+
total: subagentTotal,
|
|
6428
|
+
costUsd: subagentCost,
|
|
6429
|
+
totalDurationMs: subagentDuration,
|
|
6430
|
+
bySkill: Array.from(skillCounts.entries()).map(([skillName, v]) => ({ skillName, ...v })).sort((a, b) => b.count - a.count)
|
|
6431
|
+
} : void 0;
|
|
6298
6432
|
return {
|
|
6299
6433
|
buckets: [today, week, month, all],
|
|
6300
6434
|
byModel,
|
|
6301
6435
|
bySession,
|
|
6302
6436
|
firstSeen,
|
|
6303
|
-
lastSeen
|
|
6437
|
+
lastSeen,
|
|
6438
|
+
subagents
|
|
6304
6439
|
};
|
|
6305
6440
|
}
|
|
6306
6441
|
function formatLogSize(path = defaultUsageLogPath()) {
|
|
@@ -6404,6 +6539,7 @@ export {
|
|
|
6404
6539
|
isPlanStateEmpty,
|
|
6405
6540
|
isPlausibleKey,
|
|
6406
6541
|
listFilesSync,
|
|
6542
|
+
listFilesWithStatsSync,
|
|
6407
6543
|
listSessions,
|
|
6408
6544
|
loadApiKey,
|
|
6409
6545
|
loadDotenv,
|