comitia 0.1.0 → 0.3.0

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/index.js CHANGED
@@ -116,7 +116,7 @@ async function rpc(method, params, { token: override } = {}) {
116
116
  body: JSON.stringify({ jsonrpc: '2.0', id: 1, method, params }),
117
117
  });
118
118
  } catch (e) {
119
- die(`서버에 닿지 못했어요 (${api}).\n ${e.message}`);
119
+ die(`서버에 닿지 못했어요 (${api}).\n ${e.message}\n 회사망·VPN·보안 프로그램이 막는 경우가 많아요 — 다른 망(휴대폰 핫스팟)에서 한 번 해 보세요.`);
120
120
  }
121
121
 
122
122
  if (res.status === 401) die('연결이 끊겼어요(토큰이 끊겼거나 틀림). `comitia login` 으로 다시 연결해 주세요.');
@@ -247,7 +247,7 @@ async function browserLogin({ paste = false } = {}) {
247
247
  body: JSON.stringify({ code, code_verifier: verifier }),
248
248
  });
249
249
  } catch (e) {
250
- die(`서버에 닿지 못했어요 (${api}).\n ${e.message}`);
250
+ die(`서버에 닿지 못했어요 (${api}).\n ${e.message}\n 회사망·VPN·보안 프로그램이 막는 경우가 많아요 — 다른 망(휴대폰 핫스팟)에서 한 번 해 보세요.`);
251
251
  }
252
252
  const body = await res.json().catch(() => ({}));
253
253
  if (!res.ok || !body.token) die(body.detail || `서버가 ${res.status} 로 답했어요.`);
@@ -352,6 +352,7 @@ const BLOCK = `${MARK_START}
352
352
  | \`comitia recent\` | 최근 들어온 것 | \`comitia search <낱말>\` | 본문 검색 |
353
353
  | \`comitia find <낱말>\` | 원본에서 찾기 | \`comitia read <경로>\` | 문서 본문 |
354
354
  | \`comitia raw <id>\` | 원본 본문 | \`comitia list [접두어]\` | 문서 목록 |
355
+ | \`comitia forget <id> <낱말>\` | 원본에서 낱말 지우기(남을 이유 없는 제3자 이름 등) | | |
355
356
 
356
357
  **정리를 부탁받으면 내가 한다** — Comitia 의 AI 에게 맡기지 않는다.
357
358
 
@@ -360,6 +361,7 @@ const BLOCK = `${MARK_START}
360
361
  사용자가 고쳐 두었을 수 있으므로, 이 블록의 기억에 의존하지 않는다.**
361
362
 
362
363
  ⚠️ **슬랙에 올리는 것(\`comitia slack\`)은 팀 전체가 보는 일이다** — 채널과 문구를 먼저 보여 주고 허락받은 뒤에만 올린다.
364
+ **고치기·지우기(\`--edit\` · \`--delete\`)도 마찬가지다** — 봇이 올린 글만 되고, 무엇을 고치거나 지우는지 보여 주고 허락받는다. 지우기는 되돌릴 수 없다.
363
365
 
364
366
  Claude Code 에서는 스킬 \`/comitia:read\` · \`/comitia:ingest\` · \`/comitia:slack\` · \`/comitia:sync\` 이 순서를 담고 있다.
365
367
  자세한 명령은 \`comitia --help\`.
@@ -416,6 +418,10 @@ function parseArgs(argv) {
416
418
  if (a === '-c' || a === '--company') flags.c = argv[++i];
417
419
  else if (a === '--thread') flags.thread = argv[++i];
418
420
  else if (a === '--thread-of') flags.threadOf = argv[++i];
421
+ else if (a === '--edit') flags.edit = argv[++i];
422
+ else if (a === '--edit-of') flags.editOf = argv[++i];
423
+ else if (a === '--delete') flags.delete = argv[++i];
424
+ else if (a === '--delete-of') flags.deleteOf = argv[++i];
419
425
  else if (a === '-g' || a === '--global') flags.global = true;
420
426
  else if (a === '--paste') flags.paste = true;
421
427
  else if (a === '-h' || a === '--help') flags.help = true;
@@ -447,10 +453,14 @@ const HELP = `comitia — 회사 온톨로지를 내가 쓰는 AI에서 꺼내
447
453
  comitia recent [개수] 최근 들어온 원본
448
454
  comitia find <낱말> 원본에서 찾기
449
455
  comitia raw <id...> 원본 본문 (id 는 recent·find 가 준 것)
456
+ comitia forget <id> <낱말...> 원본에서 낱말 지우기 — 다시 수집돼도 안 돌아옴 (쓰기 토큰)
450
457
  comitia sync [slack|tiro|...] 지금 당겨오기 — 매시 자동 수집을 기다리지 않고 (쓰기 토큰)
451
458
  comitia slack <채널> <파일|-> 연결된 봇으로 슬랙에 올리기 (쓰기 토큰 · 봇에 chat:write 필요)
459
+ comitia slack <채널> --delete <ts> 봇이 올린 그 글 지우기 (되돌릴 수 없음)
452
460
  --thread <ts> 그 글의 스레드에 답글로 (부모 ts)
453
461
  --thread-of "<검색어>" 부모 글을 본문으로 찾아 그 스레드에 (최근 100건 중 최신)
462
+ --edit <ts> 새 글 대신 봇이 올린 그 글을 통째로 바꾸기 (봇 글만)
463
+ --edit-of "<검색어>" 고칠 봇 글을 본문으로 찾아서 (최근 100건 중 최신)
454
464
 
455
465
  ── 정리를 내 AI 가 한다 ── (쓰기 토큰 필요)
456
466
  comitia rules 이 워크스페이스의 위키 규칙 — **쓰기 전에 먼저**
@@ -685,6 +695,13 @@ const COMMANDS = {
685
695
  console.log(await callTool('read_raw', { company_id: needCompany(flags), ids: args }));
686
696
  },
687
697
 
698
+ /** 원본에서 낱말을 지운다. 통째로 지우면 다음 수집에 되살아나지만 이건 안 돌아온다. */
699
+ async forget(args, flags) {
700
+ const [id, ...terms] = args;
701
+ if (!id || terms.length === 0) die('원본 id 와 지울 낱말을 적어 주세요.\n z2o forget af1c6e9f "홍길동"');
702
+ console.log(await callTool('forget_raw', { company_id: needCompany(flags), id, terms }));
703
+ },
704
+
688
705
  async push(args, flags) {
689
706
  const [title, path] = args;
690
707
  if (!title || !path) die('제목과 파일을 적어 주세요.\n comitia push "회의록" note.md\n cat x.md | comitia push "제목" -');
@@ -749,12 +766,28 @@ const COMMANDS = {
749
766
 
750
767
  /** 슬랙에 올린다 — 연결된 봇으로. ⚠️ 팀에게 보이는 일이라 AI 는 올리기 전에 사람에게 허락받는다. */
751
768
  async slack([channel, file], flags) {
769
+ // 🗑️ 지우기는 올릴 글이 없다 — 채널과 ts(또는 검색어)만 받는다. 되돌릴 수 없어 스킬이 먼저 허락받는다.
770
+ if (flags.delete || flags.deleteOf) {
771
+ if (!channel) die('지울 글이 있는 채널을 적어 주세요.\n comitia slack project_0to1 --delete 1757769600.123456\n comitia slack project_0to1 --delete-of "z2o → Comitia 이름 변경"');
772
+ if (flags.delete && !/^\d{10}\.\d{6}$/.test(flags.delete)) die(`--delete 는 슬랙 ts 모양이어야 해요 (예: 1757769600.123456). 검색어로 찾으려면 --delete-of "<글의 일부>"`);
773
+ if (flags.edit || flags.editOf || flags.thread || flags.threadOf) die('--delete 는 --edit·--thread 와 같이 못 써요.');
774
+ const args = { company_id: needCompany(flags), channel };
775
+ if (flags.delete) args.ts = flags.delete;
776
+ else args.of = flags.deleteOf;
777
+ console.log(await callTool('delete_slack', args));
778
+ return;
779
+ }
752
780
  if (!channel || !file) die('채널과 파일을 적어 주세요.\n comitia slack project_0to1 글.txt\n ... | comitia slack project_0to1 -\n comitia slack weekly-meeting 글.txt --thread-of "0913 위클리" # 그 글의 스레드에 답글로');
753
781
  const text = file === '-' ? readFileSync(0, 'utf8') : readFileSync(file, 'utf8');
754
782
  if (!text.trim()) die('올릴 글이 비었어요.');
755
- if (flags.thread && !/^\d{10}\.\d{6}$/.test(flags.thread)) die(`--thread 는 슬랙 ts 모양이어야 해요 (예: 1757769600.123456). 검색어로 찾으려면 --thread-of "<글의 일부>"`);
783
+ const tsShape = /^\d{10}\.\d{6}$/;
784
+ if (flags.thread && !tsShape.test(flags.thread)) die(`--thread 는 슬랙 ts 모양이어야 해요 (예: 1757769600.123456). 검색어로 찾으려면 --thread-of "<글의 일부>"`);
785
+ if (flags.edit && !tsShape.test(flags.edit)) die(`--edit 는 슬랙 ts 모양이어야 해요 (예: 1757769600.123456). 검색어로 찾으려면 --edit-of "<글의 일부>"`);
786
+ if ((flags.edit || flags.editOf) && (flags.thread || flags.threadOf)) die('--edit 와 --thread 는 같이 못 써요. 고치기는 새 글이 아니에요.');
756
787
  const args = { company_id: needCompany(flags), channel, text };
757
- if (flags.thread) args.thread_ts = flags.thread;
788
+ if (flags.edit) args.edit_ts = flags.edit;
789
+ else if (flags.editOf) args.edit_of = flags.editOf;
790
+ else if (flags.thread) args.thread_ts = flags.thread;
758
791
  else if (flags.threadOf) args.thread_of = flags.threadOf;
759
792
  console.log(await callTool('post_slack', args));
760
793
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "comitia",
3
- "version": "0.1.0",
3
+ "version": "0.3.0",
4
4
  "description": "Comitia — 슬랙·회의·문서에 흩어진 회사의 말을 내가 쓰는 AI에서 꺼내 쓴다",
5
5
  "keywords": [
6
6
  "comitia",
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: slack
3
- description: 슬랙에 글을 올릴 때 쓴다 — "슬랙에 보내", "슬랙에 올려", "#채널에 공유해", "팀에 알려", "이거 정리해서 슬랙에". Comitia 에 연결된 봇으로 올린다. 올리기 전에 반드시 채널과 문구를 사람에게 보여 주고 허락받는다.
3
+ description: 슬랙에 글을 올리거나, 봇이 올린 글을 고치거나 지울 때 쓴다 — "슬랙에 보내", "슬랙에 올려", "#채널에 공유해", "팀에 알려", "아까 올린 거 지워줘", "그 글 고쳐줘". Comitia 에 연결된 봇으로 한다. 올리기·고치기·지우기 전에 반드시 채널과 대상을 사람에게 보여 주고 허락받는다.
4
4
  allowed-tools:
5
5
  - Bash(comitia *)
6
6
  - Bash(z2o *)
@@ -48,6 +48,10 @@ Comitia 에 연결된 **봇**이 대신 올린다. 사람 이름으로 올라가
48
48
  comitia slack <채널> <임시파일> 새 글로
49
49
  comitia slack <채널> <임시파일> --thread-of "<검색어>" 그 글의 스레드에 답글로
50
50
  comitia slack <채널> <임시파일> --thread <ts> 부모 ts 를 알 때
51
+ comitia slack <채널> <임시파일> --edit-of "<검색어>" 봇이 올린 그 글을 통째로 바꾸기 (체크리스트 갱신 등)
52
+ comitia slack <채널> <임시파일> --edit <ts> 고칠 글의 ts 를 알 때
53
+ comitia slack <채널> --delete-of "<검색어>" 봇이 올린 그 글 지우기 (파일 없음 · 되돌릴 수 없음)
54
+ comitia slack <채널> --delete <ts> 지울 글의 ts 를 알 때
51
55
  ```
52
56
 
53
57
  채널은 `project_0to1` 처럼 이름으로(`#` 는 있어도 없어도 된다). 올린 기록은 Comitia 연대기에 남는다.
@@ -57,6 +61,15 @@ comitia slack <채널> <임시파일> --thread <ts> 부모 ts 를 알
57
61
  채널 최근 100건에서 가장 최근 매치를 부모로 잡는다 — 부모가 사람 글이어도 된다. 못 찾으면 그렇다고 돌아오니
58
62
  검색어를 바꾸거나 사람에게 ts 를 받는다. 허락받을 때 **어느 글 아래에 달리는지**도 같이 보여 준다.
59
63
 
64
+ ## 5. 🗑️ 지우기 — 되돌릴 수 없다
65
+
66
+ 잘못 올린 글을 걷을 때. **봇이 올린 글만** 지운다.
67
+
68
+ - 지우기 전에 **어느 채널의 어떤 글인지**(첫 줄이라도) 보여 주고 *"이 글을 지울까요? 되돌릴 수 없어요"* 라고 묻는다.
69
+ - `--delete-of` 는 봇이 올린 글 중 최근 100건에서 찾는다 — 못 찾으면 그렇다고 돌아오니 검색어를 바꾸거나 ts 를 받는다.
70
+ - ⚠️ **스레드 부모를 지우면 답글까지 사라진다.** 답글이 달린 글이면 그 사실을 먼저 알린다.
71
+ - 지운 기록은 연대기에 남는다(채널·ts·첫 줄).
72
+
60
73
  ## 막히면
61
74
 
62
75
  | 나온 말 | 할 일 |
@@ -65,8 +78,12 @@ comitia slack <채널> <임시파일> --thread <ts> 부모 ts 를 알
65
78
  | 봇이 채널에 없다 | 사람에게 그 채널에서 `/invite @봇이름` 을 부탁한다 |
66
79
  | 쓰기 권한이 없다 | *자료·정리까지* 토큰이 필요하다. 토큰은 사람이 직접 다시 연결한다 — **대화로 받지 않는다** |
67
80
  | 글이 너무 길다 | 나눠 올릴지 사람에게 묻는다 |
81
+ | 봇이 올린 글만 지울 수 있다 | 사람이 올린 글이다 — 슬랙에서 직접 지우시라고 안내한다 |
68
82
 
69
83
  ## 못 하는 것
70
84
 
71
- 새 글과 스레드 답글만 된다. **DM·올린 글 고치기·지우기는 안 된다** —
85
+ 새 글 · 스레드 답글 · **봇이 올린 글 고치기·지우기**까지 된다. **DM · 사람이 올린 글 고치기·지우기는 안 된다** —
72
86
  부탁받으면 안 된다고 말하고, 슬랙에서 직접 하시라고 안내한다.
87
+
88
+ **고치기**는 본문을 **통째로 덮어쓴다.** 부분만 바꾸더라도 전체 새 본문을 파일에 쓰고, 허락받을 때는
89
+ 바뀐 부분을 짚어 보여 준다(예: 「0-1 · 1-4 … 17건을 ✅ 로」). 봇 자기 글만 찾으니 사람 글은 매치되지 않는다.