@geekbeer/minion 2.73.0 → 3.5.1

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/core/api.js CHANGED
@@ -87,8 +87,8 @@ async function sendHeartbeat(data) {
87
87
  }
88
88
 
89
89
  /**
90
- * Create a project thread (help or discussion) on HQ.
91
- * @param {object} data - { project_id, title, content, thread_type?, mentions?, context? }
90
+ * Create a thread (project-scoped or workspace-scoped) on HQ.
91
+ * @param {object} data - { project_id?, scope?, category?, title, content, thread_type?, mentions?, context? }
92
92
  * @returns {Promise<{ thread: object }>}
93
93
  */
94
94
  async function createThread(data) {
@@ -99,11 +99,12 @@ async function createThread(data) {
99
99
  }
100
100
 
101
101
  /**
102
- * Get open threads in this minion's projects.
102
+ * Get open threads accessible to this minion.
103
+ * @param {'project' | 'workspace' | 'all'} [scope='all'] - Filter by scope
103
104
  * @returns {Promise<{ threads: object[] }>}
104
105
  */
105
- async function getOpenThreads() {
106
- return request('/threads/open')
106
+ async function getOpenThreads(scope = 'all') {
107
+ return request(`/threads/open?scope=${scope}`)
107
108
  }
108
109
 
109
110
  /**
@@ -130,9 +130,15 @@ async function pollOnce() {
130
130
  * Process a single thread: check for new activity and evaluate if needed.
131
131
  */
132
132
  async function processThread(thread, myProjects, now) {
133
- // Find my role in this project
134
- const myProject = myProjects.find(p => p.id === thread.project_id)
135
- if (!myProject) return // Not a member
133
+ // For workspace threads, create a synthetic project context
134
+ // For project threads, find role via membership
135
+ let myProject
136
+ if (thread.scope === 'workspace') {
137
+ myProject = { id: null, name: 'Workspace', role: 'engineer' }
138
+ } else {
139
+ myProject = myProjects.find(p => p.id === thread.project_id)
140
+ if (!myProject) return // Not a member
141
+ }
136
142
 
137
143
  const state = readState.get(thread.id) || { lastMessageCount: 0, lastEvalAt: 0 }
138
144
 
@@ -212,7 +218,12 @@ async function evaluateWithLlm(threadSummary, threadDetail, allMessages, newMess
212
218
  ctx.attempted_resolution ? `試行済み: ${ctx.attempted_resolution}` : '',
213
219
  ].filter(Boolean).join('\n')
214
220
 
215
- const prompt = `あなたはプロジェクト「${myProject.name}」のチームメンバー(ロール: ${myProject.role}、ID: ${config.MINION_ID})です。
221
+ const isWorkspace = threadDetail.scope === 'workspace'
222
+ const scopeContext = isWorkspace
223
+ ? `あなたはワークスペースのメンバー(ID: ${config.MINION_ID})です。\nこれはプロジェクトに属さないワークスペーススレッドです(カテゴリ: ${threadDetail.category || 'general'})。`
224
+ : `あなたはプロジェクト「${myProject.name}」のチームメンバー(ロール: ${myProject.role}、ID: ${config.MINION_ID})です。`
225
+
226
+ const prompt = `${scopeContext}
216
227
  以下のスレッドに対して、あなたが返信すべきかどうかを判断し、返信する場合はその内容を生成してください。
217
228
 
218
229
  スレッドタイプ: ${threadType}
@@ -235,7 +246,7 @@ ${messageHistory || '(メッセージなし)'}
235
246
  判断基準:
236
247
  - 自分が起票したスレッドの場合、他のメンバーの回答を待つべき(追加情報がある場合を除く)
237
248
  - メンション対象が特定のロールやミニオンに限定されている場合、自分が対象でなければ静観する
238
- - 自分のロール(${myProject.role})に関連する話題か
249
+ ${isWorkspace ? '- ワークスペーススレッドではすべてのミニオンが参加可能。自分が貢献できる場合は積極的に参加する' : `- 自分のロール(${myProject.role})に関連する話題か`}
239
250
  - 自分が貢献できる知見や意見があるか
240
251
  - 既に十分な回答がある場合は重複を避ける
241
252
  - 人間に聞くべき場合は @user メンションを含めて返信する`
@@ -281,6 +292,9 @@ ${messageHistory || '(メッセージなし)'}
281
292
  */
282
293
  async function fallbackMemoryMatch(thread) {
283
294
  try {
295
+ // Workspace threads have no project_id — skip memory matching
296
+ if (!thread.project_id) return
297
+
284
298
  const ctx = thread.context || {}
285
299
  const category = ctx.category || ''
286
300
  const searchParam = category ? `&category=${category}` : ''
@@ -274,26 +274,30 @@ GET `/api/daemons/status` response:
274
274
  |--------|------|
275
275
  | `step_poller` | ワークフローステップの取得・実行(30秒間隔) |
276
276
  | `revision_watcher` | リビジョン要求の検知(30秒間隔、PMのみ) |
277
- | `thread_watcher` | プロジェクトスレッドの監視・LLM評価(15秒間隔) |
277
+ | `thread_watcher` | プロジェクト・ワークスペーススレッドの監視・LLM評価(15秒間隔) |
278
278
  | `reflection_scheduler` | 1日1回の振り返り(cron) |
279
279
  | `heartbeat` | HQへのハートビート(30秒間隔) |
280
280
 
281
- ### Project Threads (プロジェクトスレッド)
281
+ ### Threads (スレッド)
282
282
 
283
- プロジェクト内のコミュニケーションチャネル。ブロッカー共有やチーム議論に使う。
283
+ プロジェクト内またはワークスペースレベルのコミュニケーションチャネル。ブロッカー共有やチーム議論に使う。
284
284
  リクエストは HQ にプロキシされる。
285
285
 
286
+ **2つのスコープ:**
287
+ - **Project** (`scope: "project"`): プロジェクトに紐づくスレッド。`project_id` 必須。プロジェクトメンバーが参加。
288
+ - **Workspace** (`scope: "workspace"`): プロジェクトに属さないスレッド。ルーティンのブロッカー、全体連絡等。オーナーの全ミニオンが参加。
289
+
286
290
  | Method | Endpoint | Description |
287
291
  |--------|----------|-------------|
288
- | GET | `/api/threads` | 参加プロジェクトのオープンスレッド一覧 |
292
+ | GET | `/api/threads` | オープンスレッド一覧(プロジェクト+ワークスペース) |
289
293
  | POST | `/api/threads` | スレッドを起票(初回メッセージを同時作成) |
290
294
  | GET | `/api/threads/:id` | スレッド詳細 + メッセージ一覧 |
291
295
  | POST | `/api/threads/:id/messages` | スレッドにメッセージを投稿 |
292
296
  | POST | `/api/threads/:id/resolve` | スレッドを解決済みにする |
293
297
  | POST | `/api/threads/:id/cancel` | スレッドをキャンセル |
294
- | DELETE | `/api/threads/:id` | スレッドを完全削除(PMのみ) |
298
+ | DELETE | `/api/threads/:id` | スレッドを完全削除(project: PMのみ、workspace: オーナーの全ミニオン) |
295
299
 
296
- POST `/api/threads` body (ヘルプスレッド起票):
300
+ POST `/api/threads` body (プロジェクトスレッド — ヘルプ):
297
301
  ```json
298
302
  {
299
303
  "project_id": "uuid",
@@ -308,7 +312,23 @@ POST `/api/threads` body (ヘルプスレッド起票):
308
312
  }
309
313
  ```
310
314
 
311
- POST `/api/threads` body (ディスカッションスレッド起票):
315
+ POST `/api/threads` body (ワークスペーススレッド — ルーティンのブロッカー):
316
+ ```json
317
+ {
318
+ "scope": "workspace",
319
+ "category": "general",
320
+ "thread_type": "help",
321
+ "title": "朝作業ルーティン: APIキーの期限切れ",
322
+ "content": "外部サービスのAPIキーが期限切れでアクセスできない。更新が必要。",
323
+ "mentions": ["user"],
324
+ "context": {
325
+ "category": "auth",
326
+ "attempted_resolution": "既存のAPIキーで再試行済み、401エラー"
327
+ }
328
+ }
329
+ ```
330
+
331
+ POST `/api/threads` body (プロジェクトスレッド — ディスカッション):
312
332
  ```json
313
333
  {
314
334
  "project_id": "uuid",
@@ -321,13 +341,20 @@ POST `/api/threads` body (ディスカッションスレッド起票):
321
341
 
322
342
  | Field | Type | Required | Description |
323
343
  |-------|------|----------|-------------|
324
- | `project_id` | string | Yes | プロジェクト UUID |
344
+ | `scope` | string | No | `project`(デフォルト)or `workspace` |
345
+ | `project_id` | string | scope=project時 Yes | プロジェクト UUID |
346
+ | `category` | string | No | ワークスペーススレッドのカテゴリ: `general`(デフォルト), `ops`, `standup` |
325
347
  | `thread_type` | string | No | `help`(デフォルト)or `discussion` |
326
348
  | `title` | string | Yes | スレッドの要約 |
327
349
  | `content` | string | Yes | スレッド本文(thread_messagesの最初のメッセージとして保存) |
328
350
  | `mentions` | string[] | No | メンション対象。形式: `role:engineer`, `role:pm`, `minion:<minion_id>`, `user` |
329
351
  | `context` | object | No | 任意のメタデータ(category, urgency, workflow_execution_id等) |
330
352
 
353
+ **scope の使い分け:**
354
+ - ワークフロー実行中(プロジェクトあり)→ `scope: "project"` + `project_id`
355
+ - ルーティン実行中(プロジェクトなし)→ `scope: "workspace"`
356
+ - プロジェクト外の一般的な質問・報告 → `scope: "workspace"` + `category`
357
+
331
358
  **thread_type の違い:**
332
359
  - `help`: ブロッカー解決。`resolve` で解決
333
360
  - `discussion`: チーム内ディスカッション。`close` で完了
@@ -411,10 +438,10 @@ POST `/api/project-memories` body:
411
438
  | `source_thread_id` | string | No | 知見の出典ヘルプスレッド UUID |
412
439
 
413
440
  **推奨ワークフロー:**
414
- 1. ブロッカー発生 → `GET /api/project-memories?project_id=...&category=auth&search=2fa` で既知の知見を検索
441
+ 1. ブロッカー発生 → プロジェクトコンテキストの場合は `GET /api/project-memories?project_id=...&category=auth&search=2fa` で既知の知見を検索
415
442
  2. 該当あり → 知見に基づいて自己解決 or 即エスカレーション
416
- 3. 該当なし → `POST /api/threads` でブロッカー起票
417
- 4. 解決後 → `POST /api/project-memories` で知見を蓄積
443
+ 3. 該当なし → `POST /api/threads` でブロッカー起票(プロジェクトなら `scope: "project"` + `project_id`、ルーティンなら `scope: "workspace"`)
444
+ 4. 解決後 → プロジェクトスレッドの場合は `POST /api/project-memories` で知見を蓄積
418
445
 
419
446
  ### Commands
420
447
 
@@ -774,20 +801,20 @@ Response:
774
801
 
775
802
  スキルはバージョン管理される。push ごとに新バージョンが作成され、ファイルは Supabase Storage に保存される。
776
803
 
777
- ### Project Threads (HQ)
804
+ ### Threads (HQ)
778
805
 
779
806
  | Method | Endpoint | Description |
780
807
  |--------|----------|-------------|
781
- | POST | `/api/minion/threads` | スレッドを起票(初回メッセージを同時作成) |
782
- | GET | `/api/minion/threads/open` | 参加プロジェクトの未解決スレッド一覧 |
808
+ | POST | `/api/minion/threads` | スレッドを起票(scope, category対応。初回メッセージを同時作成) |
809
+ | GET | `/api/minion/threads/open` | 未解決スレッド一覧(`?scope=all\|project\|workspace`) |
783
810
  | GET | `/api/minion/threads/:id` | スレッド詳細 + メッセージ一覧 |
784
811
  | POST | `/api/minion/threads/:id/messages` | スレッドにメッセージを投稿 |
785
812
  | PATCH | `/api/minion/threads/:id/resolve` | スレッドを解決済みにする。Body: `{resolution}` |
786
813
  | PATCH | `/api/minion/threads/:id/cancel` | スレッドをキャンセル。Body: `{reason?}` |
787
- | DELETE | `/api/minion/threads/:id` | スレッドを完全削除(PMのみ)。メッセージもCASCADE削除 |
814
+ | DELETE | `/api/minion/threads/:id` | スレッドを完全削除(project: PMのみ、workspace: オーナーの全ミニオン)。メッセージもCASCADE削除 |
788
815
 
789
816
  ローカルエージェントの `/api/threads` は上記 HQ API へのプロキシ。
790
- 詳細なリクエスト/レスポンス仕様はローカル API セクションの「Project Threads」を参照。
817
+ 詳細なリクエスト/レスポンス仕様はローカル API セクションの「Threads」を参照。
791
818
 
792
819
  ### Project Memories (HQ)
793
820