tolingcode 2026.3.8 → 2026.3.10
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 +69 -101
- package/bin/tolingcode.js +141 -11
- package/docs/banner.png +0 -0
- package/docs/logo.png +0 -0
- package/package.json +11 -3
- package/QUICKSTART.md +0 -196
- package/scripts/publish-skill.ps1 +0 -74
- package/scripts/publish.bat +0 -30
- package/server/registry.js +0 -220
package/README.md
CHANGED
|
@@ -1,18 +1,22 @@
|
|
|
1
|
-
|
|
2
|
-
TolingCode
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="https://raw.githubusercontent.com/tolingcode/tolingcode/main/docs/logo.png" width="120" alt="TolingCode Logo">
|
|
3
|
+
</p>
|
|
4
|
+
<p align="center">
|
|
5
|
+
<img src="https://raw.githubusercontent.com/tolingcode/tolingcode/main/docs/banner.png" alt="TolingCode banner">
|
|
6
|
+
</p>
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+

|
|
10
|
+

|
|
11
|
+

|
|
11
12
|
|
|
13
|
+
# TolingCode CLI
|
|
12
14
|
|
|
15
|
+
**跨境电商私人 AI 助手** - 在个人设备上运行的本地化 AI 自动化工具 , tolingcode Skills完全兼容openclaw。
|
|
13
16
|
|
|
17
|
+
为跨境卖家提供订单履约、库存管理、产品刊登、广告管理、数据分析等核心业务能力。
|
|
14
18
|
|
|
15
|
-
|
|
19
|
+
---
|
|
16
20
|
|
|
17
21
|
## 安装
|
|
18
22
|
|
|
@@ -21,26 +25,26 @@ AI员工支持: 无缝对接openclaw,快速建立AI数字员工,完成订单
|
|
|
21
25
|
npm install -g tolingcode@latest
|
|
22
26
|
|
|
23
27
|
# 安装指定版本
|
|
24
|
-
npm install -g tolingcode@2026.03.
|
|
28
|
+
npm install -g tolingcode@2026.03.09
|
|
29
|
+
```
|
|
25
30
|
|
|
26
|
-
|
|
27
|
-
latest version 2026.03.08
|
|
31
|
+
**当前版本**: 2026.03.09
|
|
28
32
|
|
|
29
|
-
|
|
33
|
+
---
|
|
30
34
|
|
|
31
35
|
## 使用
|
|
32
36
|
|
|
33
37
|
### 安装技能 (Skill)
|
|
34
38
|
|
|
35
39
|
```bash
|
|
36
|
-
#
|
|
40
|
+
# 安装技能
|
|
37
41
|
tolingcode install skills weather
|
|
38
42
|
|
|
39
43
|
# 安装指定版本
|
|
40
|
-
tolingcode install skills weather -v 2026.03.
|
|
44
|
+
tolingcode install skills weather -v 2026.03.08
|
|
41
45
|
```
|
|
42
46
|
|
|
43
|
-
###
|
|
47
|
+
### 安装应用 (App)
|
|
44
48
|
|
|
45
49
|
```bash
|
|
46
50
|
# 安装到当前目录
|
|
@@ -50,121 +54,85 @@ tolingcode install apps myapp
|
|
|
50
54
|
tolingcode install apps myapp -g
|
|
51
55
|
```
|
|
52
56
|
|
|
53
|
-
###
|
|
57
|
+
### 查看和搜索
|
|
54
58
|
|
|
55
59
|
```bash
|
|
56
|
-
#
|
|
60
|
+
# 列出所有包
|
|
57
61
|
tolingcode list
|
|
58
62
|
|
|
59
63
|
# 只列出技能
|
|
60
64
|
tolingcode list skills
|
|
61
65
|
|
|
62
|
-
#
|
|
63
|
-
tolingcode
|
|
66
|
+
# 搜索技能 订单发货
|
|
67
|
+
tolingcode search order-fulfillment
|
|
64
68
|
```
|
|
65
69
|
|
|
66
|
-
|
|
70
|
+
---
|
|
67
71
|
|
|
68
|
-
|
|
69
|
-
tolingcode search weather
|
|
70
|
-
```
|
|
72
|
+
## 核心能力
|
|
71
73
|
|
|
72
|
-
###
|
|
74
|
+
### 电商平台技能
|
|
73
75
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
76
|
+
| 功能 | 描述 |
|
|
77
|
+
|------|------|
|
|
78
|
+
| 订单履约 | 自动处理订单发货 |
|
|
79
|
+
| 智能备货 | AI 预测库存 |
|
|
80
|
+
| 产品上架 | 自动发布商品 |
|
|
81
|
+
| 价格管理 | 修改产品价格 |
|
|
82
|
+
| 广告管理 | 自动调整广告 |
|
|
83
|
+
| 数据分析 | 获取平台报告 |
|
|
77
84
|
|
|
78
|
-
|
|
85
|
+
### 海外仓技能
|
|
79
86
|
|
|
80
|
-
|
|
87
|
+
| 功能 | 描述 |
|
|
88
|
+
|------|------|
|
|
89
|
+
| 实时库存 | 获取仓库库存 |
|
|
90
|
+
| 出入库单 | 查询入库/出库 |
|
|
91
|
+
| 创建出库单 | 创建订单出库 |
|
|
92
|
+
| LTL 出运 | 创建 LTL 运输单 |
|
|
93
|
+
| 运费查询 | 获取物流费用 |
|
|
81
94
|
|
|
82
|
-
|
|
83
|
-
- `latest` - 最新版本
|
|
95
|
+
### 物流技能
|
|
84
96
|
|
|
85
|
-
|
|
97
|
+
- 物流报价、创建面单、物流跟踪
|
|
98
|
+
- 支持:FedEx、UPS、DHL、Amazon Logistics、ITTRACK
|
|
86
99
|
|
|
87
|
-
|
|
88
|
-
# 自定义 registry 地址(默认:https://toling.me/api/registry)
|
|
89
|
-
export TOLINGCODE_REGISTRY=https://toling.me/api/registry
|
|
100
|
+
---
|
|
90
101
|
|
|
91
|
-
|
|
92
|
-
export OPENCLAW_WORKSPACE=/path/to/workspace
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
## 开发
|
|
102
|
+
## 发布技能 (开发者)
|
|
96
103
|
|
|
97
104
|
```bash
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
# 发布到 npm
|
|
104
|
-
npm version patch # 或 minor/major
|
|
105
|
-
npm publish
|
|
105
|
+
tolingcode publish ./my-skill \
|
|
106
|
+
--type skills \
|
|
107
|
+
--name my-skill \
|
|
108
|
+
--version 2026.03.09
|
|
106
109
|
```
|
|
107
110
|
|
|
108
|
-
|
|
111
|
+
### 版本规范
|
|
109
112
|
|
|
110
|
-
|
|
111
|
-
tolingcode/
|
|
112
|
-
├── bin/
|
|
113
|
-
│ └── tolingcode.js # CLI 入口
|
|
114
|
-
├── docs/
|
|
115
|
-
│ └── SERVER.md # 服务端部署文档
|
|
116
|
-
├── server/
|
|
117
|
-
│ └── registry.js # 服务端代码
|
|
118
|
-
├── scripts/
|
|
119
|
-
│ └── publish-skill.ps1 # 发布脚本
|
|
120
|
-
├── package.json
|
|
121
|
-
└── README.md
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
## 支持跨境平台
|
|
125
|
-
_** 电商平台和市场:**
|
|
126
|
-
亚马逊、eBay、阿里巴巴国际站、全球速卖通、Wish、Shopee、Lazada、Mercado Libre、Flipkart、Jumia、Wildberries、Ozon、Gmarket、
|
|
127
|
-
Auction、Coupang、Rakuten、Zalando、TikTok Shop、Temu、Shein、Pinduoduo、Etsy、Wayfair、Chewy、Newegg、Shopify、
|
|
128
|
-
BigCommerce、Magento、WooCommerce、敦煌网、京东全球售、Lowe's、The Home Depot、Walmart、Target、Best Buy、Costco、
|
|
129
|
-
Overstock、Otto、Fruugo、Allegro、ManoMano、Bol、Darty、Rue du Commerce、Cdiscount、Fnac、DHgate、Banggood、GeekBuying、
|
|
130
|
-
Vova、Poshmark、ThredUp、Mercari、Reverb、Houzz、1stDibs、Chairish、1mg、PharmEasy、Nykaa、Myntra、Ajio、Konga、Kilimall、
|
|
131
|
-
Takealot、Souq、Noon、Daraz、Tokopedia、Bukalapak、Blibli、Tiki、Sendo、Qoo10、11st、Gmarket Global、Cnova、El Corte Inglés、
|
|
132
|
-
Carrefour、Tesco、ASOS、Boohoo、Zalora、Linio、Privalia、Dafiti、Netshoes、Submarino、Americanas、Casas Bahia、Extra、
|
|
133
|
-
Magazine Luiza、ShopFully、eMAG、Kaufland、Real、MediaMarkt、Saturn、Conrad、B&Q、Screwfix、Homebase、Bunnings、Mitre 10、
|
|
134
|
-
Brico Dépôt、Leroy Merlin、Castorama、Hornbach、Bauhaus、Obi、Toom Baumarkt、Brico、ManoMano、Houzz、Porch、Build、
|
|
135
|
-
BuildDirect、Floor & Decor、Ferguson、Grainger、Fastenal、MSC Industrial、Zoro、SupplyNow、Ferguson、HD Supply、WhiteCap、
|
|
136
|
-
Sunbelt、United Rentals、Herc Rentals、BlueLine Rental、The Home Depot Pro、Lowe's For Pros、Build.com、BuildDirect、Houzz Pro、
|
|
137
|
-
Sweezy、Builders、Buildmate、Construction、Contractor、ProSupply、SupplyChain、Distribution
|
|
113
|
+
使用日期版本号:`YYYY.MM.DD`
|
|
138
114
|
|
|
115
|
+
---
|
|
139
116
|
|
|
140
|
-
|
|
141
|
-
1. 海外仓/跨境物流/货代类服务商
|
|
142
|
-
HDL 鸿运达、德合、中通、齐通、SHIPOUT、商盟、大豫宏志、Opener 开仓、远邦力、富力、天成、天铭、拓石、安天盛、无忧仓、方盛鼎、
|
|
143
|
-
天宏通、UBUY、宏聚、融贸、八爪鱼、顺、4Supply、ALING ALINO、ABM 大亿广仓、ATCAM、conwood、COSCO 中远海运、COGOLA、
|
|
144
|
-
ebuy 易趣、Xindong 鑫动力、GOODGOODS、ISW、KODA、Hollyaddy 霍莉、RJS、SPACEONE、SLM、SuperTek、Temuie、
|
|
145
|
-
WALMART WFS、WayfairCC、Pepco、USAVOY【USAVOY】全亚、【中通】国际、JDA、顺丰国际、MAERSK 上海马士基、W 中远海运、
|
|
146
|
-
中财、中通国际、中远、云驼、N++ 运通天下、安时达仓、斑马、JDL 京东物流、仓擎、仓搜、浩远、众汇、优创、华茂、华宜、华深、佳选、
|
|
147
|
-
百特、日邮、新顺电气、西润汇通、大森林、众诚达、天地华宇、天驰通、宇森、安文、京惠、快快、景程国际、荣迅国际、乐仓、黑河、文腾、
|
|
148
|
-
斑马、RMS 红鼠、仓乐、雅迅、浩方、海程、西诺、易诚、海珠、海腾、瑞元、环世、开仓、奥玛尼、美加美、美设、新希望、美天、速通国际、
|
|
149
|
-
环世、浩方、RMS 红鼠、美加美、美设、新希望、美天、SF 顺丰国际、风迪、驼铃、美邮
|
|
117
|
+
## 支持平台
|
|
150
118
|
|
|
151
|
-
|
|
152
|
-
FedEx、UPS、ITTRACK、亚马逊物流、DHL
|
|
119
|
+
**电商平台**: Amazon、eBay、AliExpress、Wish、Shopee、Lazada、Mercado Libre、Etsy、Wayfair、TikTok Shop 等
|
|
153
120
|
|
|
121
|
+
**独立站**: Shopify、WooCommerce、Magento、BigCommerce
|
|
154
122
|
|
|
123
|
+
**零售平台**: Walmart、Target、Costco、Best Buy 等
|
|
155
124
|
|
|
125
|
+
**海外仓**: 支持 100+ 海外仓系统 (中通国际、Walmart WFS、马士基、RMS 红鼠等)
|
|
156
126
|
|
|
127
|
+
---
|
|
157
128
|
|
|
158
129
|
## 相关链接
|
|
159
130
|
|
|
160
|
-
- **Registry
|
|
161
|
-
-
|
|
162
|
-
- **问题反馈**: GitHub Issues
|
|
163
|
-
|
|
164
|
-
## 作者
|
|
165
|
-
|
|
166
|
-
韩宝军 (TolingCode)
|
|
131
|
+
- **Registry**: https://toling.me
|
|
132
|
+
- **GitHub**: https://github.com/tolingcode/tolingcode
|
|
133
|
+
- **问题反馈**: GitHub Issues
|
|
167
134
|
|
|
168
|
-
|
|
135
|
+
---
|
|
169
136
|
|
|
170
|
-
|
|
137
|
+
**作者**: 韩宝军 (TolingCode)
|
|
138
|
+
**License**: MIT
|
package/bin/tolingcode.js
CHANGED
|
@@ -16,15 +16,61 @@ const REGISTRY_URL = process.env.TOLINGCODE_REGISTRY || 'https://toling.me/api/r
|
|
|
16
16
|
|
|
17
17
|
program
|
|
18
18
|
.name('tolingcode')
|
|
19
|
-
.description(
|
|
20
|
-
|
|
19
|
+
.description(`TolingCode CLI - 跨境电商 AI 助手技能管理工具
|
|
20
|
+
|
|
21
|
+
${chalk.bold('功能特性:')}
|
|
22
|
+
• 安装/更新技能 - 从 toling.me registry 安装技能
|
|
23
|
+
• 搜索技能 - 查找可用的技能包
|
|
24
|
+
• 列出技能 - 查看已安装或可用的技能
|
|
25
|
+
• 发布技能 - 发布自定义技能到 registry
|
|
26
|
+
|
|
27
|
+
${chalk.bold('适用场景:')}
|
|
28
|
+
• 跨境电商订单处理
|
|
29
|
+
• 海外仓库存管理
|
|
30
|
+
• 物流跟踪
|
|
31
|
+
• AI 产品优化
|
|
32
|
+
• 自动化运维
|
|
33
|
+
|
|
34
|
+
${chalk.bold('快速开始:')}
|
|
35
|
+
$ tolingcode install skills gigacloud-warehouse # 安装大健云仓技能
|
|
36
|
+
$ tolingcode install skills order-fulfillment # 安装订单履约技能
|
|
37
|
+
$ tolingcode search 电商 # 搜索电商相关技能`)
|
|
38
|
+
.version(pkg.version, '-v, --version', '显示版本号');
|
|
21
39
|
|
|
22
40
|
// install command
|
|
23
41
|
program
|
|
24
42
|
.command('install <type> <name>')
|
|
25
|
-
.description(
|
|
26
|
-
|
|
27
|
-
|
|
43
|
+
.description(`安装技能或应用
|
|
44
|
+
|
|
45
|
+
${chalk.bold('参数:')}
|
|
46
|
+
type 类型:skills | apps
|
|
47
|
+
name 技能/应用名称
|
|
48
|
+
|
|
49
|
+
${chalk.bold('选项:')}
|
|
50
|
+
-v, --version 指定版本 (默认:latest)
|
|
51
|
+
-g, --global 全局安装 (仅 apps)
|
|
52
|
+
|
|
53
|
+
${chalk.bold('示例:')}
|
|
54
|
+
${chalk.gray('# 安装大健云仓技能(跨境电商 B2B 分销)')}
|
|
55
|
+
$ tolingcode install skills gigacloud-warehouse
|
|
56
|
+
|
|
57
|
+
${chalk.gray('# 安装订单履约技能')}
|
|
58
|
+
$ tolingcode install skills order-fulfillment
|
|
59
|
+
|
|
60
|
+
${chalk.gray('# 安装指定版本的技能')}
|
|
61
|
+
$ tolingcode install skills weather -v 2026.3.8
|
|
62
|
+
|
|
63
|
+
${chalk.gray('# 全局安装应用')}
|
|
64
|
+
$ tolingcode install apps myapp -g
|
|
65
|
+
|
|
66
|
+
${chalk.gray('# 安装到当前目录')}
|
|
67
|
+
$ tolingcode install apps myapp
|
|
68
|
+
|
|
69
|
+
${chalk.bold('安装后:')}
|
|
70
|
+
重启 OpenClaw Gateway 以加载新技能
|
|
71
|
+
$ openclaw gateway restart`)
|
|
72
|
+
.option('-v, --version <version>', '指定版本 (例如:2026.3.8 或 latest)')
|
|
73
|
+
.option('-g, --global', '全局安装 (仅用于 apps)')
|
|
28
74
|
.action(async (type, name, options) => {
|
|
29
75
|
const version = options.version || 'latest';
|
|
30
76
|
|
|
@@ -114,7 +160,28 @@ program
|
|
|
114
160
|
// list command - list available skills/apps
|
|
115
161
|
program
|
|
116
162
|
.command('list [type]')
|
|
117
|
-
.description(
|
|
163
|
+
.description(`列出可用的技能或应用
|
|
164
|
+
|
|
165
|
+
${chalk.bold('参数:')}
|
|
166
|
+
type 类型:skills | apps | all (可选)
|
|
167
|
+
|
|
168
|
+
${chalk.bold('示例:')}
|
|
169
|
+
${chalk.gray('# 列出所有技能')}
|
|
170
|
+
$ tolingcode list skills
|
|
171
|
+
|
|
172
|
+
${chalk.gray('# 列出所有应用')}
|
|
173
|
+
$ tolingcode list apps
|
|
174
|
+
|
|
175
|
+
${chalk.gray('# 列出所有包')}
|
|
176
|
+
$ tolingcode list
|
|
177
|
+
$ tolingcode list all
|
|
178
|
+
|
|
179
|
+
${chalk.bold('可用技能:')}
|
|
180
|
+
• gigacloud-warehouse - 大健云仓(跨境电商 B2B 分销)
|
|
181
|
+
• order-fulfillment - 订单履约管理
|
|
182
|
+
• hbj-ai-shell - 远程 Linux 运维
|
|
183
|
+
• imap-smtp-email - 邮件收发
|
|
184
|
+
• weather - 天气查询`)
|
|
118
185
|
.action(async (type) => {
|
|
119
186
|
console.log(chalk.blue('\n📦 Available packages:\n'));
|
|
120
187
|
|
|
@@ -160,7 +227,31 @@ program
|
|
|
160
227
|
// search command
|
|
161
228
|
program
|
|
162
229
|
.command('search <query>')
|
|
163
|
-
.description(
|
|
230
|
+
.description(`搜索技能或应用
|
|
231
|
+
|
|
232
|
+
${chalk.bold('参数:')}
|
|
233
|
+
query 搜索关键词(支持中文)
|
|
234
|
+
|
|
235
|
+
${chalk.bold('示例:')}
|
|
236
|
+
${chalk.gray('# 搜索电商相关技能')}
|
|
237
|
+
$ tolingcode search 电商
|
|
238
|
+
|
|
239
|
+
${chalk.gray('# 搜索物流相关技能')}
|
|
240
|
+
$ tolingcode search 物流
|
|
241
|
+
|
|
242
|
+
${chalk.gray('# 搜索大健云仓')}
|
|
243
|
+
$ tolingcode search gigacloud
|
|
244
|
+
|
|
245
|
+
${chalk.gray('# 搜索订单处理')}
|
|
246
|
+
$ tolingcode search order
|
|
247
|
+
|
|
248
|
+
${chalk.gray('# 搜索 AI 相关')}
|
|
249
|
+
$ tolingcode search AI
|
|
250
|
+
|
|
251
|
+
${chalk.bold('搜索范围:')}
|
|
252
|
+
• 技能名称
|
|
253
|
+
• 技能描述
|
|
254
|
+
• 关键词标签`)
|
|
164
255
|
.action(async (query) => {
|
|
165
256
|
console.log(chalk.blue(`\n🔍 Searching for: ${query}\n`));
|
|
166
257
|
|
|
@@ -189,10 +280,49 @@ program
|
|
|
189
280
|
// publish command - for publishing skills/apps to registry
|
|
190
281
|
program
|
|
191
282
|
.command('publish <path>')
|
|
192
|
-
.description(
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
283
|
+
.description(`发布技能或应用到 registry
|
|
284
|
+
|
|
285
|
+
${chalk.bold('参数:')}
|
|
286
|
+
path 技能/应用目录路径
|
|
287
|
+
|
|
288
|
+
${chalk.bold('选项:')}
|
|
289
|
+
--type 类型:skills | apps (默认:skills)
|
|
290
|
+
--name 包名称(默认:从 package.json 读取)
|
|
291
|
+
--version 版本号(默认:从 package.json 读取)
|
|
292
|
+
|
|
293
|
+
${chalk.bold('示例:')}
|
|
294
|
+
${chalk.gray('# 发布大健云仓技能')}
|
|
295
|
+
$ tolingcode publish ./skills/gigacloud-warehouse \\
|
|
296
|
+
--type skills \\
|
|
297
|
+
--name gigacloud-warehouse \\
|
|
298
|
+
--version 2026.3.8
|
|
299
|
+
|
|
300
|
+
${chalk.gray('# 发布订单履约技能')}
|
|
301
|
+
$ tolingcode publish ./skills/order-fulfillment \\
|
|
302
|
+
--type skills \\
|
|
303
|
+
--name order-fulfillment
|
|
304
|
+
|
|
305
|
+
${chalk.gray('# 发布应用')}
|
|
306
|
+
$ tolingcode publish ./apps/myapp --type apps
|
|
307
|
+
|
|
308
|
+
${chalk.gray('# 使用 PowerShell 发布')}
|
|
309
|
+
PS> tolingcode publish .\\skills\\gigacloud-warehouse --type skills --name gigacloud-warehouse --version 2026.3.8
|
|
310
|
+
|
|
311
|
+
${chalk.bold('发布流程:')}
|
|
312
|
+
1. 打包技能目录为 .tar.gz
|
|
313
|
+
2. 上传到 toling.me registry 服务器
|
|
314
|
+
3. 更新 registry.json 索引
|
|
315
|
+
4. 其他用户可以安装
|
|
316
|
+
|
|
317
|
+
${chalk.bold('技能结构要求:')}
|
|
318
|
+
skill-name/
|
|
319
|
+
├── SKILL.md # 必需,含 YAML 头
|
|
320
|
+
├── package.json # 必需
|
|
321
|
+
├── index.js # 推荐
|
|
322
|
+
└── ...`)
|
|
323
|
+
.option('--type <type>', '包类型 (skills 或 apps)', 'skills')
|
|
324
|
+
.option('--name <name>', '包名称')
|
|
325
|
+
.option('--version <version>', '包版本号')
|
|
196
326
|
.action(async (pkgPath, options) => {
|
|
197
327
|
const absPath = path.resolve(pkgPath);
|
|
198
328
|
|
package/docs/banner.png
ADDED
|
Binary file
|
package/docs/logo.png
ADDED
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tolingcode",
|
|
3
|
-
"version": "2026.
|
|
3
|
+
"version": "2026.3.10",
|
|
4
4
|
"description": "TolingCode CLI - Install skills and apps from toling.me",
|
|
5
5
|
"main": "bin/tolingcode.js",
|
|
6
|
+
"files": [
|
|
7
|
+
"bin",
|
|
8
|
+
"docs",
|
|
9
|
+
"README.md"
|
|
10
|
+
],
|
|
6
11
|
"bin": {
|
|
7
12
|
"tolingcode": "bin/tolingcode.js",
|
|
8
13
|
"tlc": "bin/tolingcode.js"
|
|
@@ -16,10 +21,13 @@
|
|
|
16
21
|
"author": "TolingCode",
|
|
17
22
|
"license": "MIT",
|
|
18
23
|
"dependencies": {
|
|
19
|
-
"
|
|
24
|
+
"axios": "^1.6.0",
|
|
20
25
|
"chalk": "^4.1.2",
|
|
26
|
+
"commander": "^11.0.0",
|
|
27
|
+
"cors": "^2.8.6",
|
|
28
|
+
"express": "^5.2.1",
|
|
29
|
+
"multer": "^2.1.1",
|
|
21
30
|
"ora": "^5.4.1",
|
|
22
|
-
"axios": "^1.6.0",
|
|
23
31
|
"tar": "^6.2.0"
|
|
24
32
|
},
|
|
25
33
|
"engines": {
|
package/QUICKSTART.md
DELETED
|
@@ -1,196 +0,0 @@
|
|
|
1
|
-
# TolingCode 快速开始指南
|
|
2
|
-
|
|
3
|
-
## 🎯 目标
|
|
4
|
-
|
|
5
|
-
创建一个类似 `clawhub` 的 CLI 工具,通过 `toling.me` 托管和分发 skills 和 apps。
|
|
6
|
-
|
|
7
|
-
## 📦 使用流程
|
|
8
|
-
|
|
9
|
-
### 1. 用户安装 CLI
|
|
10
|
-
|
|
11
|
-
```bash
|
|
12
|
-
npm install -g tolingcode@latest
|
|
13
|
-
# 或指定版本
|
|
14
|
-
npm install -g tolingcode@2026.03.06
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
### 2. 用户安装 Skill
|
|
18
|
-
|
|
19
|
-
```bash
|
|
20
|
-
tolingcode install skills weather
|
|
21
|
-
tolingcode install skills weather -v 2026.03.06
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
### 3. 开发者发布 Skill
|
|
25
|
-
|
|
26
|
-
```bash
|
|
27
|
-
# 方法 1: 使用 publish 命令(需要 API 支持)
|
|
28
|
-
tolingcode publish ./my-skill --type skills --name my-skill --version 2026.03.06
|
|
29
|
-
|
|
30
|
-
# 方法 2: 手动上传
|
|
31
|
-
tar -czf my-skill-2026.03.06.tar.gz -C ./my-skill .
|
|
32
|
-
scp my-skill-2026.03.06.tar.gz user@toling.me:/var/www/toling.me/packages/skills/
|
|
33
|
-
# 然后更新 registry.json
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
## 🚀 部署步骤
|
|
37
|
-
|
|
38
|
-
### 第一步:准备 toling.me 服务器
|
|
39
|
-
|
|
40
|
-
```bash
|
|
41
|
-
# SSH 登录服务器
|
|
42
|
-
ssh user@toling.me
|
|
43
|
-
|
|
44
|
-
# 创建目录
|
|
45
|
-
sudo mkdir -p /var/www/toling.me/{packages/skills,packages/apps,api}
|
|
46
|
-
sudo chown -R $USER:$USER /var/www/toling.me
|
|
47
|
-
|
|
48
|
-
# 安装 Node.js (如果没有)
|
|
49
|
-
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
|
|
50
|
-
sudo apt-get install -y nodejs
|
|
51
|
-
|
|
52
|
-
# 安装依赖
|
|
53
|
-
cd /var/www/toling.me/api
|
|
54
|
-
npm init -y
|
|
55
|
-
npm install express multer
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
### 第二步:部署服务端代码
|
|
59
|
-
|
|
60
|
-
```bash
|
|
61
|
-
# 上传 registry.js 到服务器
|
|
62
|
-
scp registry.js user@toling.me:/var/www/toling.me/api/
|
|
63
|
-
|
|
64
|
-
# 创建 systemd 服务
|
|
65
|
-
sudo tee /etc/systemd/system/tolingcode-registry.service > /dev/null <<EOF
|
|
66
|
-
[Unit]
|
|
67
|
-
Description=TolingCode Registry Server
|
|
68
|
-
After=network.target
|
|
69
|
-
|
|
70
|
-
[Service]
|
|
71
|
-
Type=simple
|
|
72
|
-
User=www-data
|
|
73
|
-
WorkingDirectory=/var/www/toling.me/api
|
|
74
|
-
ExecStart=/usr/bin/node registry.js
|
|
75
|
-
Restart=on-failure
|
|
76
|
-
|
|
77
|
-
[Install]
|
|
78
|
-
WantedBy=multi-user.target
|
|
79
|
-
EOF
|
|
80
|
-
|
|
81
|
-
# 启动服务
|
|
82
|
-
sudo systemctl daemon-reload
|
|
83
|
-
sudo systemctl enable tolingcode-registry
|
|
84
|
-
sudo systemctl start tolingcode-registry
|
|
85
|
-
sudo systemctl status tolingcode-registry
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
### 第三步:配置 Nginx
|
|
89
|
-
|
|
90
|
-
```bash
|
|
91
|
-
# 编辑 Nginx 配置
|
|
92
|
-
sudo nano /etc/nginx/sites-available/toling.me
|
|
93
|
-
|
|
94
|
-
# 添加以下内容:
|
|
95
|
-
server {
|
|
96
|
-
listen 443 ssl;
|
|
97
|
-
server_name toling.me;
|
|
98
|
-
|
|
99
|
-
ssl_certificate /etc/letsencrypt/live/toling.me/fullchain.pem;
|
|
100
|
-
ssl_certificate_key /etc/letsencrypt/live/toling.me/privkey.pem;
|
|
101
|
-
|
|
102
|
-
root /var/www/toling.me;
|
|
103
|
-
|
|
104
|
-
# API
|
|
105
|
-
location /api/ {
|
|
106
|
-
proxy_pass http://localhost:3000;
|
|
107
|
-
proxy_set_header Host $host;
|
|
108
|
-
proxy_set_header X-Real-IP $remote_addr;
|
|
109
|
-
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
# Packages
|
|
113
|
-
location /packages/ {
|
|
114
|
-
alias /var/www/toling.me/packages/;
|
|
115
|
-
autoindex on;
|
|
116
|
-
add_header Content-Type application/octet-stream;
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
# 测试并重载
|
|
121
|
-
sudo nginx -t
|
|
122
|
-
sudo systemctl reload nginx
|
|
123
|
-
```
|
|
124
|
-
|
|
125
|
-
### 第四步:发布 CLI 到 npm
|
|
126
|
-
|
|
127
|
-
```bash
|
|
128
|
-
# 在本地开发机器上
|
|
129
|
-
cd tolingcode
|
|
130
|
-
|
|
131
|
-
# 登录 npm
|
|
132
|
-
npm login
|
|
133
|
-
|
|
134
|
-
# 发布
|
|
135
|
-
npm version 1.0.0
|
|
136
|
-
npm publish
|
|
137
|
-
|
|
138
|
-
# 验证
|
|
139
|
-
npm view tolingcode
|
|
140
|
-
```
|
|
141
|
-
|
|
142
|
-
### 第五步:发布第一个 Skill
|
|
143
|
-
|
|
144
|
-
```bash
|
|
145
|
-
# 创建测试 skill
|
|
146
|
-
mkdir -p test-skill
|
|
147
|
-
echo '{"name": "test", "description": "Test skill"}' > test-skill/SKILL.md
|
|
148
|
-
|
|
149
|
-
# 发布
|
|
150
|
-
cd tolingcode
|
|
151
|
-
node bin/tolingcode.js publish ../test-skill --type skills --name test-skill --version 2026.03.06
|
|
152
|
-
|
|
153
|
-
# 或者手动上传
|
|
154
|
-
tar -czf test-skill-2026.03.06.tar.gz -C ../test-skill .
|
|
155
|
-
scp test-skill-2026.03.06.tar.gz user@toling.me:/var/www/toling.me/packages/skills/
|
|
156
|
-
|
|
157
|
-
# 更新 registry.json (SSH 到服务器编辑)
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
## ✅ 测试
|
|
161
|
-
|
|
162
|
-
```bash
|
|
163
|
-
# 安装 CLI
|
|
164
|
-
npm install -g tolingcode@latest
|
|
165
|
-
|
|
166
|
-
# 列出可用技能
|
|
167
|
-
tolingcode list skills
|
|
168
|
-
|
|
169
|
-
# 安装技能
|
|
170
|
-
tolingcode install skills test-skill
|
|
171
|
-
|
|
172
|
-
# 验证安装
|
|
173
|
-
ls ~/.openclaw/workspace/skills/
|
|
174
|
-
```
|
|
175
|
-
|
|
176
|
-
## 📝 注意事项
|
|
177
|
-
|
|
178
|
-
1. **版本命名**: 使用 `YYYY.MM.DD` 格式,便于追踪发布日期
|
|
179
|
-
2. **认证**: 生产环境需要添加 API 认证(API Key 或 JWT)
|
|
180
|
-
3. **HTTPS**: 确保 toling.me 配置了 SSL 证书
|
|
181
|
-
4. **备份**: 定期备份 registry.json 和 packages 目录
|
|
182
|
-
5. **监控**: 添加日志和监控,跟踪下载量和错误
|
|
183
|
-
|
|
184
|
-
## 🔧 后续扩展
|
|
185
|
-
|
|
186
|
-
- [ ] 添加用户认证系统
|
|
187
|
-
- [ ] 支持私有包(需要 token)
|
|
188
|
-
- [ ] 添加下载统计
|
|
189
|
-
- [ ] Web 管理界面
|
|
190
|
-
- [ ] 自动版本递增
|
|
191
|
-
- [ ] 依赖管理
|
|
192
|
-
- [ ] 包签名验证
|
|
193
|
-
|
|
194
|
-
---
|
|
195
|
-
|
|
196
|
-
有问题?查看 `docs/SERVER.md` 获取详细服务端文档。
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env pwsh
|
|
2
|
-
# TolingCode Skill Publish Script (PowerShell)
|
|
3
|
-
# Usage: .\publish-skill.ps1 <skill-name> [version]
|
|
4
|
-
|
|
5
|
-
param(
|
|
6
|
-
[Parameter(Mandatory=$true)]
|
|
7
|
-
[string]$SkillName,
|
|
8
|
-
|
|
9
|
-
[string]$Version = (Get-Date -Format "yyyy.MM.dd"),
|
|
10
|
-
|
|
11
|
-
[string]$ServerHost = "iZwz91qi4kjnj5l58gbhj5Z",
|
|
12
|
-
[string]$ServerUser = "root",
|
|
13
|
-
[string]$SkillSource = "C:\Users\Administrator\.openclaw\workspace\skills"
|
|
14
|
-
)
|
|
15
|
-
|
|
16
|
-
Write-Host "📦 Publishing $SkillName@$Version" -ForegroundColor Blue
|
|
17
|
-
Write-Host ""
|
|
18
|
-
|
|
19
|
-
# 1. Check source exists
|
|
20
|
-
$sourcePath = Join-Path $SkillSource $SkillName
|
|
21
|
-
if (!(Test-Path $sourcePath)) {
|
|
22
|
-
Write-Host "❌ Skill not found: $sourcePath" -ForegroundColor Red
|
|
23
|
-
exit 1
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
Write-Host "✓ Source: $sourcePath" -ForegroundColor Green
|
|
27
|
-
|
|
28
|
-
# 2. Create tar.gz
|
|
29
|
-
$tarFile = "$SkillName-$Version.tar.gz"
|
|
30
|
-
Write-Host "📦 Creating $tarFile..." -ForegroundColor Yellow
|
|
31
|
-
tar -czf $tarFile -C $SkillSource $SkillName
|
|
32
|
-
|
|
33
|
-
if (!(Test-Path $tarFile)) {
|
|
34
|
-
Write-Host "❌ Failed to create tarball" -ForegroundColor Red
|
|
35
|
-
exit 1
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
Write-Host "✓ Created: $tarFile ($(Get-Item $tarFile).Length bytes)" -ForegroundColor Green
|
|
39
|
-
|
|
40
|
-
# 3. Upload to server
|
|
41
|
-
Write-Host "📤 Uploading to server..." -ForegroundColor Yellow
|
|
42
|
-
scp $tarFile "${ServerUser}@${ServerHost}:/var/www/toling.me/packages/skills/"
|
|
43
|
-
|
|
44
|
-
if ($LASTEXITCODE -ne 0) {
|
|
45
|
-
Write-Host "❌ Upload failed" -ForegroundColor Red
|
|
46
|
-
exit 1
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
Write-Host "✓ Uploaded to /var/www/toling.me/packages/skills/" -ForegroundColor Green
|
|
50
|
-
Write-Host ""
|
|
51
|
-
Write-Host "📝 Next step: Update registry.json on server" -ForegroundColor Yellow
|
|
52
|
-
Write-Host ""
|
|
53
|
-
Write-Host "SSH to server and run:" -ForegroundColor Gray
|
|
54
|
-
Write-Host @"
|
|
55
|
-
cat >> /var/www/toling.me/registry.json << 'EOF'
|
|
56
|
-
{
|
|
57
|
-
"skills": {
|
|
58
|
-
"$SkillName": {
|
|
59
|
-
"description": "$SkillName skill",
|
|
60
|
-
"latestVersion": "$Version",
|
|
61
|
-
"versions": {
|
|
62
|
-
"$Version": {
|
|
63
|
-
"publishedAt": "$(Get-Date -Format "yyyy-MM-ddTHH:mm:ssZ")"
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
},
|
|
68
|
-
"apps": {}
|
|
69
|
-
}
|
|
70
|
-
EOF
|
|
71
|
-
"@
|
|
72
|
-
|
|
73
|
-
Write-Host ""
|
|
74
|
-
Write-Host "🎉 Done!" -ForegroundColor Green
|
package/scripts/publish.bat
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
@echo off
|
|
2
|
-
REM TolingCode Publish Script (Windows)
|
|
3
|
-
REM Usage: publish.bat <skill-path> <name> [version]
|
|
4
|
-
|
|
5
|
-
SET SKILL_PATH=%1
|
|
6
|
-
SET NAME=%2
|
|
7
|
-
SET VERSION=%3
|
|
8
|
-
|
|
9
|
-
IF "%VERSION%"=="" (
|
|
10
|
-
REM Use today's date as version
|
|
11
|
-
FOR /F "tokens=2-4 delims=/ " %%A IN ('date /T') DO (SET VERSION=%%C.%%B.%%A)
|
|
12
|
-
)
|
|
13
|
-
|
|
14
|
-
ECHO Publishing %NAME%@%VERSION%...
|
|
15
|
-
|
|
16
|
-
REM Create tarball (requires tar.exe on Windows 10+)
|
|
17
|
-
tar -czf %NAME%-%VERSION%.tar.gz -C %SKILL_PATH% .
|
|
18
|
-
|
|
19
|
-
ECHO Created: %NAME%-%VERSION%.tar.gz
|
|
20
|
-
ECHO.
|
|
21
|
-
ECHO Next steps:
|
|
22
|
-
ECHO 1. Upload to toling.me: scp %NAME%-%VERSION%.tar.gz user@toling.me:/var/www/toling.me/packages/skills/
|
|
23
|
-
ECHO 2. Update registry.json on server
|
|
24
|
-
ECHO.
|
|
25
|
-
ECHO Or use the API (when implemented):
|
|
26
|
-
ECHO curl -X POST https://toling.me/api/registry/publish ^
|
|
27
|
-
ECHO -F "type=skills" ^
|
|
28
|
-
ECHO -F "name=%NAME%" ^
|
|
29
|
-
ECHO -F "version=%VERSION%" ^
|
|
30
|
-
ECHO -F "package=@%NAME%-%VERSION%.tar.gz"
|
package/server/registry.js
DELETED
|
@@ -1,220 +0,0 @@
|
|
|
1
|
-
// TolingCode Registry Server - Simple Node.js Implementation
|
|
2
|
-
// Deploy this on toling.me
|
|
3
|
-
|
|
4
|
-
const express = require('express');
|
|
5
|
-
const fs = require('fs');
|
|
6
|
-
const path = require('path');
|
|
7
|
-
const multer = require('multer');
|
|
8
|
-
const crypto = require('crypto');
|
|
9
|
-
|
|
10
|
-
const app = express();
|
|
11
|
-
const PORT = process.env.PORT || 3000;
|
|
12
|
-
|
|
13
|
-
// Paths
|
|
14
|
-
const BASE_DIR = process.env.REGISTRY_BASE_DIR || '/var/www/toling.me';
|
|
15
|
-
const REGISTRY_FILE = path.join(BASE_DIR, 'registry.json');
|
|
16
|
-
const PACKAGES_DIR = path.join(BASE_DIR, 'packages');
|
|
17
|
-
|
|
18
|
-
// Ensure directories exist
|
|
19
|
-
if (!fs.existsSync(PACKAGES_DIR)) {
|
|
20
|
-
fs.mkdirSync(path.join(PACKAGES_DIR, 'skills'), { recursive: true });
|
|
21
|
-
fs.mkdirSync(path.join(PACKAGES_DIR, 'apps'), { recursive: true });
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
// Initialize registry if not exists
|
|
25
|
-
if (!fs.existsSync(REGISTRY_FILE)) {
|
|
26
|
-
fs.writeFileSync(REGISTRY_FILE, JSON.stringify({ skills: {}, apps: {} }, null, 2));
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
// Middleware
|
|
30
|
-
app.use(express.json());
|
|
31
|
-
const upload = multer({ dest: path.join(BASE_DIR, 'uploads') });
|
|
32
|
-
|
|
33
|
-
// Helper: Read registry
|
|
34
|
-
function getRegistry() {
|
|
35
|
-
return JSON.parse(fs.readFileSync(REGISTRY_FILE, 'utf-8'));
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
// Helper: Write registry
|
|
39
|
-
function saveRegistry(data) {
|
|
40
|
-
fs.writeFileSync(REGISTRY_FILE, JSON.stringify(data, null, 2));
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// Helper: Calculate file hash
|
|
44
|
-
function hashFile(filePath) {
|
|
45
|
-
const content = fs.readFileSync(filePath);
|
|
46
|
-
return crypto.createHash('sha256').update(content).digest('hex');
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// GET /api/registry/:type/:name - Get package info
|
|
50
|
-
app.get('/api/registry/:type/:name', (req, res) => {
|
|
51
|
-
const { type, name } = req.params;
|
|
52
|
-
const { version = 'latest' } = req.query;
|
|
53
|
-
|
|
54
|
-
if (!['skills', 'apps'].includes(type)) {
|
|
55
|
-
return res.status(400).json({ error: 'Invalid type. Use "skills" or "apps"' });
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
const registry = getRegistry();
|
|
59
|
-
const pkg = registry[type]?.[name];
|
|
60
|
-
|
|
61
|
-
if (!pkg) {
|
|
62
|
-
return res.status(404).json({ error: `Package ${name} not found` });
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
const ver = version === 'latest' ? pkg.latestVersion : version;
|
|
66
|
-
const verInfo = pkg.versions?.[ver];
|
|
67
|
-
|
|
68
|
-
if (!verInfo) {
|
|
69
|
-
return res.status(404).json({ error: `Version ${ver} not found` });
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
res.json({
|
|
73
|
-
name,
|
|
74
|
-
type,
|
|
75
|
-
version: ver,
|
|
76
|
-
description: pkg.description || '',
|
|
77
|
-
downloadUrl: `https://toling.me/packages/${type}/${name}-${ver}.tar.gz`,
|
|
78
|
-
latestVersion: pkg.latestVersion,
|
|
79
|
-
versions: Object.keys(pkg.versions || {}).sort().reverse()
|
|
80
|
-
});
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
// GET /api/registry/list - List all packages
|
|
84
|
-
app.get('/api/registry/list', (req, res) => {
|
|
85
|
-
const { type = 'all' } = req.query;
|
|
86
|
-
const registry = getRegistry();
|
|
87
|
-
const result = [];
|
|
88
|
-
|
|
89
|
-
const types = type === 'all' ? ['skills', 'apps'] : [type];
|
|
90
|
-
|
|
91
|
-
types.forEach(t => {
|
|
92
|
-
if (registry[t]) {
|
|
93
|
-
Object.entries(registry[t]).forEach(([name, pkg]) => {
|
|
94
|
-
result.push({
|
|
95
|
-
name,
|
|
96
|
-
type: t,
|
|
97
|
-
version: pkg.latestVersion,
|
|
98
|
-
description: pkg.description || '',
|
|
99
|
-
latestVersion: pkg.latestVersion
|
|
100
|
-
});
|
|
101
|
-
});
|
|
102
|
-
}
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
res.json(result);
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
// GET /api/registry/search - Search packages
|
|
109
|
-
app.get('/api/registry/search', (req, res) => {
|
|
110
|
-
const { q } = req.query;
|
|
111
|
-
if (!q) {
|
|
112
|
-
return res.status(400).json({ error: 'Query parameter "q" is required' });
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
const registry = getRegistry();
|
|
116
|
-
const result = [];
|
|
117
|
-
const query = q.toLowerCase();
|
|
118
|
-
|
|
119
|
-
['skills', 'apps'].forEach(type => {
|
|
120
|
-
if (registry[type]) {
|
|
121
|
-
Object.entries(registry[type]).forEach(([name, pkg]) => {
|
|
122
|
-
if (name.toLowerCase().includes(query) ||
|
|
123
|
-
(pkg.description && pkg.description.toLowerCase().includes(query))) {
|
|
124
|
-
result.push({
|
|
125
|
-
name,
|
|
126
|
-
type,
|
|
127
|
-
version: pkg.latestVersion,
|
|
128
|
-
description: pkg.description || ''
|
|
129
|
-
});
|
|
130
|
-
}
|
|
131
|
-
});
|
|
132
|
-
}
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
res.json(result);
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
// POST /api/registry/publish - Publish a package (requires auth)
|
|
139
|
-
app.post('/api/registry/publish', upload.single('package'), (req, res) => {
|
|
140
|
-
// TODO: Add authentication (API key, JWT, etc.)
|
|
141
|
-
const { type, name, version } = req.body;
|
|
142
|
-
|
|
143
|
-
if (!type || !name || !version) {
|
|
144
|
-
return res.status(400).json({ error: 'Missing required fields: type, name, version' });
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
if (!['skills', 'apps'].includes(type)) {
|
|
148
|
-
return res.status(400).json({ error: 'Invalid type. Use "skills" or "apps"' });
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
if (!req.file) {
|
|
152
|
-
return res.status(400).json({ error: 'No package file uploaded' });
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
const registry = getRegistry();
|
|
156
|
-
|
|
157
|
-
// Initialize type if not exists
|
|
158
|
-
if (!registry[type]) {
|
|
159
|
-
registry[type] = {};
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
// Initialize package if not exists
|
|
163
|
-
if (!registry[type][name]) {
|
|
164
|
-
registry[type][name] = {
|
|
165
|
-
description: req.body.description || '',
|
|
166
|
-
latestVersion: version,
|
|
167
|
-
versions: {}
|
|
168
|
-
};
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
// Add version
|
|
172
|
-
const fileHash = hashFile(req.file.path);
|
|
173
|
-
registry[type][name].versions[version] = {
|
|
174
|
-
publishedAt: new Date().toISOString(),
|
|
175
|
-
hash: `sha256:${fileHash}`,
|
|
176
|
-
size: req.file.size
|
|
177
|
-
};
|
|
178
|
-
|
|
179
|
-
// Update latest version
|
|
180
|
-
registry[type][name].latestVersion = version;
|
|
181
|
-
|
|
182
|
-
// Move file to packages directory
|
|
183
|
-
const destDir = path.join(PACKAGES_DIR, type);
|
|
184
|
-
const destFile = path.join(destDir, `${name}-${version}.tar.gz`);
|
|
185
|
-
|
|
186
|
-
if (!fs.existsSync(destDir)) {
|
|
187
|
-
fs.mkdirSync(destDir, { recursive: true });
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
fs.renameSync(req.file.path, destFile);
|
|
191
|
-
|
|
192
|
-
// Save registry
|
|
193
|
-
saveRegistry(registry);
|
|
194
|
-
|
|
195
|
-
// Cleanup uploads dir
|
|
196
|
-
try {
|
|
197
|
-
fs.unlinkSync(req.file.path);
|
|
198
|
-
} catch (e) {}
|
|
199
|
-
|
|
200
|
-
res.json({
|
|
201
|
-
success: true,
|
|
202
|
-
name,
|
|
203
|
-
type,
|
|
204
|
-
version,
|
|
205
|
-
downloadUrl: `https://toling.me/packages/${type}/${name}-${version}.tar.gz`
|
|
206
|
-
});
|
|
207
|
-
});
|
|
208
|
-
|
|
209
|
-
// Serve static packages
|
|
210
|
-
app.use('/packages', express.static(path.join(BASE_DIR, 'packages')));
|
|
211
|
-
|
|
212
|
-
// Health check
|
|
213
|
-
app.get('/health', (req, res) => {
|
|
214
|
-
res.json({ status: 'ok', timestamp: new Date().toISOString() });
|
|
215
|
-
});
|
|
216
|
-
|
|
217
|
-
app.listen(PORT, () => {
|
|
218
|
-
console.log(`TolingCode Registry Server running on port ${PORT}`);
|
|
219
|
-
console.log(`Base directory: ${BASE_DIR}`);
|
|
220
|
-
});
|