volute 0.4.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/README.md +22 -22
  2. package/dist/agent-X7GJLBLW.js +79 -0
  3. package/dist/{agent-manager-AUCKMGPR.js → agent-manager-JDVXU3ON.js} +4 -4
  4. package/dist/channel-SMCNOIVQ.js +262 -0
  5. package/dist/chunk-AOKAQGO4.js +107 -0
  6. package/dist/{chunk-VRVVQIYY.js → chunk-AZEL2IEK.js} +1 -1
  7. package/dist/chunk-B3R6L2GW.js +24 -0
  8. package/dist/{chunk-MXUCNIBG.js → chunk-BX7KI4S3.js} +68 -3
  9. package/dist/{chunk-I6OHXCMV.js → chunk-G6ZNGLUX.js} +47 -9
  10. package/dist/{chunk-DNOXHLE5.js → chunk-H7AMDUIA.js} +1 -1
  11. package/dist/{chunk-YGFIWIOF.js → chunk-JR4UXCTO.js} +1 -1
  12. package/dist/{chunk-3C2XR4IY.js → chunk-UWHWAPGO.js} +120 -107
  13. package/dist/{chunk-SOZA2TLP.js → chunk-W76KWE23.js} +1 -1
  14. package/dist/{chunk-GSPKUPKU.js → chunk-XUA3JUFK.js} +2 -1
  15. package/dist/chunk-ZYGKG6VC.js +22 -0
  16. package/dist/chunk-ZZOOTYXK.js +583 -0
  17. package/dist/cli.js +83 -74
  18. package/dist/{connector-DKDJTLYZ.js → connector-Y7JPNROO.js} +11 -6
  19. package/dist/connectors/discord.js +34 -5
  20. package/dist/connectors/slack.js +36 -8
  21. package/dist/connectors/telegram.js +55 -6
  22. package/dist/create-G525LWEA.js +91 -0
  23. package/dist/{daemon-client-XR24PUJF.js → daemon-client-442IV43D.js} +2 -2
  24. package/dist/daemon.js +1273 -384
  25. package/dist/{delete-55MXCEY5.js → delete-2PH2CGDY.js} +7 -8
  26. package/dist/{down-3OB6UVAJ.js → down-FXWAN66A.js} +1 -1
  27. package/dist/{env-JB27UAC3.js → env-7GLUJCWS.js} +8 -5
  28. package/dist/{history-BKG74I43.js → history-H72ZUIBN.js} +3 -3
  29. package/dist/{import-4CI2ZUTJ.js → import-AVKQJDYC.js} +8 -8
  30. package/dist/{logs-NXFFGUKY.js → logs-EDGK26AK.js} +2 -2
  31. package/dist/message-SCOQDR3P.js +32 -0
  32. package/dist/{package-Z2SFO2SV.js → package-4DP4Y4UO.js} +1 -1
  33. package/dist/restart-O4ETYLJF.js +29 -0
  34. package/dist/{schedule-A35SH4HT.js → schedule-S6QVC5ON.js} +10 -5
  35. package/dist/send-G7PE4DOJ.js +72 -0
  36. package/dist/{setup-2FDVN7OF.js → setup-F4TCWVSP.js} +5 -5
  37. package/dist/{start-LDPMCMYT.js → start-VHQ7LNWM.js} +3 -3
  38. package/dist/{status-MVSQG54T.js → status-QAJWXKMZ.js} +3 -3
  39. package/dist/{stop-5PZTZCLL.js → stop-CAGCT5NI.js} +6 -7
  40. package/dist/{up-F7TMTLRE.js → up-CSX3ZUIU.js} +16 -4
  41. package/dist/update-XSIX3GGP.js +140 -0
  42. package/dist/update-check-5ZADDHCK.js +17 -0
  43. package/dist/{upgrade-6ZW2RD64.js → upgrade-YXKPWDRU.js} +16 -15
  44. package/dist/{variant-T64BKARF.js → variant-4Z6W3PP6.js} +15 -10
  45. package/dist/web-assets/assets/index-D5PzIndO.js +308 -0
  46. package/dist/web-assets/index.html +2 -2
  47. package/drizzle/0003_clean_ego.sql +12 -0
  48. package/drizzle/meta/0003_snapshot.json +417 -0
  49. package/drizzle/meta/_journal.json +7 -0
  50. package/package.json +1 -1
  51. package/templates/_base/.init/.config/hooks/startup-context.sh +19 -1
  52. package/templates/_base/.init/.config/scripts/session-reader.ts +59 -0
  53. package/templates/_base/_skills/sessions/SKILL.md +49 -0
  54. package/templates/_base/_skills/volute-agent/SKILL.md +114 -14
  55. package/templates/_base/home/.config/routes.json +10 -0
  56. package/templates/_base/home/VOLUTE.md +14 -35
  57. package/templates/_base/src/lib/format-prefix.ts +7 -1
  58. package/templates/_base/src/lib/router.ts +193 -19
  59. package/templates/_base/src/lib/routing.ts +55 -18
  60. package/templates/_base/src/lib/session-monitor.ts +400 -0
  61. package/templates/_base/src/lib/types.ts +5 -1
  62. package/templates/agent-sdk/.init/.config/routes.json +5 -0
  63. package/templates/agent-sdk/.init/CLAUDE.md +2 -2
  64. package/templates/agent-sdk/src/agent.ts +18 -1
  65. package/templates/agent-sdk/src/lib/hooks/session-context.ts +32 -0
  66. package/templates/agent-sdk/src/server.ts +8 -2
  67. package/templates/agent-sdk/volute-template.json +1 -1
  68. package/templates/pi/.init/.config/routes.json +5 -0
  69. package/templates/pi/.init/AGENTS.md +1 -1
  70. package/templates/pi/src/agent.ts +12 -4
  71. package/templates/pi/src/lib/session-context-extension.ts +33 -0
  72. package/templates/pi/src/server.ts +1 -1
  73. package/templates/pi/volute-template.json +1 -1
  74. package/dist/channel-DQ6UY7QB.js +0 -67
  75. package/dist/chunk-5OCWMTVS.js +0 -152
  76. package/dist/chunk-ZHCE4DPY.js +0 -110
  77. package/dist/create-ILVOG75A.js +0 -79
  78. package/dist/send-3U6OTKG7.js +0 -57
  79. package/dist/web-assets/assets/index-NS621maO.js +0 -296
  80. package/templates/agent-sdk/.init/.config/sessions.json +0 -4
  81. package/templates/pi/.init/.config/sessions.json +0 -1
  82. package/dist/{service-SA4TTMDU.js → service-HZNIDNJF.js} +3 -3
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  loadMergedEnv
4
- } from "./chunk-DNOXHLE5.js";
4
+ } from "./chunk-H7AMDUIA.js";
5
5
  import {
6
6
  applyIsolation
7
- } from "./chunk-SOZA2TLP.js";
7
+ } from "./chunk-W76KWE23.js";
8
8
  import {
9
9
  agentDir,
10
10
  findAgent,
@@ -13,11 +13,11 @@ import {
13
13
  setVariantRunning,
14
14
  validateBranchName,
15
15
  voluteHome
16
- } from "./chunk-3C2XR4IY.js";
16
+ } from "./chunk-UWHWAPGO.js";
17
17
 
18
18
  // src/lib/agent-manager.ts
19
19
  import { execFile, spawn } from "child_process";
20
- import { createWriteStream, existsSync as existsSync2, mkdirSync, readFileSync as readFileSync2, unlinkSync as unlinkSync2 } from "fs";
20
+ import { existsSync as existsSync3, mkdirSync, readFileSync as readFileSync2, unlinkSync as unlinkSync2 } from "fs";
21
21
  import { resolve } from "path";
22
22
  import { promisify } from "util";
23
23
 
@@ -58,6 +58,45 @@ function clearJsonMap(path, map) {
58
58
  }
59
59
  }
60
60
 
61
+ // src/lib/rotating-log.ts
62
+ import { createWriteStream, existsSync as existsSync2, renameSync, statSync } from "fs";
63
+ import { Writable } from "stream";
64
+ var MAX_SIZE = 10 * 1024 * 1024;
65
+ var RotatingLog = class extends Writable {
66
+ constructor(path, maxSize = MAX_SIZE) {
67
+ super();
68
+ this.path = path;
69
+ this.maxSize = maxSize;
70
+ this.on("error", () => {
71
+ });
72
+ try {
73
+ this.size = existsSync2(path) ? statSync(path).size : 0;
74
+ } catch {
75
+ this.size = 0;
76
+ }
77
+ this.stream = createWriteStream(path, { flags: "a" });
78
+ }
79
+ stream;
80
+ size;
81
+ _write(chunk, _encoding, callback) {
82
+ this.size += chunk.length;
83
+ if (this.size > this.maxSize) {
84
+ try {
85
+ renameSync(this.path, `${this.path}.1`);
86
+ const oldStream = this.stream;
87
+ this.stream = createWriteStream(this.path);
88
+ this.size = chunk.length;
89
+ oldStream.end();
90
+ } catch {
91
+ }
92
+ }
93
+ this.stream.write(chunk, callback);
94
+ }
95
+ _final(callback) {
96
+ this.stream.end(callback);
97
+ }
98
+ };
99
+
61
100
  // src/lib/agent-manager.ts
62
101
  var execFileAsync = promisify(execFile);
63
102
  var MAX_RESTART_ATTEMPTS = 5;
@@ -78,7 +117,7 @@ var AgentManager = class {
78
117
  return { dir: variant.path, port: variant.port, isVariant: true, baseName, variantName };
79
118
  }
80
119
  const dir = agentDir(baseName);
81
- if (!existsSync2(dir)) throw new Error(`Agent directory missing: ${dir}`);
120
+ if (!existsSync3(dir)) throw new Error(`Agent directory missing: ${dir}`);
82
121
  return { dir, port: entry.port, isVariant: false, baseName };
83
122
  }
84
123
  async startAgent(name) {
@@ -100,9 +139,7 @@ var AgentManager = class {
100
139
  const voluteDir = resolve(dir, ".volute");
101
140
  const logsDir = resolve(voluteDir, "logs");
102
141
  mkdirSync(logsDir, { recursive: true });
103
- const logStream = createWriteStream(resolve(logsDir, "agent.log"), {
104
- flags: "a"
105
- });
142
+ const logStream = new RotatingLog(resolve(logsDir, "agent.log"));
106
143
  const agentEnv = loadMergedEnv(dir);
107
144
  const { VOLUTE_DAEMON_TOKEN: _, ...parentEnv } = process.env;
108
145
  const env = { ...parentEnv, ...agentEnv, VOLUTE_AGENT: name };
@@ -198,7 +235,7 @@ var AgentManager = class {
198
235
  }
199
236
  async handleRestart(name, dir) {
200
237
  const restartPath = resolve(dir, ".volute", "restart.json");
201
- if (!existsSync2(restartPath)) return false;
238
+ if (!existsSync3(restartPath)) return false;
202
239
  try {
203
240
  const signal = JSON.parse(readFileSync2(restartPath, "utf-8"));
204
241
  unlinkSync2(restartPath);
@@ -326,6 +363,7 @@ export {
326
363
  loadJsonMap,
327
364
  saveJsonMap,
328
365
  clearJsonMap,
366
+ RotatingLog,
329
367
  AgentManager,
330
368
  initAgentManager,
331
369
  getAgentManager
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  voluteHome
4
- } from "./chunk-3C2XR4IY.js";
4
+ } from "./chunk-UWHWAPGO.js";
5
5
 
6
6
  // src/lib/env.ts
7
7
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  voluteHome
4
- } from "./chunk-3C2XR4IY.js";
4
+ } from "./chunk-UWHWAPGO.js";
5
5
 
6
6
  // src/lib/daemon-client.ts
7
7
  import { existsSync, readFileSync } from "fs";
@@ -1,27 +1,137 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/lib/variants.ts
4
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
4
+ import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
5
+ import { resolve as resolve2 } from "path";
6
+
7
+ // src/lib/registry.ts
8
+ import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "fs";
5
9
  import { homedir } from "os";
6
- import { resolve } from "path";
10
+ import { dirname, resolve } from "path";
11
+ import { fileURLToPath } from "url";
7
12
  function voluteHome() {
8
- return process.env.VOLUTE_HOME || resolve(homedir(), ".volute");
13
+ if (process.env.VOLUTE_HOME) return process.env.VOLUTE_HOME;
14
+ const dir = dirname(fileURLToPath(import.meta.url));
15
+ if (dir.endsWith("/src/lib")) {
16
+ throw new Error(
17
+ 'VOLUTE_HOME must be set when running from source. For tests, run via "npm test" or add "--import ./test/setup.ts".'
18
+ );
19
+ }
20
+ return resolve(homedir(), ".volute");
21
+ }
22
+ function ensureVoluteHome() {
23
+ mkdirSync(resolve(voluteHome(), "agents"), { recursive: true });
24
+ }
25
+ function readRegistry() {
26
+ const registryPath = resolve(voluteHome(), "agents.json");
27
+ if (!existsSync(registryPath)) return [];
28
+ try {
29
+ const entries = JSON.parse(readFileSync(registryPath, "utf-8"));
30
+ return entries.map((e) => ({ ...e, running: e.running ?? false }));
31
+ } catch {
32
+ return [];
33
+ }
34
+ }
35
+ function writeRegistry(entries) {
36
+ ensureVoluteHome();
37
+ const registryPath = resolve(voluteHome(), "agents.json");
38
+ const tmpPath = `${registryPath}.tmp`;
39
+ writeFileSync(tmpPath, `${JSON.stringify(entries, null, 2)}
40
+ `);
41
+ renameSync(tmpPath, registryPath);
42
+ }
43
+ var AGENT_NAME_RE = /^[a-zA-Z0-9][a-zA-Z0-9._-]*$/;
44
+ var AGENT_NAME_MAX = 64;
45
+ function validateAgentName(name) {
46
+ if (!name) return "Agent name is required";
47
+ if (name.length > AGENT_NAME_MAX)
48
+ return `Agent name must be at most ${AGENT_NAME_MAX} characters`;
49
+ if (!AGENT_NAME_RE.test(name)) {
50
+ return "Agent name must start with alphanumeric and contain only alphanumeric, dots, dashes, or underscores";
51
+ }
52
+ return null;
53
+ }
54
+ function addAgent(name, port) {
55
+ const err = validateAgentName(name);
56
+ if (err) throw new Error(err);
57
+ const entries = readRegistry();
58
+ const filtered = entries.filter((e) => e.name !== name);
59
+ filtered.push({ name, port, created: (/* @__PURE__ */ new Date()).toISOString(), running: false });
60
+ writeRegistry(filtered);
61
+ }
62
+ function removeAgent(name) {
63
+ const entries = readRegistry();
64
+ writeRegistry(entries.filter((e) => e.name !== name));
65
+ }
66
+ function setAgentRunning(name, running) {
67
+ const entries = readRegistry();
68
+ const entry = entries.find((e) => e.name === name);
69
+ if (entry) {
70
+ entry.running = running;
71
+ writeRegistry(entries);
72
+ }
73
+ }
74
+ function findAgent(name) {
75
+ return readRegistry().find((e) => e.name === name);
76
+ }
77
+ function agentDir(name) {
78
+ return resolve(voluteHome(), "agents", name);
79
+ }
80
+ function nextPort() {
81
+ const entries = readRegistry();
82
+ const usedPorts = new Set(entries.map((e) => e.port));
83
+ for (const entry of entries) {
84
+ for (const v of readVariants(entry.name)) {
85
+ if (v.port) usedPorts.add(v.port);
86
+ }
87
+ }
88
+ let port = 4100;
89
+ while (usedPorts.has(port)) port++;
90
+ if (port > 65535) throw new Error("No available ports \u2014 all ports 4100-65535 are allocated");
91
+ return port;
92
+ }
93
+ function daemonLoopback() {
94
+ const host = process.env.VOLUTE_DAEMON_HOSTNAME || "127.0.0.1";
95
+ if (host === "0.0.0.0") return "127.0.0.1";
96
+ if (host === "::") return "[::1]";
97
+ return host;
98
+ }
99
+ function resolveAgent(name) {
100
+ const [baseName, variantName] = name.split("@", 2);
101
+ const entry = findAgent(baseName);
102
+ if (!entry) {
103
+ throw new Error(`Unknown agent: ${baseName}`);
104
+ }
105
+ const dir = agentDir(baseName);
106
+ if (!existsSync(dir)) {
107
+ throw new Error(`Agent directory missing: ${dir}`);
108
+ }
109
+ if (variantName) {
110
+ const variant = findVariant(baseName, variantName);
111
+ if (!variant) {
112
+ throw new Error(`Unknown variant: ${variantName} (agent: ${baseName})`);
113
+ }
114
+ return { entry: { ...entry, port: variant.port }, dir: variant.path };
115
+ }
116
+ return { entry, dir };
9
117
  }
118
+
119
+ // src/lib/variants.ts
10
120
  function variantsPath() {
11
- return resolve(voluteHome(), "variants.json");
121
+ return resolve2(voluteHome(), "variants.json");
12
122
  }
13
123
  function readAllVariants() {
14
124
  const path = variantsPath();
15
- if (!existsSync(path)) return {};
125
+ if (!existsSync2(path)) return {};
16
126
  try {
17
- return JSON.parse(readFileSync(path, "utf-8"));
127
+ return JSON.parse(readFileSync2(path, "utf-8"));
18
128
  } catch {
19
129
  return {};
20
130
  }
21
131
  }
22
132
  function writeAllVariants(all) {
23
- mkdirSync(voluteHome(), { recursive: true });
24
- writeFileSync(variantsPath(), `${JSON.stringify(all, null, 2)}
133
+ mkdirSync2(voluteHome(), { recursive: true });
134
+ writeFileSync2(variantsPath(), `${JSON.stringify(all, null, 2)}
25
135
  `);
26
136
  }
27
137
  function readVariants(agentName) {
@@ -102,104 +212,6 @@ function validateBranchName(branch) {
102
212
  return null;
103
213
  }
104
214
 
105
- // src/lib/registry.ts
106
- import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync2, renameSync, writeFileSync as writeFileSync2 } from "fs";
107
- import { homedir as homedir2 } from "os";
108
- import { resolve as resolve2 } from "path";
109
- function voluteHome2() {
110
- return process.env.VOLUTE_HOME || resolve2(homedir2(), ".volute");
111
- }
112
- function ensureVoluteHome() {
113
- mkdirSync2(resolve2(voluteHome2(), "agents"), { recursive: true });
114
- }
115
- function readRegistry() {
116
- const registryPath = resolve2(voluteHome2(), "agents.json");
117
- if (!existsSync2(registryPath)) return [];
118
- try {
119
- const entries = JSON.parse(readFileSync2(registryPath, "utf-8"));
120
- return entries.map((e) => ({ ...e, running: e.running ?? false }));
121
- } catch {
122
- return [];
123
- }
124
- }
125
- function writeRegistry(entries) {
126
- ensureVoluteHome();
127
- const registryPath = resolve2(voluteHome2(), "agents.json");
128
- const tmpPath = `${registryPath}.tmp`;
129
- writeFileSync2(tmpPath, `${JSON.stringify(entries, null, 2)}
130
- `);
131
- renameSync(tmpPath, registryPath);
132
- }
133
- var AGENT_NAME_RE = /^[a-zA-Z0-9][a-zA-Z0-9._-]*$/;
134
- var AGENT_NAME_MAX = 64;
135
- function validateAgentName(name) {
136
- if (!name) return "Agent name is required";
137
- if (name.length > AGENT_NAME_MAX)
138
- return `Agent name must be at most ${AGENT_NAME_MAX} characters`;
139
- if (!AGENT_NAME_RE.test(name)) {
140
- return "Agent name must start with alphanumeric and contain only alphanumeric, dots, dashes, or underscores";
141
- }
142
- return null;
143
- }
144
- function addAgent(name, port) {
145
- const err = validateAgentName(name);
146
- if (err) throw new Error(err);
147
- const entries = readRegistry();
148
- const filtered = entries.filter((e) => e.name !== name);
149
- filtered.push({ name, port, created: (/* @__PURE__ */ new Date()).toISOString(), running: false });
150
- writeRegistry(filtered);
151
- }
152
- function removeAgent(name) {
153
- const entries = readRegistry();
154
- writeRegistry(entries.filter((e) => e.name !== name));
155
- }
156
- function setAgentRunning(name, running) {
157
- const entries = readRegistry();
158
- const entry = entries.find((e) => e.name === name);
159
- if (entry) {
160
- entry.running = running;
161
- writeRegistry(entries);
162
- }
163
- }
164
- function findAgent(name) {
165
- return readRegistry().find((e) => e.name === name);
166
- }
167
- function agentDir(name) {
168
- return resolve2(voluteHome2(), "agents", name);
169
- }
170
- function nextPort() {
171
- const entries = readRegistry();
172
- const usedPorts = new Set(entries.map((e) => e.port));
173
- for (const entry of entries) {
174
- for (const v of readVariants(entry.name)) {
175
- if (v.port) usedPorts.add(v.port);
176
- }
177
- }
178
- let port = 4100;
179
- while (usedPorts.has(port)) port++;
180
- if (port > 65535) throw new Error("No available ports \u2014 all ports 4100-65535 are allocated");
181
- return port;
182
- }
183
- function resolveAgent(name) {
184
- const [baseName, variantName] = name.split("@", 2);
185
- const entry = findAgent(baseName);
186
- if (!entry) {
187
- throw new Error(`Unknown agent: ${baseName}`);
188
- }
189
- const dir = agentDir(baseName);
190
- if (!existsSync2(dir)) {
191
- throw new Error(`Agent directory missing: ${dir}`);
192
- }
193
- if (variantName) {
194
- const variant = findVariant(baseName, variantName);
195
- if (!variant) {
196
- throw new Error(`Unknown variant: ${variantName} (agent: ${baseName})`);
197
- }
198
- return { entry: { ...entry, port: variant.port }, dir: variant.path };
199
- }
200
- return { entry, dir };
201
- }
202
-
203
215
  export {
204
216
  readVariants,
205
217
  writeVariants,
@@ -211,7 +223,7 @@ export {
211
223
  removeAllVariants,
212
224
  checkHealth,
213
225
  validateBranchName,
214
- voluteHome2 as voluteHome,
226
+ voluteHome,
215
227
  ensureVoluteHome,
216
228
  readRegistry,
217
229
  validateAgentName,
@@ -221,5 +233,6 @@ export {
221
233
  findAgent,
222
234
  agentDir,
223
235
  nextPort,
236
+ daemonLoopback,
224
237
  resolveAgent
225
238
  };
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  validateAgentName
4
- } from "./chunk-3C2XR4IY.js";
4
+ } from "./chunk-UWHWAPGO.js";
5
5
 
6
6
  // src/lib/isolation.ts
7
7
  import { execFile, execFileSync } from "child_process";
@@ -116,5 +116,6 @@ export {
116
116
  findTemplatesRoot,
117
117
  composeTemplate,
118
118
  copyTemplateToDir,
119
- applyInitFiles
119
+ applyInitFiles,
120
+ listFiles
120
121
  };
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/lib/read-stdin.ts
4
+ import { isatty } from "tty";
5
+ async function readStdin() {
6
+ if (isatty(0)) return void 0;
7
+ const chunks = [];
8
+ try {
9
+ for await (const chunk of process.stdin) {
10
+ chunks.push(chunk);
11
+ }
12
+ } catch (err) {
13
+ console.error(`Failed to read from stdin: ${err instanceof Error ? err.message : String(err)}`);
14
+ process.exit(1);
15
+ }
16
+ const text = Buffer.concat(chunks).toString().replace(/\r?\n$/, "");
17
+ return text || void 0;
18
+ }
19
+
20
+ export {
21
+ readStdin
22
+ };