reasonix 0.14.0 → 0.15.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/dist/cli/{chunk-PKPWI33U.js → chunk-7546PPEL.js} +5 -31
- package/dist/cli/chunk-7546PPEL.js.map +1 -0
- package/dist/cli/index.js +1499 -1147
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/{prompt-HNDDXDRH.js → prompt-XPEUBA46.js} +2 -2
- package/dist/index.d.ts +152 -2272
- package/dist/index.js +30 -418
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/cli/chunk-PKPWI33U.js.map +0 -1
- /package/dist/cli/{prompt-HNDDXDRH.js.map → prompt-XPEUBA46.js.map} +0 -0
package/dist/index.js
CHANGED
|
@@ -139,12 +139,7 @@ var DeepSeekClient = class {
|
|
|
139
139
|
}
|
|
140
140
|
return payload;
|
|
141
141
|
}
|
|
142
|
-
/**
|
|
143
|
-
* Fetch the current DeepSeek account balance. Separate endpoint
|
|
144
|
-
* from chat completions, no billing impact. Returns null on any
|
|
145
|
-
* network/auth failure so callers can gate the balance display
|
|
146
|
-
* without a hard error — the rest of the session works regardless.
|
|
147
|
-
*/
|
|
142
|
+
/** Returns null on failure so callers can degrade — session must keep working without balance UI. */
|
|
148
143
|
async getBalance(opts = {}) {
|
|
149
144
|
try {
|
|
150
145
|
const resp = await this._fetch(`${this.baseUrl}/user/balance`, {
|
|
@@ -160,13 +155,7 @@ var DeepSeekClient = class {
|
|
|
160
155
|
return null;
|
|
161
156
|
}
|
|
162
157
|
}
|
|
163
|
-
/**
|
|
164
|
-
* Fetch the model catalog DeepSeek currently exposes. Today this is
|
|
165
|
-
* `deepseek-chat` (V3) and `deepseek-reasoner` (R1), but querying is
|
|
166
|
-
* the only way to learn about new ones without a Reasonix release.
|
|
167
|
-
* Returns null on any network/auth failure so callers can degrade
|
|
168
|
-
* gracefully — e.g. `/models` falls back to the hardcoded hint.
|
|
169
|
-
*/
|
|
158
|
+
/** Returns null on failure — callers fall back to a hardcoded model hint. */
|
|
170
159
|
async listModels(opts = {}) {
|
|
171
160
|
try {
|
|
172
161
|
const resp = await this._fetch(`${this.baseUrl}/models`, {
|
|
@@ -915,19 +904,7 @@ function setByPath(target, path, value) {
|
|
|
915
904
|
var ToolRegistry = class {
|
|
916
905
|
_tools = /* @__PURE__ */ new Map();
|
|
917
906
|
_autoFlatten;
|
|
918
|
-
/**
|
|
919
|
-
* When true, `dispatch` refuses any tool whose `readOnly` flag isn't
|
|
920
|
-
* set (and whose `readOnlyCheck` doesn't pass on the specific args).
|
|
921
|
-
* Drives `reasonix code`'s Plan Mode — the model can still explore
|
|
922
|
-
* via read tools but its writes and non-allowlisted shell calls are
|
|
923
|
-
* bounced until the user approves a submitted plan.
|
|
924
|
-
*/
|
|
925
907
|
_planMode = false;
|
|
926
|
-
/**
|
|
927
|
-
* Optional hook run after arg parsing but before tool.fn. Lets the TUI
|
|
928
|
-
* reroute specific tool calls (e.g. edit_file in review mode) without
|
|
929
|
-
* modifying the tool definitions themselves.
|
|
930
|
-
*/
|
|
931
908
|
_interceptor = null;
|
|
932
909
|
constructor(opts = {}) {
|
|
933
910
|
this._autoFlatten = opts.autoFlatten !== false;
|
|
@@ -940,11 +917,7 @@ var ToolRegistry = class {
|
|
|
940
917
|
get planMode() {
|
|
941
918
|
return this._planMode;
|
|
942
919
|
}
|
|
943
|
-
/**
|
|
944
|
-
* Install or clear the dispatch interceptor. At most one interceptor
|
|
945
|
-
* is active at a time — calling twice replaces the previous. Pass
|
|
946
|
-
* `null` to remove.
|
|
947
|
-
*/
|
|
920
|
+
/** At most one interceptor active; calling twice replaces. */
|
|
948
921
|
setToolInterceptor(fn) {
|
|
949
922
|
this._interceptor = fn;
|
|
950
923
|
}
|
|
@@ -1180,33 +1153,10 @@ function blockToString(block) {
|
|
|
1180
1153
|
import { createHash } from "crypto";
|
|
1181
1154
|
var ImmutablePrefix = class {
|
|
1182
1155
|
system;
|
|
1183
|
-
/**
|
|
1184
|
-
* Backing array for `toolSpecs`. Originally `Object.freeze`d at
|
|
1185
|
-
* construction (hence the class name) — but `addTool` now lets the
|
|
1186
|
-
* dashboard register `semantic_search` after a mid-session
|
|
1187
|
-
* `reasonix index` build without forcing the user to restart. Each
|
|
1188
|
-
* add is documented to cost one cache-miss turn (the cached prefix
|
|
1189
|
-
* on DeepSeek's side is keyed by the full tool list); subsequent
|
|
1190
|
-
* turns re-cache against the new shape.
|
|
1191
|
-
*/
|
|
1156
|
+
/** Each `addTool` costs one cache-miss turn — DeepSeek's prefix cache is keyed by full tool list. */
|
|
1192
1157
|
_toolSpecs;
|
|
1193
1158
|
fewShots;
|
|
1194
|
-
/**
|
|
1195
|
-
* Cached SHA-256 of the prefix payload. Computed lazily on first
|
|
1196
|
-
* `fingerprint` access, invalidated only by mutations that go
|
|
1197
|
-
* through `addTool` (the one legitimate post-construction mutation
|
|
1198
|
-
* path). The TUI reads `fingerprint` on every render — without the
|
|
1199
|
-
* cache, that means a fresh `JSON.stringify` + sha256 over the
|
|
1200
|
-
* full prefix (system prompt + tools list + few-shots, typically
|
|
1201
|
-
* 5-10KB) on every keystroke.
|
|
1202
|
-
*
|
|
1203
|
-
* The lazy-init also acts as a cheap drift guard: if some future
|
|
1204
|
-
* code path mutates `_toolSpecs` directly without going through
|
|
1205
|
-
* `addTool`, `fingerprint` will return the stale cached value
|
|
1206
|
-
* while the actual prefix sent to DeepSeek diverges — the cache
|
|
1207
|
-
* miss would be the first symptom. {@link verifyFingerprint}
|
|
1208
|
-
* lets dev / test code assert the cache matches reality.
|
|
1209
|
-
*/
|
|
1159
|
+
/** Invalidated only via `addTool`; bypassing it leaves cache stale → fingerprint diverges from sent prefix. */
|
|
1210
1160
|
_fingerprintCache = null;
|
|
1211
1161
|
constructor(opts) {
|
|
1212
1162
|
this.system = opts.system;
|
|
@@ -1222,12 +1172,6 @@ var ImmutablePrefix = class {
|
|
|
1222
1172
|
tools() {
|
|
1223
1173
|
return this._toolSpecs.map((t) => structuredClone(t));
|
|
1224
1174
|
}
|
|
1225
|
-
/**
|
|
1226
|
-
* Add a tool spec to the prefix. Returns `true` if added, `false`
|
|
1227
|
-
* if a tool with the same name was already present (callers can
|
|
1228
|
-
* decide whether to ignore or surface the no-op). The model picks
|
|
1229
|
-
* up the new tool on the next turn after the cache busts once.
|
|
1230
|
-
*/
|
|
1231
1175
|
addTool(spec) {
|
|
1232
1176
|
const name = spec.function?.name;
|
|
1233
1177
|
if (!name) return false;
|
|
@@ -1241,14 +1185,7 @@ var ImmutablePrefix = class {
|
|
|
1241
1185
|
this._fingerprintCache = this.computeFingerprint();
|
|
1242
1186
|
return this._fingerprintCache;
|
|
1243
1187
|
}
|
|
1244
|
-
/**
|
|
1245
|
-
* Recompute the fingerprint from scratch and assert it matches the
|
|
1246
|
-
* cached value. Returns the freshly-computed hash on success; throws
|
|
1247
|
-
* with a diff if the cache drifted, which always indicates a bug —
|
|
1248
|
-
* either a non-`addTool` mutation path was added, or `addTool`
|
|
1249
|
-
* forgot to invalidate the cache. Dev / test only; the live loop
|
|
1250
|
-
* doesn't call this on the hot path.
|
|
1251
|
-
*/
|
|
1188
|
+
/** Dev/test only — throws on cache drift, which always means a non-`addTool` mutation slipped in. */
|
|
1252
1189
|
verifyFingerprint() {
|
|
1253
1190
|
const fresh = this.computeFingerprint();
|
|
1254
1191
|
if (this._fingerprintCache !== null && this._fingerprintCache !== fresh) {
|
|
@@ -1279,13 +1216,7 @@ var AppendOnlyLog = class {
|
|
|
1279
1216
|
extend(messages) {
|
|
1280
1217
|
for (const m of messages) this.append(m);
|
|
1281
1218
|
}
|
|
1282
|
-
/**
|
|
1283
|
-
* Bulk-replace entries. Intentionally named to be hard to reach for —
|
|
1284
|
-
* this is the one mutation path that breaks the log's append-only
|
|
1285
|
-
* spirit, reserved for compaction flows (`/compact`) and recovery
|
|
1286
|
-
* where the caller has consciously decided to drop old history. Any
|
|
1287
|
-
* other use is almost certainly wrong; append() is what you want.
|
|
1288
|
-
*/
|
|
1219
|
+
/** The one append-only-breaking path — reserved for `/compact` + recovery. Use `append()` otherwise. */
|
|
1289
1220
|
compactInPlace(replacement) {
|
|
1290
1221
|
this._entries = [...replacement];
|
|
1291
1222
|
}
|
|
@@ -1559,13 +1490,7 @@ var ToolCallRepair = class {
|
|
|
1559
1490
|
this.opts = opts;
|
|
1560
1491
|
this.storm = new StormBreaker(opts.stormWindow ?? 6, opts.stormThreshold ?? 3, opts.isMutating);
|
|
1561
1492
|
}
|
|
1562
|
-
/**
|
|
1563
|
-
* Drop the StormBreaker's sliding window of recent (name, args)
|
|
1564
|
-
* signatures. Called at the start of every user turn — a fresh user
|
|
1565
|
-
* message is a new intent, so carrying old repetition state into it
|
|
1566
|
-
* would turn a valid "try again with different input" flow into a
|
|
1567
|
-
* false-positive block.
|
|
1568
|
-
*/
|
|
1493
|
+
/** Called at start of every user turn — fresh intent shouldn't inherit old repetition state. */
|
|
1569
1494
|
resetStorm() {
|
|
1570
1495
|
this.storm.reset();
|
|
1571
1496
|
}
|
|
@@ -1846,85 +1771,23 @@ var CacheFirstLoop = class {
|
|
|
1846
1771
|
harvestOptions;
|
|
1847
1772
|
branchEnabled;
|
|
1848
1773
|
branchOptions;
|
|
1849
|
-
/** See ReconfigurableOptions — mutable so `/effort` can flip mid-session. */
|
|
1850
1774
|
reasoningEffort;
|
|
1851
|
-
/**
|
|
1852
|
-
* Auto-escalation toggle. `true` lets the loop self-promote to pro
|
|
1853
|
-
* mid-turn (NEEDS_PRO marker / failure threshold); `false` keeps it
|
|
1854
|
-
* pinned to `model`. Mutable so the dashboard's preset switcher can
|
|
1855
|
-
* flip it live alongside `model`.
|
|
1856
|
-
*/
|
|
1857
1775
|
autoEscalate = true;
|
|
1858
|
-
/**
|
|
1859
|
-
* Soft USD budget — see {@link CacheFirstLoopOptions.budgetUsd}.
|
|
1860
|
-
* Mutable so `/budget` slash can set / change / clear it mid-session.
|
|
1861
|
-
* `null` (the default) disables all budget checks.
|
|
1862
|
-
*/
|
|
1863
1776
|
budgetUsd;
|
|
1864
|
-
/**
|
|
1865
|
-
* Set the first time a turn crosses 80% of the budget so the warning
|
|
1866
|
-
* doesn't repeat every turn afterwards. Cleared by `setBudget` (any
|
|
1867
|
-
* change re-arms the warning, including raising the cap above the
|
|
1868
|
-
* current spend).
|
|
1869
|
-
*/
|
|
1777
|
+
/** One-shot 80% warning latch — cleared by setBudget so a bump re-arms at the new boundary. */
|
|
1870
1778
|
_budgetWarned = false;
|
|
1871
1779
|
sessionName;
|
|
1872
|
-
/**
|
|
1873
|
-
* Hook list, mutable so `/hooks reload` can swap it without
|
|
1874
|
-
* reconstructing the loop. Default empty — the filter cost on a
|
|
1875
|
-
* tool call is one array length check.
|
|
1876
|
-
*/
|
|
1877
1780
|
hooks;
|
|
1878
|
-
/**
|
|
1879
|
-
* `cwd` reported to hook stdin. Mutable so `/cwd` can switch the
|
|
1880
|
-
* working directory mid-session — the App keeps it in sync with
|
|
1881
|
-
* the same currentRootDir that drives tool re-registration.
|
|
1882
|
-
*/
|
|
1883
1781
|
hookCwd;
|
|
1884
1782
|
/** Number of messages that were pre-loaded from the session file. */
|
|
1885
1783
|
resumedMessageCount;
|
|
1886
1784
|
_turn = 0;
|
|
1887
1785
|
_streamPreference;
|
|
1888
|
-
/**
|
|
1889
|
-
* AbortController per active turn. Threaded through the DeepSeek
|
|
1890
|
-
* HTTP calls AND every tool dispatch so Esc actually cancels the
|
|
1891
|
-
* in-flight network/subprocess work — not "we'll get to it after
|
|
1892
|
-
* the current call finishes." Re-created at the start of each
|
|
1893
|
-
* `step()` (the prior turn's signal has already fired).
|
|
1894
|
-
*/
|
|
1786
|
+
/** Threaded through HTTP + every tool dispatch so Esc cancels in-flight work, not after. */
|
|
1895
1787
|
_turnAbort = new AbortController();
|
|
1896
|
-
/**
|
|
1897
|
-
* "Next turn should run on pro, regardless of this.model." Set by the
|
|
1898
|
-
* `/pro` slash command; consumed at the next turn's start (flipping
|
|
1899
|
-
* `_escalateThisTurn` on and self-clearing) so it's a fire-and-forget
|
|
1900
|
-
* single-turn upgrade. Survives across multiple slash inputs so
|
|
1901
|
-
* typing `/pro` and then hesitating a while before submitting a real
|
|
1902
|
-
* message still applies.
|
|
1903
|
-
*/
|
|
1904
1788
|
_proArmedForNextTurn = false;
|
|
1905
|
-
/**
|
|
1906
|
-
* Active for the current turn only — true means every model call
|
|
1907
|
-
* this turn uses pro instead of `this.model`. Turned on by EITHER
|
|
1908
|
-
* the pro-armed consumption OR the mid-turn auto-escalation
|
|
1909
|
-
* threshold (see `_turnFailureCount`). Cleared at turn end.
|
|
1910
|
-
*/
|
|
1911
1789
|
_escalateThisTurn = false;
|
|
1912
|
-
/**
|
|
1913
|
-
* Visible-failure count for the current turn. Incremented by tool
|
|
1914
|
-
* dispatch paths when a result matches a known "flash is struggling"
|
|
1915
|
-
* shape (SEARCH-not-found errors, scavenge / truncation / storm
|
|
1916
|
-
* repair fires). Once it hits {@link FAILURE_ESCALATION_THRESHOLD},
|
|
1917
|
-
* the remainder of the turn's model calls auto-upgrade to pro so
|
|
1918
|
-
* the user doesn't watch flash retry the same edit 5 times.
|
|
1919
|
-
*/
|
|
1920
1790
|
_turnFailureCount = 0;
|
|
1921
|
-
/**
|
|
1922
|
-
* Per-type breakdown of failure signals counted toward the turn's
|
|
1923
|
-
* auto-escalation threshold. Surfaced in the warning when the
|
|
1924
|
-
* threshold trips so the user sees what kind of trouble flash
|
|
1925
|
-
* actually hit ("3× search-mismatch, 2× truncated") rather than
|
|
1926
|
-
* just a bare count. Reset alongside _turnFailureCount.
|
|
1927
|
-
*/
|
|
1928
1791
|
_turnFailureTypes = {};
|
|
1929
1792
|
constructor(opts) {
|
|
1930
1793
|
this.client = opts.client;
|
|
@@ -1995,55 +1858,7 @@ var CacheFirstLoop = class {
|
|
|
1995
1858
|
this.resumedMessageCount = 0;
|
|
1996
1859
|
}
|
|
1997
1860
|
}
|
|
1998
|
-
/**
|
|
1999
|
-
* Shrink the log by re-truncating oversized tool results to a tighter
|
|
2000
|
-
* token cap, and persist the result back to disk so the next launch
|
|
2001
|
-
* doesn't re-inherit a fat session file. Returns a summary the TUI
|
|
2002
|
-
* can display.
|
|
2003
|
-
*
|
|
2004
|
-
* The cap is in DeepSeek V3 tokens (not chars) — so CJK text gets
|
|
2005
|
-
* capped at the same effective context footprint as English instead
|
|
2006
|
-
* of slipping past a char cap at 2× the token cost. Default 4000
|
|
2007
|
-
* tokens, matching the token-aware dispatch cap from 0.5.2.
|
|
2008
|
-
*
|
|
2009
|
-
* Only tool-role messages are touched (same rationale as
|
|
2010
|
-
* {@link healLoadedMessages}). User and assistant messages carry
|
|
2011
|
-
* authored intent we can't mechanically shrink without losing
|
|
2012
|
-
* meaning.
|
|
2013
|
-
*/
|
|
2014
|
-
/**
|
|
2015
|
-
* Conservative args-only shrink fired after every tool response —
|
|
2016
|
-
* strictly about ONE thing: stop oversized `edit_file` / `write_file`
|
|
2017
|
-
* arguments from riding every future turn's prompt.
|
|
2018
|
-
*
|
|
2019
|
-
* Why this is worth doing AUTOMATICALLY (not just on /compact):
|
|
2020
|
-
* Each tool-call arguments string sticks in the log verbatim. On a
|
|
2021
|
-
* coding session with ~10 edits, that's 20-40K tokens of stale
|
|
2022
|
-
* SEARCH/REPLACE text riding along on every turn. Even at a 98.9%
|
|
2023
|
-
* cache hit rate the input cost still adds up linearly (cache-hit
|
|
2024
|
-
* price × tokens × turns). Compacting IMMEDIATELY after the tool
|
|
2025
|
-
* responds means the next turn's prompt is already smaller — the
|
|
2026
|
-
* shrink is a one-time write that saves every future prompt.
|
|
2027
|
-
*
|
|
2028
|
-
* Threshold rationale: 800 tokens ≈ 3 KB. A typical 20-line edit's
|
|
2029
|
-
* args land well under that; massive rewrites (whole-file content,
|
|
2030
|
-
* 100+ line refactors) land above and get the compaction. Small
|
|
2031
|
-
* edits stay byte-verbatim so nothing common-case changes.
|
|
2032
|
-
*
|
|
2033
|
-
* Safety: we ONLY shrink args whose tool has ALREADY responded.
|
|
2034
|
-
* Structurally that's every call in `log.toMessages()` at this
|
|
2035
|
-
* point — the current turn's assistant/tool pairing is by
|
|
2036
|
-
* construction closed by the time we get here (append happens
|
|
2037
|
-
* AFTER dispatch). The in-flight assistant message being built
|
|
2038
|
-
* lives in scratch, not the log, so this pass can't touch it.
|
|
2039
|
-
*
|
|
2040
|
-
* Model impact: the model may occasionally want to reference the
|
|
2041
|
-
* exact SEARCH text of a prior edit — it then reads the file
|
|
2042
|
-
* directly (which shows current state) or looks at the preceding
|
|
2043
|
-
* assistant text (which has its plan). Losing the stale args is a
|
|
2044
|
-
* net win: one extra read_file vs. dragging N KB of stale text
|
|
2045
|
-
* through every subsequent turn.
|
|
2046
|
-
*/
|
|
1861
|
+
/** Shrink huge edit_file/write_file args post-dispatch — tool result already explains. */
|
|
2047
1862
|
compactToolCallArgsAfterResponse() {
|
|
2048
1863
|
const before = this.log.toMessages();
|
|
2049
1864
|
const { messages, healedCount } = shrinkOversizedToolCallArgsByTokens(
|
|
@@ -2059,25 +1874,7 @@ var CacheFirstLoop = class {
|
|
|
2059
1874
|
}
|
|
2060
1875
|
}
|
|
2061
1876
|
}
|
|
2062
|
-
/**
|
|
2063
|
-
* Fired at the END of a turn (just before `done` is yielded). Shrinks
|
|
2064
|
-
* every tool RESULT in the log that exceeds {@link TURN_END_RESULT_CAP_TOKENS}
|
|
2065
|
-
* to a tight cap so the NEXT turn's prompt doesn't re-pay for big
|
|
2066
|
-
* reads or searches done earlier. Unlike the reactive 40/80%
|
|
2067
|
-
* thresholds which react to context pressure, this runs unconditionally
|
|
2068
|
-
* — the win is preventive: each turn's big outputs get trimmed before
|
|
2069
|
-
* they ride into the next prompt. Saves compounding cost on long
|
|
2070
|
-
* sessions.
|
|
2071
|
-
*
|
|
2072
|
-
* Why compact the JUST-finished turn's results too (not just older
|
|
2073
|
-
* turns)? The same-turn iters already consumed the raw content to
|
|
2074
|
-
* make their decisions — the log is only carried forward for future
|
|
2075
|
-
* prompts. And "let me re-read the file" is vastly cheaper than
|
|
2076
|
-
* "carry this 12KB result in every future turn's prompt forever."
|
|
2077
|
-
*
|
|
2078
|
-
* Safe by construction: args-compact for THIS turn already ran
|
|
2079
|
-
* inside `compactToolCallArgsAfterResponse`; this pass is orthogonal.
|
|
2080
|
-
*/
|
|
1877
|
+
/** Preventive end-of-turn shrink — trim big results before they ride into the next prompt. */
|
|
2081
1878
|
autoCompactToolResultsOnTurnEnd() {
|
|
2082
1879
|
const before = this.log.toMessages();
|
|
2083
1880
|
const shrunk = shrinkOversizedToolResultsByTokens(before, TURN_END_RESULT_CAP_TOKENS);
|
|
@@ -2118,17 +1915,7 @@ var CacheFirstLoop = class {
|
|
|
2118
1915
|
}
|
|
2119
1916
|
}
|
|
2120
1917
|
}
|
|
2121
|
-
/**
|
|
2122
|
-
* Start a fresh conversation WITHOUT exiting. Drops every message
|
|
2123
|
-
* in the in-memory log AND rewrites the session file to empty so
|
|
2124
|
-
* a resume won't re-hydrate the old turns. Unlike `/forget`, which
|
|
2125
|
-
* deletes the session entirely, this keeps the session name and
|
|
2126
|
-
* config intact — it's the "new chat" button.
|
|
2127
|
-
*
|
|
2128
|
-
* The immutable prefix (system prompt + tool specs) is preserved
|
|
2129
|
-
* — that's the cache-first invariant, not part of the conversation.
|
|
2130
|
-
* Returns the number of messages dropped so the UI can show it.
|
|
2131
|
-
*/
|
|
1918
|
+
/** "New chat" — drops messages but keeps session + immutable prefix (cache-first invariant). */
|
|
2132
1919
|
clearLog() {
|
|
2133
1920
|
const dropped = this.log.length;
|
|
2134
1921
|
this.log.compactInPlace([]);
|
|
@@ -2141,12 +1928,6 @@ var CacheFirstLoop = class {
|
|
|
2141
1928
|
this.scratch.reset();
|
|
2142
1929
|
return { dropped };
|
|
2143
1930
|
}
|
|
2144
|
-
/**
|
|
2145
|
-
* Reconfigure model/harvest/branch/stream mid-session. The loop's log,
|
|
2146
|
-
* scratch, and stats are preserved — only the per-turn behavior changes.
|
|
2147
|
-
* Used by the TUI's slash commands and by library callers who want to
|
|
2148
|
-
* flip a knob between turns.
|
|
2149
|
-
*/
|
|
2150
1931
|
configure(opts) {
|
|
2151
1932
|
if (opts.model !== void 0) this.model = opts.model;
|
|
2152
1933
|
if (opts.stream !== void 0) this._streamPreference = opts.stream;
|
|
@@ -2173,22 +1954,12 @@ var CacheFirstLoop = class {
|
|
|
2173
1954
|
}
|
|
2174
1955
|
this.stream = this.branchEnabled ? false : this._streamPreference;
|
|
2175
1956
|
}
|
|
2176
|
-
/**
|
|
2177
|
-
* Set / change / clear the soft USD budget. `null` (or any non-
|
|
2178
|
-
* positive number) disables the cap entirely. Re-arms the 80%
|
|
2179
|
-
* warning so a user who bumps the cap mid-session sees a fresh
|
|
2180
|
-
* threshold message at the new boundary.
|
|
2181
|
-
*/
|
|
1957
|
+
/** `null` disables the cap; any change re-arms the 80% warning. */
|
|
2182
1958
|
setBudget(usd) {
|
|
2183
1959
|
this.budgetUsd = typeof usd === "number" && usd > 0 ? usd : null;
|
|
2184
1960
|
this._budgetWarned = false;
|
|
2185
1961
|
}
|
|
2186
|
-
/**
|
|
2187
|
-
* Arm pro for the next turn (consumed at turn start). Called by
|
|
2188
|
-
* `/pro`. Idempotent — repeated calls stay armed, `disarmPro()`
|
|
2189
|
-
* clears. Separate from `/preset max` which persistently switches
|
|
2190
|
-
* this.model; armed state is strictly single-turn.
|
|
2191
|
-
*/
|
|
1962
|
+
/** Single-turn upgrade consumed at next step() — distinct from `/preset max` (persistent). */
|
|
2192
1963
|
armProForNextTurn() {
|
|
2193
1964
|
this._proArmedForNextTurn = true;
|
|
2194
1965
|
}
|
|
@@ -2204,25 +1975,10 @@ var CacheFirstLoop = class {
|
|
|
2204
1975
|
get escalatedThisTurn() {
|
|
2205
1976
|
return this._escalateThisTurn;
|
|
2206
1977
|
}
|
|
2207
|
-
/**
|
|
2208
|
-
* Model the current model call should use. Defaults to `this.model`;
|
|
2209
|
-
* upgrades to {@link ESCALATION_MODEL} when the turn is armed for
|
|
2210
|
-
* pro (via `/pro`) or has hit the failure-escalation threshold.
|
|
2211
|
-
* Same thinking + effort policy applies regardless — pro defaults
|
|
2212
|
-
* to thinking=enabled and effort=max, which the current turn wanted
|
|
2213
|
-
* anyway when flash was struggling.
|
|
2214
|
-
*/
|
|
2215
1978
|
modelForCurrentCall() {
|
|
2216
1979
|
return this._escalateThisTurn ? ESCALATION_MODEL : this.model;
|
|
2217
1980
|
}
|
|
2218
|
-
/**
|
|
2219
|
-
* Parse the escalation marker out of the model's leading content.
|
|
2220
|
-
* Returns `{ matched: true, reason? }` for both bare and reason-
|
|
2221
|
-
* carrying forms. Only the FIRST line matters — the model is
|
|
2222
|
-
* instructed to emit the marker as the first output token if at
|
|
2223
|
-
* all. Matches anywhere else in the text are normal content
|
|
2224
|
-
* references (e.g. the user asked about the marker itself).
|
|
2225
|
-
*/
|
|
1981
|
+
/** Anchored to lead — mid-text matches are normal content (user asking about the marker). */
|
|
2226
1982
|
parseEscalationMarker(content) {
|
|
2227
1983
|
const m = NEEDS_PRO_MARKER_RE.exec(content.trimStart());
|
|
2228
1984
|
if (!m) return { matched: false };
|
|
@@ -2233,14 +1989,7 @@ var CacheFirstLoop = class {
|
|
|
2233
1989
|
isEscalationRequest(content) {
|
|
2234
1990
|
return this.parseEscalationMarker(content).matched;
|
|
2235
1991
|
}
|
|
2236
|
-
/**
|
|
2237
|
-
* Could `buf` STILL plausibly become the full marker as more chunks
|
|
2238
|
-
* arrive? Drives the streaming buffer's flush decision: while this
|
|
2239
|
-
* is true we keep accumulating; once it's false (or the buffer
|
|
2240
|
-
* exceeds the byte limit) we flush so the user isn't staring at a
|
|
2241
|
-
* delayed display for arbitrary content that just happens to start
|
|
2242
|
-
* with `<`.
|
|
2243
|
-
*/
|
|
1992
|
+
/** Drives streaming flush — while plausibly partial, keep accumulating; else flush. */
|
|
2244
1993
|
looksLikePartialEscalationMarker(buf) {
|
|
2245
1994
|
const t = buf.trimStart();
|
|
2246
1995
|
if (t.length === 0) return true;
|
|
@@ -2252,16 +2001,7 @@ var CacheFirstLoop = class {
|
|
|
2252
2001
|
if (rest[0] !== ">" && rest[0] !== ":") return false;
|
|
2253
2002
|
return true;
|
|
2254
2003
|
}
|
|
2255
|
-
/**
|
|
2256
|
-
* Check whether a tool result string looks like a "flash struggled"
|
|
2257
|
-
* signal and, if so, increment the turn's failure counter. Escalates
|
|
2258
|
-
* the REST of the current turn to pro once the threshold is hit.
|
|
2259
|
-
* Idempotent after escalation — further failures don't re-escalate,
|
|
2260
|
-
* but the turn is already on pro so it doesn't matter.
|
|
2261
|
-
*
|
|
2262
|
-
* Return: `true` when this call tipped the turn into escalation
|
|
2263
|
-
* mode (so the loop can surface a one-time warning to the user).
|
|
2264
|
-
*/
|
|
2004
|
+
/** Returns true ONLY on the tipping call — caller surfaces a one-shot warning. */
|
|
2265
2005
|
noteToolFailureSignal(resultJson, repair) {
|
|
2266
2006
|
let bumped = false;
|
|
2267
2007
|
const bump = (kind, by = 1) => {
|
|
@@ -2283,12 +2023,6 @@ var CacheFirstLoop = class {
|
|
|
2283
2023
|
}
|
|
2284
2024
|
return false;
|
|
2285
2025
|
}
|
|
2286
|
-
/**
|
|
2287
|
-
* Render `_turnFailureTypes` as a comma-separated breakdown like
|
|
2288
|
-
* "2× search-mismatch, 1× truncated" for the auto-escalation
|
|
2289
|
-
* warning. Empty if no types have been recorded yet (defensive —
|
|
2290
|
-
* the warning sites only call this after a bump).
|
|
2291
|
-
*/
|
|
2292
2026
|
formatFailureBreakdown() {
|
|
2293
2027
|
const parts = Object.entries(this._turnFailureTypes).filter(([, n]) => n > 0).map(([kind, n]) => `${n}\xD7 ${kind}`);
|
|
2294
2028
|
return parts.length > 0 ? parts.join(", ") : `${this._turnFailureCount} repair/error signal(s)`;
|
|
@@ -2299,28 +2033,10 @@ var CacheFirstLoop = class {
|
|
|
2299
2033
|
if (pendingUser !== null) msgs.push({ role: "user", content: pendingUser });
|
|
2300
2034
|
return msgs;
|
|
2301
2035
|
}
|
|
2302
|
-
/**
|
|
2303
|
-
* Signal the currently-running {@link step} to stop **now**. Cancels
|
|
2304
|
-
* the in-flight network request (DeepSeek HTTP/SSE) AND any tool call
|
|
2305
|
-
* currently dispatching (MCP `notifications/cancelled` + promise
|
|
2306
|
-
* reject). The loop itself also sees `signal.aborted` at each
|
|
2307
|
-
* iteration boundary and exits quickly instead of looping again.
|
|
2308
|
-
* Called by the TUI on Esc.
|
|
2309
|
-
*/
|
|
2310
2036
|
abort() {
|
|
2311
2037
|
this._turnAbort.abort();
|
|
2312
2038
|
}
|
|
2313
|
-
/**
|
|
2314
|
-
* Drop everything in the log after (and including) the most recent
|
|
2315
|
-
* user message. Used by `/retry` so the caller can re-send that
|
|
2316
|
-
* message with a fresh turn instead of layering another response on
|
|
2317
|
-
* top of the prior exchange. Returns the content of the dropped user
|
|
2318
|
-
* message, or `null` if there isn't one yet.
|
|
2319
|
-
*
|
|
2320
|
-
* Persists by rewriting the session file — otherwise the next
|
|
2321
|
-
* launch would rehydrate the old exchange and `/retry` would seem
|
|
2322
|
-
* to have done nothing.
|
|
2323
|
-
*/
|
|
2039
|
+
/** Drop the last user message + everything after; caller re-sends. Persists to session file. */
|
|
2324
2040
|
retryLastUser() {
|
|
2325
2041
|
const entries = this.log.entries;
|
|
2326
2042
|
let lastUserIdx = -1;
|
|
@@ -2931,22 +2647,7 @@ ${summary}`;
|
|
|
2931
2647
|
}
|
|
2932
2648
|
return final;
|
|
2933
2649
|
}
|
|
2934
|
-
/**
|
|
2935
|
-
* Build an assistant message for the log. The `producingModel` arg is
|
|
2936
|
-
* the model that actually generated this turn (flash, pro, the
|
|
2937
|
-
* forced-summary flash call, `this.model` for synthetics, etc.) —
|
|
2938
|
-
* NOT `this.model`, because escalation + forced-summary can both
|
|
2939
|
-
* route a single turn to a different model.
|
|
2940
|
-
*
|
|
2941
|
-
* The single invariant this encodes: if the producing model is
|
|
2942
|
-
* thinking-mode, `reasoning_content` MUST be present on the
|
|
2943
|
-
* persisted message — even as an empty string. DeepSeek's validator
|
|
2944
|
-
* 400s the NEXT request if any historical thinking-mode assistant
|
|
2945
|
-
* turn is missing it. We used to gate on `reasoning.length > 0`,
|
|
2946
|
-
* which silently dropped the field whenever the stream emitted zero
|
|
2947
|
-
* reasoning deltas or the API returned `reasoning_content: null` —
|
|
2948
|
-
* both legitimate edge cases the 0.5.15/0.5.18 fixes missed.
|
|
2949
|
-
*/
|
|
2650
|
+
/** Thinking-mode producer ⇒ reasoning_content MUST be set (even ""), or next call 400s. */
|
|
2950
2651
|
assistantMessage(content, toolCalls, producingModel, reasoningContent) {
|
|
2951
2652
|
const msg = { role: "assistant", content };
|
|
2952
2653
|
if (toolCalls.length > 0) msg.tool_calls = toolCalls;
|
|
@@ -2955,13 +2656,7 @@ ${summary}`;
|
|
|
2955
2656
|
}
|
|
2956
2657
|
return msg;
|
|
2957
2658
|
}
|
|
2958
|
-
/**
|
|
2959
|
-
* Synthetic assistant message (abort notices, future system injections)
|
|
2960
|
-
* — no real API round trip. Delegates to {@link assistantMessage} with
|
|
2961
|
-
* `this.model` as the stand-in producer, so the same thinking-mode
|
|
2962
|
-
* invariant applies: reasoner sessions get an empty-string
|
|
2963
|
-
* `reasoning_content`; V3 sessions get nothing.
|
|
2964
|
-
*/
|
|
2659
|
+
/** Abort notices etc — uses this.model as stand-in producer for the thinking-mode stamp. */
|
|
2965
2660
|
syntheticAssistantMessage(content) {
|
|
2966
2661
|
return this.assistantMessage(content, [], this.model, "");
|
|
2967
2662
|
}
|
|
@@ -3594,11 +3289,7 @@ var SkillStore = class {
|
|
|
3594
3289
|
hasProjectScope() {
|
|
3595
3290
|
return this.projectRoot !== void 0;
|
|
3596
3291
|
}
|
|
3597
|
-
/**
|
|
3598
|
-
* Root directories scanned, in priority order. Project scope first
|
|
3599
|
-
* so a per-repo skill overrides a global one with the same name —
|
|
3600
|
-
* users expect the local copy to win when both exist.
|
|
3601
|
-
*/
|
|
3292
|
+
/** Project scope first so per-repo skill overrides a global with the same name. */
|
|
3602
3293
|
roots() {
|
|
3603
3294
|
const out = [];
|
|
3604
3295
|
if (this.projectRoot) {
|
|
@@ -3610,11 +3301,7 @@ var SkillStore = class {
|
|
|
3610
3301
|
out.push({ dir: join6(this.homeDir, ".reasonix", SKILLS_DIRNAME), scope: "global" });
|
|
3611
3302
|
return out;
|
|
3612
3303
|
}
|
|
3613
|
-
/**
|
|
3614
|
-
* List every skill visible to this store. On name collisions the
|
|
3615
|
-
* higher-priority root (project over global over builtin) wins.
|
|
3616
|
-
* Sorted by name for stable prefix hashing.
|
|
3617
|
-
*/
|
|
3304
|
+
/** Higher-priority root wins on collision (project > global > builtin); sorted for stable prefix hash. */
|
|
3618
3305
|
list() {
|
|
3619
3306
|
const byName = /* @__PURE__ */ new Map();
|
|
3620
3307
|
for (const { dir, scope } of this.roots()) {
|
|
@@ -4001,10 +3688,6 @@ var MemoryStore = class {
|
|
|
4001
3688
|
hasProjectScope() {
|
|
4002
3689
|
return this.projectRoot !== void 0;
|
|
4003
3690
|
}
|
|
4004
|
-
/**
|
|
4005
|
-
* Read the `MEMORY.md` index for a scope. Returns post-cap content
|
|
4006
|
-
* (with a truncation marker if clipped), or `null` when absent / empty.
|
|
4007
|
-
*/
|
|
4008
3691
|
loadIndex(scope) {
|
|
4009
3692
|
if (scope === "project" && !this.projectRoot) return null;
|
|
4010
3693
|
const file = join7(
|
|
@@ -4043,11 +3726,7 @@ var MemoryStore = class {
|
|
|
4043
3726
|
createdAt: data.created ?? ""
|
|
4044
3727
|
};
|
|
4045
3728
|
}
|
|
4046
|
-
/**
|
|
4047
|
-
* List every memory in this store. Scans both scopes (skips project
|
|
4048
|
-
* scope if unconfigured). Silently skips malformed files; the index
|
|
4049
|
-
* must stay queryable even if one file is hand-edited into nonsense.
|
|
4050
|
-
*/
|
|
3729
|
+
/** Skips malformed files — index stays queryable even if one file is hand-edited into nonsense. */
|
|
4051
3730
|
list() {
|
|
4052
3731
|
const out = [];
|
|
4053
3732
|
const scopes = this.projectRoot ? ["global", "project"] : ["global"];
|
|
@@ -4072,11 +3751,6 @@ var MemoryStore = class {
|
|
|
4072
3751
|
}
|
|
4073
3752
|
return out;
|
|
4074
3753
|
}
|
|
4075
|
-
/**
|
|
4076
|
-
* Write a new memory (or overwrite existing). Creates the scope dir,
|
|
4077
|
-
* writes the `.md` file, and regenerates `MEMORY.md`. Returns the
|
|
4078
|
-
* absolute path written to.
|
|
4079
|
-
*/
|
|
4080
3754
|
write(input) {
|
|
4081
3755
|
if (input.scope === "project" && !this.projectRoot) {
|
|
4082
3756
|
throw new Error("cannot write project-scoped memory: no projectRoot configured");
|
|
@@ -4112,12 +3786,7 @@ var MemoryStore = class {
|
|
|
4112
3786
|
this.regenerateIndex(scope);
|
|
4113
3787
|
return true;
|
|
4114
3788
|
}
|
|
4115
|
-
/**
|
|
4116
|
-
* Rebuild `MEMORY.md` from the `.md` files currently in the scope dir.
|
|
4117
|
-
* Called after every write/delete. Sorted by name for stable prefix
|
|
4118
|
-
* hashing — two stores with the same set of files produce byte-identical
|
|
4119
|
-
* MEMORY.md content, keeping the cache prefix reproducible.
|
|
4120
|
-
*/
|
|
3789
|
+
/** Sorted by name — same file set must produce byte-identical MEMORY.md for stable prefix hashing. */
|
|
4121
3790
|
regenerateIndex(scope) {
|
|
4122
3791
|
const dir = scopeDir({ homeDir: this.homeDir, scope, projectRoot: this.projectRoot });
|
|
4123
3792
|
if (!existsSync7(dir)) return;
|
|
@@ -5053,12 +4722,6 @@ var PlanProposedError = class extends Error {
|
|
|
5053
4722
|
this.steps = steps;
|
|
5054
4723
|
this.summary = summary;
|
|
5055
4724
|
}
|
|
5056
|
-
/**
|
|
5057
|
-
* Structured tool-result shape. Consumed by the TUI to extract the
|
|
5058
|
-
* plan without regex-scraping the error message. Optional fields
|
|
5059
|
-
* are omitted from the payload when absent so consumers don't see
|
|
5060
|
-
* `undefined` keys in the JSON.
|
|
5061
|
-
*/
|
|
5062
4725
|
toToolResult() {
|
|
5063
4726
|
const payload = {
|
|
5064
4727
|
error: `${this.name}: ${this.message}`,
|
|
@@ -5569,11 +5232,7 @@ var READY_SIGNALS = [
|
|
|
5569
5232
|
var JobRegistry = class {
|
|
5570
5233
|
jobs = /* @__PURE__ */ new Map();
|
|
5571
5234
|
nextId = 1;
|
|
5572
|
-
/**
|
|
5573
|
-
* Spawn a background child. Resolves after `waitSec` OR on ready
|
|
5574
|
-
* signal OR on early exit, whichever comes first. The child continues
|
|
5575
|
-
* to run (and buffer output) regardless of which path fires.
|
|
5576
|
-
*/
|
|
5235
|
+
/** Resolves on (a) ready signal, (b) early exit, or (c) waitSec deadline — child keeps running regardless. */
|
|
5577
5236
|
async start(command, opts) {
|
|
5578
5237
|
const trimmed = command.trim();
|
|
5579
5238
|
if (!trimmed) throw new Error("run_background: empty command");
|
|
@@ -5708,12 +5367,6 @@ ${job.output.slice(start)}`;
|
|
|
5708
5367
|
exitCode: job.exitCode
|
|
5709
5368
|
};
|
|
5710
5369
|
}
|
|
5711
|
-
/**
|
|
5712
|
-
* Read a job's accumulated output. `since` lets a caller poll
|
|
5713
|
-
* incrementally: pass the byte count returned from the last call to
|
|
5714
|
-
* get only newly-written content. Returns both full output and a
|
|
5715
|
-
* running snapshot so the caller can use whichever.
|
|
5716
|
-
*/
|
|
5717
5370
|
read(id, opts = {}) {
|
|
5718
5371
|
const job = this.jobs.get(id);
|
|
5719
5372
|
if (!job) return null;
|
|
@@ -5737,11 +5390,7 @@ ${job.output.slice(start)}`;
|
|
|
5737
5390
|
spawnError: job.spawnError
|
|
5738
5391
|
};
|
|
5739
5392
|
}
|
|
5740
|
-
/**
|
|
5741
|
-
* Send SIGTERM, wait `graceMs`, then SIGKILL if still alive. Returns
|
|
5742
|
-
* the final job record (or null when the job id is unknown). Safe to
|
|
5743
|
-
* call on an already-exited job — returns the record unchanged.
|
|
5744
|
-
*/
|
|
5393
|
+
/** SIGTERM, wait graceMs, then SIGKILL. Idempotent on already-exited jobs. */
|
|
5745
5394
|
async stop(id, opts = {}) {
|
|
5746
5395
|
const job = this.jobs.get(id);
|
|
5747
5396
|
if (!job) return null;
|
|
@@ -5772,11 +5421,6 @@ ${job.output.slice(start)}`;
|
|
|
5772
5421
|
list() {
|
|
5773
5422
|
return [...this.jobs.values()].map(snapshot);
|
|
5774
5423
|
}
|
|
5775
|
-
/**
|
|
5776
|
-
* Best-effort kill of every still-running job. Called on TUI shutdown
|
|
5777
|
-
* so dev servers don't outlive the Reasonix process. Resolves after
|
|
5778
|
-
* every child has closed or a hard deadline passes (3s total).
|
|
5779
|
-
*/
|
|
5780
5424
|
async shutdown(deadlineMs = 5e3) {
|
|
5781
5425
|
const start = Date.now();
|
|
5782
5426
|
const runningJobs = [...this.jobs.values()].filter((j) => j.running && j.child);
|
|
@@ -7240,10 +6884,7 @@ var McpClient = class {
|
|
|
7240
6884
|
get serverInstructions() {
|
|
7241
6885
|
return this._instructions;
|
|
7242
6886
|
}
|
|
7243
|
-
/**
|
|
7244
|
-
* Complete the initialize → initialized handshake. Must be called
|
|
7245
|
-
* before any other method (otherwise compliant servers reject).
|
|
7246
|
-
*/
|
|
6887
|
+
/** Compliant servers reject other methods until this completes. */
|
|
7247
6888
|
async initialize() {
|
|
7248
6889
|
if (this.initialized) throw new Error("MCP client already initialized");
|
|
7249
6890
|
this.startReaderIfNeeded();
|
|
@@ -7273,22 +6914,7 @@ var McpClient = class {
|
|
|
7273
6914
|
this.assertInitialized();
|
|
7274
6915
|
return this.request("tools/list", {});
|
|
7275
6916
|
}
|
|
7276
|
-
/**
|
|
7277
|
-
* Invoke a tool by name. When `onProgress` is supplied, attaches a
|
|
7278
|
-
* fresh progress token so the server can send incremental updates
|
|
7279
|
-
* via `notifications/progress`; they're routed to the callback until
|
|
7280
|
-
* the final response arrives (or the request times out, in which
|
|
7281
|
-
* case the handler is simply dropped — no extra notification).
|
|
7282
|
-
*
|
|
7283
|
-
* When `signal` is supplied, aborting it:
|
|
7284
|
-
* 1) fires `notifications/cancelled` to the server (MCP 2024-11-05
|
|
7285
|
-
* way of saying "forget this request, I no longer care"), and
|
|
7286
|
-
* 2) rejects the pending promise immediately with an AbortError,
|
|
7287
|
-
* so the caller doesn't have to wait for the subprocess to
|
|
7288
|
-
* finish its in-flight file write or network request.
|
|
7289
|
-
* The server MAY still emit a late response; we drop it in dispatch
|
|
7290
|
-
* since the request id is gone from `pending`.
|
|
7291
|
-
*/
|
|
6917
|
+
/** Abort sends `notifications/cancelled` and rejects immediately; late server responses are dropped. */
|
|
7292
6918
|
async callTool(name, args, opts = {}) {
|
|
7293
6919
|
this.assertInitialized();
|
|
7294
6920
|
const params = { name, arguments: args ?? {} };
|
|
@@ -7304,13 +6930,7 @@ var McpClient = class {
|
|
|
7304
6930
|
if (token !== void 0) this.progressHandlers.delete(token);
|
|
7305
6931
|
}
|
|
7306
6932
|
}
|
|
7307
|
-
/**
|
|
7308
|
-
* List resources the server exposes. Supports a pagination cursor;
|
|
7309
|
-
* callers interested in the full set should loop on `nextCursor`.
|
|
7310
|
-
* Servers that don't support resources respond with method-not-found
|
|
7311
|
-
* (−32601) — we surface that as a thrown Error so callers can gate
|
|
7312
|
-
* on the `serverCapabilities.resources` field first.
|
|
7313
|
-
*/
|
|
6933
|
+
/** Throws on method-not-found; callers should gate on `serverCapabilities.resources` first. */
|
|
7314
6934
|
async listResources(cursor) {
|
|
7315
6935
|
this.assertInitialized();
|
|
7316
6936
|
return this.request("resources/list", {
|
|
@@ -7331,11 +6951,6 @@ var McpClient = class {
|
|
|
7331
6951
|
...cursor ? { cursor } : {}
|
|
7332
6952
|
});
|
|
7333
6953
|
}
|
|
7334
|
-
/**
|
|
7335
|
-
* Fetch a rendered prompt by name. `args` supplies values for any
|
|
7336
|
-
* required template arguments; the server validates. Returns messages
|
|
7337
|
-
* ready to prepend to the model's input.
|
|
7338
|
-
*/
|
|
7339
6954
|
async getPrompt(name, args) {
|
|
7340
6955
|
this.assertInitialized();
|
|
7341
6956
|
return this.request("prompts/get", {
|
|
@@ -7352,7 +6967,6 @@ var McpClient = class {
|
|
|
7352
6967
|
this.pending.clear();
|
|
7353
6968
|
await this.transport.close();
|
|
7354
6969
|
}
|
|
7355
|
-
// ---------- internals ----------
|
|
7356
6970
|
assertInitialized() {
|
|
7357
6971
|
if (!this.initialized) throw new Error("MCP client not initialized \u2014 call initialize() first");
|
|
7358
6972
|
}
|
|
@@ -7620,7 +7234,6 @@ var SseTransport = class {
|
|
|
7620
7234
|
} catch {
|
|
7621
7235
|
}
|
|
7622
7236
|
}
|
|
7623
|
-
// ---------- internals ----------
|
|
7624
7237
|
async runStream() {
|
|
7625
7238
|
let res;
|
|
7626
7239
|
try {
|
|
@@ -7812,7 +7425,6 @@ var StreamableHttpTransport = class {
|
|
|
7812
7425
|
getSessionId() {
|
|
7813
7426
|
return this.sessionId;
|
|
7814
7427
|
}
|
|
7815
|
-
// ---------- internals ----------
|
|
7816
7428
|
async consumeStream(body) {
|
|
7817
7429
|
const parser = createParser3({
|
|
7818
7430
|
onEvent: (ev) => {
|