Commit d42664790ea47474382846672be5eb47e318ffdb
1 parent
2bee467f
fix(cli): lemon.js goal create/list/status 改走公司级 /api/company/:id/goals
38 号文档 Phase 2 把 /api/okr 收紧成 admin-only,agent 走 CLI 调用必 401; 公司级正确入口是 POST/GET /api/company/:id/goals(requireAuthOrInternal)。 新增 --company / LEMON_COMPANY 兜底,缺省给出明确提示而非裸 401。 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PKPAmaoRGb6UdGwPbStCwJ
Showing
1 changed file
with
28 additions
and
8 deletions
bin/lemon.js
| ... | ... | @@ -98,10 +98,19 @@ async function run() { |
| 98 | 98 | } |
| 99 | 99 | else if (command === 'okr create' || command === 'goal create') { |
| 100 | 100 | const { values } = parseArgs({ args: args.slice(2), options: { |
| 101 | - title: { type: 'string' }, desc: { type: 'string' }, owner: { type: 'string' } | |
| 101 | + title: { type: 'string' }, desc: { type: 'string' }, owner: { type: 'string' }, | |
| 102 | + // 38 号文档 Phase 2 把 /api/okr 收紧成 requireAdmin,agent 跑 CLI 必 401; | |
| 103 | + // 公司级正确入口是 POST /api/company/:id/goals(requireAuthOrInternal)。--company | |
| 104 | + // 缺省回落到 LEMON_COMPANY(agent 子进程由公司心跳带下来时可直接省略)。 | |
| 105 | + company: { type: 'string' } | |
| 102 | 106 | }}); |
| 103 | - const res = await request('POST', '/okr', { title: values.title, description: values.desc, owner: values.owner }); | |
| 104 | - console.log(JSON.stringify(res.data, null, 2)); | |
| 107 | + const cid = values.company || process.env.LEMON_COMPANY; | |
| 108 | + if (!cid) { | |
| 109 | + console.log('❌ goal create 需要公司级入口:请带 --company <companyId>(或设 LEMON_COMPANY)。/api/okr 是 admin-only,agent 调必 401。'); | |
| 110 | + } else { | |
| 111 | + const res = await request('POST', `/company/${cid}/goals`, { title: values.title, description: values.desc, split: false, report_to: values.owner }); | |
| 112 | + console.log(JSON.stringify(res.data, null, 2)); | |
| 113 | + } | |
| 105 | 114 | } |
| 106 | 115 | else if (command === 'okr add-node' || command === 'goal add-node') { |
| 107 | 116 | const { values } = parseArgs({ args: args.slice(2), options: { |
| ... | ... | @@ -124,13 +133,24 @@ async function run() { |
| 124 | 133 | console.log(JSON.stringify(res.data, null, 2)); |
| 125 | 134 | } |
| 126 | 135 | else if (command === 'okr list' || command === 'goal list') { |
| 127 | - const res = await request('GET', '/okr'); | |
| 128 | - console.log(JSON.stringify(res.data, null, 2)); | |
| 136 | + const { values } = parseArgs({ args: args.slice(2), options: { company: { type: 'string' } }}); | |
| 137 | + const cid = values.company || process.env.LEMON_COMPANY; | |
| 138 | + if (!cid) { | |
| 139 | + console.log('❌ goal list 请带 --company <companyId>(或设 LEMON_COMPANY)。/api/okr 是 admin-only,agent 调必 401。'); | |
| 140 | + } else { | |
| 141 | + const res = await request('GET', `/company/${cid}/goals`); | |
| 142 | + console.log(JSON.stringify(res.data, null, 2)); | |
| 143 | + } | |
| 129 | 144 | } |
| 130 | 145 | else if (command === 'okr status' || command === 'goal status') { |
| 131 | - const { values } = parseArgs({ args: args.slice(2), options: { goal: { type: 'string' } }}); | |
| 132 | - const res = await request('GET', `/okr/${values.goal}/progress`); | |
| 133 | - console.log(JSON.stringify(res.data, null, 2)); | |
| 146 | + const { values } = parseArgs({ args: args.slice(2), options: { goal: { type: 'string' }, company: { type: 'string' } }}); | |
| 147 | + const cid = values.company || process.env.LEMON_COMPANY; | |
| 148 | + if (!cid) { | |
| 149 | + console.log('❌ goal status 请带 --company <companyId>(或设 LEMON_COMPANY)。/api/okr 是 admin-only,agent 调必 401。'); | |
| 150 | + } else { | |
| 151 | + const res = await request('GET', `/company/${cid}/goals/${values.goal}`); | |
| 152 | + console.log(JSON.stringify(res.data, null, 2)); | |
| 153 | + } | |
| 134 | 154 | } |
| 135 | 155 | else if (command === 'goal update') { |
| 136 | 156 | const { values } = parseArgs({ args: args.slice(2), options: { | ... | ... |