@elyun/bylane 1.0.0 → 1.1.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.
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"trackers": {
|
|
3
|
+
"primary": "github",
|
|
4
|
+
"linear": {
|
|
5
|
+
"enabled": false
|
|
6
|
+
}
|
|
7
|
+
},
|
|
8
|
+
"notifications": {
|
|
9
|
+
"telegram": {
|
|
10
|
+
"enabled": true,
|
|
11
|
+
"chatIdEnv": "TELEGRAM_CHAT_ID",
|
|
12
|
+
"botTokenEnv": "TELEGRAM_BOT_TOKEN"
|
|
13
|
+
},
|
|
14
|
+
"slack": {
|
|
15
|
+
"enabled": false
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"team": {
|
|
19
|
+
"enabled": true,
|
|
20
|
+
"members": [],
|
|
21
|
+
"reviewAssignment": "round-robin"
|
|
22
|
+
},
|
|
23
|
+
"permissions": {
|
|
24
|
+
"scope": "write"
|
|
25
|
+
},
|
|
26
|
+
"maxRetries": 3,
|
|
27
|
+
"loopTimeoutMinutes": 30,
|
|
28
|
+
"figma": {
|
|
29
|
+
"enabled": false
|
|
30
|
+
},
|
|
31
|
+
"branch": {
|
|
32
|
+
"pattern": "{tracker}-{issue-number}",
|
|
33
|
+
"defaults": {
|
|
34
|
+
"tracker": "issues"
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
package/package.json
CHANGED
package/src/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { cpSync, mkdirSync, symlinkSync, existsSync, readdirSync } from 'fs'
|
|
2
|
+
import { cpSync, mkdirSync, symlinkSync, existsSync, readdirSync, copyFileSync, renameSync } from 'fs'
|
|
3
3
|
import { join, dirname } from 'path'
|
|
4
4
|
import { fileURLToPath } from 'url'
|
|
5
5
|
import { homedir } from 'os'
|
|
@@ -18,33 +18,48 @@ const TARGETS = [
|
|
|
18
18
|
{ src: join(ROOT, 'hooks'), dest: join(CLAUDE_DIR, 'hooks'), label: 'Hooks' },
|
|
19
19
|
]
|
|
20
20
|
|
|
21
|
+
function backupAndCopy(src, dest, file, label) {
|
|
22
|
+
const destFile = join(dest, file)
|
|
23
|
+
const srcFile = join(src, file)
|
|
24
|
+
|
|
25
|
+
if (existsSync(destFile)) {
|
|
26
|
+
const backupPath = `${destFile}.bak`
|
|
27
|
+
renameSync(destFile, backupPath)
|
|
28
|
+
copyFileSync(srcFile, destFile)
|
|
29
|
+
console.log(` ~ ${label}: ${file} (기존 파일 -> ${file}.bak)`)
|
|
30
|
+
} else {
|
|
31
|
+
copyFileSync(srcFile, destFile)
|
|
32
|
+
console.log(` + ${label}: ${file}`)
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
21
36
|
function install() {
|
|
22
37
|
console.log('\n byLane 설치 중...\n')
|
|
23
38
|
|
|
24
39
|
for (const { src, dest, label } of TARGETS) {
|
|
25
40
|
mkdirSync(dest, { recursive: true })
|
|
41
|
+
const files = readdirSync(src)
|
|
26
42
|
|
|
27
43
|
if (useSymlink) {
|
|
28
|
-
const files = readdirSync(src)
|
|
29
44
|
for (const file of files) {
|
|
30
45
|
const linkPath = join(dest, file)
|
|
31
46
|
const targetPath = join(src, file)
|
|
32
|
-
if (
|
|
47
|
+
if (existsSync(linkPath)) {
|
|
48
|
+
console.log(` = ${label}: ${file} (심볼릭 링크 이미 존재, 건너뜀)`)
|
|
49
|
+
} else {
|
|
33
50
|
symlinkSync(targetPath, linkPath)
|
|
51
|
+
console.log(` + ${label}: ${file} -> ${linkPath}`)
|
|
34
52
|
}
|
|
35
|
-
console.log(` ✓ ${label}: ${file} → ${linkPath}`)
|
|
36
53
|
}
|
|
37
54
|
} else {
|
|
38
|
-
cpSync(src, dest, { recursive: true })
|
|
39
|
-
const files = readdirSync(src)
|
|
40
55
|
for (const file of files) {
|
|
41
|
-
|
|
56
|
+
backupAndCopy(src, dest, file, label)
|
|
42
57
|
}
|
|
43
58
|
}
|
|
44
59
|
}
|
|
45
60
|
|
|
46
61
|
console.log(`
|
|
47
|
-
|
|
62
|
+
byLane 설치 완료!
|
|
48
63
|
|
|
49
64
|
다음 단계:
|
|
50
65
|
1. Claude Code를 열고 프로젝트 디렉토리로 이동
|
package/src/monitor/index.js
CHANGED
|
File without changes
|
package/src/monitor/layout.js
CHANGED
|
@@ -22,7 +22,7 @@ export function createLayout() {
|
|
|
22
22
|
left: 0,
|
|
23
23
|
width: '100%',
|
|
24
24
|
height: 1,
|
|
25
|
-
content: ' [q]종료 [p]일시정지 [c]작업취소 [Tab]포커스 [
|
|
25
|
+
content: ' [q]종료 [p]일시정지 [c]작업취소 [Tab]포커스 [j/k]로그스크롤 [?]도움말',
|
|
26
26
|
style: { fg: 'black', bg: 'cyan' }
|
|
27
27
|
})
|
|
28
28
|
screen.append(footer)
|
|
@@ -25,7 +25,7 @@ export function createLogPanel(screen) {
|
|
|
25
25
|
for (const entry of (state.log ?? []).slice(-5)) {
|
|
26
26
|
const ts = new Date(entry.ts).toLocaleTimeString('ko-KR', { hour12: false })
|
|
27
27
|
newLines.push(` ${ts} {cyan-fg}${state.agent}{/cyan-fg}`)
|
|
28
|
-
newLines.push(`
|
|
28
|
+
newLines.push(` > ${entry.msg}`)
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
31
|
const all = [...lines, ...newLines].slice(-50)
|
|
@@ -6,10 +6,10 @@ const AGENTS = [
|
|
|
6
6
|
]
|
|
7
7
|
|
|
8
8
|
const STATUS_ICON = {
|
|
9
|
-
idle: '[
|
|
10
|
-
in_progress: '[
|
|
11
|
-
completed: '[
|
|
12
|
-
failed: '[
|
|
9
|
+
idle: '[ ]',
|
|
10
|
+
in_progress: '[>]',
|
|
11
|
+
completed: '[v]',
|
|
12
|
+
failed: '[x]',
|
|
13
13
|
escalated: '[!]'
|
|
14
14
|
}
|
|
15
15
|
|
|
@@ -36,7 +36,7 @@ export function createPipelinePanel(screen) {
|
|
|
36
36
|
? `${Math.floor((Date.now() - new Date(s.startedAt)) / 1000)}s`
|
|
37
37
|
: ''
|
|
38
38
|
const bar = s.progress > 0
|
|
39
|
-
? `${'
|
|
39
|
+
? `${'#'.repeat(Math.floor(s.progress / 10))}${'-'.repeat(10 - Math.floor(s.progress / 10))} ${s.progress}%`
|
|
40
40
|
: ''
|
|
41
41
|
return ` ${icon} ${name.padEnd(16)} ${elapsed.padEnd(6)} ${bar}`
|
|
42
42
|
})
|
|
@@ -17,7 +17,7 @@ export function createStatusPanel(screen) {
|
|
|
17
17
|
return {
|
|
18
18
|
update() {
|
|
19
19
|
const config = loadConfig()
|
|
20
|
-
const check = (v) => v ? '{green-fg}
|
|
20
|
+
const check = (v) => v ? '{green-fg}OK{/green-fg}' : '{red-fg}--{/red-fg}'
|
|
21
21
|
const lines = [
|
|
22
22
|
` GitHub ${check(true)} 연결됨`,
|
|
23
23
|
` Linear ${check(config.trackers.linear.enabled)} ${config.trackers.linear.enabled ? '활성' : '비활성'}`,
|