Commit d42664790ea47474382846672be5eb47e318ffdb

Authored by yibo
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,10 +98,19 @@ async function run() {
98 } 98 }
99 else if (command === 'okr create' || command === 'goal create') { 99 else if (command === 'okr create' || command === 'goal create') {
100 const { values } = parseArgs({ args: args.slice(2), options: { 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 else if (command === 'okr add-node' || command === 'goal add-node') { 115 else if (command === 'okr add-node' || command === 'goal add-node') {
107 const { values } = parseArgs({ args: args.slice(2), options: { 116 const { values } = parseArgs({ args: args.slice(2), options: {
@@ -124,13 +133,24 @@ async function run() { @@ -124,13 +133,24 @@ async function run() {
124 console.log(JSON.stringify(res.data, null, 2)); 133 console.log(JSON.stringify(res.data, null, 2));
125 } 134 }
126 else if (command === 'okr list' || command === 'goal list') { 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 else if (command === 'okr status' || command === 'goal status') { 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 else if (command === 'goal update') { 155 else if (command === 'goal update') {
136 const { values } = parseArgs({ args: args.slice(2), options: { 156 const { values } = parseArgs({ args: args.slice(2), options: {