reasonix 0.32.0 → 0.33.1
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/chat-Q5ZCVIOO.js +39 -0
- package/dist/cli/chunk-2AWTGJ2C.js +110 -0
- package/dist/cli/chunk-2AWTGJ2C.js.map +1 -0
- package/dist/cli/chunk-3Q3C4W66.js +30 -0
- package/dist/cli/chunk-3Q3C4W66.js.map +1 -0
- package/dist/cli/chunk-4DCHFFEY.js +149 -0
- package/dist/cli/chunk-4DCHFFEY.js.map +1 -0
- package/dist/cli/chunk-5X7LZJDE.js +36 -0
- package/dist/cli/chunk-5X7LZJDE.js.map +1 -0
- package/dist/cli/chunk-63KAV5DX.js +106 -0
- package/dist/cli/chunk-63KAV5DX.js.map +1 -0
- package/dist/cli/chunk-6TMHAK5D.js +576 -0
- package/dist/cli/chunk-6TMHAK5D.js.map +1 -0
- package/dist/cli/chunk-APPB3ZPQ.js +43 -0
- package/dist/cli/chunk-APPB3ZPQ.js.map +1 -0
- package/dist/cli/chunk-BQNUJJN7.js +42 -0
- package/dist/cli/chunk-BQNUJJN7.js.map +1 -0
- package/dist/cli/chunk-CPOV2O73.js +39 -0
- package/dist/cli/chunk-CPOV2O73.js.map +1 -0
- package/dist/cli/chunk-D5DKXIP5.js +368 -0
- package/dist/cli/chunk-D5DKXIP5.js.map +1 -0
- package/dist/cli/chunk-DFP4YSVM.js +247 -0
- package/dist/cli/chunk-DFP4YSVM.js.map +1 -0
- package/dist/cli/chunk-DULSP7JH.js +410 -0
- package/dist/cli/chunk-DULSP7JH.js.map +1 -0
- package/dist/cli/chunk-FM57FNPJ.js +46 -0
- package/dist/cli/chunk-FM57FNPJ.js.map +1 -0
- package/dist/cli/chunk-FWGEHRB7.js +54 -0
- package/dist/cli/chunk-FWGEHRB7.js.map +1 -0
- package/dist/cli/chunk-FXGQ5NHE.js +513 -0
- package/dist/cli/chunk-FXGQ5NHE.js.map +1 -0
- package/dist/cli/chunk-G3XNWSFN.js +53 -0
- package/dist/cli/chunk-G3XNWSFN.js.map +1 -0
- package/dist/cli/chunk-I6YIAK6C.js +757 -0
- package/dist/cli/chunk-I6YIAK6C.js.map +1 -0
- package/dist/cli/chunk-J5VLP23S.js +94 -0
- package/dist/cli/chunk-J5VLP23S.js.map +1 -0
- package/dist/cli/chunk-KMWKGPFZ.js +303 -0
- package/dist/cli/chunk-KMWKGPFZ.js.map +1 -0
- package/dist/cli/chunk-MDHVWCJ4.js +14965 -0
- package/dist/cli/chunk-MDHVWCJ4.js.map +1 -0
- package/dist/cli/chunk-MHDNZXJJ.js +48 -0
- package/dist/cli/chunk-MHDNZXJJ.js.map +1 -0
- package/dist/cli/chunk-ORM6PK57.js +140 -0
- package/dist/cli/chunk-ORM6PK57.js.map +1 -0
- package/dist/cli/chunk-Q6YFXW7H.js +4986 -0
- package/dist/cli/chunk-Q6YFXW7H.js.map +1 -0
- package/dist/cli/chunk-QGE6AF76.js +1467 -0
- package/dist/cli/chunk-QGE6AF76.js.map +1 -0
- package/dist/cli/chunk-RFX7TYVV.js +28 -0
- package/dist/cli/chunk-RFX7TYVV.js.map +1 -0
- package/dist/cli/chunk-RZILUXUC.js +940 -0
- package/dist/cli/chunk-RZILUXUC.js.map +1 -0
- package/dist/cli/chunk-SDE5U32Z.js +535 -0
- package/dist/cli/chunk-SDE5U32Z.js.map +1 -0
- package/dist/cli/chunk-SOZE7V7V.js +340 -0
- package/dist/cli/chunk-SOZE7V7V.js.map +1 -0
- package/dist/cli/chunk-U3V2ZQ5J.js +479 -0
- package/dist/cli/chunk-U3V2ZQ5J.js.map +1 -0
- package/dist/cli/chunk-W4LDFAZ6.js +1544 -0
- package/dist/cli/chunk-W4LDFAZ6.js.map +1 -0
- package/dist/cli/chunk-WBDE4IRI.js +208 -0
- package/dist/cli/chunk-WBDE4IRI.js.map +1 -0
- package/dist/cli/chunk-XHQIK7B6.js +189 -0
- package/dist/cli/chunk-XHQIK7B6.js.map +1 -0
- package/dist/cli/chunk-XJLZ4HKU.js +307 -0
- package/dist/cli/chunk-XJLZ4HKU.js.map +1 -0
- package/dist/cli/chunk-ZPTSJGX5.js +88 -0
- package/dist/cli/chunk-ZPTSJGX5.js.map +1 -0
- package/dist/cli/chunk-ZTLZO42A.js +231 -0
- package/dist/cli/chunk-ZTLZO42A.js.map +1 -0
- package/dist/cli/code-DLR77NPZ.js +151 -0
- package/dist/cli/code-DLR77NPZ.js.map +1 -0
- package/dist/cli/commands-JWT2MWVH.js +352 -0
- package/dist/cli/commands-JWT2MWVH.js.map +1 -0
- package/dist/cli/commit-RPZBOZS2.js +288 -0
- package/dist/cli/commit-RPZBOZS2.js.map +1 -0
- package/dist/cli/diff-NTEHCSDW.js +145 -0
- package/dist/cli/diff-NTEHCSDW.js.map +1 -0
- package/dist/cli/doctor-3TGB2NZN.js +19 -0
- package/dist/cli/doctor-3TGB2NZN.js.map +1 -0
- package/dist/cli/events-P27CX7LN.js +338 -0
- package/dist/cli/events-P27CX7LN.js.map +1 -0
- package/dist/cli/index.js +80 -33693
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/mcp-ARTNQ24O.js +266 -0
- package/dist/cli/mcp-ARTNQ24O.js.map +1 -0
- package/dist/cli/mcp-browse-HLO2ENDL.js +163 -0
- package/dist/cli/mcp-browse-HLO2ENDL.js.map +1 -0
- package/dist/cli/mcp-inspect-T2HBR22P.js +103 -0
- package/dist/cli/mcp-inspect-T2HBR22P.js.map +1 -0
- package/dist/cli/{prompt-XHICFAYN.js → prompt-V47QKSAR.js} +3 -2
- package/dist/cli/prompt-V47QKSAR.js.map +1 -0
- package/dist/cli/prune-sessions-ERL6B4G5.js +42 -0
- package/dist/cli/prune-sessions-ERL6B4G5.js.map +1 -0
- package/dist/cli/replay-Q43DSMG6.js +273 -0
- package/dist/cli/replay-Q43DSMG6.js.map +1 -0
- package/dist/cli/run-JMEOTQCG.js +215 -0
- package/dist/cli/run-JMEOTQCG.js.map +1 -0
- package/dist/cli/server-SYC3OVOP.js +2967 -0
- package/dist/cli/server-SYC3OVOP.js.map +1 -0
- package/dist/cli/sessions-MOJAALJI.js +102 -0
- package/dist/cli/sessions-MOJAALJI.js.map +1 -0
- package/dist/cli/setup-CCJZAWTY.js +404 -0
- package/dist/cli/setup-CCJZAWTY.js.map +1 -0
- package/dist/cli/stats-5RJCATCE.js +12 -0
- package/dist/cli/stats-5RJCATCE.js.map +1 -0
- package/dist/cli/update-4TJWRUIN.js +90 -0
- package/dist/cli/update-4TJWRUIN.js.map +1 -0
- package/dist/cli/version-3MYFE4G6.js +29 -0
- package/dist/cli/version-3MYFE4G6.js.map +1 -0
- package/dist/index.d.ts +13 -2
- package/dist/index.js +493 -89
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/cli/chunk-VWFJNLIK.js +0 -1031
- package/dist/cli/chunk-VWFJNLIK.js.map +0 -1
- /package/dist/cli/{prompt-XHICFAYN.js.map → chat-Q5ZCVIOO.js.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/cli/commands/sessions.ts"],"sourcesContent":["import { listSessions, loadSessionMessages, sessionPath } from \"../../index.js\";\nimport type { ChatMessage } from \"../../index.js\";\n\nexport interface SessionsOptions {\n /** When present, inspect that session instead of listing. */\n name?: string;\n /** Include assistant tool-call metadata in the inspect output. */\n verbose?: boolean;\n}\n\nexport function sessionsCommand(opts: SessionsOptions): void {\n if (opts.name) {\n inspectSession(opts.name, !!opts.verbose);\n } else {\n listAll();\n }\n}\n\nfunction listAll(): void {\n const items = listSessions();\n if (items.length === 0) {\n console.log(\n \"no saved sessions yet — run `reasonix chat` (sessions are auto-saved unless --no-session).\",\n );\n return;\n }\n console.log(\"Saved sessions (~/.reasonix/sessions/):\");\n console.log(\"\");\n console.log(` ${\"name\".padEnd(22)} ${\"msgs\".padStart(6)} ${\"size\".padStart(8)} modified`);\n console.log(` ${\"─\".repeat(60)}`);\n for (const s of items) {\n const sizeKb = `${(s.size / 1024).toFixed(1)} KB`;\n const when = s.mtime.toISOString().replace(\"T\", \" \").slice(0, 16);\n console.log(\n ` ${s.name.padEnd(22)} ${String(s.messageCount).padStart(6)} ${sizeKb.padStart(8)} ${when}`,\n );\n }\n console.log(\"\");\n console.log(\"Inspect: reasonix sessions <name>\");\n console.log(\"Resume: reasonix chat --session <name>\");\n}\n\nfunction inspectSession(name: string, verbose: boolean): void {\n const path = sessionPath(name);\n const messages = loadSessionMessages(name);\n if (messages.length === 0) {\n console.error(`no session named \"${name}\" (or it's empty).`);\n console.error(`looked at: ${path}`);\n process.exit(1);\n }\n\n console.log(`[session] ${name} ${messages.length} messages ${path}`);\n console.log(\"\");\n\n let turnIndex = 0;\n for (const msg of messages) {\n renderMessage(msg, turnIndex, verbose);\n // Roughly bump \"turn\" after each user message so the reader can follow\n // the conversation shape without the transcript's richer turn numbering.\n if (msg.role === \"user\") turnIndex++;\n }\n}\n\nfunction renderMessage(msg: ChatMessage, turnIdx: number, verbose: boolean): void {\n const turn = turnIdx > 0 ? `[t${turnIdx}]` : \"[start]\";\n const content = typeof msg.content === \"string\" ? msg.content : \"\";\n const flat = oneLine(content);\n\n if (msg.role === \"user\") {\n console.log(`${turn} USER: ${flat}`);\n } else if (msg.role === \"assistant\") {\n console.log(`${turn} AGENT: ${flat || \"(tool call only)\"}`);\n if (verbose && msg.tool_calls?.length) {\n for (const tc of msg.tool_calls) {\n console.log(\n ` → call ${tc.function?.name} ${truncate(tc.function?.arguments ?? \"\", 80)}`,\n );\n }\n }\n } else if (msg.role === \"tool\") {\n console.log(`${turn} TOOL ${msg.name ?? \"?\"}: ${truncate(flat, 160)}`);\n } else if (msg.role === \"system\") {\n if (verbose) console.log(`${turn} SYSTEM: ${truncate(flat, 160)}`);\n // otherwise suppress — session's system prompt is usually session-wide\n // boilerplate.\n }\n}\n\nfunction oneLine(s: string, max = 200): string {\n const collapsed = s.replace(/\\s+/g, \" \").trim();\n return collapsed.length > max ? `${collapsed.slice(0, max)}…` : collapsed;\n}\n\nfunction truncate(s: string, max: number): string {\n return s.length <= max ? s : `${s.slice(0, max)}…`;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,404 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
MultiSelect,
|
|
4
|
+
SingleSelect
|
|
5
|
+
} from "./chunk-SDE5U32Z.js";
|
|
6
|
+
import "./chunk-ZPTSJGX5.js";
|
|
7
|
+
import {
|
|
8
|
+
PRESET_DESCRIPTIONS
|
|
9
|
+
} from "./chunk-MHDNZXJJ.js";
|
|
10
|
+
import {
|
|
11
|
+
loadDotenv
|
|
12
|
+
} from "./chunk-3Q3C4W66.js";
|
|
13
|
+
import {
|
|
14
|
+
MCP_CATALOG
|
|
15
|
+
} from "./chunk-FM57FNPJ.js";
|
|
16
|
+
import {
|
|
17
|
+
detectSystemLanguage,
|
|
18
|
+
getLanguage,
|
|
19
|
+
getSupportedLanguages,
|
|
20
|
+
notifyLanguageChange,
|
|
21
|
+
onLanguageChange,
|
|
22
|
+
setLanguage,
|
|
23
|
+
t
|
|
24
|
+
} from "./chunk-QGE6AF76.js";
|
|
25
|
+
import {
|
|
26
|
+
defaultConfigPath,
|
|
27
|
+
isPlausibleKey,
|
|
28
|
+
loadApiKey,
|
|
29
|
+
readConfig,
|
|
30
|
+
redactKey,
|
|
31
|
+
writeConfig
|
|
32
|
+
} from "./chunk-DULSP7JH.js";
|
|
33
|
+
|
|
34
|
+
// src/cli/commands/setup.tsx
|
|
35
|
+
import { render } from "ink";
|
|
36
|
+
import React2 from "react";
|
|
37
|
+
|
|
38
|
+
// src/cli/ui/Wizard.tsx
|
|
39
|
+
import { mkdirSync, statSync } from "fs";
|
|
40
|
+
import { Box, Text, useApp, useInput } from "ink";
|
|
41
|
+
import TextInput from "ink-text-input";
|
|
42
|
+
import React, { useEffect, useState } from "react";
|
|
43
|
+
var CATALOG_BY_NAME = new Map(MCP_CATALOG.map((e) => [e.name, e]));
|
|
44
|
+
var LANGUAGE_LABELS = {
|
|
45
|
+
EN: "English",
|
|
46
|
+
"zh-CN": "\u7B80\u4F53\u4E2D\u6587"
|
|
47
|
+
};
|
|
48
|
+
function Wizard({ onComplete, onCancel, existingApiKey, initial }) {
|
|
49
|
+
const { exit } = useApp();
|
|
50
|
+
const [, setLanguageVersion] = useState(0);
|
|
51
|
+
useEffect(() => onLanguageChange(() => setLanguageVersion((v) => v + 1)), []);
|
|
52
|
+
const [step, setStep] = useState("language");
|
|
53
|
+
const [data, setData] = useState({
|
|
54
|
+
language: getLanguage(),
|
|
55
|
+
apiKey: existingApiKey ?? "",
|
|
56
|
+
preset: initial?.preset ?? "auto",
|
|
57
|
+
selectedCatalog: deriveInitialCatalog(initial?.mcp ?? []),
|
|
58
|
+
catalogArgs: {}
|
|
59
|
+
});
|
|
60
|
+
const [error, setError] = useState(null);
|
|
61
|
+
useInput((_input, key) => {
|
|
62
|
+
if (key.escape && step !== "saved" && onCancel) onCancel();
|
|
63
|
+
});
|
|
64
|
+
if (step === "language") {
|
|
65
|
+
return /* @__PURE__ */ React.createElement(
|
|
66
|
+
LanguageStep,
|
|
67
|
+
{
|
|
68
|
+
initialValue: data.language,
|
|
69
|
+
onSubmit: (lang) => {
|
|
70
|
+
setLanguage(lang);
|
|
71
|
+
notifyLanguageChange();
|
|
72
|
+
setData((d) => ({ ...d, language: lang }));
|
|
73
|
+
setStep(existingApiKey ? "preset" : "apiKey");
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
if (step === "apiKey") {
|
|
79
|
+
return /* @__PURE__ */ React.createElement(
|
|
80
|
+
ApiKeyStep,
|
|
81
|
+
{
|
|
82
|
+
onSubmit: (key) => {
|
|
83
|
+
setData((d) => ({ ...d, apiKey: key }));
|
|
84
|
+
setError(null);
|
|
85
|
+
setStep("preset");
|
|
86
|
+
},
|
|
87
|
+
error,
|
|
88
|
+
onError: setError
|
|
89
|
+
}
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
if (step === "preset") {
|
|
93
|
+
return /* @__PURE__ */ React.createElement(StepFrame, { title: t("wizard.presetTitle"), step: 1, total: 3 }, /* @__PURE__ */ React.createElement(
|
|
94
|
+
SingleSelect,
|
|
95
|
+
{
|
|
96
|
+
items: presetItems(),
|
|
97
|
+
initialValue: data.preset,
|
|
98
|
+
onSubmit: (preset) => {
|
|
99
|
+
setData((d) => ({ ...d, preset }));
|
|
100
|
+
setStep("mcp");
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
), /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, { dimColor: true }, t("wizard.selectFooter"))));
|
|
104
|
+
}
|
|
105
|
+
if (step === "mcp") {
|
|
106
|
+
return /* @__PURE__ */ React.createElement(StepFrame, { title: t("wizard.mcpTitle"), step: 2, total: 3 }, /* @__PURE__ */ React.createElement(
|
|
107
|
+
MultiSelect,
|
|
108
|
+
{
|
|
109
|
+
items: mcpItems(),
|
|
110
|
+
initialSelected: data.selectedCatalog,
|
|
111
|
+
onSubmit: (selected) => {
|
|
112
|
+
setData((d) => ({ ...d, selectedCatalog: selected }));
|
|
113
|
+
const needsArgs = selected.some((name) => CATALOG_BY_NAME.get(name)?.userArgs);
|
|
114
|
+
setStep(needsArgs ? "mcpArgs" : "review");
|
|
115
|
+
},
|
|
116
|
+
footer: t("wizard.mcpFooterMulti")
|
|
117
|
+
}
|
|
118
|
+
));
|
|
119
|
+
}
|
|
120
|
+
if (step === "mcpArgs") {
|
|
121
|
+
const pending = data.selectedCatalog.filter((name) => {
|
|
122
|
+
const entry2 = CATALOG_BY_NAME.get(name);
|
|
123
|
+
return entry2?.userArgs && !data.catalogArgs[name];
|
|
124
|
+
});
|
|
125
|
+
if (pending.length === 0) {
|
|
126
|
+
setStep("review");
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
const currentName = pending[0];
|
|
130
|
+
const entry = CATALOG_BY_NAME.get(currentName);
|
|
131
|
+
return /* @__PURE__ */ React.createElement(
|
|
132
|
+
McpArgsStep,
|
|
133
|
+
{
|
|
134
|
+
entry,
|
|
135
|
+
error,
|
|
136
|
+
onSubmit: (value) => {
|
|
137
|
+
setData((d) => ({
|
|
138
|
+
...d,
|
|
139
|
+
catalogArgs: { ...d.catalogArgs, [currentName]: value }
|
|
140
|
+
}));
|
|
141
|
+
setError(null);
|
|
142
|
+
},
|
|
143
|
+
onError: setError
|
|
144
|
+
}
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
if (step === "review") {
|
|
148
|
+
const specs = data.selectedCatalog.map((name) => buildSpec(name, data.catalogArgs));
|
|
149
|
+
return /* @__PURE__ */ React.createElement(StepFrame, { title: t("wizard.reviewTitle"), step: 3, total: 3 }, /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, /* @__PURE__ */ React.createElement(
|
|
150
|
+
SummaryLine,
|
|
151
|
+
{
|
|
152
|
+
label: t("wizard.reviewLabelLanguage"),
|
|
153
|
+
value: LANGUAGE_LABELS[data.language]
|
|
154
|
+
}
|
|
155
|
+
), /* @__PURE__ */ React.createElement(SummaryLine, { label: t("wizard.reviewLabelApiKey"), value: redactKey(data.apiKey) }), /* @__PURE__ */ React.createElement(SummaryLine, { label: t("wizard.reviewLabelPreset"), value: data.preset }), /* @__PURE__ */ React.createElement(
|
|
156
|
+
SummaryLine,
|
|
157
|
+
{
|
|
158
|
+
label: t("wizard.reviewLabelMcp"),
|
|
159
|
+
value: specs.length === 0 ? t("wizard.reviewMcpNone") : t("wizard.reviewMcpServers", { count: specs.length })
|
|
160
|
+
}
|
|
161
|
+
), specs.map((spec, i) => (
|
|
162
|
+
// biome-ignore lint/suspicious/noArrayIndexKey: review-only render, order fixed
|
|
163
|
+
/* @__PURE__ */ React.createElement(Box, { key: i, paddingLeft: 14 }, /* @__PURE__ */ React.createElement(Text, { dimColor: true }, "\xB7 ", spec))
|
|
164
|
+
)), /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, null, t("wizard.reviewSavesTo", { path: defaultConfigPath() }))), error ? /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, { color: "red" }, error)) : null, /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, { dimColor: true }, t("wizard.reviewFooter")))), /* @__PURE__ */ React.createElement(
|
|
165
|
+
ReviewConfirm,
|
|
166
|
+
{
|
|
167
|
+
onConfirm: () => {
|
|
168
|
+
try {
|
|
169
|
+
const specsNow = data.selectedCatalog.map(
|
|
170
|
+
(name) => buildSpec(name, data.catalogArgs)
|
|
171
|
+
);
|
|
172
|
+
const prev = readConfig();
|
|
173
|
+
const next = {
|
|
174
|
+
...prev,
|
|
175
|
+
apiKey: data.apiKey,
|
|
176
|
+
preset: data.preset,
|
|
177
|
+
mcp: specsNow,
|
|
178
|
+
setupCompleted: true
|
|
179
|
+
};
|
|
180
|
+
writeConfig(next);
|
|
181
|
+
setStep("saved");
|
|
182
|
+
onComplete(next);
|
|
183
|
+
} catch (e) {
|
|
184
|
+
setError(t("wizard.reviewSaveError", { message: e.message }));
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
));
|
|
189
|
+
}
|
|
190
|
+
return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", borderStyle: "round", borderColor: "green", paddingX: 1 }, /* @__PURE__ */ React.createElement(Text, { bold: true, color: "green" }, t("wizard.savedTitle")), /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, null, t("ui.welcome"))), /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, { dimColor: true }, t("wizard.savedFooter"))), /* @__PURE__ */ React.createElement(ExitOnEnter, { onExit: exit }));
|
|
191
|
+
}
|
|
192
|
+
function LanguageStep({
|
|
193
|
+
initialValue,
|
|
194
|
+
onSubmit
|
|
195
|
+
}) {
|
|
196
|
+
const items = getSupportedLanguages().map((code) => ({
|
|
197
|
+
value: code,
|
|
198
|
+
label: LANGUAGE_LABELS[code],
|
|
199
|
+
hint: code === detectSystemLanguage() ? "(detected)" : void 0
|
|
200
|
+
}));
|
|
201
|
+
return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1 }, /* @__PURE__ */ React.createElement(Text, { bold: true, color: "cyan" }, t("wizard.languageTitle")), /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, { dimColor: true }, t("wizard.languageSubtitle"))), /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(
|
|
202
|
+
SingleSelect,
|
|
203
|
+
{
|
|
204
|
+
items,
|
|
205
|
+
initialValue,
|
|
206
|
+
onSubmit,
|
|
207
|
+
footer: t("wizard.selectFooter")
|
|
208
|
+
}
|
|
209
|
+
)));
|
|
210
|
+
}
|
|
211
|
+
function ApiKeyStep({
|
|
212
|
+
onSubmit,
|
|
213
|
+
error,
|
|
214
|
+
onError
|
|
215
|
+
}) {
|
|
216
|
+
const [value, setValue] = useState("");
|
|
217
|
+
return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1 }, /* @__PURE__ */ React.createElement(Text, { bold: true, color: "cyan" }, t("wizard.welcomeTitle")), /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, null, t("wizard.apiKeyPrompt"))), /* @__PURE__ */ React.createElement(Text, { dimColor: true }, t("wizard.apiKeyGetOne")), /* @__PURE__ */ React.createElement(Text, { dimColor: true }, t("wizard.apiKeySavedLocally", { path: defaultConfigPath() })), /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, { bold: true, color: "cyan" }, t("wizard.apiKeyInputLabel")), /* @__PURE__ */ React.createElement(
|
|
218
|
+
TextInput,
|
|
219
|
+
{
|
|
220
|
+
value,
|
|
221
|
+
onChange: setValue,
|
|
222
|
+
onSubmit: (raw) => {
|
|
223
|
+
const trimmed = raw.trim();
|
|
224
|
+
if (!isPlausibleKey(trimmed)) {
|
|
225
|
+
onError(t("wizard.apiKeyInvalid"));
|
|
226
|
+
setValue("");
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
onSubmit(trimmed);
|
|
230
|
+
},
|
|
231
|
+
mask: "\u2022",
|
|
232
|
+
placeholder: "sk-..."
|
|
233
|
+
}
|
|
234
|
+
)), error ? /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, { color: "red" }, error)) : value ? /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, { dimColor: true }, t("wizard.apiKeyPreview", { redacted: redactKey(value) }))) : null);
|
|
235
|
+
}
|
|
236
|
+
function McpArgsStep({
|
|
237
|
+
entry,
|
|
238
|
+
error,
|
|
239
|
+
onSubmit,
|
|
240
|
+
onError
|
|
241
|
+
}) {
|
|
242
|
+
const [value, setValue] = useState("");
|
|
243
|
+
const [pendingCreate, setPendingCreate] = useState(null);
|
|
244
|
+
useInput((input, key) => {
|
|
245
|
+
if (!pendingCreate) return;
|
|
246
|
+
const ch = input.toLowerCase();
|
|
247
|
+
if (ch === "y" || key.return) {
|
|
248
|
+
try {
|
|
249
|
+
mkdirSync(pendingCreate, { recursive: true });
|
|
250
|
+
const created = pendingCreate;
|
|
251
|
+
setPendingCreate(null);
|
|
252
|
+
setValue("");
|
|
253
|
+
onError(null);
|
|
254
|
+
onSubmit(created);
|
|
255
|
+
} catch (e) {
|
|
256
|
+
onError(
|
|
257
|
+
t("wizard.mcpArgsDirCreateFailed", {
|
|
258
|
+
path: pendingCreate,
|
|
259
|
+
message: e.message
|
|
260
|
+
})
|
|
261
|
+
);
|
|
262
|
+
setPendingCreate(null);
|
|
263
|
+
}
|
|
264
|
+
} else if (ch === "n" || key.escape) {
|
|
265
|
+
setPendingCreate(null);
|
|
266
|
+
onError(null);
|
|
267
|
+
}
|
|
268
|
+
});
|
|
269
|
+
if (pendingCreate) {
|
|
270
|
+
return /* @__PURE__ */ React.createElement(StepFrame, { title: t("wizard.mcpArgsTitle", { name: entry.name }), step: 2, total: 3 }, /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, /* @__PURE__ */ React.createElement(Text, null, t("wizard.mcpArgsDirMissing", { path: pendingCreate })), /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, { dimColor: true }, t("wizard.mcpArgsDirCreateHint"))), error ? /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, { color: "red" }, error)) : null));
|
|
271
|
+
}
|
|
272
|
+
return /* @__PURE__ */ React.createElement(StepFrame, { title: t("wizard.mcpArgsTitle", { name: entry.name }), step: 2, total: 3 }, /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, /* @__PURE__ */ React.createElement(Text, null, entry.summary), entry.note ? /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, { dimColor: true }, entry.note)) : null, /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, null, t("wizard.mcpArgsRequiredParam")), /* @__PURE__ */ React.createElement(Text, { bold: true }, entry.userArgs)), /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, { bold: true, color: "cyan" }, entry.userArgs, " \u203A "), /* @__PURE__ */ React.createElement(
|
|
273
|
+
TextInput,
|
|
274
|
+
{
|
|
275
|
+
value,
|
|
276
|
+
onChange: setValue,
|
|
277
|
+
onSubmit: (raw) => {
|
|
278
|
+
const trimmed = raw.trim();
|
|
279
|
+
if (!trimmed) {
|
|
280
|
+
onError(t("wizard.mcpArgsEmpty", { name: entry.name }));
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
if (entry.name === "filesystem") {
|
|
284
|
+
const check = checkFilesystemPath(trimmed);
|
|
285
|
+
if (check.kind === "missing") {
|
|
286
|
+
setPendingCreate(trimmed);
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
if (check.kind === "not-a-dir") {
|
|
290
|
+
onError(t("wizard.mcpArgsNotADir", { path: trimmed }));
|
|
291
|
+
return;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
onSubmit(trimmed);
|
|
295
|
+
setValue("");
|
|
296
|
+
},
|
|
297
|
+
placeholder: placeholderFor(entry)
|
|
298
|
+
}
|
|
299
|
+
)), error ? /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, { color: "red" }, error)) : null));
|
|
300
|
+
}
|
|
301
|
+
function checkFilesystemPath(p) {
|
|
302
|
+
try {
|
|
303
|
+
return { kind: statSync(p).isDirectory() ? "ok" : "not-a-dir" };
|
|
304
|
+
} catch {
|
|
305
|
+
return { kind: "missing" };
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
function ReviewConfirm({ onConfirm }) {
|
|
309
|
+
useInput((_i, key) => {
|
|
310
|
+
if (key.return) onConfirm();
|
|
311
|
+
});
|
|
312
|
+
return null;
|
|
313
|
+
}
|
|
314
|
+
function ExitOnEnter({ onExit }) {
|
|
315
|
+
useInput((_i, key) => {
|
|
316
|
+
if (key.return) onExit();
|
|
317
|
+
});
|
|
318
|
+
return null;
|
|
319
|
+
}
|
|
320
|
+
function StepFrame({
|
|
321
|
+
title,
|
|
322
|
+
step,
|
|
323
|
+
total,
|
|
324
|
+
children
|
|
325
|
+
}) {
|
|
326
|
+
return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1 }, /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, { dimColor: true }, t("wizard.stepCounter", { step, total })), /* @__PURE__ */ React.createElement(Text, { bold: true, color: "cyan" }, title)), /* @__PURE__ */ React.createElement(Box, { marginTop: 1, flexDirection: "column" }, children));
|
|
327
|
+
}
|
|
328
|
+
function SummaryLine({ label, value }) {
|
|
329
|
+
return /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, null, label.padEnd(12)), /* @__PURE__ */ React.createElement(Text, { bold: true }, value));
|
|
330
|
+
}
|
|
331
|
+
function presetItems() {
|
|
332
|
+
return ["auto", "flash", "pro"].map((name) => ({
|
|
333
|
+
value: name,
|
|
334
|
+
label: `${name} \u2014 ${PRESET_DESCRIPTIONS[name].headline}`,
|
|
335
|
+
hint: PRESET_DESCRIPTIONS[name].cost
|
|
336
|
+
}));
|
|
337
|
+
}
|
|
338
|
+
function mcpItems() {
|
|
339
|
+
return MCP_CATALOG.map((entry) => {
|
|
340
|
+
const hintParts = [entry.summary];
|
|
341
|
+
if (entry.userArgs) hintParts.push(t("wizard.mcpUserArgsHint", { arg: entry.userArgs }));
|
|
342
|
+
if (entry.note) hintParts.push(entry.note);
|
|
343
|
+
return {
|
|
344
|
+
value: entry.name,
|
|
345
|
+
label: entry.name,
|
|
346
|
+
hint: hintParts.join(" \xB7 ")
|
|
347
|
+
};
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
function placeholderFor(entry) {
|
|
351
|
+
if (entry.name === "filesystem") return "e.g. /tmp/reasonix-sandbox";
|
|
352
|
+
if (entry.name === "sqlite") return "e.g. ./notes.sqlite";
|
|
353
|
+
return entry.userArgs ?? "";
|
|
354
|
+
}
|
|
355
|
+
function deriveInitialCatalog(existingSpecs) {
|
|
356
|
+
const packageToName = new Map(MCP_CATALOG.map((e) => [e.package, e.name]));
|
|
357
|
+
const out = [];
|
|
358
|
+
for (const spec of existingSpecs) {
|
|
359
|
+
for (const [pkg, name] of packageToName) {
|
|
360
|
+
if (spec.includes(pkg)) {
|
|
361
|
+
out.push(name);
|
|
362
|
+
break;
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
return out;
|
|
367
|
+
}
|
|
368
|
+
function buildSpec(name, argsByName) {
|
|
369
|
+
const entry = CATALOG_BY_NAME.get(name);
|
|
370
|
+
if (!entry) return name;
|
|
371
|
+
const userArg = entry.userArgs ? argsByName[name] : void 0;
|
|
372
|
+
const tail = userArg ? ` ${quoteIfNeeded(userArg)}` : "";
|
|
373
|
+
return `${entry.name}=npx -y ${entry.package}${tail}`;
|
|
374
|
+
}
|
|
375
|
+
function quoteIfNeeded(s) {
|
|
376
|
+
return /\s|"/.test(s) ? `"${s.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"` : s;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
// src/cli/commands/setup.tsx
|
|
380
|
+
async function setupCommand(_opts = {}) {
|
|
381
|
+
loadDotenv();
|
|
382
|
+
const existingKey = loadApiKey();
|
|
383
|
+
const existing = readConfig();
|
|
384
|
+
const { waitUntilExit, unmount } = render(
|
|
385
|
+
/* @__PURE__ */ React2.createElement(
|
|
386
|
+
Wizard,
|
|
387
|
+
{
|
|
388
|
+
existingApiKey: existingKey,
|
|
389
|
+
initial: { preset: existing.preset, mcp: existing.mcp },
|
|
390
|
+
onComplete: () => {
|
|
391
|
+
},
|
|
392
|
+
onCancel: () => {
|
|
393
|
+
unmount();
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
),
|
|
397
|
+
{ exitOnCtrlC: true, patchConsole: false }
|
|
398
|
+
);
|
|
399
|
+
await waitUntilExit();
|
|
400
|
+
}
|
|
401
|
+
export {
|
|
402
|
+
setupCommand
|
|
403
|
+
};
|
|
404
|
+
//# sourceMappingURL=setup-CCJZAWTY.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/cli/commands/setup.tsx","../../src/cli/ui/Wizard.tsx"],"sourcesContent":["/**\n * `reasonix setup` — re-mount the first-run wizard on demand so users\n * can reconfigure (add/remove MCP servers, switch preset) without\n * editing JSON by hand.\n *\n * Invoked both explicitly (`reasonix setup`) and implicitly (the no-args\n * entry point when `setupCompleted` is false).\n */\n\nimport { render } from \"ink\";\nimport React from \"react\";\nimport { loadApiKey, readConfig } from \"../../config.js\";\nimport { loadDotenv } from \"../../env.js\";\nimport { Wizard } from \"../ui/Wizard.js\";\n\nexport interface SetupOptions {\n /**\n * When true, bypass the API-key step even if no key is saved — useful\n * from test harnesses. Normal CLI use always pushes through the key\n * step when missing.\n */\n skipKeyStep?: boolean;\n}\n\nexport async function setupCommand(_opts: SetupOptions = {}): Promise<void> {\n loadDotenv();\n const existingKey = loadApiKey();\n const existing = readConfig();\n\n const { waitUntilExit, unmount } = render(\n <Wizard\n existingApiKey={existingKey}\n initial={{ preset: existing.preset, mcp: existing.mcp }}\n onComplete={() => {\n // Ink handles its own enter-to-exit inside the \"saved\" step; we\n // just wait for the app to exit naturally.\n }}\n onCancel={() => {\n unmount();\n }}\n />,\n { exitOnCtrlC: true, patchConsole: false },\n );\n await waitUntilExit();\n}\n","/**\n * First-run / re-configure wizard.\n *\n * Walks a new user through: language → API key → preset pick → MCP server\n * pick → per-server args → save. Saved output lives in\n * `~/.reasonix/config.json` so the next `reasonix chat` starts with\n * everything already wired.\n */\n\nimport { mkdirSync, statSync } from \"node:fs\";\nimport { Box, Text, useApp, useInput } from \"ink\";\nimport TextInput from \"ink-text-input\";\n// biome-ignore lint/style/useImportType: JSX (jsx: \"react\") needs React as a value at runtime\nimport React, { useEffect, useState } from \"react\";\nimport {\n type PresetName,\n type ReasonixConfig,\n defaultConfigPath,\n isPlausibleKey,\n readConfig,\n redactKey,\n writeConfig,\n} from \"../../config.js\";\nimport {\n detectSystemLanguage,\n getLanguage,\n getSupportedLanguages,\n notifyLanguageChange,\n onLanguageChange,\n setLanguage,\n t,\n} from \"../../i18n/index.js\";\nimport type { LanguageCode } from \"../../i18n/types.js\";\nimport { type CatalogEntry, MCP_CATALOG } from \"../../mcp/catalog.js\";\nimport { MultiSelect, type SelectItem, SingleSelect } from \"./Select.js\";\nimport { PRESET_DESCRIPTIONS } from \"./presets.js\";\n\nexport interface WizardProps {\n /** Called once the config has been saved. */\n onComplete: (cfg: ReasonixConfig) => void;\n /** Called if the user presses Esc to abort. */\n onCancel?: () => void;\n /** Skip the API-key step if a key already exists (env or config). */\n existingApiKey?: string;\n /** Pre-fill selections when re-running (reconfigure flow). */\n initial?: {\n preset?: PresetName;\n mcp?: string[];\n };\n}\n\ntype Step = \"language\" | \"apiKey\" | \"preset\" | \"mcp\" | \"mcpArgs\" | \"review\" | \"saved\";\n\ninterface WizardData {\n language: LanguageCode;\n apiKey: string;\n preset: PresetName;\n selectedCatalog: string[];\n catalogArgs: Record<string, string>;\n}\n\nconst CATALOG_BY_NAME = new Map(MCP_CATALOG.map((e) => [e.name, e]));\n\nconst LANGUAGE_LABELS: Record<LanguageCode, string> = {\n EN: \"English\",\n \"zh-CN\": \"简体中文\",\n};\n\nexport function Wizard({ onComplete, onCancel, existingApiKey, initial }: WizardProps) {\n const { exit } = useApp();\n const [, setLanguageVersion] = useState(0);\n useEffect(() => onLanguageChange(() => setLanguageVersion((v) => v + 1)), []);\n\n const [step, setStep] = useState<Step>(\"language\");\n const [data, setData] = useState<WizardData>({\n language: getLanguage(),\n apiKey: existingApiKey ?? \"\",\n preset: initial?.preset ?? \"auto\",\n selectedCatalog: deriveInitialCatalog(initial?.mcp ?? []),\n catalogArgs: {},\n });\n const [error, setError] = useState<string | null>(null);\n\n useInput((_input, key) => {\n if (key.escape && step !== \"saved\" && onCancel) onCancel();\n });\n\n if (step === \"language\") {\n return (\n <LanguageStep\n initialValue={data.language}\n onSubmit={(lang) => {\n setLanguage(lang);\n notifyLanguageChange();\n setData((d) => ({ ...d, language: lang }));\n setStep(existingApiKey ? \"preset\" : \"apiKey\");\n }}\n />\n );\n }\n\n if (step === \"apiKey\") {\n return (\n <ApiKeyStep\n onSubmit={(key) => {\n setData((d) => ({ ...d, apiKey: key }));\n setError(null);\n setStep(\"preset\");\n }}\n error={error}\n onError={setError}\n />\n );\n }\n\n if (step === \"preset\") {\n return (\n <StepFrame title={t(\"wizard.presetTitle\")} step={1} total={3}>\n <SingleSelect<PresetName>\n items={presetItems()}\n initialValue={data.preset}\n onSubmit={(preset) => {\n setData((d) => ({ ...d, preset }));\n setStep(\"mcp\");\n }}\n />\n <Box marginTop={1}>\n <Text dimColor>{t(\"wizard.selectFooter\")}</Text>\n </Box>\n </StepFrame>\n );\n }\n\n if (step === \"mcp\") {\n return (\n <StepFrame title={t(\"wizard.mcpTitle\")} step={2} total={3}>\n <MultiSelect\n items={mcpItems()}\n initialSelected={data.selectedCatalog}\n onSubmit={(selected) => {\n setData((d) => ({ ...d, selectedCatalog: selected }));\n const needsArgs = selected.some((name) => CATALOG_BY_NAME.get(name)?.userArgs);\n setStep(needsArgs ? \"mcpArgs\" : \"review\");\n }}\n footer={t(\"wizard.mcpFooterMulti\")}\n />\n </StepFrame>\n );\n }\n\n if (step === \"mcpArgs\") {\n const pending = data.selectedCatalog.filter((name) => {\n const entry = CATALOG_BY_NAME.get(name);\n return entry?.userArgs && !data.catalogArgs[name];\n });\n if (pending.length === 0) {\n setStep(\"review\");\n return null;\n }\n const currentName = pending[0]!;\n const entry = CATALOG_BY_NAME.get(currentName)!;\n return (\n <McpArgsStep\n entry={entry}\n error={error}\n onSubmit={(value) => {\n setData((d) => ({\n ...d,\n catalogArgs: { ...d.catalogArgs, [currentName]: value },\n }));\n setError(null);\n }}\n onError={setError}\n />\n );\n }\n\n if (step === \"review\") {\n const specs = data.selectedCatalog.map((name) => buildSpec(name, data.catalogArgs));\n return (\n <StepFrame title={t(\"wizard.reviewTitle\")} step={3} total={3}>\n <Box flexDirection=\"column\">\n <SummaryLine\n label={t(\"wizard.reviewLabelLanguage\")}\n value={LANGUAGE_LABELS[data.language]}\n />\n <SummaryLine label={t(\"wizard.reviewLabelApiKey\")} value={redactKey(data.apiKey)} />\n <SummaryLine label={t(\"wizard.reviewLabelPreset\")} value={data.preset} />\n <SummaryLine\n label={t(\"wizard.reviewLabelMcp\")}\n value={\n specs.length === 0\n ? t(\"wizard.reviewMcpNone\")\n : t(\"wizard.reviewMcpServers\", { count: specs.length })\n }\n />\n {specs.map((spec, i) => (\n // biome-ignore lint/suspicious/noArrayIndexKey: review-only render, order fixed\n <Box key={i} paddingLeft={14}>\n <Text dimColor>· {spec}</Text>\n </Box>\n ))}\n <Box marginTop={1}>\n <Text>{t(\"wizard.reviewSavesTo\", { path: defaultConfigPath() })}</Text>\n </Box>\n {error ? (\n <Box marginTop={1}>\n <Text color=\"red\">{error}</Text>\n </Box>\n ) : null}\n <Box marginTop={1}>\n <Text dimColor>{t(\"wizard.reviewFooter\")}</Text>\n </Box>\n </Box>\n <ReviewConfirm\n onConfirm={() => {\n try {\n const specsNow = data.selectedCatalog.map((name) =>\n buildSpec(name, data.catalogArgs),\n );\n const prev = readConfig();\n const next: ReasonixConfig = {\n ...prev,\n apiKey: data.apiKey,\n preset: data.preset,\n mcp: specsNow,\n setupCompleted: true,\n };\n writeConfig(next);\n setStep(\"saved\");\n onComplete(next);\n } catch (e) {\n setError(t(\"wizard.reviewSaveError\", { message: (e as Error).message }));\n }\n }}\n />\n </StepFrame>\n );\n }\n\n return (\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor=\"green\" paddingX={1}>\n <Text bold color=\"green\">\n {t(\"wizard.savedTitle\")}\n </Text>\n <Box marginTop={1}>\n <Text>{t(\"ui.welcome\")}</Text>\n </Box>\n <Box marginTop={1}>\n <Text dimColor>{t(\"wizard.savedFooter\")}</Text>\n </Box>\n <ExitOnEnter onExit={exit} />\n </Box>\n );\n}\n\n// ---------- step components ----------\n\nfunction LanguageStep({\n initialValue,\n onSubmit,\n}: {\n initialValue: LanguageCode;\n onSubmit: (lang: LanguageCode) => void;\n}) {\n const items: SelectItem<LanguageCode>[] = getSupportedLanguages().map((code) => ({\n value: code,\n label: LANGUAGE_LABELS[code],\n hint: code === detectSystemLanguage() ? \"(detected)\" : undefined,\n }));\n return (\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor=\"cyan\" paddingX={1}>\n <Text bold color=\"cyan\">\n {t(\"wizard.languageTitle\")}\n </Text>\n <Box marginTop={1}>\n <Text dimColor>{t(\"wizard.languageSubtitle\")}</Text>\n </Box>\n <Box marginTop={1}>\n <SingleSelect<LanguageCode>\n items={items}\n initialValue={initialValue}\n onSubmit={onSubmit}\n footer={t(\"wizard.selectFooter\")}\n />\n </Box>\n </Box>\n );\n}\n\nfunction ApiKeyStep({\n onSubmit,\n error,\n onError,\n}: {\n onSubmit: (key: string) => void;\n error: string | null;\n onError: (e: string | null) => void;\n}) {\n const [value, setValue] = useState(\"\");\n return (\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor=\"cyan\" paddingX={1}>\n <Text bold color=\"cyan\">\n {t(\"wizard.welcomeTitle\")}\n </Text>\n <Box marginTop={1}>\n <Text>{t(\"wizard.apiKeyPrompt\")}</Text>\n </Box>\n <Text dimColor>{t(\"wizard.apiKeyGetOne\")}</Text>\n <Text dimColor>{t(\"wizard.apiKeySavedLocally\", { path: defaultConfigPath() })}</Text>\n <Box marginTop={1}>\n <Text bold color=\"cyan\">\n {t(\"wizard.apiKeyInputLabel\")}\n </Text>\n <TextInput\n value={value}\n onChange={setValue}\n onSubmit={(raw) => {\n const trimmed = raw.trim();\n if (!isPlausibleKey(trimmed)) {\n onError(t(\"wizard.apiKeyInvalid\"));\n setValue(\"\");\n return;\n }\n onSubmit(trimmed);\n }}\n mask=\"•\"\n placeholder=\"sk-...\"\n />\n </Box>\n {error ? (\n <Box marginTop={1}>\n <Text color=\"red\">{error}</Text>\n </Box>\n ) : value ? (\n <Box marginTop={1}>\n <Text dimColor>{t(\"wizard.apiKeyPreview\", { redacted: redactKey(value) })}</Text>\n </Box>\n ) : null}\n </Box>\n );\n}\n\nfunction McpArgsStep({\n entry,\n error,\n onSubmit,\n onError,\n}: {\n entry: CatalogEntry;\n error: string | null;\n onSubmit: (value: string) => void;\n onError: (e: string | null) => void;\n}) {\n const [value, setValue] = useState(\"\");\n const [pendingCreate, setPendingCreate] = useState<string | null>(null);\n\n useInput((input, key) => {\n if (!pendingCreate) return;\n const ch = input.toLowerCase();\n if (ch === \"y\" || key.return) {\n try {\n mkdirSync(pendingCreate, { recursive: true });\n const created = pendingCreate;\n setPendingCreate(null);\n setValue(\"\");\n onError(null);\n onSubmit(created);\n } catch (e) {\n onError(\n t(\"wizard.mcpArgsDirCreateFailed\", {\n path: pendingCreate,\n message: (e as Error).message,\n }),\n );\n setPendingCreate(null);\n }\n } else if (ch === \"n\" || key.escape) {\n setPendingCreate(null);\n onError(null);\n }\n });\n\n if (pendingCreate) {\n return (\n <StepFrame title={t(\"wizard.mcpArgsTitle\", { name: entry.name })} step={2} total={3}>\n <Box flexDirection=\"column\">\n <Text>{t(\"wizard.mcpArgsDirMissing\", { path: pendingCreate })}</Text>\n <Box marginTop={1}>\n <Text dimColor>{t(\"wizard.mcpArgsDirCreateHint\")}</Text>\n </Box>\n {error ? (\n <Box marginTop={1}>\n <Text color=\"red\">{error}</Text>\n </Box>\n ) : null}\n </Box>\n </StepFrame>\n );\n }\n\n return (\n <StepFrame title={t(\"wizard.mcpArgsTitle\", { name: entry.name })} step={2} total={3}>\n <Box flexDirection=\"column\">\n <Text>{entry.summary}</Text>\n {entry.note ? (\n <Box marginTop={1}>\n <Text dimColor>{entry.note}</Text>\n </Box>\n ) : null}\n <Box marginTop={1}>\n <Text>{t(\"wizard.mcpArgsRequiredParam\")}</Text>\n <Text bold>{entry.userArgs}</Text>\n </Box>\n <Box marginTop={1}>\n <Text bold color=\"cyan\">\n {entry.userArgs}\n {\" › \"}\n </Text>\n <TextInput\n value={value}\n onChange={setValue}\n onSubmit={(raw) => {\n const trimmed = raw.trim();\n if (!trimmed) {\n onError(t(\"wizard.mcpArgsEmpty\", { name: entry.name }));\n return;\n }\n if (entry.name === \"filesystem\") {\n const check = checkFilesystemPath(trimmed);\n if (check.kind === \"missing\") {\n setPendingCreate(trimmed);\n return;\n }\n if (check.kind === \"not-a-dir\") {\n onError(t(\"wizard.mcpArgsNotADir\", { path: trimmed }));\n return;\n }\n }\n onSubmit(trimmed);\n setValue(\"\");\n }}\n placeholder={placeholderFor(entry)}\n />\n </Box>\n {error ? (\n <Box marginTop={1}>\n <Text color=\"red\">{error}</Text>\n </Box>\n ) : null}\n </Box>\n </StepFrame>\n );\n}\n\nfunction checkFilesystemPath(p: string): { kind: \"ok\" | \"missing\" | \"not-a-dir\" } {\n try {\n return { kind: statSync(p).isDirectory() ? \"ok\" : \"not-a-dir\" };\n } catch {\n return { kind: \"missing\" };\n }\n}\n\nfunction ReviewConfirm({ onConfirm }: { onConfirm: () => void }) {\n useInput((_i, key) => {\n if (key.return) onConfirm();\n });\n return null;\n}\n\nfunction ExitOnEnter({ onExit }: { onExit: () => void }) {\n useInput((_i, key) => {\n if (key.return) onExit();\n });\n return null;\n}\n\nfunction StepFrame({\n title,\n step,\n total,\n children,\n}: {\n title: string;\n step: number;\n total: number;\n children: React.ReactNode;\n}) {\n return (\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor=\"cyan\" paddingX={1}>\n <Box>\n <Text dimColor>{t(\"wizard.stepCounter\", { step, total })}</Text>\n <Text bold color=\"cyan\">\n {title}\n </Text>\n </Box>\n <Box marginTop={1} flexDirection=\"column\">\n {children}\n </Box>\n </Box>\n );\n}\n\nfunction SummaryLine({ label, value }: { label: string; value: string }) {\n return (\n <Box>\n <Text>{label.padEnd(12)}</Text>\n <Text bold>{value}</Text>\n </Box>\n );\n}\n\nfunction presetItems(): SelectItem<PresetName>[] {\n return ([\"auto\", \"flash\", \"pro\"] as const).map((name) => ({\n value: name as PresetName,\n label: `${name} — ${PRESET_DESCRIPTIONS[name].headline}`,\n hint: PRESET_DESCRIPTIONS[name].cost,\n }));\n}\n\nfunction mcpItems(): SelectItem<string>[] {\n return MCP_CATALOG.map((entry) => {\n const hintParts: string[] = [entry.summary];\n if (entry.userArgs) hintParts.push(t(\"wizard.mcpUserArgsHint\", { arg: entry.userArgs }));\n if (entry.note) hintParts.push(entry.note);\n return {\n value: entry.name,\n label: entry.name,\n hint: hintParts.join(\" · \"),\n };\n });\n}\n\nfunction placeholderFor(entry: CatalogEntry): string {\n if (entry.name === \"filesystem\") return \"e.g. /tmp/reasonix-sandbox\";\n if (entry.name === \"sqlite\") return \"e.g. ./notes.sqlite\";\n return entry.userArgs ?? \"\";\n}\n\nfunction deriveInitialCatalog(existingSpecs: string[]): string[] {\n const packageToName = new Map(MCP_CATALOG.map((e) => [e.package, e.name]));\n const out: string[] = [];\n for (const spec of existingSpecs) {\n for (const [pkg, name] of packageToName) {\n if (spec.includes(pkg)) {\n out.push(name);\n break;\n }\n }\n }\n return out;\n}\n\n/**\n * Build the `--mcp` spec string for a catalog entry. Same format\n * `mcpCommandFor` produces for `reasonix mcp list`, minus the leading\n * `--mcp \"...\"` wrapper — we store the inner spec directly.\n */\nexport function buildSpec(name: string, argsByName: Record<string, string>): string {\n const entry = CATALOG_BY_NAME.get(name);\n if (!entry) return name;\n const userArg = entry.userArgs ? argsByName[name] : undefined;\n const tail = userArg ? ` ${quoteIfNeeded(userArg)}` : \"\";\n return `${entry.name}=npx -y ${entry.package}${tail}`;\n}\n\nfunction quoteIfNeeded(s: string): string {\n // Escape backslashes BEFORE quotes — otherwise a trailing `\\` in the\n // input would consume the closing quote when a downstream parser\n // un-escapes the output (CodeQL js/incomplete-sanitization).\n return /\\s|\"/.test(s) ? `\"${s.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"')}\"` : s;\n}\n"],"mappings":"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","names":["React","entry","React"]}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
renderDashboard,
|
|
4
|
+
statsCommand
|
|
5
|
+
} from "./chunk-4DCHFFEY.js";
|
|
6
|
+
import "./chunk-ZTLZO42A.js";
|
|
7
|
+
import "./chunk-ORM6PK57.js";
|
|
8
|
+
export {
|
|
9
|
+
renderDashboard,
|
|
10
|
+
statsCommand
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=stats-5RJCATCE.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
VERSION,
|
|
4
|
+
compareVersions,
|
|
5
|
+
getLatestVersion,
|
|
6
|
+
isNpxInstall
|
|
7
|
+
} from "./chunk-2AWTGJ2C.js";
|
|
8
|
+
|
|
9
|
+
// src/cli/commands/update.ts
|
|
10
|
+
import { spawn } from "child_process";
|
|
11
|
+
function planUpdate(input) {
|
|
12
|
+
const diff = compareVersions(input.current, input.latest);
|
|
13
|
+
if (diff > 0) {
|
|
14
|
+
return {
|
|
15
|
+
action: "newer-local",
|
|
16
|
+
message: `current (${input.current}) is newer than the published ${input.latest} \u2014 nothing to do.`
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
if (diff === 0) {
|
|
20
|
+
return { action: "up-to-date", message: `reasonix ${input.current} is up to date.` };
|
|
21
|
+
}
|
|
22
|
+
if (input.npx) {
|
|
23
|
+
return {
|
|
24
|
+
action: "npx-hint",
|
|
25
|
+
message: [
|
|
26
|
+
`reasonix ${input.latest} is available.`,
|
|
27
|
+
"you're running via npx \u2014 the next `npx reasonix ...` launch will auto-fetch",
|
|
28
|
+
"the latest (npx caches packages for a short window). to force a refresh",
|
|
29
|
+
"sooner, clear the cache: `npm cache clean --force`."
|
|
30
|
+
].join("\n")
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
return {
|
|
34
|
+
action: "run-npm-install",
|
|
35
|
+
message: `upgrading reasonix ${input.current} \u2192 ${input.latest}`,
|
|
36
|
+
command: ["npm", "install", "-g", "reasonix@latest"]
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
function defaultSpawn(argv) {
|
|
40
|
+
return new Promise((resolve, reject) => {
|
|
41
|
+
const child = spawn(argv[0], argv.slice(1), {
|
|
42
|
+
stdio: "inherit",
|
|
43
|
+
shell: process.platform === "win32"
|
|
44
|
+
});
|
|
45
|
+
child.once("error", reject);
|
|
46
|
+
child.once("exit", (code) => resolve(code ?? 1));
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
async function updateCommand(opts = {}) {
|
|
50
|
+
const write = opts.write ?? ((m) => process.stdout.write(m));
|
|
51
|
+
const exit = opts.exit ?? ((c) => process.exit(c));
|
|
52
|
+
const fetchLatest = opts.fetchLatest ?? (() => getLatestVersion({ force: true }));
|
|
53
|
+
const isNpx = opts.isNpx ?? isNpxInstall;
|
|
54
|
+
const doSpawn = opts.spawnInstall ?? defaultSpawn;
|
|
55
|
+
write(`current: reasonix ${VERSION}
|
|
56
|
+
`);
|
|
57
|
+
const latest = await fetchLatest();
|
|
58
|
+
if (!latest) {
|
|
59
|
+
write("could not reach registry.npmjs.org \u2014 check your network.\n");
|
|
60
|
+
exit(1);
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
write(`latest: reasonix ${latest}
|
|
64
|
+
`);
|
|
65
|
+
const plan = planUpdate({ current: VERSION, latest, npx: isNpx() });
|
|
66
|
+
write(`
|
|
67
|
+
${plan.message}
|
|
68
|
+
`);
|
|
69
|
+
if (plan.action !== "run-npm-install" || !plan.command) return;
|
|
70
|
+
if (opts.dryRun) {
|
|
71
|
+
write(`(dry run) would run: ${plan.command.join(" ")}
|
|
72
|
+
`);
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
write(`
|
|
76
|
+
running: ${plan.command.join(" ")}
|
|
77
|
+
`);
|
|
78
|
+
const code = await doSpawn(plan.command);
|
|
79
|
+
if (code !== 0) {
|
|
80
|
+
write(`
|
|
81
|
+
npm exited with code ${code}. upgrade did not complete.
|
|
82
|
+
`);
|
|
83
|
+
exit(code);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
export {
|
|
87
|
+
planUpdate,
|
|
88
|
+
updateCommand
|
|
89
|
+
};
|
|
90
|
+
//# sourceMappingURL=update-4TJWRUIN.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/cli/commands/update.ts"],"sourcesContent":["import { spawn } from \"node:child_process\";\nimport { VERSION, compareVersions, getLatestVersion, isNpxInstall } from \"../../version.js\";\n\nexport type UpdateAction = \"up-to-date\" | \"newer-local\" | \"npx-hint\" | \"run-npm-install\";\n\nexport interface UpdatePlan {\n action: UpdateAction;\n /** Human-readable summary; the CLI prints this verbatim. */\n message: string;\n command?: string[];\n}\n\nexport interface PlanUpdateInput {\n current: string;\n latest: string;\n /** Overrides `isNpxInstall()` (tests). */\n npx?: boolean;\n}\n\n/** Pure decision — split out so tests don't need to spawn child processes or hit the network. */\nexport function planUpdate(input: PlanUpdateInput): UpdatePlan {\n const diff = compareVersions(input.current, input.latest);\n if (diff > 0) {\n return {\n action: \"newer-local\",\n message: `current (${input.current}) is newer than the published ${input.latest} — nothing to do.`,\n };\n }\n if (diff === 0) {\n return { action: \"up-to-date\", message: `reasonix ${input.current} is up to date.` };\n }\n if (input.npx) {\n return {\n action: \"npx-hint\",\n message: [\n `reasonix ${input.latest} is available.`,\n \"you're running via npx — the next `npx reasonix ...` launch will auto-fetch\",\n \"the latest (npx caches packages for a short window). to force a refresh\",\n \"sooner, clear the cache: `npm cache clean --force`.\",\n ].join(\"\\n\"),\n };\n }\n return {\n action: \"run-npm-install\",\n message: `upgrading reasonix ${input.current} → ${input.latest}`,\n command: [\"npm\", \"install\", \"-g\", \"reasonix@latest\"],\n };\n}\n\nexport interface UpdateCommandOptions {\n /** Skip spawning npm; print the decision only. */\n dryRun?: boolean;\n /** Test seam: override the registry lookup. Returns null = offline. */\n fetchLatest?: () => Promise<string | null>;\n /** Test seam: override the npx detector. */\n isNpx?: () => boolean;\n /** Test seam: override the spawner. Must return exit code. */\n spawnInstall?: (argv: string[]) => Promise<number>;\n /** Test seam: stdout writer. */\n write?: (msg: string) => void;\n /** Test seam: process exit — tests don't want to tear down vitest. */\n exit?: (code: number) => void;\n}\n\nfunction defaultSpawn(argv: string[]): Promise<number> {\n return new Promise((resolve, reject) => {\n // `shell: true` on Windows is what lets `npm` resolve to `npm.cmd`\n // without routing through our `prepareSpawn` helper. The args here\n // are literal strings under our control — no user input flows in,\n // so injection is not a concern. Avoiding `prepareSpawn` keeps\n // this command free of a dep on the shell tools module.\n const child = spawn(argv[0]!, argv.slice(1), {\n stdio: \"inherit\",\n shell: process.platform === \"win32\",\n });\n child.once(\"error\", reject);\n child.once(\"exit\", (code) => resolve(code ?? 1));\n });\n}\n\nexport async function updateCommand(opts: UpdateCommandOptions = {}): Promise<void> {\n const write = opts.write ?? ((m: string) => process.stdout.write(m));\n const exit = opts.exit ?? ((c: number) => process.exit(c));\n const fetchLatest = opts.fetchLatest ?? (() => getLatestVersion({ force: true }));\n const isNpx = opts.isNpx ?? isNpxInstall;\n const doSpawn = opts.spawnInstall ?? defaultSpawn;\n\n write(`current: reasonix ${VERSION}\\n`);\n const latest = await fetchLatest();\n if (!latest) {\n write(\"could not reach registry.npmjs.org — check your network.\\n\");\n exit(1);\n return;\n }\n write(`latest: reasonix ${latest}\\n`);\n\n const plan = planUpdate({ current: VERSION, latest, npx: isNpx() });\n write(`\\n${plan.message}\\n`);\n\n if (plan.action !== \"run-npm-install\" || !plan.command) return;\n if (opts.dryRun) {\n write(`(dry run) would run: ${plan.command.join(\" \")}\\n`);\n return;\n }\n write(`\\nrunning: ${plan.command.join(\" \")}\\n`);\n const code = await doSpawn(plan.command);\n if (code !== 0) {\n write(`\\nnpm exited with code ${code}. upgrade did not complete.\\n`);\n exit(code);\n }\n}\n"],"mappings":";;;;;;;;;AAAA,SAAS,aAAa;AAoBf,SAAS,WAAW,OAAoC;AAC7D,QAAM,OAAO,gBAAgB,MAAM,SAAS,MAAM,MAAM;AACxD,MAAI,OAAO,GAAG;AACZ,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,SAAS,YAAY,MAAM,OAAO,iCAAiC,MAAM,MAAM;AAAA,IACjF;AAAA,EACF;AACA,MAAI,SAAS,GAAG;AACd,WAAO,EAAE,QAAQ,cAAc,SAAS,YAAY,MAAM,OAAO,kBAAkB;AAAA,EACrF;AACA,MAAI,MAAM,KAAK;AACb,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,YAAY,MAAM,MAAM;AAAA,QACxB;AAAA,QACA;AAAA,QACA;AAAA,MACF,EAAE,KAAK,IAAI;AAAA,IACb;AAAA,EACF;AACA,SAAO;AAAA,IACL,QAAQ;AAAA,IACR,SAAS,sBAAsB,MAAM,OAAO,WAAM,MAAM,MAAM;AAAA,IAC9D,SAAS,CAAC,OAAO,WAAW,MAAM,iBAAiB;AAAA,EACrD;AACF;AAiBA,SAAS,aAAa,MAAiC;AACrD,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AAMtC,UAAM,QAAQ,MAAM,KAAK,CAAC,GAAI,KAAK,MAAM,CAAC,GAAG;AAAA,MAC3C,OAAO;AAAA,MACP,OAAO,QAAQ,aAAa;AAAA,IAC9B,CAAC;AACD,UAAM,KAAK,SAAS,MAAM;AAC1B,UAAM,KAAK,QAAQ,CAAC,SAAS,QAAQ,QAAQ,CAAC,CAAC;AAAA,EACjD,CAAC;AACH;AAEA,eAAsB,cAAc,OAA6B,CAAC,GAAkB;AAClF,QAAM,QAAQ,KAAK,UAAU,CAAC,MAAc,QAAQ,OAAO,MAAM,CAAC;AAClE,QAAM,OAAO,KAAK,SAAS,CAAC,MAAc,QAAQ,KAAK,CAAC;AACxD,QAAM,cAAc,KAAK,gBAAgB,MAAM,iBAAiB,EAAE,OAAO,KAAK,CAAC;AAC/E,QAAM,QAAQ,KAAK,SAAS;AAC5B,QAAM,UAAU,KAAK,gBAAgB;AAErC,QAAM,qBAAqB,OAAO;AAAA,CAAI;AACtC,QAAM,SAAS,MAAM,YAAY;AACjC,MAAI,CAAC,QAAQ;AACX,UAAM,iEAA4D;AAClE,SAAK,CAAC;AACN;AAAA,EACF;AACA,QAAM,qBAAqB,MAAM;AAAA,CAAI;AAErC,QAAM,OAAO,WAAW,EAAE,SAAS,SAAS,QAAQ,KAAK,MAAM,EAAE,CAAC;AAClE,QAAM;AAAA,EAAK,KAAK,OAAO;AAAA,CAAI;AAE3B,MAAI,KAAK,WAAW,qBAAqB,CAAC,KAAK,QAAS;AACxD,MAAI,KAAK,QAAQ;AACf,UAAM,wBAAwB,KAAK,QAAQ,KAAK,GAAG,CAAC;AAAA,CAAI;AACxD;AAAA,EACF;AACA,QAAM;AAAA,WAAc,KAAK,QAAQ,KAAK,GAAG,CAAC;AAAA,CAAI;AAC9C,QAAM,OAAO,MAAM,QAAQ,KAAK,OAAO;AACvC,MAAI,SAAS,GAAG;AACd,UAAM;AAAA,uBAA0B,IAAI;AAAA,CAA+B;AACnE,SAAK,IAAI;AAAA,EACX;AACF;","names":[]}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import "./chunk-Q6YFXW7H.js";
|
|
3
|
+
import "./chunk-I6YIAK6C.js";
|
|
4
|
+
import "./chunk-XJLZ4HKU.js";
|
|
5
|
+
import "./chunk-XHQIK7B6.js";
|
|
6
|
+
import "./chunk-6TMHAK5D.js";
|
|
7
|
+
import "./chunk-KMWKGPFZ.js";
|
|
8
|
+
import "./chunk-3Q3C4W66.js";
|
|
9
|
+
import "./chunk-W4LDFAZ6.js";
|
|
10
|
+
import "./chunk-U3V2ZQ5J.js";
|
|
11
|
+
import "./chunk-WBDE4IRI.js";
|
|
12
|
+
import {
|
|
13
|
+
VERSION
|
|
14
|
+
} from "./chunk-2AWTGJ2C.js";
|
|
15
|
+
import "./chunk-5X7LZJDE.js";
|
|
16
|
+
import "./chunk-DFP4YSVM.js";
|
|
17
|
+
import "./chunk-QGE6AF76.js";
|
|
18
|
+
import "./chunk-DULSP7JH.js";
|
|
19
|
+
import "./chunk-ZTLZO42A.js";
|
|
20
|
+
import "./chunk-ORM6PK57.js";
|
|
21
|
+
|
|
22
|
+
// src/cli/commands/version.ts
|
|
23
|
+
function versionCommand() {
|
|
24
|
+
console.log(`reasonix ${VERSION}`);
|
|
25
|
+
}
|
|
26
|
+
export {
|
|
27
|
+
versionCommand
|
|
28
|
+
};
|
|
29
|
+
//# sourceMappingURL=version-3MYFE4G6.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/cli/commands/version.ts"],"sourcesContent":["import { VERSION } from \"../../index.js\";\n\nexport function versionCommand(): void {\n console.log(`reasonix ${VERSION}`);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAEO,SAAS,iBAAuB;AACrC,UAAQ,IAAI,YAAY,OAAO,EAAE;AACnC;","names":[]}
|