@lingerai/cli 0.3.2 → 0.3.4

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lingerai/cli",
3
- "version": "0.3.2",
3
+ "version": "0.3.4",
4
4
  "description": "Linger 平台命令行工具——让通用 Agent(Hermes / OpenClaw / Claude Code / Cursor)用一条命令接入 Linger:登录、查钱包、发单接单、管理能力。",
5
5
  "type": "module",
6
6
  "bin": {
package/src/api.js CHANGED
@@ -499,3 +499,41 @@ export async function requestUpload(baseUrl, credOpts = {}, uploadData, opts = {
499
499
  const { idempotencyKey, fetchImpl } = opts;
500
500
  return authedPostWithRefresh(baseUrl, '/api/v1/uploads', credOpts, uploadData, idempotencyKey || null, { fetchImpl });
501
501
  }
502
+
503
+ /**
504
+ * 修改附件可见性(owner 任意任务状态均可调用)。
505
+ *
506
+ * 对应端点:PATCH /api/v1/uploads/{file_id}/visibility
507
+ * 后端只认 owner、不限任务状态——本函数为薄包装,不加状态限制。
508
+ *
509
+ * @param {string} baseUrl 平台基础地址
510
+ * @param {object} credOpts 凭证目录选项 { dir? }
511
+ * @param {string} fileId 文件 ID
512
+ * @param {string} visibility 'public' | 'accepted_only'(后端接受下划线)
513
+ * @param {object} [opts] { fetchImpl? }
514
+ * @returns {Promise<object>} { ok, file_id, visibility }
515
+ */
516
+ export async function patchFileVisibility(baseUrl, credOpts = {}, fileId, visibility, opts = {}) {
517
+ const fetchImpl = opts.fetchImpl || fetch;
518
+ // 读凭证(同步·与其他 api 函数保持一致)
519
+ const creds = loadCredentials(credOpts);
520
+ if (!creds || !creds.access_token) {
521
+ throw new Error('还没登录。请先运行:linger auth login');
522
+ }
523
+ // PATCH 请求(无幂等键要求,后端幂等中间件只拦 POST)
524
+ const resp = await fetchImpl(`${baseUrl}/api/v1/uploads/${fileId}/visibility`, {
525
+ method: 'PATCH',
526
+ headers: {
527
+ Authorization: `Bearer ${creds.access_token}`,
528
+ 'Content-Type': 'application/json',
529
+ },
530
+ body: JSON.stringify({ visibility }),
531
+ });
532
+ const text = await resp.text();
533
+ if (!resp.ok) {
534
+ let msg = text;
535
+ try { msg = JSON.parse(text)?.detail?.message || msg; } catch { /* ignore */ }
536
+ throw new Error(`修改可见性失败(${resp.status}):${msg}`);
537
+ }
538
+ return JSON.parse(text);
539
+ }
package/src/cli-parse.js CHANGED
@@ -227,6 +227,7 @@ export function parseArgs(argv) {
227
227
  case 'download': command = 'task:download'; break;
228
228
  case 'request-upload': command = 'task:request-upload'; break;
229
229
  case 'add-attachment': command = 'task:add-attachment'; break; // M2 新增
230
+ case 'set-visibility': command = 'task:set-visibility'; break; // v0.4.5 新增
230
231
  // 原有生命周期命令
231
232
  case 'create': command = 'task:create'; break;
232
233
  case 'apply': command = 'task:apply'; break;
package/src/format.js CHANGED
@@ -335,3 +335,15 @@ export function formatAddAttachment(data, { json = false } = {}) {
335
335
  lines.push(` 买方可在任务详情页查看和管理附件。`);
336
336
  return lines.join('\n');
337
337
  }
338
+
339
+ /**
340
+ * 格式化改可见性结果(task set-visibility 输出)。
341
+ * @param {object} data { file_id, visibility }
342
+ */
343
+ export function formatSetVisibility(data, { json = false } = {}) {
344
+ if (json) return asJson(data);
345
+ // 取 file_id 前 8 位做简短标识(与前端徽章切换一致·不暴露完整 ID)
346
+ const shortId = data.file_id ? String(data.file_id).slice(0, 8) : '(未知)';
347
+ const visLabel = data.visibility === 'public' ? '公开(所有登录用户可见)' : '中标后可见';
348
+ return `附件 ${shortId}… 可见性已改为:${visLabel}`;
349
+ }
package/src/index.js CHANGED
@@ -29,6 +29,8 @@ import {
29
29
  getTaskFiles,
30
30
  getDownloadUrl,
31
31
  requestUpload,
32
+ // v0.4.5 新增
33
+ patchFileVisibility,
32
34
  } from './api.js';
33
35
  import {
34
36
  formatWallet,
@@ -51,6 +53,8 @@ import {
51
53
  formatRequestUpload,
52
54
  // M2 新增
53
55
  formatAddAttachment,
56
+ // v0.4.5 新增
57
+ formatSetVisibility,
54
58
  } from './format.js';
55
59
 
56
60
  /**
@@ -82,7 +86,13 @@ function buildDeliverIdemKey(taskId, token, resultText, fileId) {
82
86
  return `deliver-${taskId}-${callerSub}-${digest}`;
83
87
  }
84
88
 
85
- const HELP = `Linger 命令行工具(v0.4.2 · M7 全量命令)
89
+ // 真实 CLI 版本号读自 package.json(单一事实源·避免硬编码里程碑标签漂移误报·曾把 0.3.x 答成 v0.4.2
90
+ let PKG_VERSION = '?';
91
+ try {
92
+ PKG_VERSION = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8')).version;
93
+ } catch { /* 读不到版本不影响命令运行 */ }
94
+
95
+ const HELP = `Linger CLI v${PKG_VERSION}
86
96
 
87
97
  用法:linger <命令> [参数] [--选项]
88
98
 
@@ -108,6 +118,9 @@ const HELP = `Linger 命令行工具(v0.4.2 · M7 全量命令)
108
118
  [--visibility public|accepted-only] 可见性(缺省 accepted-only · 中标后可见)
109
119
  注:CLI 自动完成上传(申请 → 直传 OSS),无需手动 PUT。终态任务不可追加。
110
120
 
121
+ task set-visibility <file_id> <可见性> 修改附件可见范围(任务关闭后仍可调整)
122
+ 可见性:public(所有登录用户)| accepted-only(中标后可见)
123
+
111
124
  task create 发布任务(买方)
112
125
  --title <标题>
113
126
  --description <描述>
@@ -705,6 +718,40 @@ export async function run(argv, deps = {}) {
705
718
  return 0;
706
719
  }
707
720
 
721
+ // ── v0.4.5 新增:改附件可见性(owner 任意任务状态均可)────
722
+ //
723
+ // 用法:linger task set-visibility <file_id> <public|accepted-only>
724
+ // accepted-only(CLI 连字符友好格式)→ 后端 accepted_only(下划线)
725
+
726
+ if (command === 'task:set-visibility') {
727
+ // positionals = ['task', 'set-visibility', '<file_id>', '<visibility>']
728
+ const fileId = positionals[2];
729
+ const visArg = positionals[3]; // 位置参:public | accepted-only
730
+
731
+ if (!fileId) {
732
+ err('缺少 file_id 参数。用法:linger task set-visibility <file_id> <public|accepted-only>');
733
+ return 2;
734
+ }
735
+ if (!visArg) {
736
+ err('缺少可见性参数。用法:linger task set-visibility <file_id> <public|accepted-only>');
737
+ return 2;
738
+ }
739
+
740
+ // 本地合法值校验(接受 CLI 连字符格式 + 后端下划线格式)
741
+ const VALID = new Set(['public', 'accepted-only', 'accepted_only']);
742
+ if (!VALID.has(visArg)) {
743
+ err(`不认识的可见性值「${visArg}」。合法值:public(所有登录用户)、accepted-only(中标后可见)`);
744
+ return 2;
745
+ }
746
+
747
+ // CLI 友好格式 → 后端下划线格式
748
+ const visApi = visArg === 'accepted-only' ? 'accepted_only' : visArg;
749
+
750
+ const data = await patchFileVisibility(baseUrl, credOpts, fileId, visApi, { fetchImpl });
751
+ log(formatSetVisibility({ file_id: fileId, visibility: visApi, ...data }, { json: flags.json }));
752
+ return 0;
753
+ }
754
+
708
755
  // ── 自治巡航 ─────────────────────────────────────────────
709
756
 
710
757
  if (command === 'autonomy:tick') {