reasonix 0.0.5 → 0.0.6
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 +8 -1
- package/dist/cli/index.js +213 -24
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +43 -1
- package/dist/index.js +126 -12
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -73,11 +73,18 @@ Measured on live DeepSeek API:
|
|
|
73
73
|
### CLI
|
|
74
74
|
|
|
75
75
|
```bash
|
|
76
|
-
npx reasonix chat #
|
|
76
|
+
npx reasonix chat # auto-saves to session 'default'; resumes next time
|
|
77
|
+
npx reasonix chat --session work # use a different named session
|
|
78
|
+
npx reasonix chat --no-session # ephemeral — nothing persisted
|
|
77
79
|
npx reasonix run "ask anything" # one-shot, streams to stdout
|
|
78
80
|
npx reasonix stats session.jsonl # read back a saved transcript
|
|
79
81
|
```
|
|
80
82
|
|
|
83
|
+
Sessions live as JSONL under `~/.reasonix/sessions/<name>.jsonl` — every
|
|
84
|
+
turn's message log is appended atomically, so killing the CLI never loses
|
|
85
|
+
context. Inside the TUI: `/sessions` to list, `/forget` to delete the
|
|
86
|
+
current one.
|
|
87
|
+
|
|
81
88
|
### Inside the chat — slash commands
|
|
82
89
|
|
|
83
90
|
A command strip runs under the input box so you don't have to memorize
|
package/dist/cli/index.js
CHANGED
|
@@ -783,6 +783,93 @@ function signature2(call) {
|
|
|
783
783
|
return `${call.function?.name ?? ""}::${call.function?.arguments ?? ""}`;
|
|
784
784
|
}
|
|
785
785
|
|
|
786
|
+
// src/session.ts
|
|
787
|
+
import {
|
|
788
|
+
appendFileSync,
|
|
789
|
+
chmodSync,
|
|
790
|
+
existsSync,
|
|
791
|
+
mkdirSync,
|
|
792
|
+
readFileSync,
|
|
793
|
+
readdirSync,
|
|
794
|
+
statSync,
|
|
795
|
+
unlinkSync
|
|
796
|
+
} from "fs";
|
|
797
|
+
import { homedir } from "os";
|
|
798
|
+
import { dirname, join } from "path";
|
|
799
|
+
function sessionsDir() {
|
|
800
|
+
return join(homedir(), ".reasonix", "sessions");
|
|
801
|
+
}
|
|
802
|
+
function sessionPath(name) {
|
|
803
|
+
return join(sessionsDir(), `${sanitizeName(name)}.jsonl`);
|
|
804
|
+
}
|
|
805
|
+
function sanitizeName(name) {
|
|
806
|
+
const cleaned = name.replace(/[^\w\-\u4e00-\u9fa5]/g, "_").slice(0, 64);
|
|
807
|
+
return cleaned || "default";
|
|
808
|
+
}
|
|
809
|
+
function loadSessionMessages(name) {
|
|
810
|
+
const path = sessionPath(name);
|
|
811
|
+
if (!existsSync(path)) return [];
|
|
812
|
+
try {
|
|
813
|
+
const raw = readFileSync(path, "utf8");
|
|
814
|
+
const out = [];
|
|
815
|
+
for (const line of raw.split(/\r?\n/)) {
|
|
816
|
+
const trimmed = line.trim();
|
|
817
|
+
if (!trimmed) continue;
|
|
818
|
+
try {
|
|
819
|
+
const msg = JSON.parse(trimmed);
|
|
820
|
+
if (msg && typeof msg === "object" && "role" in msg) out.push(msg);
|
|
821
|
+
} catch {
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
return out;
|
|
825
|
+
} catch {
|
|
826
|
+
return [];
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
function appendSessionMessage(name, message) {
|
|
830
|
+
const path = sessionPath(name);
|
|
831
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
832
|
+
appendFileSync(path, `${JSON.stringify(message)}
|
|
833
|
+
`, "utf8");
|
|
834
|
+
try {
|
|
835
|
+
chmodSync(path, 384);
|
|
836
|
+
} catch {
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
function listSessions() {
|
|
840
|
+
const dir = sessionsDir();
|
|
841
|
+
if (!existsSync(dir)) return [];
|
|
842
|
+
try {
|
|
843
|
+
const files = readdirSync(dir).filter((f) => f.endsWith(".jsonl"));
|
|
844
|
+
return files.map((file) => {
|
|
845
|
+
const path = join(dir, file);
|
|
846
|
+
const stat = statSync(path);
|
|
847
|
+
const name = file.replace(/\.jsonl$/, "");
|
|
848
|
+
const messageCount = countLines(path);
|
|
849
|
+
return { name, path, size: stat.size, messageCount, mtime: stat.mtime };
|
|
850
|
+
}).sort((a, b) => b.mtime.getTime() - a.mtime.getTime());
|
|
851
|
+
} catch {
|
|
852
|
+
return [];
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
function deleteSession(name) {
|
|
856
|
+
const path = sessionPath(name);
|
|
857
|
+
try {
|
|
858
|
+
unlinkSync(path);
|
|
859
|
+
return true;
|
|
860
|
+
} catch {
|
|
861
|
+
return false;
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
function countLines(path) {
|
|
865
|
+
try {
|
|
866
|
+
const raw = readFileSync(path, "utf8");
|
|
867
|
+
return raw.split(/\r?\n/).filter((l) => l.trim()).length;
|
|
868
|
+
} catch {
|
|
869
|
+
return 0;
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
|
|
786
873
|
// src/telemetry.ts
|
|
787
874
|
var DEEPSEEK_PRICING = {
|
|
788
875
|
"deepseek-chat": { inputCacheHit: 0.07, inputCacheMiss: 0.27, output: 1.1 },
|
|
@@ -939,6 +1026,9 @@ var CacheFirstLoop = class {
|
|
|
939
1026
|
harvestOptions;
|
|
940
1027
|
branchEnabled;
|
|
941
1028
|
branchOptions;
|
|
1029
|
+
sessionName;
|
|
1030
|
+
/** Number of messages that were pre-loaded from the session file. */
|
|
1031
|
+
resumedMessageCount;
|
|
942
1032
|
_turn = 0;
|
|
943
1033
|
_streamPreference;
|
|
944
1034
|
constructor(opts) {
|
|
@@ -962,6 +1052,23 @@ var CacheFirstLoop = class {
|
|
|
962
1052
|
this.stream = this.branchEnabled ? false : this._streamPreference;
|
|
963
1053
|
const allowedNames = /* @__PURE__ */ new Set([...this.prefix.toolSpecs.map((s) => s.function.name)]);
|
|
964
1054
|
this.repair = new ToolCallRepair({ allowedToolNames: allowedNames });
|
|
1055
|
+
this.sessionName = opts.session ?? null;
|
|
1056
|
+
if (this.sessionName) {
|
|
1057
|
+
const prior = loadSessionMessages(this.sessionName);
|
|
1058
|
+
for (const msg of prior) this.log.append(msg);
|
|
1059
|
+
this.resumedMessageCount = prior.length;
|
|
1060
|
+
} else {
|
|
1061
|
+
this.resumedMessageCount = 0;
|
|
1062
|
+
}
|
|
1063
|
+
}
|
|
1064
|
+
appendAndPersist(message) {
|
|
1065
|
+
this.log.append(message);
|
|
1066
|
+
if (this.sessionName) {
|
|
1067
|
+
try {
|
|
1068
|
+
appendSessionMessage(this.sessionName, message);
|
|
1069
|
+
} catch {
|
|
1070
|
+
}
|
|
1071
|
+
}
|
|
965
1072
|
}
|
|
966
1073
|
/**
|
|
967
1074
|
* Reconfigure model/harvest/branch/stream mid-session. The loop's log,
|
|
@@ -1149,7 +1256,7 @@ var CacheFirstLoop = class {
|
|
|
1149
1256
|
}
|
|
1150
1257
|
const turnStats = this.stats.record(this._turn, this.model, usage ?? new Usage());
|
|
1151
1258
|
if (pendingUser !== null) {
|
|
1152
|
-
this.
|
|
1259
|
+
this.appendAndPersist({ role: "user", content: pendingUser });
|
|
1153
1260
|
pendingUser = null;
|
|
1154
1261
|
}
|
|
1155
1262
|
this.scratch.reasoning = reasoningContent || null;
|
|
@@ -1158,7 +1265,7 @@ var CacheFirstLoop = class {
|
|
|
1158
1265
|
toolCalls,
|
|
1159
1266
|
reasoningContent || null
|
|
1160
1267
|
);
|
|
1161
|
-
this.
|
|
1268
|
+
this.appendAndPersist(this.assistantMessage(assistantContent, repairedCalls));
|
|
1162
1269
|
yield {
|
|
1163
1270
|
turn: this._turn,
|
|
1164
1271
|
role: "assistant_final",
|
|
@@ -1176,7 +1283,7 @@ var CacheFirstLoop = class {
|
|
|
1176
1283
|
const name = call.function?.name ?? "";
|
|
1177
1284
|
const args = call.function?.arguments ?? "{}";
|
|
1178
1285
|
const result = await this.tools.dispatch(name, args);
|
|
1179
|
-
this.
|
|
1286
|
+
this.appendAndPersist({
|
|
1180
1287
|
role: "tool",
|
|
1181
1288
|
tool_call_id: call.id ?? "",
|
|
1182
1289
|
name,
|
|
@@ -1212,12 +1319,12 @@ function summarizeBranch(chosen, samples) {
|
|
|
1212
1319
|
}
|
|
1213
1320
|
|
|
1214
1321
|
// src/env.ts
|
|
1215
|
-
import { readFileSync } from "fs";
|
|
1322
|
+
import { readFileSync as readFileSync2 } from "fs";
|
|
1216
1323
|
import { resolve } from "path";
|
|
1217
1324
|
function loadDotenv(path = ".env") {
|
|
1218
1325
|
let raw;
|
|
1219
1326
|
try {
|
|
1220
|
-
raw =
|
|
1327
|
+
raw = readFileSync2(resolve(process.cwd(), path), "utf8");
|
|
1221
1328
|
} catch {
|
|
1222
1329
|
return;
|
|
1223
1330
|
}
|
|
@@ -1236,15 +1343,15 @@ function loadDotenv(path = ".env") {
|
|
|
1236
1343
|
}
|
|
1237
1344
|
|
|
1238
1345
|
// src/config.ts
|
|
1239
|
-
import { chmodSync, mkdirSync, readFileSync as
|
|
1240
|
-
import { homedir } from "os";
|
|
1241
|
-
import { dirname, join } from "path";
|
|
1346
|
+
import { chmodSync as chmodSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync3, writeFileSync } from "fs";
|
|
1347
|
+
import { homedir as homedir2 } from "os";
|
|
1348
|
+
import { dirname as dirname2, join as join2 } from "path";
|
|
1242
1349
|
function defaultConfigPath() {
|
|
1243
|
-
return
|
|
1350
|
+
return join2(homedir2(), ".reasonix", "config.json");
|
|
1244
1351
|
}
|
|
1245
1352
|
function readConfig(path = defaultConfigPath()) {
|
|
1246
1353
|
try {
|
|
1247
|
-
const raw =
|
|
1354
|
+
const raw = readFileSync3(path, "utf8");
|
|
1248
1355
|
const parsed = JSON.parse(raw);
|
|
1249
1356
|
if (parsed && typeof parsed === "object") return parsed;
|
|
1250
1357
|
} catch {
|
|
@@ -1252,10 +1359,10 @@ function readConfig(path = defaultConfigPath()) {
|
|
|
1252
1359
|
return {};
|
|
1253
1360
|
}
|
|
1254
1361
|
function writeConfig(cfg, path = defaultConfigPath()) {
|
|
1255
|
-
|
|
1362
|
+
mkdirSync2(dirname2(path), { recursive: true });
|
|
1256
1363
|
writeFileSync(path, JSON.stringify(cfg, null, 2), "utf8");
|
|
1257
1364
|
try {
|
|
1258
|
-
|
|
1365
|
+
chmodSync2(path, 384);
|
|
1259
1366
|
} catch {
|
|
1260
1367
|
}
|
|
1261
1368
|
}
|
|
@@ -1629,15 +1736,51 @@ function handleSlash(cmd, args, loop) {
|
|
|
1629
1736
|
" /model <id> deepseek-chat or deepseek-reasoner",
|
|
1630
1737
|
" /harvest [on|off] Pillar 2: structured plan-state extraction",
|
|
1631
1738
|
" /branch <N|off> run N parallel samples (N>=2), pick most confident",
|
|
1632
|
-
" /
|
|
1739
|
+
" /sessions list saved sessions (current is marked with \u25B8)",
|
|
1740
|
+
" /forget delete the current session from disk",
|
|
1741
|
+
" /clear clear displayed history (log + session kept)",
|
|
1633
1742
|
" /exit quit",
|
|
1634
1743
|
"",
|
|
1635
1744
|
"Presets:",
|
|
1636
1745
|
" fast deepseek-chat no harvest no branch ~1\xA2/100turns \u2190 default",
|
|
1637
1746
|
" smart reasoner harvest ~10x cost, slower",
|
|
1638
|
-
" max reasoner harvest branch 3 ~30x cost, slowest"
|
|
1747
|
+
" max reasoner harvest branch 3 ~30x cost, slowest",
|
|
1748
|
+
"",
|
|
1749
|
+
"Sessions (auto-enabled by default, named 'default'):",
|
|
1750
|
+
" reasonix chat --session <name> use a different named session",
|
|
1751
|
+
" reasonix chat --no-session disable persistence for this run"
|
|
1639
1752
|
].join("\n")
|
|
1640
1753
|
};
|
|
1754
|
+
case "sessions": {
|
|
1755
|
+
const items = listSessions();
|
|
1756
|
+
if (items.length === 0) {
|
|
1757
|
+
return {
|
|
1758
|
+
info: "no saved sessions yet \u2014 chat normally and your messages will be saved automatically"
|
|
1759
|
+
};
|
|
1760
|
+
}
|
|
1761
|
+
const lines = ["Saved sessions:"];
|
|
1762
|
+
for (const s of items) {
|
|
1763
|
+
const sizeKb = (s.size / 1024).toFixed(1);
|
|
1764
|
+
const when = s.mtime.toISOString().replace("T", " ").slice(0, 16);
|
|
1765
|
+
const marker = s.name === loop.sessionName ? "\u25B8" : " ";
|
|
1766
|
+
lines.push(
|
|
1767
|
+
` ${marker} ${s.name.padEnd(22)} ${String(s.messageCount).padStart(5)} msgs ${sizeKb.padStart(7)} KB ${when}`
|
|
1768
|
+
);
|
|
1769
|
+
}
|
|
1770
|
+
lines.push("");
|
|
1771
|
+
lines.push("Resume with: reasonix chat --session <name>");
|
|
1772
|
+
return { info: lines.join("\n") };
|
|
1773
|
+
}
|
|
1774
|
+
case "forget": {
|
|
1775
|
+
if (!loop.sessionName) {
|
|
1776
|
+
return { info: "not in a session \u2014 nothing to forget" };
|
|
1777
|
+
}
|
|
1778
|
+
const name = loop.sessionName;
|
|
1779
|
+
const ok = deleteSession(name);
|
|
1780
|
+
return {
|
|
1781
|
+
info: ok ? `\u25B8 deleted session "${name}" \u2014 current screen still shows the conversation, but next launch starts fresh` : `could not delete session "${name}" (already gone?)`
|
|
1782
|
+
};
|
|
1783
|
+
}
|
|
1641
1784
|
case "status": {
|
|
1642
1785
|
const branchBudget = loop.branchOptions.budget ?? 1;
|
|
1643
1786
|
return {
|
|
@@ -1697,7 +1840,7 @@ function handleSlash(cmd, args, loop) {
|
|
|
1697
1840
|
|
|
1698
1841
|
// src/cli/ui/App.tsx
|
|
1699
1842
|
var FLUSH_INTERVAL_MS = 60;
|
|
1700
|
-
function App({ model, system, transcript, harvest: harvest2, branch }) {
|
|
1843
|
+
function App({ model, system, transcript, harvest: harvest2, branch, session }) {
|
|
1701
1844
|
const { exit } = useApp();
|
|
1702
1845
|
const [historical, setHistorical] = useState2([]);
|
|
1703
1846
|
const [streaming, setStreaming] = useState2(null);
|
|
@@ -1724,10 +1867,43 @@ function App({ model, system, transcript, harvest: harvest2, branch }) {
|
|
|
1724
1867
|
if (loopRef.current) return loopRef.current;
|
|
1725
1868
|
const client = new DeepSeekClient();
|
|
1726
1869
|
const prefix = new ImmutablePrefix({ system });
|
|
1727
|
-
const l = new CacheFirstLoop({ client, prefix, model, harvest: harvest2, branch });
|
|
1870
|
+
const l = new CacheFirstLoop({ client, prefix, model, harvest: harvest2, branch, session });
|
|
1728
1871
|
loopRef.current = l;
|
|
1729
1872
|
return l;
|
|
1730
|
-
}, [model, system, harvest2, branch]);
|
|
1873
|
+
}, [model, system, harvest2, branch, session]);
|
|
1874
|
+
const sessionBannerShown = useRef(false);
|
|
1875
|
+
useEffect2(() => {
|
|
1876
|
+
if (sessionBannerShown.current) return;
|
|
1877
|
+
sessionBannerShown.current = true;
|
|
1878
|
+
if (!session) {
|
|
1879
|
+
setHistorical((prev) => [
|
|
1880
|
+
...prev,
|
|
1881
|
+
{
|
|
1882
|
+
id: `sys-session-${Date.now()}`,
|
|
1883
|
+
role: "info",
|
|
1884
|
+
text: "\u25B8 ephemeral chat (no session persistence) \u2014 drop --no-session to enable"
|
|
1885
|
+
}
|
|
1886
|
+
]);
|
|
1887
|
+
} else if (loop.resumedMessageCount > 0) {
|
|
1888
|
+
setHistorical((prev) => [
|
|
1889
|
+
...prev,
|
|
1890
|
+
{
|
|
1891
|
+
id: `sys-resume-${Date.now()}`,
|
|
1892
|
+
role: "info",
|
|
1893
|
+
text: `\u25B8 resumed session "${session}" with ${loop.resumedMessageCount} prior messages \xB7 /forget to start over \xB7 /sessions to list`
|
|
1894
|
+
}
|
|
1895
|
+
]);
|
|
1896
|
+
} else {
|
|
1897
|
+
setHistorical((prev) => [
|
|
1898
|
+
...prev,
|
|
1899
|
+
{
|
|
1900
|
+
id: `sys-newsession-${Date.now()}`,
|
|
1901
|
+
role: "info",
|
|
1902
|
+
text: `\u25B8 session "${session}" (new) \u2014 auto-saved as you chat \xB7 /forget to delete \xB7 /sessions to list`
|
|
1903
|
+
}
|
|
1904
|
+
]);
|
|
1905
|
+
}
|
|
1906
|
+
}, [session, loop]);
|
|
1731
1907
|
const prefixHash = loop.prefix.fingerprint;
|
|
1732
1908
|
const writeTranscript = useCallback((ev) => {
|
|
1733
1909
|
transcriptRef.current?.write(
|
|
@@ -1873,7 +2049,7 @@ function App({ model, system, transcript, harvest: harvest2, branch }) {
|
|
|
1873
2049
|
), /* @__PURE__ */ React5.createElement(Static, { items: historical }, (item) => /* @__PURE__ */ React5.createElement(EventRow, { key: item.id, event: item })), streaming ? /* @__PURE__ */ React5.createElement(Box5, { marginY: 1 }, /* @__PURE__ */ React5.createElement(EventRow, { event: streaming })) : null, /* @__PURE__ */ React5.createElement(PromptInput, { value: input, onChange: setInput, onSubmit: handleSubmit, disabled: busy }), /* @__PURE__ */ React5.createElement(CommandStrip, null));
|
|
1874
2050
|
}
|
|
1875
2051
|
function CommandStrip() {
|
|
1876
|
-
return /* @__PURE__ */ React5.createElement(Box5, { paddingX: 2 }, /* @__PURE__ */ React5.createElement(Text5, { dimColor: true }, "/help \xB7 /preset ", "<fast|smart|max>", " \xB7 /model \xB7 /harvest \xB7 /branch \xB7 /clear \xB7 /exit"));
|
|
2052
|
+
return /* @__PURE__ */ React5.createElement(Box5, { paddingX: 2 }, /* @__PURE__ */ React5.createElement(Text5, { dimColor: true }, "/help \xB7 /preset ", "<fast|smart|max>", " \xB7 /sessions \xB7 /model \xB7 /harvest \xB7 /branch \xB7 /clear \xB7 /exit"));
|
|
1877
2053
|
}
|
|
1878
2054
|
function describeRepair(repair) {
|
|
1879
2055
|
const parts = [];
|
|
@@ -1944,7 +2120,8 @@ function Root({ initialKey, ...appProps }) {
|
|
|
1944
2120
|
system: appProps.system,
|
|
1945
2121
|
transcript: appProps.transcript,
|
|
1946
2122
|
harvest: appProps.harvest,
|
|
1947
|
-
branch: appProps.branch
|
|
2123
|
+
branch: appProps.branch,
|
|
2124
|
+
session: appProps.session
|
|
1948
2125
|
}
|
|
1949
2126
|
);
|
|
1950
2127
|
}
|
|
@@ -2017,13 +2194,13 @@ async function runCommand(opts) {
|
|
|
2017
2194
|
}
|
|
2018
2195
|
|
|
2019
2196
|
// src/cli/commands/stats.ts
|
|
2020
|
-
import { existsSync, readFileSync as
|
|
2197
|
+
import { existsSync as existsSync2, readFileSync as readFileSync4 } from "fs";
|
|
2021
2198
|
function statsCommand(opts) {
|
|
2022
|
-
if (!
|
|
2199
|
+
if (!existsSync2(opts.transcript)) {
|
|
2023
2200
|
console.error(`no such transcript: ${opts.transcript}`);
|
|
2024
2201
|
process.exit(1);
|
|
2025
2202
|
}
|
|
2026
|
-
const lines =
|
|
2203
|
+
const lines = readFileSync4(opts.transcript, "utf8").split(/\r?\n/).filter(Boolean);
|
|
2027
2204
|
let assistantTurns = 0;
|
|
2028
2205
|
let toolCalls = 0;
|
|
2029
2206
|
let lastTurn = 0;
|
|
@@ -2058,13 +2235,25 @@ program.command("chat").description("Interactive Ink TUI with live cache/cost pa
|
|
|
2058
2235
|
"--branch <n>",
|
|
2059
2236
|
"Self-consistency: run N parallel samples per turn and pick the most confident (disables streaming; enables harvest)",
|
|
2060
2237
|
(v) => Number.parseInt(v, 10)
|
|
2061
|
-
).
|
|
2238
|
+
).option(
|
|
2239
|
+
"--session <name>",
|
|
2240
|
+
"Use a named session (default: 'default'). Resume the same session next time."
|
|
2241
|
+
).option("--no-session", "Disable session persistence for this run (ephemeral chat)").action(async (opts) => {
|
|
2242
|
+
let session;
|
|
2243
|
+
if (opts.session === false) {
|
|
2244
|
+
session = void 0;
|
|
2245
|
+
} else if (typeof opts.session === "string" && opts.session.length > 0) {
|
|
2246
|
+
session = opts.session;
|
|
2247
|
+
} else {
|
|
2248
|
+
session = "default";
|
|
2249
|
+
}
|
|
2062
2250
|
await chatCommand({
|
|
2063
2251
|
model: opts.model,
|
|
2064
2252
|
system: opts.system,
|
|
2065
2253
|
transcript: opts.transcript,
|
|
2066
2254
|
harvest: !!opts.harvest,
|
|
2067
|
-
branch: Number.isFinite(opts.branch) && opts.branch > 1 ? opts.branch : void 0
|
|
2255
|
+
branch: Number.isFinite(opts.branch) && opts.branch > 1 ? opts.branch : void 0,
|
|
2256
|
+
session
|
|
2068
2257
|
});
|
|
2069
2258
|
});
|
|
2070
2259
|
program.command("run <task>").description("Run a single task non-interactively, streaming output.").option("-m, --model <id>", "DeepSeek model id", "deepseek-chat").option("-s, --system <prompt>", "System prompt", DEFAULT_SYSTEM).action(async (task, opts) => {
|