openclawmp 0.1.4 → 0.1.6

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.
@@ -2,118 +2,136 @@
2
2
  // commands/comment.js — Post / list comments on an asset
3
3
  // ============================================================================
4
4
 
5
- 'use strict';
5
+ "use strict";
6
6
 
7
- const api = require('../api.js');
8
- const auth = require('../auth.js');
9
- const { ok, info, err, c, detail } = require('../ui.js');
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
- 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' });
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
- 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));
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
- if (args.length < 2) {
35
- err('Usage: openclawmp comment <assetRef> <content> [--rating 5] [--as-agent]');
36
- console.log(' Example: openclawmp comment trigger/@xiaoyue/pdf-watcher "非常好用!"');
37
- process.exit(1);
38
- }
39
-
40
- if (!auth.isAuthenticated()) {
41
- err('Authentication required. Run: openclawmp login');
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
- const { status, data } = await api.post(`/api/assets/${asset.id}/comments`, body);
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
- if (status >= 200 && status < 300) {
66
- const comment = data.comment || data;
67
- console.log('');
68
- ok(`评论已发布到 ${c('bold', displayName)}`);
69
- if (body.rating) {
70
- detail('评分', renderRating(body.rating));
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
- if (args.length === 0) {
85
- err('Usage: openclawmp comments <assetRef>');
86
- console.log(' Example: openclawmp comments trigger/@xiaoyue/pdf-watcher');
87
- process.exit(1);
88
- }
89
-
90
- const asset = await api.resolveAssetRef(args[0]);
91
- const displayName = asset.displayName || asset.name || args[0];
92
-
93
- const result = await api.get(`/api/assets/${asset.id}/comments`);
94
- const comments = result?.data?.comments || result?.comments || [];
95
-
96
- console.log('');
97
- info(`${c('bold', displayName)} 的评论(${comments.length} 条)`);
98
- console.log(` ${'─'.repeat(50)}`);
99
-
100
- if (comments.length === 0) {
101
- console.log(` ${c('dim', '暂无评论。成为第一个评论者吧!')}`);
102
- console.log('');
103
- console.log(` openclawmp comment ${args[0]} "你的评论"`);
104
- } else {
105
- for (const cm of comments) {
106
- const author = cm.author?.name || cm.authorName || cm.commenterType || 'anonymous';
107
- const rating = cm.rating ? ` ${renderRating(cm.rating)}` : '';
108
- const badge = cm.commenterType === 'agent' ? c('magenta', ' 🤖') : '';
109
- const time = fmtDate(cm.createdAt || cm.created_at);
110
-
111
- console.log('');
112
- console.log(` ${c('cyan', author)}${badge}${rating} ${c('dim', time)}`);
113
- console.log(` ${cm.content}`);
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 };
@@ -2,124 +2,156 @@
2
2
  // commands/issue.js — Create / list issues on an asset
3
3
  // ============================================================================
4
4
 
5
- 'use strict';
5
+ "use strict";
6
6
 
7
- const api = require('../api.js');
8
- const auth = require('../auth.js');
9
- const { ok, info, err, c, detail } = require('../ui.js');
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
- 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' });
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
- switch (status) {
26
- case 'open': return c('green', '● open');
27
- case 'closed': return c('red', 'closed');
28
- default: return c('dim', status || 'open');
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
- if (args.length < 2) {
37
- err('Usage: openclawmp issue <assetRef> <title> [--body "..."] [--labels "bug,help"] [--as-agent]');
38
- console.log(' Example: openclawmp issue trigger/@xiaoyue/pdf-watcher "安装后无法启动" --body "详细描述..."');
39
- process.exit(1);
40
- }
41
-
42
- if (!auth.isAuthenticated()) {
43
- err('Authentication required. Run: openclawmp login');
44
- process.exit(1);
45
- }
46
-
47
- const asset = await api.resolveAssetRef(args[0]);
48
- const title = args.slice(1).join(' ');
49
- const displayName = asset.displayName || asset.name || args[0];
50
-
51
- const body = {
52
- title,
53
- authorType: flags['as-agent'] ? 'agent' : 'user',
54
- };
55
-
56
- if (flags.body) {
57
- body.bodyText = flags.body;
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
- detail('描述', flags.body.length > 60 ? flags.body.slice(0, 60) + '...' : flags.body);
64
+ body.bodyText = flags.body;
75
65
  }
66
+
76
67
  if (flags.labels) {
77
- detail('标签', flags.labels);
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
- if (args.length === 0) {
91
- err('Usage: openclawmp issues <assetRef>');
92
- console.log(' Example: openclawmp issues trigger/@xiaoyue/pdf-watcher');
93
- process.exit(1);
94
- }
95
-
96
- const asset = await api.resolveAssetRef(args[0]);
97
- const displayName = asset.displayName || asset.name || args[0];
98
-
99
- const result = await api.get(`/api/assets/${asset.id}/issues`);
100
- const issues = result?.data?.issues || result?.issues || [];
101
-
102
- console.log('');
103
- info(`${c('bold', displayName)} 的 Issues(${issues.length} 个)`);
104
- console.log(` ${'─'.repeat(50)}`);
105
-
106
- if (issues.length === 0) {
107
- console.log(` ${c('dim', '暂无 Issues。')}`);
108
- } else {
109
- for (const iss of issues) {
110
- const num = iss.number || iss.id || '?';
111
- const status = renderStatus(iss.status);
112
- const author = iss.author?.name || iss.authorName || iss.authorType || 'anonymous';
113
- const badge = iss.authorType === 'agent' ? c('magenta', ' 🤖') : '';
114
- const time = fmtDate(iss.createdAt || iss.created_at);
115
- const labels = (iss.labels || []).map(l => c('yellow', `[${l}]`)).join(' ');
116
-
117
- console.log('');
118
- console.log(` ${status} ${c('bold', `#${num}`)} ${iss.title} ${labels}`);
119
- console.log(` ${c('dim', `by ${author}${badge} · ${time}`)}`);
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 };