openclawmp 0.1.4 → 0.1.5
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/lib/commands/comment.js +101 -83
- package/lib/commands/issue.js +121 -89
- package/lib/commands/publish.js +472 -306
- package/lib/config.js +104 -97
- package/package.json +3 -3
package/lib/commands/comment.js
CHANGED
|
@@ -2,118 +2,136 @@
|
|
|
2
2
|
// commands/comment.js — Post / list comments on an asset
|
|
3
3
|
// ============================================================================
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
"use strict";
|
|
6
6
|
|
|
7
|
-
const api = require(
|
|
8
|
-
const auth = require(
|
|
9
|
-
const { ok, info, err, c, detail } = require(
|
|
7
|
+
const api = require("../api.js");
|
|
8
|
+
const auth = require("../auth.js");
|
|
9
|
+
const { ok, info, err, c, detail } = require("../ui.js");
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* Format a timestamp to a readable date string
|
|
13
13
|
*/
|
|
14
14
|
function fmtDate(ts) {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
if (!ts) return "?";
|
|
16
|
+
const d = new Date(ts);
|
|
17
|
+
if (isNaN(d.getTime())) return String(ts);
|
|
18
|
+
return d.toLocaleString("zh-CN", { timeZone: "Asia/Shanghai" });
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
22
|
* Render star rating: ★★★★☆
|
|
23
23
|
*/
|
|
24
24
|
function renderRating(rating) {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
if (!rating) return "";
|
|
26
|
+
const n = Math.max(0, Math.min(5, Math.round(rating)));
|
|
27
|
+
return c("yellow", "★".repeat(n)) + c("dim", "☆".repeat(5 - n));
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
/**
|
|
31
31
|
* openclawmp comment <assetRef> <content> [--rating N] [--as-agent]
|
|
32
32
|
*/
|
|
33
33
|
async function runComment(args, flags) {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
process.exit(1);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
const asset = await api.resolveAssetRef(args[0]);
|
|
46
|
-
const content = args.slice(1).join(' ');
|
|
47
|
-
const displayName = asset.displayName || asset.name || args[0];
|
|
48
|
-
|
|
49
|
-
const body = {
|
|
50
|
-
content,
|
|
51
|
-
commenterType: flags['as-agent'] ? 'agent' : 'user',
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
if (flags.rating !== undefined) {
|
|
55
|
-
const rating = parseInt(flags.rating, 10);
|
|
56
|
-
if (isNaN(rating) || rating < 1 || rating > 5) {
|
|
57
|
-
err('Rating must be between 1 and 5');
|
|
58
|
-
process.exit(1);
|
|
34
|
+
if (args.length < 2) {
|
|
35
|
+
err(
|
|
36
|
+
"Usage: openclawmp comment <assetRef> <content> [--rating 5] [--as-agent]",
|
|
37
|
+
);
|
|
38
|
+
console.log(
|
|
39
|
+
' Example: openclawmp comment trigger/@xiaoyue/pdf-watcher "非常好用!"',
|
|
40
|
+
);
|
|
41
|
+
process.exit(1);
|
|
59
42
|
}
|
|
60
|
-
body.rating = rating;
|
|
61
|
-
}
|
|
62
43
|
|
|
63
|
-
|
|
44
|
+
if (!auth.isAuthenticated()) {
|
|
45
|
+
err("Authentication required. Run: openclawmp login");
|
|
46
|
+
process.exit(1);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const asset = await api.resolveAssetRef(args[0]);
|
|
50
|
+
const content = args.slice(1).join(" ");
|
|
51
|
+
const displayName = asset.displayName || asset.name || args[0];
|
|
52
|
+
|
|
53
|
+
const body = {
|
|
54
|
+
content,
|
|
55
|
+
commenterType: flags["as-agent"] ? "agent" : "user",
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
if (flags.rating !== undefined) {
|
|
59
|
+
const rating = parseInt(flags.rating, 10);
|
|
60
|
+
if (isNaN(rating) || rating < 1 || rating > 5) {
|
|
61
|
+
err("Rating must be between 1 and 5");
|
|
62
|
+
process.exit(1);
|
|
63
|
+
}
|
|
64
|
+
body.rating = rating;
|
|
65
|
+
}
|
|
64
66
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
67
|
+
const { status, data } = await api.post(
|
|
68
|
+
`/api/assets/${asset.id}/comments`,
|
|
69
|
+
body,
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
if (status >= 200 && status < 300) {
|
|
73
|
+
const comment = data.comment || data;
|
|
74
|
+
console.log("");
|
|
75
|
+
ok(`评论审核成功后自动发布 ${c("bold", displayName)}`);
|
|
76
|
+
if (body.rating) {
|
|
77
|
+
detail("评分", renderRating(body.rating));
|
|
78
|
+
}
|
|
79
|
+
detail("内容", content);
|
|
80
|
+
console.log("");
|
|
81
|
+
} else {
|
|
82
|
+
err(
|
|
83
|
+
`评论失败 (${status}): ${data.error || data.message || JSON.stringify(data)}`,
|
|
84
|
+
);
|
|
85
|
+
process.exit(1);
|
|
71
86
|
}
|
|
72
|
-
detail('内容', content);
|
|
73
|
-
console.log('');
|
|
74
|
-
} else {
|
|
75
|
-
err(`评论失败 (${status}): ${data.error || data.message || JSON.stringify(data)}`);
|
|
76
|
-
process.exit(1);
|
|
77
|
-
}
|
|
78
87
|
}
|
|
79
88
|
|
|
80
89
|
/**
|
|
81
90
|
* openclawmp comments <assetRef>
|
|
82
91
|
*/
|
|
83
92
|
async function runComments(args) {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
93
|
+
if (args.length === 0) {
|
|
94
|
+
err("Usage: openclawmp comments <assetRef>");
|
|
95
|
+
console.log(
|
|
96
|
+
" Example: openclawmp comments trigger/@xiaoyue/pdf-watcher",
|
|
97
|
+
);
|
|
98
|
+
process.exit(1);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const asset = await api.resolveAssetRef(args[0]);
|
|
102
|
+
const displayName = asset.displayName || asset.name || args[0];
|
|
103
|
+
|
|
104
|
+
const result = await api.get(`/api/assets/${asset.id}/comments`);
|
|
105
|
+
const comments = result?.data?.comments || result?.comments || [];
|
|
106
|
+
|
|
107
|
+
console.log("");
|
|
108
|
+
info(`${c("bold", displayName)} 的评论(${comments.length} 条)`);
|
|
109
|
+
console.log(` ${"─".repeat(50)}`);
|
|
110
|
+
|
|
111
|
+
if (comments.length === 0) {
|
|
112
|
+
console.log(` ${c("dim", "暂无评论。成为第一个评论者吧!")}`);
|
|
113
|
+
console.log("");
|
|
114
|
+
console.log(` openclawmp comment ${args[0]} "你的评论"`);
|
|
115
|
+
} else {
|
|
116
|
+
for (const cm of comments) {
|
|
117
|
+
const author =
|
|
118
|
+
cm.author?.name ||
|
|
119
|
+
cm.authorName ||
|
|
120
|
+
cm.commenterType ||
|
|
121
|
+
"anonymous";
|
|
122
|
+
const rating = cm.rating ? ` ${renderRating(cm.rating)}` : "";
|
|
123
|
+
const badge =
|
|
124
|
+
cm.commenterType === "agent" ? c("magenta", " 🤖") : "";
|
|
125
|
+
const time = fmtDate(cm.createdAt || cm.created_at);
|
|
126
|
+
|
|
127
|
+
console.log("");
|
|
128
|
+
console.log(
|
|
129
|
+
` ${c("cyan", author)}${badge}${rating} ${c("dim", time)}`,
|
|
130
|
+
);
|
|
131
|
+
console.log(` ${cm.content}`);
|
|
132
|
+
}
|
|
114
133
|
}
|
|
115
|
-
|
|
116
|
-
console.log('');
|
|
134
|
+
console.log("");
|
|
117
135
|
}
|
|
118
136
|
|
|
119
137
|
module.exports = { runComment, runComments };
|
package/lib/commands/issue.js
CHANGED
|
@@ -2,124 +2,156 @@
|
|
|
2
2
|
// commands/issue.js — Create / list issues on an asset
|
|
3
3
|
// ============================================================================
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
"use strict";
|
|
6
6
|
|
|
7
|
-
const api = require(
|
|
8
|
-
const auth = require(
|
|
9
|
-
const { ok, info, err, c, detail } = require(
|
|
7
|
+
const api = require("../api.js");
|
|
8
|
+
const auth = require("../auth.js");
|
|
9
|
+
const { ok, info, err, c, detail } = require("../ui.js");
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* Format a timestamp to a readable date string
|
|
13
13
|
*/
|
|
14
14
|
function fmtDate(ts) {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
if (!ts) return "?";
|
|
16
|
+
const d = new Date(ts);
|
|
17
|
+
if (isNaN(d.getTime())) return String(ts);
|
|
18
|
+
return d.toLocaleString("zh-CN", { timeZone: "Asia/Shanghai" });
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
22
|
* Render issue status with color
|
|
23
23
|
*/
|
|
24
24
|
function renderStatus(status) {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
25
|
+
switch (status) {
|
|
26
|
+
case "open":
|
|
27
|
+
return c("green", "● open");
|
|
28
|
+
case "closed":
|
|
29
|
+
return c("red", "● closed");
|
|
30
|
+
default:
|
|
31
|
+
return c("dim", status || "open");
|
|
32
|
+
}
|
|
30
33
|
}
|
|
31
34
|
|
|
32
35
|
/**
|
|
33
36
|
* openclawmp issue <assetRef> <title> [--body "..."] [--labels "bug,help"] [--as-agent]
|
|
34
37
|
*/
|
|
35
38
|
async function runIssue(args, flags) {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
title
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
if (flags.labels) {
|
|
61
|
-
body.labels = flags.labels.split(',').map(l => l.trim()).filter(Boolean);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const { status, data } = await api.post(`/api/assets/${asset.id}/issues`, body);
|
|
65
|
-
|
|
66
|
-
if (status >= 200 && status < 300) {
|
|
67
|
-
const issue = data.issue || data;
|
|
68
|
-
const issueNum = issue.number || issue.id || '?';
|
|
69
|
-
|
|
70
|
-
console.log('');
|
|
71
|
-
ok(`Issue #${issueNum} 已创建于 ${c('bold', displayName)}`);
|
|
72
|
-
detail('标题', title);
|
|
39
|
+
if (args.length < 2) {
|
|
40
|
+
err(
|
|
41
|
+
'Usage: openclawmp issue <assetRef> <title> [--body "..."] [--labels "bug,help"] [--as-agent]',
|
|
42
|
+
);
|
|
43
|
+
console.log(
|
|
44
|
+
' Example: openclawmp issue trigger/@xiaoyue/pdf-watcher "安装后无法启动" --body "详细描述..."',
|
|
45
|
+
);
|
|
46
|
+
process.exit(1);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (!auth.isAuthenticated()) {
|
|
50
|
+
err("Authentication required. Run: openclawmp login");
|
|
51
|
+
process.exit(1);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const asset = await api.resolveAssetRef(args[0]);
|
|
55
|
+
const title = args.slice(1).join(" ");
|
|
56
|
+
const displayName = asset.displayName || asset.name || args[0];
|
|
57
|
+
|
|
58
|
+
const body = {
|
|
59
|
+
title,
|
|
60
|
+
authorType: flags["as-agent"] ? "agent" : "user",
|
|
61
|
+
};
|
|
62
|
+
|
|
73
63
|
if (flags.body) {
|
|
74
|
-
|
|
64
|
+
body.bodyText = flags.body;
|
|
75
65
|
}
|
|
66
|
+
|
|
76
67
|
if (flags.labels) {
|
|
77
|
-
|
|
68
|
+
body.labels = flags.labels
|
|
69
|
+
.split(",")
|
|
70
|
+
.map((l) => l.trim())
|
|
71
|
+
.filter(Boolean);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const { status, data } = await api.post(
|
|
75
|
+
`/api/assets/${asset.id}/issues`,
|
|
76
|
+
body,
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
if (status >= 200 && status < 300) {
|
|
80
|
+
const issue = data.issue || data;
|
|
81
|
+
const issueNum = issue.number || issue.id || "?";
|
|
82
|
+
|
|
83
|
+
console.log("");
|
|
84
|
+
ok(
|
|
85
|
+
`Issue #${issueNum} 正在审核 ${c("bold", displayName)},审核后自动创建`,
|
|
86
|
+
);
|
|
87
|
+
detail("标题", title);
|
|
88
|
+
if (flags.body) {
|
|
89
|
+
detail(
|
|
90
|
+
"描述",
|
|
91
|
+
flags.body.length > 60
|
|
92
|
+
? flags.body.slice(0, 60) + "..."
|
|
93
|
+
: flags.body,
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
if (flags.labels) {
|
|
97
|
+
detail("标签", flags.labels);
|
|
98
|
+
}
|
|
99
|
+
console.log("");
|
|
100
|
+
} else {
|
|
101
|
+
err(
|
|
102
|
+
`创建 Issue 失败 (${status}): ${data.error || data.message || JSON.stringify(data)}`,
|
|
103
|
+
);
|
|
104
|
+
process.exit(1);
|
|
78
105
|
}
|
|
79
|
-
console.log('');
|
|
80
|
-
} else {
|
|
81
|
-
err(`创建 Issue 失败 (${status}): ${data.error || data.message || JSON.stringify(data)}`);
|
|
82
|
-
process.exit(1);
|
|
83
|
-
}
|
|
84
106
|
}
|
|
85
107
|
|
|
86
108
|
/**
|
|
87
109
|
* openclawmp issues <assetRef>
|
|
88
110
|
*/
|
|
89
111
|
async function runIssues(args) {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
112
|
+
if (args.length === 0) {
|
|
113
|
+
err("Usage: openclawmp issues <assetRef>");
|
|
114
|
+
console.log(
|
|
115
|
+
" Example: openclawmp issues trigger/@xiaoyue/pdf-watcher",
|
|
116
|
+
);
|
|
117
|
+
process.exit(1);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const asset = await api.resolveAssetRef(args[0]);
|
|
121
|
+
const displayName = asset.displayName || asset.name || args[0];
|
|
122
|
+
|
|
123
|
+
const result = await api.get(`/api/assets/${asset.id}/issues`);
|
|
124
|
+
const issues = result?.data?.issues || result?.issues || [];
|
|
125
|
+
|
|
126
|
+
console.log("");
|
|
127
|
+
info(`${c("bold", displayName)} 的 Issues(${issues.length} 个)`);
|
|
128
|
+
console.log(` ${"─".repeat(50)}`);
|
|
129
|
+
|
|
130
|
+
if (issues.length === 0) {
|
|
131
|
+
console.log(` ${c("dim", "暂无 Issues。")}`);
|
|
132
|
+
} else {
|
|
133
|
+
for (const iss of issues) {
|
|
134
|
+
const num = iss.number || iss.id || "?";
|
|
135
|
+
const status = renderStatus(iss.status);
|
|
136
|
+
const author =
|
|
137
|
+
iss.author?.name ||
|
|
138
|
+
iss.authorName ||
|
|
139
|
+
iss.authorType ||
|
|
140
|
+
"anonymous";
|
|
141
|
+
const badge = iss.authorType === "agent" ? c("magenta", " 🤖") : "";
|
|
142
|
+
const time = fmtDate(iss.createdAt || iss.created_at);
|
|
143
|
+
const labels = (iss.labels || [])
|
|
144
|
+
.map((l) => c("yellow", `[${l}]`))
|
|
145
|
+
.join(" ");
|
|
146
|
+
|
|
147
|
+
console.log("");
|
|
148
|
+
console.log(
|
|
149
|
+
` ${status} ${c("bold", `#${num}`)} ${iss.title} ${labels}`,
|
|
150
|
+
);
|
|
151
|
+
console.log(` ${c("dim", `by ${author}${badge} · ${time}`)}`);
|
|
152
|
+
}
|
|
120
153
|
}
|
|
121
|
-
|
|
122
|
-
console.log('');
|
|
154
|
+
console.log("");
|
|
123
155
|
}
|
|
124
156
|
|
|
125
157
|
module.exports = { runIssue, runIssues };
|