volute 0.6.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -13
- package/dist/{agent-X7GJLBLW.js → agent-YORVRB6I.js} +10 -10
- package/dist/{agent-manager-JDVXU3ON.js → agent-manager-CMMH5KQQ.js} +4 -4
- package/dist/{channel-SMCNOIVQ.js → channel-RDGHBFSI.js} +16 -56
- package/dist/{chunk-JR4UXCTO.js → chunk-23L3MKEV.js} +1 -1
- package/dist/{chunk-5SKQ6J7T.js → chunk-5C5JWR2L.js} +15 -7
- package/dist/{chunk-UWHWAPGO.js → chunk-DP2DX4WV.js} +9 -1
- package/dist/chunk-ECPQXRLB.js +264 -0
- package/dist/{down-FXWAN66A.js → chunk-HZ5LTOEJ.js} +48 -13
- package/dist/{chunk-W76KWE23.js → chunk-IQXBMFZG.js} +6 -4
- package/dist/{chunk-ZZOOTYXK.js → chunk-LIPPXNIE.js} +60 -74
- package/dist/{chunk-BX7KI4S3.js → chunk-N6MLQ26B.js} +23 -96
- package/dist/{chunk-H7AMDUIA.js → chunk-QF22MYDJ.js} +6 -5
- package/dist/{chunk-AOKAQGO4.js → chunk-RT6Y7AR3.js} +2 -1
- package/dist/{chunk-G6ZNGLUX.js → chunk-W6TMWYU3.js} +133 -78
- package/dist/{up-CSX3ZUIU.js → chunk-XSJ27WEM.js} +2 -2
- package/dist/cli.js +25 -19
- package/dist/{connector-Y7JPNROO.js → connector-ZP6MEFF4.js} +3 -3
- package/dist/connectors/discord.js +24 -61
- package/dist/connectors/slack.js +21 -38
- package/dist/connectors/telegram.js +31 -49
- package/dist/{create-G525LWEA.js → create-HGJHLABX.js} +22 -17
- package/dist/{daemon-client-442IV43D.js → daemon-client-54J3EIZD.js} +2 -2
- package/dist/daemon-restart-CPBLMMRI.js +23 -0
- package/dist/daemon.js +397 -661
- package/dist/{delete-2PH2CGDY.js → delete-45TGQC4N.js} +13 -4
- package/dist/down-O4EWZTVA.js +11 -0
- package/dist/{env-7GLUJCWS.js → env-KMNYGVZ2.js} +7 -9
- package/dist/{history-H72ZUIBN.js → history-PXJVYLVY.js} +2 -2
- package/dist/{import-AVKQJDYC.js → import-CNEDF3TD.js} +6 -6
- package/dist/{logs-EDGK26AK.js → logs-TZB3MTLZ.js} +5 -4
- package/dist/{package-4DP4Y4UO.js → package-5UCKNK6J.js} +1 -1
- package/dist/{restart-O4ETYLJF.js → restart-KVH3TK5N.js} +2 -2
- package/dist/{schedule-S6QVC5ON.js → schedule-HCUCBNQI.js} +2 -2
- package/dist/send-BNC2S5BY.js +162 -0
- package/dist/{service-HZNIDNJF.js → service-R4MCNBOA.js} +1 -1
- package/dist/{setup-F4TCWVSP.js → setup-JXDCJX7W.js} +25 -6
- package/dist/{start-VHQ7LNWM.js → start-QU73YTJW.js} +2 -2
- package/dist/{status-QAJWXKMZ.js → status-Q6ZQJXNI.js} +2 -2
- package/dist/{stop-CAGCT5NI.js → stop-N7U5N6A7.js} +2 -2
- package/dist/up-V6EAA7OZ.js +12 -0
- package/dist/{update-XSIX3GGP.js → update-EUCZ7XGG.js} +3 -3
- package/dist/{update-check-5ZADDHCK.js → update-check-SM4244SU.js} +2 -2
- package/dist/{upgrade-YXKPWDRU.js → upgrade-CZF6PN7Y.js} +4 -4
- package/dist/{variant-4Z6W3PP6.js → variant-RKXPN5DH.js} +20 -46
- package/dist/web-assets/assets/index-D-3zx6vs.js +307 -0
- package/dist/web-assets/index.html +1 -1
- package/drizzle/0004_magical_silverclaw.sql +1 -0
- package/drizzle/meta/0004_snapshot.json +410 -0
- package/drizzle/meta/_journal.json +7 -0
- package/package.json +1 -1
- package/templates/_base/_skills/volute-agent/SKILL.md +32 -16
- package/templates/_base/home/.config/routes.json +4 -8
- package/templates/_base/home/VOLUTE.md +16 -14
- package/templates/_base/src/lib/auto-reply.ts +38 -0
- package/templates/_base/src/lib/daemon-client.ts +53 -0
- package/templates/_base/src/lib/router.ts +66 -14
- package/templates/_base/src/lib/routing.ts +48 -9
- package/templates/_base/src/lib/startup.ts +1 -25
- package/templates/_base/src/lib/types.ts +2 -1
- package/templates/_base/src/lib/volute-server.ts +29 -14
- package/templates/agent-sdk/src/agent.ts +53 -111
- package/templates/agent-sdk/src/lib/content.ts +41 -0
- package/templates/agent-sdk/src/lib/session-store.ts +43 -0
- package/templates/agent-sdk/src/lib/stream-consumer.ts +66 -0
- package/templates/agent-sdk/src/server.ts +5 -13
- package/templates/pi/.init/AGENTS.md +5 -5
- package/templates/pi/src/agent.ts +32 -84
- package/templates/pi/src/lib/content.ts +15 -0
- package/templates/pi/src/lib/event-handler.ts +74 -0
- package/templates/pi/src/lib/resolve-model.ts +21 -0
- package/templates/pi/src/server.ts +3 -7
- package/dist/chunk-B3R6L2GW.js +0 -24
- package/dist/chunk-ZYGKG6VC.js +0 -22
- package/dist/message-SCOQDR3P.js +0 -32
- package/dist/send-G7PE4DOJ.js +0 -72
- package/dist/web-assets/assets/index-D5PzIndO.js +0 -308
package/dist/connectors/slack.js
CHANGED
|
@@ -1,19 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
buildChannelSlug,
|
|
4
|
-
fireAndForget,
|
|
5
|
-
handleAgentMessage,
|
|
6
4
|
loadEnv,
|
|
7
5
|
loadFollowedChannels,
|
|
8
6
|
onShutdown,
|
|
9
|
-
|
|
7
|
+
sendToAgent,
|
|
10
8
|
writeChannelEntry
|
|
11
|
-
} from "../chunk-
|
|
9
|
+
} from "../chunk-N6MLQ26B.js";
|
|
10
|
+
import "../chunk-DP2DX4WV.js";
|
|
12
11
|
import "../chunk-K3NQKI34.js";
|
|
13
12
|
|
|
14
13
|
// src/connectors/slack.ts
|
|
15
14
|
import { App } from "@slack/bolt";
|
|
16
|
-
var SLACK_MAX_LENGTH = 4e3;
|
|
17
15
|
var env = loadEnv();
|
|
18
16
|
var botToken = process.env.SLACK_BOT_TOKEN;
|
|
19
17
|
var appToken = process.env.SLACK_APP_TOKEN;
|
|
@@ -30,7 +28,7 @@ var app = new App({
|
|
|
30
28
|
});
|
|
31
29
|
var botUserId;
|
|
32
30
|
var serverName;
|
|
33
|
-
app.message(async ({ message
|
|
31
|
+
app.message(async ({ message }) => {
|
|
34
32
|
if (message.subtype) return;
|
|
35
33
|
if (!("user" in message) || !("text" in message)) return;
|
|
36
34
|
if ("bot_id" in message && message.bot_id) return;
|
|
@@ -98,14 +96,16 @@ app.message(async ({ message, say }) => {
|
|
|
98
96
|
channelName: channelName ?? message.channel,
|
|
99
97
|
serverName
|
|
100
98
|
});
|
|
101
|
-
|
|
102
|
-
writeChannelEntry(env.
|
|
99
|
+
try {
|
|
100
|
+
writeChannelEntry(env.agentName, channelKey, {
|
|
103
101
|
platformId: message.channel,
|
|
104
102
|
platform: "slack",
|
|
105
103
|
name: channelName ? `#${channelName}` : void 0,
|
|
106
104
|
server: serverName,
|
|
107
105
|
type: isDM ? "dm" : "channel"
|
|
108
106
|
});
|
|
107
|
+
} catch (err) {
|
|
108
|
+
console.error(`[slack] failed to write channel entry for ${channelKey}:`, err);
|
|
109
109
|
}
|
|
110
110
|
const participantCount = message.channel_type === "im" ? 2 : numMembers;
|
|
111
111
|
const payload = {
|
|
@@ -119,38 +119,21 @@ app.message(async ({ message, say }) => {
|
|
|
119
119
|
...participantCount ? { participantCount } : {}
|
|
120
120
|
};
|
|
121
121
|
if (isFollowedChannel && !isMentioned) {
|
|
122
|
-
await
|
|
122
|
+
const result2 = await sendToAgent(env, payload);
|
|
123
|
+
if (!result2.ok)
|
|
124
|
+
app.client.chat.postMessage({
|
|
125
|
+
channel: message.channel,
|
|
126
|
+
text: result2.error ?? "Failed to process message"
|
|
127
|
+
}).catch((err) => {
|
|
128
|
+
console.warn(`[slack] failed to send error reply: ${err}`);
|
|
129
|
+
});
|
|
123
130
|
return;
|
|
124
131
|
}
|
|
125
|
-
await
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
await app.client.filesUploadV2({
|
|
131
|
-
channel_id: message.channel,
|
|
132
|
-
file: Buffer.from(img.data, "base64"),
|
|
133
|
-
filename: `image.${ext}`
|
|
134
|
-
});
|
|
135
|
-
} catch (err) {
|
|
136
|
-
console.error(`Failed to upload image: ${err}`);
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
if (!text2) return;
|
|
140
|
-
const chunks = splitMessage(text2, SLACK_MAX_LENGTH);
|
|
141
|
-
for (const chunk of chunks) {
|
|
142
|
-
try {
|
|
143
|
-
await say(chunk);
|
|
144
|
-
} catch (err) {
|
|
145
|
-
console.error(`Failed to send message: ${err}`);
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
},
|
|
149
|
-
onError: async (msg) => {
|
|
150
|
-
await say(msg).catch(() => {
|
|
151
|
-
});
|
|
152
|
-
}
|
|
153
|
-
});
|
|
132
|
+
const result = await sendToAgent(env, payload);
|
|
133
|
+
if (!result.ok)
|
|
134
|
+
app.client.chat.postMessage({ channel: message.channel, text: result.error ?? "Failed to process message" }).catch((err) => {
|
|
135
|
+
console.warn(`[slack] failed to send error reply: ${err}`);
|
|
136
|
+
});
|
|
154
137
|
});
|
|
155
138
|
async function start() {
|
|
156
139
|
await app.start();
|
|
@@ -1,19 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
buildChannelSlug,
|
|
4
|
-
fireAndForget,
|
|
5
|
-
handleAgentMessage,
|
|
6
4
|
loadEnv,
|
|
7
5
|
loadFollowedChannels,
|
|
8
|
-
|
|
6
|
+
sendToAgent,
|
|
9
7
|
writeChannelEntry
|
|
10
|
-
} from "../chunk-
|
|
8
|
+
} from "../chunk-N6MLQ26B.js";
|
|
9
|
+
import "../chunk-DP2DX4WV.js";
|
|
11
10
|
import "../chunk-K3NQKI34.js";
|
|
12
11
|
|
|
13
12
|
// src/connectors/telegram.ts
|
|
14
|
-
import {
|
|
13
|
+
import { Telegraf } from "telegraf";
|
|
15
14
|
import { message } from "telegraf/filters";
|
|
16
|
-
var TELEGRAM_MAX_LENGTH = 4096;
|
|
17
15
|
var TYPING_INTERVAL_MS = 5e3;
|
|
18
16
|
var env = loadEnv();
|
|
19
17
|
var botToken = process.env.TELEGRAM_BOT_TOKEN;
|
|
@@ -56,13 +54,15 @@ bot.on(message("text"), async (ctx) => {
|
|
|
56
54
|
}) : buildChannelSlug("telegram", {
|
|
57
55
|
channelName: chatTitle ?? String(ctx.chat.id)
|
|
58
56
|
});
|
|
59
|
-
|
|
60
|
-
writeChannelEntry(env.
|
|
57
|
+
try {
|
|
58
|
+
writeChannelEntry(env.agentName, channelSlug, {
|
|
61
59
|
platformId: String(ctx.chat.id),
|
|
62
60
|
platform: "telegram",
|
|
63
61
|
name: chatTitle,
|
|
64
62
|
type: isDM ? "dm" : "channel"
|
|
65
63
|
});
|
|
64
|
+
} catch (err) {
|
|
65
|
+
console.error(`[telegram] failed to write channel entry for ${channelSlug}:`, err);
|
|
66
66
|
}
|
|
67
67
|
const payload = {
|
|
68
68
|
content,
|
|
@@ -74,15 +74,14 @@ bot.on(message("text"), async (ctx) => {
|
|
|
74
74
|
...participantCount ? { participantCount } : {}
|
|
75
75
|
};
|
|
76
76
|
if (isFollowedChat && !isMentioned) {
|
|
77
|
-
await
|
|
77
|
+
const result = await sendToAgent(env, payload);
|
|
78
|
+
if (!result.ok)
|
|
79
|
+
ctx.reply(result.error ?? "Failed to process message").catch((err) => {
|
|
80
|
+
console.warn(`[telegram] failed to send error reply: ${err}`);
|
|
81
|
+
});
|
|
78
82
|
return;
|
|
79
83
|
}
|
|
80
|
-
await handleTelegramMessage(
|
|
81
|
-
ctx.chat.id,
|
|
82
|
-
payload,
|
|
83
|
-
(text2) => ctx.reply(text2),
|
|
84
|
-
(source) => ctx.replyWithPhoto(source)
|
|
85
|
-
);
|
|
84
|
+
await handleTelegramMessage(ctx, payload);
|
|
86
85
|
});
|
|
87
86
|
bot.on(message("photo"), async (ctx) => {
|
|
88
87
|
if (ctx.message.from.is_bot) return;
|
|
@@ -127,13 +126,15 @@ bot.on(message("photo"), async (ctx) => {
|
|
|
127
126
|
}) : buildChannelSlug("telegram", {
|
|
128
127
|
channelName: chatTitle ?? String(ctx.chat.id)
|
|
129
128
|
});
|
|
130
|
-
|
|
131
|
-
writeChannelEntry(env.
|
|
129
|
+
try {
|
|
130
|
+
writeChannelEntry(env.agentName, channelSlug, {
|
|
132
131
|
platformId: String(ctx.chat.id),
|
|
133
132
|
platform: "telegram",
|
|
134
133
|
name: chatTitle,
|
|
135
134
|
type: isDM ? "dm" : "channel"
|
|
136
135
|
});
|
|
136
|
+
} catch (err) {
|
|
137
|
+
console.error(`[telegram] failed to write channel entry for ${channelSlug}:`, err);
|
|
137
138
|
}
|
|
138
139
|
const payload = {
|
|
139
140
|
content,
|
|
@@ -145,17 +146,17 @@ bot.on(message("photo"), async (ctx) => {
|
|
|
145
146
|
...participantCount ? { participantCount } : {}
|
|
146
147
|
};
|
|
147
148
|
if (isFollowedChat) {
|
|
148
|
-
await
|
|
149
|
+
const result = await sendToAgent(env, payload);
|
|
150
|
+
if (!result.ok)
|
|
151
|
+
ctx.reply(result.error ?? "Failed to process message").catch((err) => {
|
|
152
|
+
console.warn(`[telegram] failed to send error reply: ${err}`);
|
|
153
|
+
});
|
|
149
154
|
return;
|
|
150
155
|
}
|
|
151
|
-
await handleTelegramMessage(
|
|
152
|
-
ctx.chat.id,
|
|
153
|
-
payload,
|
|
154
|
-
(text) => ctx.reply(text),
|
|
155
|
-
(source) => ctx.replyWithPhoto(source)
|
|
156
|
-
);
|
|
156
|
+
await handleTelegramMessage(ctx, payload);
|
|
157
157
|
});
|
|
158
|
-
async function handleTelegramMessage(
|
|
158
|
+
async function handleTelegramMessage(ctx, payload) {
|
|
159
|
+
const chatId = ctx.chat.id;
|
|
159
160
|
const typingInterval = setInterval(() => {
|
|
160
161
|
bot.telegram.sendChatAction(chatId, "typing").catch(() => {
|
|
161
162
|
});
|
|
@@ -163,30 +164,11 @@ async function handleTelegramMessage(chatId, payload, reply, replyWithPhoto) {
|
|
|
163
164
|
bot.telegram.sendChatAction(chatId, "typing").catch(() => {
|
|
164
165
|
});
|
|
165
166
|
try {
|
|
166
|
-
await
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
} catch (err) {
|
|
172
|
-
console.error(`Failed to send image: ${err}`);
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
if (!text) return;
|
|
176
|
-
const chunks = splitMessage(text, TELEGRAM_MAX_LENGTH);
|
|
177
|
-
for (const chunk of chunks) {
|
|
178
|
-
try {
|
|
179
|
-
await reply(chunk);
|
|
180
|
-
} catch (err) {
|
|
181
|
-
console.error(`Failed to send message: ${err}`);
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
},
|
|
185
|
-
onError: async (msg) => {
|
|
186
|
-
await reply(msg).catch(() => {
|
|
187
|
-
});
|
|
188
|
-
}
|
|
189
|
-
});
|
|
167
|
+
const result = await sendToAgent(env, payload);
|
|
168
|
+
if (!result.ok)
|
|
169
|
+
ctx.reply(result.error ?? "Failed to process message").catch((err) => {
|
|
170
|
+
console.warn(`[telegram] failed to send error reply: ${err}`);
|
|
171
|
+
});
|
|
190
172
|
} finally {
|
|
191
173
|
clearInterval(typingInterval);
|
|
192
174
|
}
|
|
@@ -12,18 +12,20 @@ import {
|
|
|
12
12
|
import {
|
|
13
13
|
chownAgentDir,
|
|
14
14
|
createAgentUser,
|
|
15
|
-
ensureVoluteGroup
|
|
16
|
-
|
|
15
|
+
ensureVoluteGroup,
|
|
16
|
+
getAgentUserIds,
|
|
17
|
+
isIsolationEnabled
|
|
18
|
+
} from "./chunk-IQXBMFZG.js";
|
|
17
19
|
import {
|
|
18
20
|
exec,
|
|
19
21
|
execInherit
|
|
20
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-5C5JWR2L.js";
|
|
21
23
|
import {
|
|
22
24
|
addAgent,
|
|
23
25
|
agentDir,
|
|
24
26
|
ensureVoluteHome,
|
|
25
27
|
nextPort
|
|
26
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-DP2DX4WV.js";
|
|
27
29
|
import "./chunk-K3NQKI34.js";
|
|
28
30
|
|
|
29
31
|
// src/commands/create.ts
|
|
@@ -53,11 +55,16 @@ async function run(args) {
|
|
|
53
55
|
applyInitFiles(dest);
|
|
54
56
|
const port = nextPort();
|
|
55
57
|
addAgent(name, port);
|
|
58
|
+
ensureVoluteGroup();
|
|
59
|
+
createAgentUser(name);
|
|
60
|
+
chownAgentDir(dest, name);
|
|
61
|
+
const ids = isIsolationEnabled() ? await getAgentUserIds(name) : void 0;
|
|
62
|
+
const env = ids ? { ...process.env, HOME: dest } : void 0;
|
|
56
63
|
console.log("Installing dependencies...");
|
|
57
|
-
await execInherit("npm", ["install"], { cwd: dest });
|
|
64
|
+
await execInherit("npm", ["install"], { cwd: dest, uid: ids?.uid, gid: ids?.gid, env });
|
|
58
65
|
try {
|
|
59
|
-
await exec("git", ["init"], { cwd: dest });
|
|
60
|
-
await initTemplateBranch(dest, composedDir, manifest);
|
|
66
|
+
await exec("git", ["init"], { cwd: dest, uid: ids?.uid, gid: ids?.gid, env });
|
|
67
|
+
await initTemplateBranch(dest, composedDir, manifest, ids, env);
|
|
61
68
|
} catch (err) {
|
|
62
69
|
rmSync(resolve(dest, ".git"), { recursive: true, force: true });
|
|
63
70
|
console.warn(
|
|
@@ -66,9 +73,6 @@ async function run(args) {
|
|
|
66
73
|
);
|
|
67
74
|
console.warn("Details:", err.message ?? err);
|
|
68
75
|
}
|
|
69
|
-
ensureVoluteGroup();
|
|
70
|
-
createAgentUser(name);
|
|
71
|
-
chownAgentDir(dest, name);
|
|
72
76
|
console.log(`
|
|
73
77
|
Created agent: ${name} (port ${port})`);
|
|
74
78
|
console.log(`
|
|
@@ -77,14 +81,15 @@ Created agent: ${name} (port ${port})`);
|
|
|
77
81
|
rmSync(composedDir, { recursive: true, force: true });
|
|
78
82
|
}
|
|
79
83
|
}
|
|
80
|
-
async function initTemplateBranch(projectRoot, composedDir, manifest) {
|
|
84
|
+
async function initTemplateBranch(projectRoot, composedDir, manifest, ids, env) {
|
|
81
85
|
const templateFiles = listFiles(composedDir).filter((f) => !f.startsWith(".init/") && !f.startsWith(".init\\")).map((f) => manifest.rename[f] ?? f);
|
|
82
|
-
|
|
83
|
-
await exec("git", ["
|
|
84
|
-
await exec("git", ["
|
|
85
|
-
await exec("git", ["
|
|
86
|
-
await exec("git", ["
|
|
87
|
-
await exec("git", ["
|
|
86
|
+
const opts = { cwd: projectRoot, uid: ids?.uid, gid: ids?.gid, env };
|
|
87
|
+
await exec("git", ["checkout", "--orphan", TEMPLATE_BRANCH], opts);
|
|
88
|
+
await exec("git", ["add", "--", ...templateFiles], opts);
|
|
89
|
+
await exec("git", ["commit", "-m", "template update"], opts);
|
|
90
|
+
await exec("git", ["checkout", "-b", "main"], opts);
|
|
91
|
+
await exec("git", ["add", "-A"], opts);
|
|
92
|
+
await exec("git", ["commit", "-m", "initial commit"], opts);
|
|
88
93
|
}
|
|
89
94
|
export {
|
|
90
95
|
run
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
run
|
|
4
|
+
} from "./chunk-XSJ27WEM.js";
|
|
5
|
+
import {
|
|
6
|
+
stopDaemon
|
|
7
|
+
} from "./chunk-HZ5LTOEJ.js";
|
|
8
|
+
import "./chunk-D424ZQGI.js";
|
|
9
|
+
import "./chunk-DP2DX4WV.js";
|
|
10
|
+
import "./chunk-K3NQKI34.js";
|
|
11
|
+
|
|
12
|
+
// src/commands/daemon-restart.ts
|
|
13
|
+
async function run2(args) {
|
|
14
|
+
const result = await stopDaemon();
|
|
15
|
+
if (!result.stopped && result.reason === "kill-failed") {
|
|
16
|
+
console.error("Cannot restart: failed to stop the running daemon.");
|
|
17
|
+
process.exit(1);
|
|
18
|
+
}
|
|
19
|
+
await run(args);
|
|
20
|
+
}
|
|
21
|
+
export {
|
|
22
|
+
run2 as run
|
|
23
|
+
};
|