@team-semicolon/semo-cli 4.1.5 → 4.2.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/README.md +3 -4
- package/dist/commands/audit.d.ts +27 -0
- package/dist/commands/audit.js +338 -0
- package/dist/commands/bots.js +524 -24
- package/dist/commands/context.d.ts +14 -3
- package/dist/commands/context.js +192 -113
- package/dist/commands/db.d.ts +9 -0
- package/dist/commands/db.js +189 -0
- package/dist/commands/get.d.ts +1 -2
- package/dist/commands/get.js +24 -116
- package/dist/commands/sessions.d.ts +2 -1
- package/dist/commands/sessions.js +31 -62
- package/dist/commands/skill-sync.d.ts +28 -0
- package/dist/commands/skill-sync.js +111 -0
- package/dist/commands/skill-sync.test.d.ts +16 -0
- package/dist/commands/skill-sync.test.js +186 -0
- package/dist/database.d.ts +41 -3
- package/dist/database.js +128 -554
- package/dist/env-parser.d.ts +5 -0
- package/dist/env-parser.js +27 -0
- package/dist/global-cache.d.ts +12 -0
- package/dist/global-cache.js +184 -0
- package/dist/index.js +352 -817
- package/dist/kb.d.ts +24 -39
- package/dist/kb.js +121 -175
- package/package.json +1 -1
package/dist/database.js
CHANGED
|
@@ -2,12 +2,15 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* SEMO CLI - PostgreSQL 데이터베이스 클라이언트
|
|
4
4
|
*
|
|
5
|
-
*
|
|
5
|
+
* 스킬, 커맨드, 에이전트 정보를 조회합니다.
|
|
6
6
|
* DB 연결 실패 시 하드코딩된 폴백 데이터를 사용합니다.
|
|
7
7
|
*
|
|
8
8
|
* v3.14.0: Supabase → PostgreSQL 전환
|
|
9
|
-
*
|
|
10
|
-
*
|
|
9
|
+
* v4.0.0: 스키마 통합 — SoT를 *_definitions 테이블로 변경
|
|
10
|
+
* - skill_definitions (prompt as content)
|
|
11
|
+
* - agent_definitions (persona_prompt as content)
|
|
12
|
+
* - command_definitions (prompt as content)
|
|
13
|
+
* - semo.skills / semo.agents / semo.commands 는 하위 호환 뷰
|
|
11
14
|
*/
|
|
12
15
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
13
16
|
if (k2 === undefined) k2 = k;
|
|
@@ -46,16 +49,20 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
46
49
|
exports.getPool = getPool;
|
|
47
50
|
exports.getActiveSkills = getActiveSkills;
|
|
48
51
|
exports.getActiveSkillNames = getActiveSkillNames;
|
|
52
|
+
exports.getActiveSkillsForBot = getActiveSkillsForBot;
|
|
49
53
|
exports.getCommands = getCommands;
|
|
50
54
|
exports.getAgents = getAgents;
|
|
51
55
|
exports.getPackages = getPackages;
|
|
52
56
|
exports.getSkillCountByCategory = getSkillCountByCategory;
|
|
57
|
+
exports.getDelegations = getDelegations;
|
|
58
|
+
exports.getProtocol = getProtocol;
|
|
53
59
|
exports.closeConnection = closeConnection;
|
|
54
60
|
exports.isDbConnected = isDbConnected;
|
|
55
61
|
const pg_1 = require("pg");
|
|
56
62
|
const fs = __importStar(require("fs"));
|
|
57
63
|
const os = __importStar(require("os"));
|
|
58
64
|
const path = __importStar(require("path"));
|
|
65
|
+
const env_parser_1 = require("./env-parser");
|
|
59
66
|
// ~/.semo.env 자동 로드 — LaunchAgent / Claude Code 앱 / cron 등
|
|
60
67
|
// 인터랙티브 쉘이 아닌 환경에서 환경변수를 공급한다.
|
|
61
68
|
// 이미 설정된 환경변수는 덮어쓰지 않는다 (env var > file).
|
|
@@ -64,20 +71,9 @@ function loadSemoEnv() {
|
|
|
64
71
|
if (!fs.existsSync(envFile))
|
|
65
72
|
return;
|
|
66
73
|
try {
|
|
67
|
-
const
|
|
68
|
-
for (const
|
|
69
|
-
|
|
70
|
-
if (!line || line.startsWith("#"))
|
|
71
|
-
continue;
|
|
72
|
-
const eqIdx = line.indexOf("=");
|
|
73
|
-
if (eqIdx === -1)
|
|
74
|
-
continue;
|
|
75
|
-
const key = line.slice(0, eqIdx).trim();
|
|
76
|
-
let val = line.slice(eqIdx + 1).trim();
|
|
77
|
-
if ((val.startsWith("'") && val.endsWith("'")) || (val.startsWith('"') && val.endsWith('"'))) {
|
|
78
|
-
val = val.slice(1, -1);
|
|
79
|
-
}
|
|
80
|
-
if (key && !process.env[key])
|
|
74
|
+
const creds = (0, env_parser_1.parseEnvContent)(fs.readFileSync(envFile, "utf8"));
|
|
75
|
+
for (const [key, val] of Object.entries(creds)) {
|
|
76
|
+
if (!process.env[key])
|
|
81
77
|
process.env[key] = val;
|
|
82
78
|
}
|
|
83
79
|
}
|
|
@@ -139,554 +135,45 @@ async function checkDbConnection() {
|
|
|
139
135
|
// ============================================================
|
|
140
136
|
// 폴백 데이터 (DB 연결 실패 시 사용)
|
|
141
137
|
// ============================================================
|
|
142
|
-
const FALLBACK_SKILLS = [
|
|
143
|
-
|
|
144
|
-
{
|
|
145
|
-
id: "sk-1",
|
|
146
|
-
name: "workflow-start",
|
|
147
|
-
display_name: "워크플로우 시작",
|
|
148
|
-
description: "워크플로우 인스턴스 생성 및 시작",
|
|
149
|
-
content: `---
|
|
150
|
-
name: workflow-start
|
|
151
|
-
description: 워크플로우 인스턴스 생성 및 시작
|
|
152
|
-
---
|
|
153
|
-
|
|
154
|
-
# workflow-start
|
|
155
|
-
|
|
156
|
-
워크플로우 인스턴스를 생성하고 시작합니다.
|
|
157
|
-
|
|
158
|
-
## Usage
|
|
159
|
-
|
|
160
|
-
\`\`\`
|
|
161
|
-
skill:workflow-start workflow_command="greenfield"
|
|
162
|
-
\`\`\`
|
|
163
|
-
`,
|
|
164
|
-
category: "workflow",
|
|
165
|
-
package: "core",
|
|
166
|
-
is_active: true,
|
|
167
|
-
is_required: true,
|
|
168
|
-
install_order: 1,
|
|
169
|
-
version: "1.0.0",
|
|
170
|
-
},
|
|
171
|
-
{
|
|
172
|
-
id: "sk-2",
|
|
173
|
-
name: "workflow-progress",
|
|
174
|
-
display_name: "워크플로우 진행",
|
|
175
|
-
description: "워크플로우 진행 상황 조회",
|
|
176
|
-
content: `---
|
|
177
|
-
name: workflow-progress
|
|
178
|
-
description: 워크플로우 진행 상황 조회
|
|
179
|
-
---
|
|
180
|
-
|
|
181
|
-
# workflow-progress
|
|
182
|
-
|
|
183
|
-
진행 중인 워크플로우의 현재 상태를 조회합니다.
|
|
184
|
-
`,
|
|
185
|
-
category: "workflow",
|
|
186
|
-
package: "core",
|
|
187
|
-
is_active: true,
|
|
188
|
-
is_required: true,
|
|
189
|
-
install_order: 2,
|
|
190
|
-
version: "1.0.0",
|
|
191
|
-
},
|
|
192
|
-
{
|
|
193
|
-
id: "sk-3",
|
|
194
|
-
name: "workflow-resume",
|
|
195
|
-
display_name: "워크플로우 재개",
|
|
196
|
-
description: "중단된 워크플로우 재개",
|
|
197
|
-
content: `---
|
|
198
|
-
name: workflow-resume
|
|
199
|
-
description: 중단된 워크플로우 재개
|
|
200
|
-
---
|
|
201
|
-
|
|
202
|
-
# workflow-resume
|
|
203
|
-
|
|
204
|
-
중단된 워크플로우를 재개합니다.
|
|
205
|
-
`,
|
|
206
|
-
category: "workflow",
|
|
207
|
-
package: "core",
|
|
208
|
-
is_active: true,
|
|
209
|
-
is_required: true,
|
|
210
|
-
install_order: 3,
|
|
211
|
-
version: "1.0.0",
|
|
212
|
-
},
|
|
213
|
-
// Discovery (1개)
|
|
214
|
-
{
|
|
215
|
-
id: "sk-10",
|
|
216
|
-
name: "ideate",
|
|
217
|
-
display_name: "아이디에이션",
|
|
218
|
-
description: "아이디어 발굴 및 분석",
|
|
219
|
-
content: `---
|
|
220
|
-
name: ideate
|
|
221
|
-
description: 아이디어 발굴 및 분석
|
|
222
|
-
---
|
|
223
|
-
|
|
224
|
-
# ideate
|
|
225
|
-
|
|
226
|
-
새로운 아이디어를 발굴하고 분석합니다.
|
|
227
|
-
`,
|
|
228
|
-
category: "discovery",
|
|
229
|
-
package: "core",
|
|
230
|
-
is_active: true,
|
|
231
|
-
is_required: true,
|
|
232
|
-
install_order: 10,
|
|
233
|
-
version: "1.0.0",
|
|
234
|
-
},
|
|
235
|
-
// Planning (3개)
|
|
236
|
-
{
|
|
237
|
-
id: "sk-20",
|
|
238
|
-
name: "create-epic",
|
|
239
|
-
display_name: "Epic 생성",
|
|
240
|
-
description: "Epic 이슈 생성",
|
|
241
|
-
content: `---
|
|
242
|
-
name: create-epic
|
|
243
|
-
description: Epic 이슈 생성
|
|
244
|
-
---
|
|
245
|
-
|
|
246
|
-
# create-epic
|
|
247
|
-
|
|
248
|
-
Epic 이슈를 생성합니다.
|
|
249
|
-
`,
|
|
250
|
-
category: "planning",
|
|
251
|
-
package: "core",
|
|
252
|
-
is_active: true,
|
|
253
|
-
is_required: true,
|
|
254
|
-
install_order: 20,
|
|
255
|
-
version: "1.0.0",
|
|
256
|
-
},
|
|
257
|
-
{
|
|
258
|
-
id: "sk-21",
|
|
259
|
-
name: "design-user-flow",
|
|
260
|
-
display_name: "사용자 흐름 설계",
|
|
261
|
-
description: "UX 사용자 흐름 다이어그램 설계",
|
|
262
|
-
content: `---
|
|
263
|
-
name: design-user-flow
|
|
264
|
-
description: UX 사용자 흐름 다이어그램 설계
|
|
265
|
-
---
|
|
266
|
-
|
|
267
|
-
# design-user-flow
|
|
268
|
-
|
|
269
|
-
사용자 흐름을 설계합니다.
|
|
270
|
-
`,
|
|
271
|
-
category: "planning",
|
|
272
|
-
package: "core",
|
|
273
|
-
is_active: true,
|
|
274
|
-
is_required: true,
|
|
275
|
-
install_order: 21,
|
|
276
|
-
version: "1.0.0",
|
|
277
|
-
},
|
|
278
|
-
{
|
|
279
|
-
id: "sk-22",
|
|
280
|
-
name: "generate-mockup",
|
|
281
|
-
display_name: "목업 생성",
|
|
282
|
-
description: "UI 목업 생성",
|
|
283
|
-
content: `---
|
|
284
|
-
name: generate-mockup
|
|
285
|
-
description: UI 목업 생성
|
|
286
|
-
---
|
|
287
|
-
|
|
288
|
-
# generate-mockup
|
|
289
|
-
|
|
290
|
-
UI 목업을 생성합니다.
|
|
291
|
-
`,
|
|
292
|
-
category: "planning",
|
|
293
|
-
package: "core",
|
|
294
|
-
is_active: true,
|
|
295
|
-
is_required: true,
|
|
296
|
-
install_order: 22,
|
|
297
|
-
version: "1.0.0",
|
|
298
|
-
},
|
|
299
|
-
// Solutioning (4개)
|
|
300
|
-
{
|
|
301
|
-
id: "sk-30",
|
|
302
|
-
name: "scaffold-domain",
|
|
303
|
-
display_name: "도메인 스캐폴딩",
|
|
304
|
-
description: "DDD 4-layer 도메인 구조 생성",
|
|
305
|
-
content: `---
|
|
306
|
-
name: scaffold-domain
|
|
307
|
-
description: DDD 4-layer 도메인 구조 생성
|
|
308
|
-
---
|
|
309
|
-
|
|
310
|
-
# scaffold-domain
|
|
311
|
-
|
|
312
|
-
DDD 4-layer 도메인 구조를 생성합니다.
|
|
313
|
-
`,
|
|
314
|
-
category: "solutioning",
|
|
315
|
-
package: "core",
|
|
316
|
-
is_active: true,
|
|
317
|
-
is_required: true,
|
|
318
|
-
install_order: 30,
|
|
319
|
-
version: "1.0.0",
|
|
320
|
-
},
|
|
321
|
-
{
|
|
322
|
-
id: "sk-31",
|
|
323
|
-
name: "validate-architecture",
|
|
324
|
-
display_name: "아키텍처 검증",
|
|
325
|
-
description: "DDD 4-layer 아키텍처 준수 검증",
|
|
326
|
-
content: `---
|
|
327
|
-
name: validate-architecture
|
|
328
|
-
description: DDD 4-layer 아키텍처 준수 검증
|
|
329
|
-
---
|
|
330
|
-
|
|
331
|
-
# validate-architecture
|
|
332
|
-
|
|
333
|
-
아키텍처 준수 여부를 검증합니다.
|
|
334
|
-
`,
|
|
335
|
-
category: "solutioning",
|
|
336
|
-
package: "core",
|
|
337
|
-
is_active: true,
|
|
338
|
-
is_required: true,
|
|
339
|
-
install_order: 31,
|
|
340
|
-
version: "1.0.0",
|
|
341
|
-
},
|
|
342
|
-
{
|
|
343
|
-
id: "sk-32",
|
|
344
|
-
name: "generate-spec",
|
|
345
|
-
display_name: "명세 생성",
|
|
346
|
-
description: "Speckit 워크플로우 통합 실행",
|
|
347
|
-
content: `---
|
|
348
|
-
name: generate-spec
|
|
349
|
-
description: Speckit 워크플로우 통합 실행
|
|
350
|
-
---
|
|
351
|
-
|
|
352
|
-
# generate-spec
|
|
353
|
-
|
|
354
|
-
명세 문서를 생성합니다.
|
|
355
|
-
`,
|
|
356
|
-
category: "solutioning",
|
|
357
|
-
package: "core",
|
|
358
|
-
is_active: true,
|
|
359
|
-
is_required: true,
|
|
360
|
-
install_order: 32,
|
|
361
|
-
version: "1.0.0",
|
|
362
|
-
},
|
|
363
|
-
{
|
|
364
|
-
id: "sk-33",
|
|
365
|
-
name: "design-tests",
|
|
366
|
-
display_name: "테스트 설계",
|
|
367
|
-
description: "구현 전 테스트 케이스 설계 (TDD)",
|
|
368
|
-
content: `---
|
|
369
|
-
name: design-tests
|
|
370
|
-
description: 구현 전 테스트 케이스 설계 (TDD)
|
|
371
|
-
---
|
|
372
|
-
|
|
373
|
-
# design-tests
|
|
374
|
-
|
|
375
|
-
테스트 케이스를 설계합니다.
|
|
376
|
-
`,
|
|
377
|
-
category: "solutioning",
|
|
378
|
-
package: "core",
|
|
379
|
-
is_active: true,
|
|
380
|
-
is_required: true,
|
|
381
|
-
install_order: 33,
|
|
382
|
-
version: "1.0.0",
|
|
383
|
-
},
|
|
384
|
-
// Implementation (6개)
|
|
385
|
-
{
|
|
386
|
-
id: "sk-40",
|
|
387
|
-
name: "create-sprint",
|
|
388
|
-
display_name: "스프린트 생성",
|
|
389
|
-
description: "Sprint 목표 설정 및 시작",
|
|
390
|
-
content: `---
|
|
391
|
-
name: create-sprint
|
|
392
|
-
description: Sprint 목표 설정 및 시작
|
|
393
|
-
---
|
|
394
|
-
|
|
395
|
-
# create-sprint
|
|
396
|
-
|
|
397
|
-
스프린트를 생성하고 시작합니다.
|
|
398
|
-
`,
|
|
399
|
-
category: "implementation",
|
|
400
|
-
package: "core",
|
|
401
|
-
is_active: true,
|
|
402
|
-
is_required: true,
|
|
403
|
-
install_order: 40,
|
|
404
|
-
version: "1.0.0",
|
|
405
|
-
},
|
|
406
|
-
{
|
|
407
|
-
id: "sk-41",
|
|
408
|
-
name: "start-task",
|
|
409
|
-
display_name: "태스크 시작",
|
|
410
|
-
description: "작업 시작 (이슈 상태 변경, 브랜치 생성)",
|
|
411
|
-
content: `---
|
|
412
|
-
name: start-task
|
|
413
|
-
description: 작업 시작 (이슈 상태 변경, 브랜치 생성)
|
|
414
|
-
---
|
|
415
|
-
|
|
416
|
-
# start-task
|
|
417
|
-
|
|
418
|
-
태스크를 시작합니다.
|
|
419
|
-
`,
|
|
420
|
-
category: "implementation",
|
|
421
|
-
package: "core",
|
|
422
|
-
is_active: true,
|
|
423
|
-
is_required: true,
|
|
424
|
-
install_order: 41,
|
|
425
|
-
version: "1.0.0",
|
|
426
|
-
},
|
|
427
|
-
{
|
|
428
|
-
id: "sk-42",
|
|
429
|
-
name: "review-task",
|
|
430
|
-
display_name: "태스크 리뷰",
|
|
431
|
-
description: "태스크 이슈 기반 구현 완료 리뷰",
|
|
432
|
-
content: `---
|
|
433
|
-
name: review-task
|
|
434
|
-
description: 태스크 이슈 기반 구현 완료 리뷰
|
|
435
|
-
---
|
|
436
|
-
|
|
437
|
-
# review-task
|
|
438
|
-
|
|
439
|
-
태스크 구현을 리뷰합니다.
|
|
440
|
-
`,
|
|
441
|
-
category: "implementation",
|
|
442
|
-
package: "core",
|
|
443
|
-
is_active: true,
|
|
444
|
-
is_required: true,
|
|
445
|
-
install_order: 42,
|
|
446
|
-
version: "1.0.0",
|
|
447
|
-
},
|
|
448
|
-
{
|
|
449
|
-
id: "sk-43",
|
|
450
|
-
name: "write-code",
|
|
451
|
-
display_name: "코드 작성",
|
|
452
|
-
description: "코드 작성, 수정, 구현",
|
|
453
|
-
content: `---
|
|
454
|
-
name: write-code
|
|
455
|
-
description: 코드 작성, 수정, 구현
|
|
456
|
-
---
|
|
457
|
-
|
|
458
|
-
# write-code
|
|
459
|
-
|
|
460
|
-
코드를 작성합니다.
|
|
461
|
-
`,
|
|
462
|
-
category: "implementation",
|
|
463
|
-
package: "core",
|
|
464
|
-
is_active: true,
|
|
465
|
-
is_required: true,
|
|
466
|
-
install_order: 43,
|
|
467
|
-
version: "1.0.0",
|
|
468
|
-
},
|
|
469
|
-
{
|
|
470
|
-
id: "sk-44",
|
|
471
|
-
name: "run-code-review",
|
|
472
|
-
display_name: "코드 리뷰",
|
|
473
|
-
description: "프로젝트 통합 코드 리뷰",
|
|
474
|
-
content: `---
|
|
475
|
-
name: run-code-review
|
|
476
|
-
description: 프로젝트 통합 코드 리뷰
|
|
477
|
-
---
|
|
478
|
-
|
|
479
|
-
# run-code-review
|
|
480
|
-
|
|
481
|
-
코드 리뷰를 실행합니다.
|
|
482
|
-
`,
|
|
483
|
-
category: "implementation",
|
|
484
|
-
package: "core",
|
|
485
|
-
is_active: true,
|
|
486
|
-
is_required: true,
|
|
487
|
-
install_order: 44,
|
|
488
|
-
version: "1.0.0",
|
|
489
|
-
},
|
|
490
|
-
{
|
|
491
|
-
id: "sk-45",
|
|
492
|
-
name: "close-sprint",
|
|
493
|
-
display_name: "스프린트 종료",
|
|
494
|
-
description: "Sprint 종료 및 회고 정리",
|
|
495
|
-
content: `---
|
|
496
|
-
name: close-sprint
|
|
497
|
-
description: Sprint 종료 및 회고 정리
|
|
498
|
-
---
|
|
499
|
-
|
|
500
|
-
# close-sprint
|
|
501
|
-
|
|
502
|
-
스프린트를 종료합니다.
|
|
503
|
-
`,
|
|
504
|
-
category: "implementation",
|
|
505
|
-
package: "core",
|
|
506
|
-
is_active: true,
|
|
507
|
-
is_required: true,
|
|
508
|
-
install_order: 45,
|
|
509
|
-
version: "1.0.0",
|
|
510
|
-
},
|
|
511
|
-
// Supporting (2개)
|
|
512
|
-
{
|
|
513
|
-
id: "sk-50",
|
|
514
|
-
name: "git-workflow",
|
|
515
|
-
display_name: "Git 워크플로우",
|
|
516
|
-
description: "Git 커밋/푸시/PR 자동화",
|
|
517
|
-
content: `---
|
|
518
|
-
name: git-workflow
|
|
519
|
-
description: Git 커밋/푸시/PR 자동화
|
|
520
|
-
---
|
|
521
|
-
|
|
522
|
-
# git-workflow
|
|
523
|
-
|
|
524
|
-
Git 워크플로우를 자동화합니다.
|
|
525
|
-
`,
|
|
526
|
-
category: "supporting",
|
|
527
|
-
package: "core",
|
|
528
|
-
is_active: true,
|
|
529
|
-
is_required: true,
|
|
530
|
-
install_order: 50,
|
|
531
|
-
version: "1.0.0",
|
|
532
|
-
},
|
|
533
|
-
{
|
|
534
|
-
id: "sk-51",
|
|
535
|
-
name: "notify-slack",
|
|
536
|
-
display_name: "Slack 알림",
|
|
537
|
-
description: "Slack 채널에 메시지 전송",
|
|
538
|
-
content: `---
|
|
539
|
-
name: notify-slack
|
|
540
|
-
description: Slack 채널에 메시지 전송
|
|
541
|
-
---
|
|
542
|
-
|
|
543
|
-
# notify-slack
|
|
544
|
-
|
|
545
|
-
Slack에 알림을 전송합니다.
|
|
546
|
-
`,
|
|
547
|
-
category: "supporting",
|
|
548
|
-
package: "core",
|
|
549
|
-
is_active: true,
|
|
550
|
-
is_required: true,
|
|
551
|
-
install_order: 51,
|
|
552
|
-
version: "1.0.0",
|
|
553
|
-
},
|
|
554
|
-
];
|
|
555
|
-
const FALLBACK_COMMANDS = [
|
|
556
|
-
{
|
|
557
|
-
id: "cmd-1",
|
|
558
|
-
name: "help",
|
|
559
|
-
folder: "SEMO",
|
|
560
|
-
content: `# /SEMO:help
|
|
561
|
-
|
|
562
|
-
SEMO 도움말을 표시합니다.
|
|
563
|
-
|
|
564
|
-
## Usage
|
|
565
|
-
|
|
566
|
-
\`\`\`
|
|
567
|
-
/SEMO:help
|
|
568
|
-
\`\`\`
|
|
569
|
-
`,
|
|
570
|
-
description: "SEMO 도움말",
|
|
571
|
-
is_active: true,
|
|
572
|
-
},
|
|
573
|
-
{
|
|
574
|
-
id: "cmd-2",
|
|
575
|
-
name: "dry-run",
|
|
576
|
-
folder: "SEMO",
|
|
577
|
-
content: `# /SEMO:dry-run
|
|
578
|
-
|
|
579
|
-
명령을 실행하지 않고 라우팅 결과만 확인합니다.
|
|
580
|
-
|
|
581
|
-
## Usage
|
|
582
|
-
|
|
583
|
-
\`\`\`
|
|
584
|
-
/SEMO:dry-run {프롬프트}
|
|
585
|
-
\`\`\`
|
|
586
|
-
`,
|
|
587
|
-
description: "명령 검증 (라우팅 시뮬레이션)",
|
|
588
|
-
is_active: true,
|
|
589
|
-
},
|
|
590
|
-
{
|
|
591
|
-
id: "cmd-3",
|
|
592
|
-
name: "greenfield",
|
|
593
|
-
folder: "SEMO-workflow",
|
|
594
|
-
content: `# /SEMO-workflow:greenfield
|
|
595
|
-
|
|
596
|
-
BMad Method Greenfield Workflow를 시작합니다.
|
|
597
|
-
|
|
598
|
-
## Purpose
|
|
599
|
-
|
|
600
|
-
새로운 프로젝트를 처음부터 구축하는 4-Phase 워크플로우입니다.
|
|
601
|
-
|
|
602
|
-
\`\`\`
|
|
603
|
-
Phase 1: Discovery (Optional) - 아이디어 발굴 및 분석
|
|
604
|
-
Phase 2: Planning (Required) - PRD/Epic 생성 및 UX 설계
|
|
605
|
-
Phase 3: Solutioning (Required) - 아키텍처 및 명세 작성
|
|
606
|
-
Phase 4: Implementation (Required) - 스프린트 기반 개발
|
|
607
|
-
\`\`\`
|
|
608
|
-
|
|
609
|
-
## Usage
|
|
610
|
-
|
|
611
|
-
\`\`\`
|
|
612
|
-
/SEMO-workflow:greenfield
|
|
613
|
-
\`\`\`
|
|
614
|
-
`,
|
|
615
|
-
description: "Greenfield 워크플로우 시작",
|
|
616
|
-
is_active: true,
|
|
617
|
-
},
|
|
618
|
-
];
|
|
138
|
+
const FALLBACK_SKILLS = [];
|
|
139
|
+
const FALLBACK_COMMANDS = [];
|
|
619
140
|
const FALLBACK_AGENTS = [
|
|
620
|
-
{
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
name:
|
|
626
|
-
|
|
627
|
-
---
|
|
628
|
-
|
|
629
|
-
# Orchestrator Agent
|
|
630
|
-
|
|
631
|
-
사용자 요청을 분석하고 적절한 Agent/Skill로 라우팅합니다.
|
|
632
|
-
|
|
633
|
-
## Routing Table
|
|
634
|
-
|
|
635
|
-
| Intent | Agent/Skill |
|
|
636
|
-
|--------|-------------|
|
|
637
|
-
| 코드 작성 | write-code |
|
|
638
|
-
| Git 커밋 | git-workflow |
|
|
639
|
-
| 테스트 작성 | write-test |
|
|
640
|
-
`,
|
|
641
|
-
package: "core",
|
|
642
|
-
is_active: true,
|
|
643
|
-
install_order: 1,
|
|
644
|
-
},
|
|
141
|
+
{ id: "agent-semiclaw", name: "semiclaw", display_name: "SemiClaw 🦀", content: "", package: "openclaw", is_active: true, install_order: 1 },
|
|
142
|
+
{ id: "agent-workclaw", name: "workclaw", display_name: "WorkClaw 🛠️", content: "", package: "openclaw", is_active: true, install_order: 2 },
|
|
143
|
+
{ id: "agent-reviewclaw", name: "reviewclaw", display_name: "ReviewClaw 🔍", content: "", package: "openclaw", is_active: true, install_order: 3 },
|
|
144
|
+
{ id: "agent-planclaw", name: "planclaw", display_name: "PlanClaw 🗓️", content: "", package: "openclaw", is_active: true, install_order: 4 },
|
|
145
|
+
{ id: "agent-designclaw", name: "designclaw", display_name: "DesignClaw 🎨", content: "", package: "openclaw", is_active: true, install_order: 5 },
|
|
146
|
+
{ id: "agent-infraclaw", name: "infraclaw", display_name: "InfraClaw 🏗️", content: "", package: "openclaw", is_active: true, install_order: 6 },
|
|
147
|
+
{ id: "agent-growthclaw", name: "growthclaw", display_name: "GrowthClaw 🌱", content: "", package: "openclaw", is_active: true, install_order: 7 },
|
|
645
148
|
];
|
|
646
149
|
const FALLBACK_PACKAGES = [
|
|
647
|
-
{
|
|
648
|
-
|
|
649
|
-
name: "semo-core",
|
|
650
|
-
display_name: "SEMO Core",
|
|
651
|
-
description: "원칙, 오케스트레이터",
|
|
652
|
-
layer: "standard",
|
|
653
|
-
package_type: "standard",
|
|
654
|
-
version: "3.14.0",
|
|
655
|
-
is_active: true,
|
|
656
|
-
is_required: true,
|
|
657
|
-
install_order: 10,
|
|
658
|
-
},
|
|
659
|
-
{
|
|
660
|
-
id: "pkg-skills",
|
|
661
|
-
name: "semo-skills",
|
|
662
|
-
display_name: "SEMO Skills",
|
|
663
|
-
description: "19개 핵심 스킬",
|
|
664
|
-
layer: "standard",
|
|
665
|
-
package_type: "standard",
|
|
666
|
-
version: "3.14.0",
|
|
667
|
-
is_active: true,
|
|
668
|
-
is_required: true,
|
|
669
|
-
install_order: 20,
|
|
670
|
-
},
|
|
150
|
+
{ id: "pkg-cli", name: "semo-cli", display_name: "SEMO CLI", description: "CLI 도구 (컨텍스트 동기화, 봇 관리)", layer: "standard", package_type: "standard", version: "4.2.0", is_active: true, is_required: true, install_order: 10 },
|
|
151
|
+
{ id: "pkg-dashboard", name: "semo-dashboard", display_name: "SEMO Dashboard", description: "봇 상태/KB 대시보드", layer: "standard", package_type: "standard", version: "0.1.0", is_active: true, is_required: false, install_order: 30 },
|
|
671
152
|
];
|
|
672
153
|
// ============================================================
|
|
673
154
|
// DB 조회 함수
|
|
674
155
|
// ============================================================
|
|
675
156
|
/**
|
|
676
157
|
* 활성 스킬 목록 조회
|
|
158
|
+
* SoT: skill_definitions (prompt as content — CLI 인터페이스 유지)
|
|
677
159
|
*/
|
|
678
160
|
async function getActiveSkills() {
|
|
679
161
|
const isConnected = await checkDbConnection();
|
|
680
162
|
if (!isConnected) {
|
|
681
|
-
console.warn("⚠️ DB 연결 실패, 폴백 스킬 목록 사용
|
|
163
|
+
console.warn("⚠️ DB 연결 실패, 폴백 스킬 목록 사용");
|
|
682
164
|
return FALLBACK_SKILLS.filter((s) => s.is_active);
|
|
683
165
|
}
|
|
684
166
|
try {
|
|
685
167
|
const result = await getPool().query(`
|
|
686
|
-
SELECT id, name, display_name, description,
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
168
|
+
SELECT id, name, display_name, description,
|
|
169
|
+
prompt AS content,
|
|
170
|
+
COALESCE(
|
|
171
|
+
ARRAY(SELECT jsonb_array_elements_text(metadata->'bot_ids')),
|
|
172
|
+
ARRAY[]::text[]
|
|
173
|
+
) AS bot_ids,
|
|
174
|
+
category, package, is_active, is_required, install_order, version
|
|
175
|
+
FROM skill_definitions
|
|
176
|
+
WHERE is_active = true AND office_id IS NULL
|
|
690
177
|
ORDER BY install_order
|
|
691
178
|
`);
|
|
692
179
|
return result.rows;
|
|
@@ -703,8 +190,42 @@ async function getActiveSkillNames() {
|
|
|
703
190
|
const skills = await getActiveSkills();
|
|
704
191
|
return skills.map((s) => s.name);
|
|
705
192
|
}
|
|
193
|
+
/**
|
|
194
|
+
* 특정 봇의 스킬 목록 조회 (공유 + 봇 전용)
|
|
195
|
+
* skill_definitions.target_agents 배열로 매핑 — 전용 스킬 먼저, 공유 스킬 뒤
|
|
196
|
+
*/
|
|
197
|
+
async function getActiveSkillsForBot(botId) {
|
|
198
|
+
const isConnected = await checkDbConnection();
|
|
199
|
+
if (!isConnected) {
|
|
200
|
+
console.warn("⚠️ DB 연결 실패, 폴백 스킬 목록 사용");
|
|
201
|
+
return FALLBACK_SKILLS.filter((s) => s.is_active);
|
|
202
|
+
}
|
|
203
|
+
try {
|
|
204
|
+
const result = await getPool().query(`SELECT sd.id, sd.name, sd.display_name, sd.description,
|
|
205
|
+
sd.prompt AS content,
|
|
206
|
+
COALESCE(
|
|
207
|
+
ARRAY(SELECT jsonb_array_elements_text(sd.metadata->'bot_ids')),
|
|
208
|
+
ARRAY[]::text[]
|
|
209
|
+
) AS bot_ids,
|
|
210
|
+
sd.category, sd.package, sd.is_active, sd.is_required,
|
|
211
|
+
sd.install_order, sd.version
|
|
212
|
+
FROM skill_definitions sd
|
|
213
|
+
WHERE sd.is_active = true
|
|
214
|
+
AND sd.office_id IS NULL
|
|
215
|
+
AND (NOT sd.metadata ? 'bot_ids' OR sd.metadata->'bot_ids' ? $1)
|
|
216
|
+
ORDER BY
|
|
217
|
+
CASE WHEN sd.metadata->'bot_ids' ? $1 THEN 0 ELSE 1 END,
|
|
218
|
+
sd.install_order`, [botId]);
|
|
219
|
+
return result.rows;
|
|
220
|
+
}
|
|
221
|
+
catch (error) {
|
|
222
|
+
console.warn("⚠️ 봇 스킬 조회 실패, 폴백 데이터 사용:", error);
|
|
223
|
+
return FALLBACK_SKILLS.filter((s) => s.is_active);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
706
226
|
/**
|
|
707
227
|
* 커맨드 목록 조회
|
|
228
|
+
* SoT: command_definitions (prompt as content — CLI 인터페이스 유지)
|
|
708
229
|
*/
|
|
709
230
|
async function getCommands() {
|
|
710
231
|
const isConnected = await checkDbConnection();
|
|
@@ -714,9 +235,11 @@ async function getCommands() {
|
|
|
714
235
|
}
|
|
715
236
|
try {
|
|
716
237
|
const result = await getPool().query(`
|
|
717
|
-
SELECT id, name, folder,
|
|
718
|
-
|
|
719
|
-
|
|
238
|
+
SELECT id, name, folder,
|
|
239
|
+
prompt AS content,
|
|
240
|
+
description, is_active
|
|
241
|
+
FROM command_definitions
|
|
242
|
+
WHERE is_active = true AND office_id IS NULL
|
|
720
243
|
`);
|
|
721
244
|
return result.rows;
|
|
722
245
|
}
|
|
@@ -727,6 +250,7 @@ async function getCommands() {
|
|
|
727
250
|
}
|
|
728
251
|
/**
|
|
729
252
|
* 에이전트 목록 조회
|
|
253
|
+
* SoT: agent_definitions (persona_prompt as content — CLI 인터페이스 유지)
|
|
730
254
|
*/
|
|
731
255
|
async function getAgents() {
|
|
732
256
|
const isConnected = await checkDbConnection();
|
|
@@ -736,9 +260,11 @@ async function getAgents() {
|
|
|
736
260
|
}
|
|
737
261
|
try {
|
|
738
262
|
const result = await getPool().query(`
|
|
739
|
-
SELECT id, name,
|
|
740
|
-
|
|
741
|
-
|
|
263
|
+
SELECT id, name, name AS display_name,
|
|
264
|
+
persona_prompt AS content,
|
|
265
|
+
package, is_active, install_order
|
|
266
|
+
FROM agent_definitions
|
|
267
|
+
WHERE is_active = true AND office_id IS NULL
|
|
742
268
|
ORDER BY install_order
|
|
743
269
|
`);
|
|
744
270
|
return result.rows;
|
|
@@ -791,6 +317,54 @@ async function getSkillCountByCategory() {
|
|
|
791
317
|
}
|
|
792
318
|
return counts;
|
|
793
319
|
}
|
|
320
|
+
/**
|
|
321
|
+
* 위임 매트릭스 조회
|
|
322
|
+
*/
|
|
323
|
+
async function getDelegations(botId) {
|
|
324
|
+
const isConnected = await checkDbConnection();
|
|
325
|
+
if (!isConnected)
|
|
326
|
+
return [];
|
|
327
|
+
try {
|
|
328
|
+
let query = `
|
|
329
|
+
SELECT id, from_bot_id, to_bot_id, delegation_type,
|
|
330
|
+
domains, method, channel, max_roundtrips, priority, is_active
|
|
331
|
+
FROM semo.bot_delegation
|
|
332
|
+
WHERE is_active = true
|
|
333
|
+
`;
|
|
334
|
+
const params = [];
|
|
335
|
+
if (botId) {
|
|
336
|
+
query += ` AND from_bot_id = $1`;
|
|
337
|
+
params.push(botId);
|
|
338
|
+
}
|
|
339
|
+
query += ` ORDER BY from_bot_id, to_bot_id`;
|
|
340
|
+
const result = await getPool().query(query, params);
|
|
341
|
+
return result.rows;
|
|
342
|
+
}
|
|
343
|
+
catch {
|
|
344
|
+
// Table may not exist yet
|
|
345
|
+
return [];
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* 프로토콜 메타데이터 조회
|
|
350
|
+
*/
|
|
351
|
+
async function getProtocol() {
|
|
352
|
+
const isConnected = await checkDbConnection();
|
|
353
|
+
if (!isConnected)
|
|
354
|
+
return [];
|
|
355
|
+
try {
|
|
356
|
+
const result = await getPool().query(`
|
|
357
|
+
SELECT id, key, value, description
|
|
358
|
+
FROM semo.bot_protocol
|
|
359
|
+
ORDER BY key
|
|
360
|
+
`);
|
|
361
|
+
return result.rows;
|
|
362
|
+
}
|
|
363
|
+
catch {
|
|
364
|
+
// Table may not exist yet
|
|
365
|
+
return [];
|
|
366
|
+
}
|
|
367
|
+
}
|
|
794
368
|
/**
|
|
795
369
|
* DB 연결 종료
|
|
796
370
|
*/
|