@jiangyuan1209/yuan-claw 0.1.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/.env.example +28 -0
- package/README.md +441 -0
- package/dist/agent/build-system-prompt.js +46 -0
- package/dist/agent/message-types.js +1 -0
- package/dist/agent/message-utils.js +239 -0
- package/dist/agent/parse-agent-response.js +48 -0
- package/dist/agent/prompts.js +27 -0
- package/dist/agent/protocol.js +1 -0
- package/dist/agent/read-approval.js +45 -0
- package/dist/agent/read-confirmation.js +17 -0
- package/dist/agent/run-local-agent-loop.js +272 -0
- package/dist/cli/help.js +24 -0
- package/dist/cli/main.js +108 -0
- package/dist/cli/parse-args.js +75 -0
- package/dist/cli/repl.js +188 -0
- package/dist/config/config-path.js +9 -0
- package/dist/config/init-user-config.js +39 -0
- package/dist/config/load-config.js +46 -0
- package/dist/config.js +29 -0
- package/dist/events/event-bus.js +62 -0
- package/dist/lib/initGlobalProxy.js +52 -0
- package/dist/memory/session-store.js +43 -0
- package/dist/memory/types.js +1 -0
- package/dist/model/client.js +7 -0
- package/dist/model/providers/openai-compatible.js +42 -0
- package/dist/scripts/test-brave.js +16 -0
- package/dist/security/network-policy.js +19 -0
- package/dist/security/path-guards.js +18 -0
- package/dist/security/shell-policy.js +40 -0
- package/dist/shared/utils.js +1 -0
- package/dist/tools/file/grep-text.js +85 -0
- package/dist/tools/file/list-files.js +52 -0
- package/dist/tools/file/read-file.js +39 -0
- package/dist/tools/file/write-file.js +37 -0
- package/dist/tools/git/git-diff.js +54 -0
- package/dist/tools/git/git-status.js +44 -0
- package/dist/tools/registry.js +41 -0
- package/dist/tools/shell/shell-exec.js +41 -0
- package/dist/tools/types.js +1 -0
- package/dist/tools/web/extract-readable-text.js +54 -0
- package/dist/tools/web/http-fetch.js +55 -0
- package/dist/tools/web/index.js +4 -0
- package/dist/tools/web/search-providers/brave.js +31 -0
- package/dist/tools/web/web-search.js +33 -0
- package/package.json +26 -0
package/.env.example
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# =========================
|
|
2
|
+
# 模型服务配置(推荐)
|
|
3
|
+
# =========================
|
|
4
|
+
|
|
5
|
+
MODEL_API_KEY=
|
|
6
|
+
MODEL_BASE_URL=
|
|
7
|
+
MODEL_NAME=
|
|
8
|
+
|
|
9
|
+
# =========================
|
|
10
|
+
# OpenAI 风格兼容变量(可选)
|
|
11
|
+
# =========================
|
|
12
|
+
|
|
13
|
+
OPENAI_API_KEY=
|
|
14
|
+
OPENAI_BASE_URL=
|
|
15
|
+
OPENAI_MODEL=
|
|
16
|
+
|
|
17
|
+
# =========================
|
|
18
|
+
# 网页搜索配置
|
|
19
|
+
# =========================
|
|
20
|
+
|
|
21
|
+
BRAVE_SEARCH_API_KEY=
|
|
22
|
+
|
|
23
|
+
# =========================
|
|
24
|
+
# 代理配置(可选)
|
|
25
|
+
# =========================
|
|
26
|
+
|
|
27
|
+
HTTP_PROXY=
|
|
28
|
+
HTTPS_PROXY=
|
package/README.md
ADDED
|
@@ -0,0 +1,441 @@
|
|
|
1
|
+
# yuan-claw
|
|
2
|
+
|
|
3
|
+
一个基于 **Node.js + TypeScript** 的本地 CLI Agent。
|
|
4
|
+
它可以在命令行中使用大模型完成任务,并按需调用网页搜索、HTTP 抓取、网页正文提取以及本地工具。
|
|
5
|
+
|
|
6
|
+
## Features
|
|
7
|
+
|
|
8
|
+
- 🤖 本地命令行智能体
|
|
9
|
+
- 🧠 基于大模型的任务执行与推理
|
|
10
|
+
- 🔧 可扩展的工具调用机制
|
|
11
|
+
- 🌐 支持 Brave Search 网页搜索
|
|
12
|
+
- 📄 支持 HTTP 抓取与网页正文提取
|
|
13
|
+
- 💬 支持多轮会话
|
|
14
|
+
- 🖥️ 支持交互式 REPL
|
|
15
|
+
- ✅ 支持工具执行前确认(approval)
|
|
16
|
+
- ⌨️ 支持 `↑ / ↓ / Enter` 选择确认项
|
|
17
|
+
- 🔁 支持会话级“总是允许”模式
|
|
18
|
+
- 🔌 支持代理配置
|
|
19
|
+
- 🛠️ 基于 TypeScript,便于二次开发
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Requirements
|
|
24
|
+
|
|
25
|
+
- Node.js >= 20
|
|
26
|
+
- npm >= 9
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Installation
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
git clone https://github.com/your-name/yuan-claw.git
|
|
34
|
+
cd yuan-claw
|
|
35
|
+
npm install
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Quick Start
|
|
41
|
+
|
|
42
|
+
### 1. 配置环境变量
|
|
43
|
+
|
|
44
|
+
在项目根目录创建 `.env` 文件:
|
|
45
|
+
|
|
46
|
+
```env
|
|
47
|
+
MODEL_API_KEY=
|
|
48
|
+
MODEL_BASE_URL=
|
|
49
|
+
MODEL_NAME=
|
|
50
|
+
|
|
51
|
+
BRAVE_SEARCH_API_KEY=
|
|
52
|
+
|
|
53
|
+
HTTP_PROXY=
|
|
54
|
+
HTTPS_PROXY=
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
最小可用配置通常只需要:
|
|
58
|
+
|
|
59
|
+
```env
|
|
60
|
+
MODEL_API_KEY=your_api_key
|
|
61
|
+
MODEL_BASE_URL=https://api.openai.com/v1
|
|
62
|
+
MODEL_NAME=gpt-4o-mini
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
### 2. 开发模式运行
|
|
68
|
+
|
|
69
|
+
#### 单次命令
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
npm run dev -- "帮我搜索 OpenAI 最新消息"
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
#### 交互式 REPL
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
npm run dev
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
启动后你会看到:
|
|
82
|
+
|
|
83
|
+
```txt
|
|
84
|
+
Welcome to yuan-claw!
|
|
85
|
+
Type /help for commands, /exit to quit.
|
|
86
|
+
Approval mode is shown in the prompt: [ask] or [always].
|
|
87
|
+
|
|
88
|
+
yuan-claw[ask]>
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
### 3. 编译后运行
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
npm run build
|
|
97
|
+
npm run start
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
单次命令模式:
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
npm run start -- "帮我总结这个项目的功能"
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## REPL Usage
|
|
109
|
+
|
|
110
|
+
不传入 prompt 时,程序会进入 REPL 模式。你可以连续输入多轮指令,例如:
|
|
111
|
+
|
|
112
|
+
```txt
|
|
113
|
+
yuan-claw[ask]> 帮我总结这个项目
|
|
114
|
+
yuan-claw[ask]> 再简短一点
|
|
115
|
+
yuan-claw[ask]> 输出成要点列表
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
支持的内置命令:
|
|
119
|
+
|
|
120
|
+
```txt
|
|
121
|
+
/help 显示帮助
|
|
122
|
+
/exit 退出
|
|
123
|
+
/quit 退出
|
|
124
|
+
/clear 清空当前会话历史,并重置 approval 模式
|
|
125
|
+
/save 保存当前会话
|
|
126
|
+
/reset 将 approval 模式重置为 ask
|
|
127
|
+
/status 查看当前会话状态
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## Approval / 工具执行确认
|
|
133
|
+
|
|
134
|
+
某些工具调用在执行前需要你的确认,例如执行本地命令时:
|
|
135
|
+
|
|
136
|
+
```txt
|
|
137
|
+
我需要执行 `pwd` 命令来显示当前工作目录。是否允许执行?
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
此时可以使用:
|
|
141
|
+
|
|
142
|
+
- `↑ / ↓`:切换选项
|
|
143
|
+
- `Enter`:确认
|
|
144
|
+
- `Ctrl+C`:拒绝
|
|
145
|
+
|
|
146
|
+
可选项包括:
|
|
147
|
+
|
|
148
|
+
- **不允许**
|
|
149
|
+
- **允许**
|
|
150
|
+
- **总是允许**
|
|
151
|
+
|
|
152
|
+
如果选择 **总是允许**,当前会话后续的相关工具调用将自动通过,提示符也会变为:
|
|
153
|
+
|
|
154
|
+
```txt
|
|
155
|
+
yuan-claw[always]>
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
如需恢复逐次确认,可执行:
|
|
159
|
+
|
|
160
|
+
```txt
|
|
161
|
+
/reset
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## Scripts
|
|
167
|
+
|
|
168
|
+
```json
|
|
169
|
+
{
|
|
170
|
+
"scripts": {
|
|
171
|
+
"dev": "tsx src/cli/main.ts",
|
|
172
|
+
"build": "tsc -p tsconfig.json",
|
|
173
|
+
"start": "node dist/cli/main.js",
|
|
174
|
+
"check": "tsc --noEmit"
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### 脚本说明
|
|
180
|
+
|
|
181
|
+
- `npm run dev`:开发模式运行源码
|
|
182
|
+
- `npm run build`:编译到 `dist/`
|
|
183
|
+
- `npm run start`:运行编译后的 CLI
|
|
184
|
+
- `npm run check`:执行 TypeScript 类型检查
|
|
185
|
+
|
|
186
|
+
说明:
|
|
187
|
+
|
|
188
|
+
- `npm run dev` / `npm run start`
|
|
189
|
+
- 不传参数:进入 REPL
|
|
190
|
+
- 传入参数:执行单次命令
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
## CLI Usage
|
|
195
|
+
|
|
196
|
+
项目在 `package.json` 中定义了可执行命令:
|
|
197
|
+
|
|
198
|
+
```json
|
|
199
|
+
"bin": {
|
|
200
|
+
"yuan-claw": "./dist/cli/main.js"
|
|
201
|
+
}
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
构建并安装后,可以直接使用:
|
|
205
|
+
|
|
206
|
+
```bash
|
|
207
|
+
yuan-claw
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
或:
|
|
211
|
+
|
|
212
|
+
```bash
|
|
213
|
+
yuan-claw "帮我搜索 AI 新闻"
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
---
|
|
217
|
+
|
|
218
|
+
## Environment Variables
|
|
219
|
+
|
|
220
|
+
项目使用 **OpenAI-compatible API**,按以下优先级读取配置:
|
|
221
|
+
|
|
222
|
+
### API Key
|
|
223
|
+
|
|
224
|
+
1. `MODEL_API_KEY`
|
|
225
|
+
2. `OPENAI_API_KEY`
|
|
226
|
+
|
|
227
|
+
### Base URL
|
|
228
|
+
|
|
229
|
+
1. `MODEL_BASE_URL`
|
|
230
|
+
2. `OPENAI_BASE_URL`
|
|
231
|
+
|
|
232
|
+
### Model Name
|
|
233
|
+
|
|
234
|
+
1. `MODEL_NAME`
|
|
235
|
+
2. `OPENAI_MODEL`
|
|
236
|
+
3. 默认值:`gpt-4o-mini`
|
|
237
|
+
|
|
238
|
+
### OpenAI 风格兼容变量
|
|
239
|
+
|
|
240
|
+
如果你更习惯 OpenAI 风格变量名,也可以使用:
|
|
241
|
+
|
|
242
|
+
```env
|
|
243
|
+
OPENAI_API_KEY=
|
|
244
|
+
OPENAI_BASE_URL=
|
|
245
|
+
OPENAI_MODEL=
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
---
|
|
249
|
+
|
|
250
|
+
## Web Search
|
|
251
|
+
|
|
252
|
+
如果你希望启用网页搜索工具,请配置:
|
|
253
|
+
|
|
254
|
+
```env
|
|
255
|
+
BRAVE_SEARCH_API_KEY=your_brave_search_api_key
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
未配置时,`web_search` 工具会被禁用。
|
|
259
|
+
|
|
260
|
+
---
|
|
261
|
+
|
|
262
|
+
## Proxy
|
|
263
|
+
|
|
264
|
+
如需通过代理访问模型服务或外部网站,可以配置:
|
|
265
|
+
|
|
266
|
+
```env
|
|
267
|
+
HTTP_PROXY=http://127.0.0.1:33210
|
|
268
|
+
HTTPS_PROXY=http://127.0.0.1:33210
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
程序会自动读取以下变量:
|
|
272
|
+
|
|
273
|
+
- `HTTP_PROXY`
|
|
274
|
+
- `HTTPS_PROXY`
|
|
275
|
+
- `http_proxy`
|
|
276
|
+
- `https_proxy`
|
|
277
|
+
|
|
278
|
+
---
|
|
279
|
+
|
|
280
|
+
## Recommended `.env.example`
|
|
281
|
+
|
|
282
|
+
建议在仓库中提供如下 `.env.example`:
|
|
283
|
+
|
|
284
|
+
```env
|
|
285
|
+
# =========================
|
|
286
|
+
# 模型服务配置(推荐)
|
|
287
|
+
# =========================
|
|
288
|
+
|
|
289
|
+
MODEL_API_KEY=
|
|
290
|
+
MODEL_BASE_URL=
|
|
291
|
+
MODEL_NAME=
|
|
292
|
+
|
|
293
|
+
# =========================
|
|
294
|
+
# OpenAI 风格兼容变量(可选)
|
|
295
|
+
# =========================
|
|
296
|
+
|
|
297
|
+
OPENAI_API_KEY=
|
|
298
|
+
OPENAI_BASE_URL=
|
|
299
|
+
OPENAI_MODEL=
|
|
300
|
+
|
|
301
|
+
# =========================
|
|
302
|
+
# 网页搜索配置
|
|
303
|
+
# =========================
|
|
304
|
+
|
|
305
|
+
BRAVE_SEARCH_API_KEY=
|
|
306
|
+
|
|
307
|
+
# =========================
|
|
308
|
+
# 代理配置(可选)
|
|
309
|
+
# =========================
|
|
310
|
+
|
|
311
|
+
HTTP_PROXY=
|
|
312
|
+
HTTPS_PROXY=
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
---
|
|
316
|
+
|
|
317
|
+
## Examples
|
|
318
|
+
|
|
319
|
+
### 普通问答
|
|
320
|
+
|
|
321
|
+
```bash
|
|
322
|
+
npm run dev -- "帮我总结这个项目的功能"
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
### 搜索最新消息
|
|
326
|
+
|
|
327
|
+
```bash
|
|
328
|
+
npm run dev -- "帮我搜索 OpenAI 最新消息"
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
### 进入 REPL
|
|
332
|
+
|
|
333
|
+
```bash
|
|
334
|
+
npm run dev
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
### 编译后运行
|
|
338
|
+
|
|
339
|
+
```bash
|
|
340
|
+
npm run build
|
|
341
|
+
npm run start -- "帮我搜索 AI 新闻"
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
---
|
|
345
|
+
|
|
346
|
+
## Troubleshooting
|
|
347
|
+
|
|
348
|
+
### `Missing MODEL_API_KEY / OPENAI_API_KEY in environment variables.`
|
|
349
|
+
|
|
350
|
+
说明模型 API Key 未配置。请至少设置其一:
|
|
351
|
+
|
|
352
|
+
```env
|
|
353
|
+
MODEL_API_KEY=your_api_key
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
或:
|
|
357
|
+
|
|
358
|
+
```env
|
|
359
|
+
OPENAI_API_KEY=your_api_key
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
---
|
|
363
|
+
|
|
364
|
+
### `web_search disabled: set BRAVE_SEARCH_API_KEY`
|
|
365
|
+
|
|
366
|
+
说明未配置 Brave Search API Key。请添加:
|
|
367
|
+
|
|
368
|
+
```env
|
|
369
|
+
BRAVE_SEARCH_API_KEY=your_key
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
---
|
|
373
|
+
|
|
374
|
+
### 无法访问外部服务 / 请求超时
|
|
375
|
+
|
|
376
|
+
请检查是否需要代理:
|
|
377
|
+
|
|
378
|
+
```env
|
|
379
|
+
HTTP_PROXY=http://127.0.0.1:33210
|
|
380
|
+
HTTPS_PROXY=http://127.0.0.1:33210
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
---
|
|
384
|
+
|
|
385
|
+
### 某些网页返回 403 / Forbidden
|
|
386
|
+
|
|
387
|
+
这通常是目标站点的反爬策略导致的,不一定是程序错误。
|
|
388
|
+
建议优先使用搜索 API 或可信数据源。
|
|
389
|
+
|
|
390
|
+
---
|
|
391
|
+
|
|
392
|
+
### `npm run start` 无法运行
|
|
393
|
+
|
|
394
|
+
请先执行:
|
|
395
|
+
|
|
396
|
+
```bash
|
|
397
|
+
npm run build
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
因为 `start` 依赖编译输出文件:
|
|
401
|
+
|
|
402
|
+
```txt
|
|
403
|
+
dist/cli/main.js
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
---
|
|
407
|
+
|
|
408
|
+
## Development
|
|
409
|
+
|
|
410
|
+
```bash
|
|
411
|
+
npm run check
|
|
412
|
+
npm run dev
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
---
|
|
416
|
+
|
|
417
|
+
## Roadmap
|
|
418
|
+
|
|
419
|
+
- [ ] 优化 approval 菜单显示体验
|
|
420
|
+
- [ ] 增强搜索结果验证能力
|
|
421
|
+
- [ ] 优化网页正文提取效果
|
|
422
|
+
- [ ] 增加更多内置工具
|
|
423
|
+
- [ ] 支持更多模型服务商
|
|
424
|
+
- [ ] 完善自动化测试
|
|
425
|
+
- [ ] 增加 Docker 部署支持
|
|
426
|
+
|
|
427
|
+
---
|
|
428
|
+
|
|
429
|
+
## License
|
|
430
|
+
|
|
431
|
+
MIT
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
|
|
435
|
+
## `.gitignore`
|
|
436
|
+
|
|
437
|
+
```gitignore
|
|
438
|
+
node_modules
|
|
439
|
+
dist
|
|
440
|
+
.env
|
|
441
|
+
```
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
function formatToolsForPrompt(tools) {
|
|
2
|
+
if (tools.length === 0) {
|
|
3
|
+
return "- No tools available.";
|
|
4
|
+
}
|
|
5
|
+
return tools
|
|
6
|
+
.map((tool) => {
|
|
7
|
+
const risk = tool.riskLevel ?? "safe";
|
|
8
|
+
return `- ${tool.name} [${risk}]: ${tool.description}`;
|
|
9
|
+
})
|
|
10
|
+
.join("\n");
|
|
11
|
+
}
|
|
12
|
+
export function buildSystemPrompt(tools) {
|
|
13
|
+
return [
|
|
14
|
+
"You are a local CLI coding agent.",
|
|
15
|
+
"You do not have direct filesystem, shell, git, or network access unless you use the provided tools.",
|
|
16
|
+
"Use tools to inspect files, search code, read git state, fetch web content, write files, and run shell commands.",
|
|
17
|
+
"",
|
|
18
|
+
"CRITICAL OUTPUT RULES:",
|
|
19
|
+
"You must respond with exactly one JSON object and nothing else.",
|
|
20
|
+
"Do not output markdown.",
|
|
21
|
+
"Do not output code fences.",
|
|
22
|
+
"Do not output explanations outside the JSON object.",
|
|
23
|
+
"",
|
|
24
|
+
"Allowed response formats:",
|
|
25
|
+
'1. {"type":"tool_call","toolName":"<tool name>","args":{}}',
|
|
26
|
+
'2. {"type":"final","message":"<answer>"}',
|
|
27
|
+
'3. {"type":"ask_confirmation","message":"<question for the user>"}',
|
|
28
|
+
"",
|
|
29
|
+
"TOOL RULES:",
|
|
30
|
+
"- Use tools when you need real information from files, git, shell, or the web.",
|
|
31
|
+
"- Call at most one tool per response.",
|
|
32
|
+
"- Never invent tool results.",
|
|
33
|
+
"- If a tool is marked [confirm] or [dangerous], ask for confirmation before calling it.",
|
|
34
|
+
"- Prefer safe read-only inspection before making changes.",
|
|
35
|
+
"- If the task is complete, return a final response.",
|
|
36
|
+
"- Always return valid JSON.",
|
|
37
|
+
"",
|
|
38
|
+
"AVAILABLE TOOLS:",
|
|
39
|
+
formatToolsForPrompt(tools),
|
|
40
|
+
"",
|
|
41
|
+
"Examples:",
|
|
42
|
+
'{"type":"tool_call","toolName":"read_file","args":{"path":"package.json"}}',
|
|
43
|
+
'{"type":"ask_confirmation","message":"I need to overwrite README.md. Do you want me to continue?"}',
|
|
44
|
+
'{"type":"final","message":"I found the issue in src/main.ts and explained it."}',
|
|
45
|
+
].join("\n");
|
|
46
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|