@satori-sh/cli 0.0.15 → 0.0.17

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/index.js CHANGED
@@ -3,9 +3,10 @@
3
3
  // src/index.ts
4
4
  import { Command } from "commander";
5
5
  import { readFileSync, realpathSync } from "fs";
6
- import { execFile } from "child_process";
7
- import { dirname as dirname2, join as join3 } from "path";
8
- import { fileURLToPath as fileURLToPath2 } from "url";
6
+ import { homedir as homedir2 } from "os";
7
+ import { execFile, spawn, spawnSync } from "child_process";
8
+ import { dirname, join as join2 } from "path";
9
+ import { fileURLToPath } from "url";
9
10
  import chalk from "chalk";
10
11
 
11
12
  // src/config.ts
@@ -227,258 +228,40 @@ ${memoryText}`
227
228
  return [systemMessage, ...messages];
228
229
  }
229
230
 
230
- // src/ui.tsx
231
- import { render, useRenderer, useTerminalDimensions } from "@opentui/solid";
232
- import { For, Show, createSignal, onMount, onCleanup } from "solid-js";
233
- import cliSpinners from "cli-spinners";
234
-
235
- // src/logo.ts
236
- import { dirname, join as join2 } from "path";
237
- import { fileURLToPath } from "url";
238
- async function loadLogo() {
239
- const { default: fs } = await import("fs");
240
- const __dirname = dirname(fileURLToPath(import.meta.url));
241
- const logoPath = join2(__dirname, "..", "logos", "satori.ans");
242
- return fs.readFileSync(logoPath, "utf8");
243
- }
244
-
245
- // src/ui.tsx
246
- async function runInteractiveApp({
247
- initialPrompt,
248
- options,
249
- processUserInput,
250
- infoLine,
251
- infoDisplay
252
- }) {
253
- const logo = await loadLogo();
254
- console.log(` ${logo}`);
255
- const rows = process.stdout.rows ?? 24;
256
- const logoHeight = logo.endsWith("\n") ? logo.slice(0, -1).split("\n").length : logo.split("\n").length;
257
- const splitHeight = Math.max(1, rows - logoHeight - 1);
258
- render(
259
- () => /* @__PURE__ */ React.createElement(
260
- App,
261
- {
262
- initialPrompt,
263
- options,
264
- processUserInput,
265
- infoLine,
266
- infoDisplay
267
- }
268
- ),
269
- {
270
- useAlternateScreen: false,
271
- exitOnCtrlC: true,
272
- useMouse: true,
273
- enableMouseMovement: true,
274
- experimental_splitHeight: splitHeight
275
- }
276
- );
277
- }
278
- function App({ initialPrompt, options, processUserInput, infoLine, infoDisplay }) {
279
- const renderer = useRenderer();
280
- const dimensions = useTerminalDimensions();
281
- const [messages, setMessages] = createSignal([]);
282
- const [inputValue, setInputValue] = createSignal("");
283
- const [showIntro, setShowIntro] = createSignal(true);
284
- const [isFullScreen, setIsFullScreen] = createSignal(false);
285
- const [spinnerFrame, setSpinnerFrame] = createSignal(0);
286
- const [isLoading, setIsLoading] = createSignal(false);
287
- const promptFg = "#00ffff";
288
- const responseFg = "#ffffff";
289
- const promptBg = "#2b2b2b";
290
- let inputRef;
291
- let currentMemoryId = options.memoryId;
292
- let messageId = 0;
293
- const usageText = infoDisplay?.usageLine ?? infoLine ?? "";
294
- const versionText = infoDisplay?.versionLine ?? "";
295
- const modelText = infoDisplay?.modelLine ?? "";
296
- const appendMessage = (role, text) => {
297
- setMessages((prev) => [...prev, { id: messageId++, role, text }]);
298
- };
299
- const exitApp = () => {
300
- renderer.destroy();
301
- process.exit(0);
302
- };
303
- const submitPrompt = async (raw) => {
304
- const trimmed = raw.trim();
305
- if (!trimmed) return;
306
- if (trimmed.toLowerCase() === "exit" || trimmed.toLowerCase() === "quit") {
307
- exitApp();
308
- return;
309
- }
310
- if (showIntro()) {
311
- setShowIntro(false);
312
- }
313
- if (!isFullScreen()) {
314
- setIsFullScreen(true);
315
- }
316
- setInputValue("");
317
- if (inputRef) {
318
- inputRef.value = "";
319
- }
320
- appendMessage("prompt", trimmed);
321
- try {
322
- setIsLoading(true);
323
- const result = await processUserInput(trimmed, { ...options, memoryId: currentMemoryId }, "tui");
324
- currentMemoryId = result.memoryId;
325
- appendMessage("response", result.response);
326
- if (result.instruction) {
327
- appendMessage("response", result.instruction);
328
- }
329
- } catch (error) {
330
- const message = error instanceof Error ? error.message : String(error);
331
- appendMessage("response", `Error: ${message}`);
332
- } finally {
333
- setIsLoading(false);
334
- }
335
- };
336
- onMount(async () => {
337
- const spinner = cliSpinners.dots;
338
- const timer = setInterval(() => {
339
- if (isLoading()) {
340
- setSpinnerFrame((prev) => (prev + 1) % spinner.frames.length);
341
- }
342
- }, spinner.interval);
343
- onCleanup(() => clearInterval(timer));
344
- if (initialPrompt) {
345
- await submitPrompt(initialPrompt);
346
- }
347
- if (inputRef) {
348
- inputRef.focus();
349
- }
350
- });
351
- const inputBoxWidth = () => Math.max(1, Math.round(dimensions().width * 0.6));
352
- const inputBoxLeft = () => Math.max(0, Math.round(dimensions().width * 0.15));
353
- const inputBoxHeight = () => isFullScreen() ? 7 : 14;
354
- const inputBoxTop = () => isFullScreen() ? Math.max(1, dimensions().height - inputBoxHeight() - 2) : Math.max(1, Math.round(dimensions().height * 0.666));
355
- const messagesTop = () => 1;
356
- const messagesHeight = () => Math.max(1, inputBoxTop() - messagesTop() - 1);
357
- const messagesWidth = () => Math.min(dimensions().width - 2, inputBoxWidth() + 10);
358
- const messagesLeft = () => Math.max(1, inputBoxLeft() - 5);
359
- return /* @__PURE__ */ React.createElement("box", { width: "100%", height: "100%", flexDirection: "column" }, /* @__PURE__ */ React.createElement(
360
- "scrollbox",
361
- {
362
- id: "messages",
363
- width: messagesWidth(),
364
- height: messagesHeight(),
365
- position: "absolute",
366
- left: messagesLeft(),
367
- top: messagesTop(),
368
- paddingLeft: 1,
369
- paddingRight: 1,
370
- focused: true,
371
- stickyScroll: true,
372
- stickyStart: "bottom"
373
- },
374
- /* @__PURE__ */ React.createElement("box", { width: "100%", flexDirection: "column" }, /* @__PURE__ */ React.createElement(For, { each: messages() }, (message) => /* @__PURE__ */ React.createElement(
375
- "box",
376
- {
377
- width: "100%",
378
- flexDirection: "row",
379
- justifyContent: message.role === "prompt" ? "flex-start" : "flex-end",
380
- marginBottom: 1
381
- },
382
- /* @__PURE__ */ React.createElement(
383
- "box",
384
- {
385
- paddingLeft: 1,
386
- paddingRight: 1,
387
- paddingTop: 1,
388
- paddingBottom: 1,
389
- backgroundColor: message.role === "prompt" ? promptBg : void 0
390
- },
391
- /* @__PURE__ */ React.createElement(
392
- "text",
393
- {
394
- fg: message.role === "prompt" ? promptFg : responseFg,
395
- width: "100%",
396
- wrapMode: "word",
397
- selectable: false
398
- },
399
- message.text
400
- )
401
- )
402
- )))
403
- ), /* @__PURE__ */ React.createElement(
404
- "box",
405
- {
406
- id: "input-box",
407
- width: inputBoxWidth(),
408
- height: inputBoxHeight(),
409
- position: "absolute",
410
- left: inputBoxLeft(),
411
- top: inputBoxTop(),
412
- paddingLeft: 1,
413
- paddingRight: 1,
414
- paddingTop: 1,
415
- flexDirection: "column"
416
- },
417
- /* @__PURE__ */ React.createElement(For, { each: !isFullScreen() && showIntro() ? [
418
- "Use Satori just like you would use ChatGPT.",
419
- "Except, it stores your conversations in a long term memory.",
420
- "The memories you store here can be accessed through the SDK."
421
- ] : [] }, (line) => /* @__PURE__ */ React.createElement("text", { fg: "cyan" }, line)),
422
- /* @__PURE__ */ React.createElement(
423
- "box",
424
- {
425
- id: "input-box",
426
- width: inputBoxWidth(),
427
- height: 5,
428
- backgroundColor: "#1a1a1a",
429
- flexDirection: "column",
430
- justifyContent: "center"
431
- },
432
- /* @__PURE__ */ React.createElement(
433
- "input",
434
- {
435
- id: "input",
436
- width: "100%",
437
- height: 1,
438
- placeholder: "Type a message and press Enter...",
439
- focusedBackgroundColor: "#1a1a1a",
440
- onInput: (value) => setInputValue(value),
441
- onSubmit: () => submitPrompt(inputValue()),
442
- ref: (r) => {
443
- inputRef = r;
444
- }
445
- }
446
- ),
447
- /* @__PURE__ */ React.createElement("box", { flexDirection: "row", flexShrink: 0, paddingTop: 1 }, /* @__PURE__ */ React.createElement("text", { fg: "#ffffff" }, modelText))
448
- )
449
- ), /* @__PURE__ */ React.createElement(Show, { when: isLoading() }, /* @__PURE__ */ React.createElement(
450
- "box",
451
- {
452
- id: "spinner",
453
- position: "absolute",
454
- left: inputBoxLeft(),
455
- top: inputBoxTop() + inputBoxHeight(),
456
- paddingLeft: 1
457
- },
458
- /* @__PURE__ */ React.createElement("text", { fg: "#00ffff" }, cliSpinners.dots.frames[spinnerFrame()])
459
- )), /* @__PURE__ */ React.createElement(
460
- "box",
461
- {
462
- id: "footer",
463
- width: dimensions().width,
464
- height: 1,
465
- position: "absolute",
466
- bottom: 0,
467
- left: 0,
468
- backgroundColor: "#000000",
469
- paddingLeft: 1,
470
- paddingRight: 1,
471
- flexDirection: "row",
472
- justifyContent: "space-between",
473
- alignItems: "center"
474
- },
475
- /* @__PURE__ */ React.createElement("text", { fg: "#00ffff", wrapMode: "none", width: "100%" }, usageText),
476
- /* @__PURE__ */ React.createElement("box", { flexShrink: 0, paddingLeft: 1 }, /* @__PURE__ */ React.createElement("text", { fg: "#00ffff" }, versionText))
477
- ));
478
- }
479
-
480
231
  // src/index.ts
481
232
  async function main() {
233
+ const modulePath2 = realpathSync(fileURLToPath(import.meta.url));
234
+ const isInteractive = process.stdin.isTTY && process.stdout.isTTY;
235
+ if (isInteractive && !globalThis.Bun && !process.env.SATORI_BUN_REEXEC) {
236
+ const bunBinDir = join2(homedir2(), ".bun", "bin");
237
+ const bunPath = join2(bunBinDir, "bun");
238
+ const baseEnv = { ...process.env, PATH: `${bunBinDir}:${process.env.PATH ?? ""}` };
239
+ const bunCheck = spawnSync("bun", ["--version"], { stdio: "ignore", env: baseEnv });
240
+ if (bunCheck.status !== 0) {
241
+ const installResult = spawnSync(
242
+ "bash",
243
+ ["-lc", "curl -fsSL https://bun.sh/install | bash"],
244
+ { stdio: "inherit" }
245
+ );
246
+ if (installResult.status !== 0) {
247
+ console.error("Failed to install Bun. Please install manually and retry.");
248
+ process.exit(1);
249
+ }
250
+ }
251
+ const bunProcess = spawn(
252
+ bunPath,
253
+ [modulePath2, ...process.argv.slice(2)],
254
+ { env: { ...baseEnv, SATORI_BUN_REEXEC: "1" }, stdio: "inherit" }
255
+ );
256
+ bunProcess.on("error", (error) => {
257
+ console.error("Failed to launch Bun:", error.message);
258
+ process.exit(1);
259
+ });
260
+ bunProcess.on("exit", (code) => {
261
+ process.exit(code ?? 0);
262
+ });
263
+ return;
264
+ }
482
265
  const argv = process.argv.slice(2);
483
266
  const isGetApiKey = argv[0] === "get" && argv[1] === "api-key";
484
267
  if (!isGetApiKey) {
@@ -494,8 +277,8 @@ async function main() {
494
277
  program.option("--memory-id <id>", "Memory ID for scoping");
495
278
  const DEFAULT_LLM_MODEL = "gpt-4o";
496
279
  const getCliVersion = () => {
497
- const __dirname = dirname2(fileURLToPath2(import.meta.url));
498
- const packagePath = join3(__dirname, "..", "package.json");
280
+ const __dirname = dirname(fileURLToPath(import.meta.url));
281
+ const packagePath = join2(__dirname, "..", "package.json");
499
282
  const raw = readFileSync(packagePath, "utf8");
500
283
  const data = JSON.parse(raw);
501
284
  return data.version ?? "unknown";
@@ -583,6 +366,7 @@ ${instruction}`);
583
366
  return;
584
367
  }
585
368
  const info = await getInfoDisplay();
369
+ const { runInteractiveApp } = await import("./ui-AFMM6JTQ.js");
586
370
  await runInteractiveApp({
587
371
  initialPrompt,
588
372
  options,
@@ -649,7 +433,7 @@ ${instruction}`);
649
433
  program.parse();
650
434
  }
651
435
  var entryPath = process.argv[1] ? realpathSync(process.argv[1]) : "";
652
- var modulePath = realpathSync(fileURLToPath2(import.meta.url));
436
+ var modulePath = realpathSync(fileURLToPath(import.meta.url));
653
437
  if (entryPath === modulePath) {
654
438
  main();
655
439
  }
@@ -0,0 +1,252 @@
1
+ // src/ui.tsx
2
+ import { render, useRenderer, useTerminalDimensions } from "@opentui/solid";
3
+ import { For, Show, createSignal, onMount, onCleanup } from "solid-js";
4
+ import cliSpinners from "cli-spinners";
5
+
6
+ // src/logo.ts
7
+ import { dirname, join } from "path";
8
+ import { fileURLToPath } from "url";
9
+ async function loadLogo() {
10
+ const { default: fs } = await import("fs");
11
+ const __dirname = dirname(fileURLToPath(import.meta.url));
12
+ const logoPath = join(__dirname, "..", "logos", "satori.ans");
13
+ return fs.readFileSync(logoPath, "utf8");
14
+ }
15
+
16
+ // src/ui.tsx
17
+ async function runInteractiveApp({
18
+ initialPrompt,
19
+ options,
20
+ processUserInput,
21
+ infoLine,
22
+ infoDisplay
23
+ }) {
24
+ const logo = await loadLogo();
25
+ console.log(` ${logo}`);
26
+ const rows = process.stdout.rows ?? 24;
27
+ const logoHeight = logo.endsWith("\n") ? logo.slice(0, -1).split("\n").length : logo.split("\n").length;
28
+ const splitHeight = Math.max(1, rows - logoHeight - 1);
29
+ render(
30
+ () => /* @__PURE__ */ React.createElement(
31
+ App,
32
+ {
33
+ initialPrompt,
34
+ options,
35
+ processUserInput,
36
+ infoLine,
37
+ infoDisplay
38
+ }
39
+ ),
40
+ {
41
+ useAlternateScreen: false,
42
+ exitOnCtrlC: true,
43
+ useMouse: true,
44
+ enableMouseMovement: true,
45
+ experimental_splitHeight: splitHeight
46
+ }
47
+ );
48
+ }
49
+ function App({ initialPrompt, options, processUserInput, infoLine, infoDisplay }) {
50
+ const renderer = useRenderer();
51
+ const dimensions = useTerminalDimensions();
52
+ const [messages, setMessages] = createSignal([]);
53
+ const [inputValue, setInputValue] = createSignal("");
54
+ const [showIntro, setShowIntro] = createSignal(true);
55
+ const [isFullScreen, setIsFullScreen] = createSignal(false);
56
+ const [spinnerFrame, setSpinnerFrame] = createSignal(0);
57
+ const [isLoading, setIsLoading] = createSignal(false);
58
+ const promptFg = "#00ffff";
59
+ const responseFg = "#ffffff";
60
+ const promptBg = "#2b2b2b";
61
+ let inputRef;
62
+ let currentMemoryId = options.memoryId;
63
+ let messageId = 0;
64
+ const usageText = infoDisplay?.usageLine ?? infoLine ?? "";
65
+ const versionText = infoDisplay?.versionLine ?? "";
66
+ const modelText = infoDisplay?.modelLine ?? "";
67
+ const appendMessage = (role, text) => {
68
+ setMessages((prev) => [...prev, { id: messageId++, role, text }]);
69
+ };
70
+ const exitApp = () => {
71
+ renderer.destroy();
72
+ process.exit(0);
73
+ };
74
+ const submitPrompt = async (raw) => {
75
+ const trimmed = raw.trim();
76
+ if (!trimmed) return;
77
+ if (trimmed.toLowerCase() === "exit" || trimmed.toLowerCase() === "quit") {
78
+ exitApp();
79
+ return;
80
+ }
81
+ if (showIntro()) {
82
+ setShowIntro(false);
83
+ }
84
+ if (!isFullScreen()) {
85
+ setIsFullScreen(true);
86
+ }
87
+ setInputValue("");
88
+ if (inputRef) {
89
+ inputRef.value = "";
90
+ }
91
+ appendMessage("prompt", trimmed);
92
+ try {
93
+ setIsLoading(true);
94
+ const result = await processUserInput(trimmed, { ...options, memoryId: currentMemoryId }, "tui");
95
+ currentMemoryId = result.memoryId;
96
+ appendMessage("response", result.response);
97
+ if (result.instruction) {
98
+ appendMessage("response", result.instruction);
99
+ }
100
+ } catch (error) {
101
+ const message = error instanceof Error ? error.message : String(error);
102
+ appendMessage("response", `Error: ${message}`);
103
+ } finally {
104
+ setIsLoading(false);
105
+ }
106
+ };
107
+ onMount(async () => {
108
+ const spinner = cliSpinners.dots;
109
+ const timer = setInterval(() => {
110
+ if (isLoading()) {
111
+ setSpinnerFrame((prev) => (prev + 1) % spinner.frames.length);
112
+ }
113
+ }, spinner.interval);
114
+ onCleanup(() => clearInterval(timer));
115
+ if (initialPrompt) {
116
+ await submitPrompt(initialPrompt);
117
+ }
118
+ if (inputRef) {
119
+ inputRef.focus();
120
+ }
121
+ });
122
+ const inputBoxWidth = () => Math.max(1, Math.round(dimensions().width * 0.6));
123
+ const inputBoxLeft = () => Math.max(0, Math.round(dimensions().width * 0.15));
124
+ const inputBoxHeight = () => isFullScreen() ? 7 : 14;
125
+ const inputBoxTop = () => isFullScreen() ? Math.max(1, dimensions().height - inputBoxHeight() - 2) : Math.max(1, Math.round(dimensions().height * 0.666));
126
+ const messagesTop = () => 1;
127
+ const messagesHeight = () => Math.max(1, inputBoxTop() - messagesTop() - 1);
128
+ const messagesWidth = () => Math.min(dimensions().width - 2, inputBoxWidth() + 10);
129
+ const messagesLeft = () => Math.max(1, inputBoxLeft() - 5);
130
+ return /* @__PURE__ */ React.createElement("box", { width: "100%", height: "100%", flexDirection: "column" }, /* @__PURE__ */ React.createElement(
131
+ "scrollbox",
132
+ {
133
+ id: "messages",
134
+ width: messagesWidth(),
135
+ height: messagesHeight(),
136
+ position: "absolute",
137
+ left: messagesLeft(),
138
+ top: messagesTop(),
139
+ paddingLeft: 1,
140
+ paddingRight: 1,
141
+ focused: true,
142
+ stickyScroll: true,
143
+ stickyStart: "bottom"
144
+ },
145
+ /* @__PURE__ */ React.createElement("box", { width: "100%", flexDirection: "column" }, /* @__PURE__ */ React.createElement(For, { each: messages() }, (message) => /* @__PURE__ */ React.createElement(
146
+ "box",
147
+ {
148
+ width: "100%",
149
+ flexDirection: "row",
150
+ justifyContent: message.role === "prompt" ? "flex-start" : "flex-end",
151
+ marginBottom: 1
152
+ },
153
+ /* @__PURE__ */ React.createElement(
154
+ "box",
155
+ {
156
+ paddingLeft: 1,
157
+ paddingRight: 1,
158
+ paddingTop: 1,
159
+ paddingBottom: 1,
160
+ backgroundColor: message.role === "prompt" ? promptBg : void 0
161
+ },
162
+ /* @__PURE__ */ React.createElement(
163
+ "text",
164
+ {
165
+ fg: message.role === "prompt" ? promptFg : responseFg,
166
+ width: "100%",
167
+ wrapMode: "word",
168
+ selectable: false
169
+ },
170
+ message.text
171
+ )
172
+ )
173
+ )))
174
+ ), /* @__PURE__ */ React.createElement(
175
+ "box",
176
+ {
177
+ id: "input-box",
178
+ width: inputBoxWidth(),
179
+ height: inputBoxHeight(),
180
+ position: "absolute",
181
+ left: inputBoxLeft(),
182
+ top: inputBoxTop(),
183
+ paddingLeft: 1,
184
+ paddingRight: 1,
185
+ paddingTop: 1,
186
+ flexDirection: "column"
187
+ },
188
+ /* @__PURE__ */ React.createElement(For, { each: !isFullScreen() && showIntro() ? [
189
+ "Use Satori just like you would use ChatGPT.",
190
+ "Except, it stores your conversations in a long term memory.",
191
+ "The memories you store here can be accessed through the SDK."
192
+ ] : [] }, (line) => /* @__PURE__ */ React.createElement("text", { fg: "cyan" }, line)),
193
+ /* @__PURE__ */ React.createElement(
194
+ "box",
195
+ {
196
+ id: "input-box",
197
+ width: inputBoxWidth(),
198
+ height: 5,
199
+ backgroundColor: "#1a1a1a",
200
+ flexDirection: "column",
201
+ justifyContent: "center"
202
+ },
203
+ /* @__PURE__ */ React.createElement(
204
+ "input",
205
+ {
206
+ id: "input",
207
+ width: "100%",
208
+ height: 1,
209
+ placeholder: "Type a message and press Enter...",
210
+ focusedBackgroundColor: "#1a1a1a",
211
+ onInput: (value) => setInputValue(value),
212
+ onSubmit: () => submitPrompt(inputValue()),
213
+ ref: (r) => {
214
+ inputRef = r;
215
+ }
216
+ }
217
+ ),
218
+ /* @__PURE__ */ React.createElement("box", { flexDirection: "row", flexShrink: 0, paddingTop: 1 }, /* @__PURE__ */ React.createElement("text", { fg: "#ffffff" }, modelText))
219
+ )
220
+ ), /* @__PURE__ */ React.createElement(Show, { when: isLoading() }, /* @__PURE__ */ React.createElement(
221
+ "box",
222
+ {
223
+ id: "spinner",
224
+ position: "absolute",
225
+ left: inputBoxLeft(),
226
+ top: inputBoxTop() + inputBoxHeight(),
227
+ paddingLeft: 1
228
+ },
229
+ /* @__PURE__ */ React.createElement("text", { fg: "#00ffff" }, cliSpinners.dots.frames[spinnerFrame()])
230
+ )), /* @__PURE__ */ React.createElement(
231
+ "box",
232
+ {
233
+ id: "footer",
234
+ width: dimensions().width,
235
+ height: 1,
236
+ position: "absolute",
237
+ bottom: 0,
238
+ left: 0,
239
+ backgroundColor: "#000000",
240
+ paddingLeft: 1,
241
+ paddingRight: 1,
242
+ flexDirection: "row",
243
+ justifyContent: "space-between",
244
+ alignItems: "center"
245
+ },
246
+ /* @__PURE__ */ React.createElement("text", { fg: "#00ffff", wrapMode: "none", width: "100%" }, usageText),
247
+ /* @__PURE__ */ React.createElement("box", { flexShrink: 0, paddingLeft: 1 }, /* @__PURE__ */ React.createElement("text", { fg: "#00ffff" }, versionText))
248
+ ));
249
+ }
250
+ export {
251
+ runInteractiveApp
252
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@satori-sh/cli",
3
- "version": "0.0.15",
3
+ "version": "0.0.17",
4
4
  "description": "CLI tool for Satori memory server",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",