pinglet-cli 0.2.3 โ 0.2.5
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 +57 -99
- package/dist/commands/login.js +72 -13
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,127 +1,85 @@
|
|
|
1
|
-
# Pinglet
|
|
1
|
+
# Pinglet ๐
|
|
2
2
|
|
|
3
|
-
AI๊ฐ ์๊ฐํ๋
|
|
3
|
+
**AI๊ฐ ์๊ฐํ๋ ๋์, ๋ค๋ฅธ ๊ฐ๋ฐ์์ ํ ์ค์ ๋ง๋์ธ์.**
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
Claude Code๊ฐ ์ฝ๋๋ฅผ ๊ณ ์น๋ ๋์ "Befuddlingโฆ" ์คํผ๋๋ง ๋ฐ๋ผ๋ณด๋ ๊ทธ ์๋ฆฌ์,
|
|
6
|
+
๋ค๋ฅธ ๊ฐ๋ฐ์๋ค์ด ๋จ๊ธด ์งง์ ๋ฉ์์ง(**Ping**)๊ฐ ๋์ ํ์๋ฉ๋๋ค.
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
```bash
|
|
11
|
-
npm install -g pinglet-cli # ์ค์น ํ ๋ช
๋ น์ด๋ `pinglet`
|
|
8
|
+
```
|
|
9
|
+
โถ ๐ "๊ธ์์ผ ์คํ ๋ฐฐํฌ๋ ๋ค์ ์์ ํฉ์๋ค." (12s ยท โ 1.2k tokens)
|
|
12
10
|
```
|
|
13
11
|
|
|
14
|
-
|
|
15
|
-
(pnpm/bun์ฒ๋ผ postinstall์ ์ฐจ๋จํ๋ ๋งค๋์ ์์๋ `pinglet install`์ ์ง์ ์คํ)
|
|
16
|
-
|
|
17
|
-
์ ๊ฑฐํ ๋๋ ๋ฐ๋์ integration ์ ๋ฆฌ๋ฅผ ๋จผ์ ํ๋ค โ npm์ uninstall ์
|
|
18
|
-
์คํฌ๋ฆฝํธ๋ฅผ ์คํํ์ง ์์ผ๋ฏ๋ก ์์๊ฐ ๋ฐ๋๋ฉด ์ค์ ์ด ๋จ๋๋ค:
|
|
12
|
+
## ์์ํ๊ธฐ
|
|
19
13
|
|
|
20
14
|
```bash
|
|
21
|
-
pinglet
|
|
22
|
-
npm uninstall -g pinglet-cli
|
|
15
|
+
npm install -g pinglet-cli
|
|
23
16
|
```
|
|
24
17
|
|
|
25
|
-
|
|
18
|
+
์ค์น๊ฐ ๋๋๋ฉด ์๋์ผ๋ก Claude Code์ ์ฐ๊ฒฐ๋ฉ๋๋ค. ์ดํ๋ ํ์์ฒ๋ผ `claude`๋ฅผ
|
|
19
|
+
์คํํ๊ธฐ๋ง ํ๋ฉด ๋ผ์. ์๋ ์ค์ ์ด ์ ๋๋ค๋ฉด `pinglet install` ํ ๋ฒ์ด๋ฉด ๋ฉ๋๋ค.
|
|
26
20
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
npm run build
|
|
21
|
+
- ๊ธฐ์กด statusline ์ค์ ์ด ์๋ค๋ฉด **๋ฐฑ์
ํ ๊ต์ฒดํ ์ง ๋ฌผ์ด๋ณด๊ณ **, ์ ๊ฑฐ ์ ์๋๋๋ก ๋ณต์ํฉ๋๋ค.
|
|
22
|
+
- Codex๋ ์ง์ํฉ๋๋ค(experimental) โ turn ์๋ฃ ์ macOS ์๋ฆผ์ผ๋ก Ping์ด ๋์ฐฉํฉ๋๋ค.
|
|
30
23
|
|
|
31
|
-
|
|
32
|
-
node dist/cli.js install --api http://localhost:3000
|
|
24
|
+
## Ping ๋ณด๋ด๊ธฐ
|
|
33
25
|
|
|
34
|
-
|
|
35
|
-
claude # statusline์ ๐ Ping ํ์
|
|
36
|
-
codex # turn ์๋ฃ ์ macOS ์๋ฆผ์ผ๋ก Ping ์ ๋ฌ (experimental)
|
|
37
|
-
```
|
|
26
|
+
Claude Code ์ธ์
์์์ ๋ฐ๋ก:
|
|
38
27
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
| `pinglet uninstall [--purge]` | integration ์ ๊ฑฐ, ๊ธฐ์กด ์ค์ ๋ณต์. `--purge`๋ `~/.pinglet`๊น์ง ์ญ์ |
|
|
43
|
-
| `pinglet login [--token <jwt>]` | GitHub ๋ก๊ทธ์ธ ํ ์ต๋ช
์ค์น๋ฅผ ๊ณ์ ์ ์ฐ๊ฒฐ |
|
|
44
|
-
| `pinglet post "๋ฉ์์ง" [--category <c>]` | ๋ฉ์์ง ์์ฑ (GitHub ๋ก๊ทธ์ธ ํ์, ์ฝ๊ธฐ๋ ๋ก๊ทธ์ธ ์์ด ๊ฐ๋ฅ) |
|
|
45
|
-
| `pinglet doctor` | ์ค์น/์บ์/ํ/์๋ฒ ์ํ ์ง๋จ |
|
|
46
|
-
| `pinglet ping` | ๋ฉ์์ง ๋ฏธ๋ฆฌ๋ณด๊ธฐ (์ด๋ฒคํธ ๊ธฐ๋ก ์์) |
|
|
28
|
+
```
|
|
29
|
+
> /pinglet ์ค๋๋ ๋น๋๊ฐ ์ด๋ก๋ถ์ด๊ธธ
|
|
30
|
+
```
|
|
47
31
|
|
|
48
|
-
|
|
32
|
+
๋๋ ํฐ๋ฏธ๋์์:
|
|
49
33
|
|
|
50
|
-
|
|
34
|
+
```bash
|
|
35
|
+
pinglet login # GitHub ๋ก๊ทธ์ธ โ ๋ธ๋ผ์ฐ์ ๊ฐ ์ด๋ฆฌ๊ณ ์๋์ผ๋ก ์๋ฃ๋ฉ๋๋ค (์ต์ด 1ํ)
|
|
36
|
+
pinglet post "๋ฉ์์ง"
|
|
37
|
+
```
|
|
51
38
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
๋ฑ๋ก ์์ฒด๋ command ์์ ์ธ๋ผ์ธ bash ์คํ(`pinglet post`)์ด ์ํํ๊ณ
|
|
55
|
-
๋ชจ๋ธ์ ๊ฒฐ๊ณผ ํ ์ค๋ง ์ ๋ฌํ๋ฏ๋ก ํ ํฐ ์ฌ์ฉ์ด ๋งค์ฐ ์ ๋ค.
|
|
39
|
+
์ฝ๊ธฐ๋ ๋ก๊ทธ์ธ ์์ด ๊ฐ๋ฅํ๊ณ , **์์ฑ์๋ง GitHub ๋ก๊ทธ์ธ์ด ํ์ํฉ๋๋ค.**
|
|
40
|
+
๋ด๊ฐ ๋ณด๋ธ Ping์ด ์ผ๋ง๋ ํผ์ก๋์ง๋ statusline์์ ๋ฐ๋ก ํ์ธ๋ฉ๋๋ค:
|
|
56
41
|
|
|
57
42
|
```
|
|
58
|
-
|
|
43
|
+
๐ ๋ด Ping "์ค๋๋ ๋น๋๊ฐ ์ด๋ก๋ถ์ด๊ธธ" โ ๋๋ฌ๋ฅ 17%
|
|
59
44
|
```
|
|
60
45
|
|
|
61
|
-
##
|
|
62
|
-
|
|
63
|
-
- **Claude Adapter** โ `~/.claude/settings.json`์ `statusLine` hook์
|
|
64
|
-
`node <cli> statusline`์ ์ฐ๊ฒฐํ๋ค. statusline์ UI ์์ญ์ด๋ผ LLM context์
|
|
65
|
-
์ ํ ๋ค์ด๊ฐ์ง ์์ผ๋ฉฐ(Zero Token), Thinking/Working ์ค์ ๋ฉ์์ง๊ฐ ๋ณด์ธ๋ค.
|
|
66
|
-
๊ธฐ์กด statusLine ์ค์ ์ ๋ฐฑ์
ํ uninstall ์ ๋ณต์ํ๋ค.
|
|
67
|
-
- **Spinner verbs (pool=1 ํ์ )** โ `spinnerVerbs`(mode: "replace")์ ๋ฉ์์ง๋ฅผ
|
|
68
|
-
**ํ ๋ฒ์ ํ๋๋ง** ๋ฑ๋กํด "Befuddlingโฆ" ์๋ฆฌ์ Ping์ด ํ์๋๋ค. statusline์ด
|
|
69
|
-
60์ด๋ง๋ค ๋ค์ ๋ฉ์์ง๋ก ๊ต์ฒดํ๋ฉฐ, Claude Code๊ฐ ์ค์ ์ ํซ๋ฆฌ๋ก๋ํ๋ฏ๋ก ์ธ์
|
|
70
|
-
์ค์๋ ์ฆ์ ๋ฐ์๋๋ค. pool์ด 1๊ฐ๋ผ "spinner๊ฐ ๋์๋ค = ์ด ๋ฉ์์ง๊ฐ ํ์๋๋ค"๊ฐ
|
|
71
|
-
ํ์ ๋๋ค. Pinglet verb๋ zero-width space ๋ง์ปค๋ก ์๋ณํ๋ฏ๋ก ์ฌ์ฉ์๊ฐ ์ง์
|
|
72
|
-
๋ฑ๋กํ verb๋ ๊ฑด๋๋ฆฌ์ง ์๊ณ , uninstall ์ ์๋๋๋ก ๋ณต์ํ๋ค.
|
|
73
|
-
- **Codex Adapter (experimental)** โ `~/.codex/config.toml`์ `notify` hook์ ์ฐ๊ฒฐ.
|
|
74
|
-
notify๋ TUI ๋ฐ ํ๋ก์ธ์ค๋ผ ํฐ๋ฏธ๋ ์์ ๊ทธ๋ฆด ์ ์์ด, MVP์์๋ turn ์๋ฃ ์
|
|
75
|
-
macOS ์๋ฆผ์ผ๋ก ์ ๋ฌํ๋ค.
|
|
76
|
-
|
|
77
|
-
## ์ํคํ
์ฒ ์์น ๊ตฌํ
|
|
78
|
-
|
|
79
|
-
- **Local-first Rendering** โ ์๋ฒ feed๋ฅผ 30~50๊ฐ ๋ฏธ๋ฆฌ ๋ฐ์ `~/.pinglet/feed.json`์
|
|
80
|
-
์บ์ํ๊ณ , ๋ ๋๋ง ์๊ฐ์๋ ๋ก์ปฌ ํ์ผ๋ง ๋๊ธฐ I/O๋ก ์ฝ๋๋ค. ๋ ๋๋ง path์
|
|
81
|
-
๋คํธ์ํฌ๊ฐ ์ ๋ ๋ค์ด๊ฐ์ง ์๋๋ค.
|
|
82
|
-
- **์คํ๋ผ์ธ ๋์** โ ์๋ฒ ๋ฏธ์ฐ๊ฒฐ ์ ์๋ ๋ฉ์์ง๋ก ๋์ํ๊ณ , ๋ฑ๋ก/feed ๊ฐฑ์ ์
|
|
83
|
-
๋ฐฑ๊ทธ๋ผ์ด๋ `refresh`๊ฐ ์จ๋ผ์ธ์ด ๋๋ฉด ์๋ ์ฌ์๋ํ๋ค.
|
|
84
|
-
- **DELIVERED / QUALIFIED_IMPRESSION ๋ถ๋ฆฌ** โ ๋ฉ์์ง๊ฐ spinner์ armed๋๋ฉด
|
|
85
|
-
DELIVERED(์ค์น๋น 1ํ), armed๋ ๋์ spinner๊ฐ 3์ด ์ด์ ์ค์ ๋ก ๋์์ผ๋ฉด
|
|
86
|
-
QUALIFIED_IMPRESSION(visibleMs ํฌํจ)์ผ๋ก ์ ์ฐํ๋ค. "์ค์ ๋ก ๋์๋์ง"๋
|
|
87
|
-
statusline hook์ด ๋ฐ๋ `cost.total_api_duration_ms` ์ฆ๊ฐ๋ถ์ผ๋ก ์ธก์ ํ๋ค โ
|
|
88
|
-
pool์ด 1๊ฐ์ด๋ฏ๋ก API ํ๋ ์๊ฐ๋งํผ ๊ทธ ๋ฉ์์ง๊ฐ ํ์๋ ๊ฒ์ด ํ์ ๋๋ค.
|
|
89
|
-
- **Async Telemetry** โ ์ด๋ฒคํธ๋ `~/.pinglet/events.jsonl`(Local Event Queue)์
|
|
90
|
-
appendํ๊ณ , 20๊ฐ ์ด์ ๋๋ 60์ด ์ฃผ๊ธฐ๋ก detached ํ๋ก์ธ์ค๊ฐ batch ์ ์กํ๋ค.
|
|
91
|
-
์ ์ก ์ฑ๊ณต๋ถ๋ง ํ์์ ์ ๊ฑฐํ๋ฏ๋ก ์คํจ๋ถ์ ์๋ ์ฌ์๋๋๋ฉฐ, ์ฌ์ ์ก ์ค๋ณต์
|
|
92
|
-
์๋ฒ๊ฐ `eventId`๋ก dedupeํ๋ค.
|
|
93
|
-
- **Privacy** โ prompt/์๋ต/์ฝ๋/ํ๊ฒฝ๋ณ์๋ฅผ ์ฝ์ง ์๋๋ค. ์์งํ๋ ๊ฒ์
|
|
94
|
-
installationId, agentType, OS, clientVersion, ๋ฉ์์ง delivery ์ด๋ฒคํธ๋ฟ์ด๋ค.
|
|
95
|
-
|
|
96
|
-
## ๋ฐฑ์๋ API ์ฌ์ฉ (pinglet-backend)
|
|
97
|
-
|
|
98
|
-
| ์๋ํฌ์ธํธ | ์ฉ๋ |
|
|
99
|
-
|---|---|
|
|
100
|
-
| `POST /installations` | agent๋ณ ์ต๋ช
์ค์น ๋ฑ๋ก โ `{installationId, token}` |
|
|
101
|
-
| `GET /feed?limit=50` | ๋ก์ปฌ ์บ์์ฉ feed ์์ (installation JWT) |
|
|
102
|
-
| `POST /events/batch` | ์ด๋ฒคํธ batch ์ ์ก (์ต๋ 200๊ฐ, eventId dedupe) |
|
|
103
|
-
| `POST /messages` | ๋ฉ์์ง ์์ฑ (`post` ๋ช
๋ น, ์ ์ JWT ๋๋ installation JWT) |
|
|
104
|
-
| `POST /installations/heartbeat` | lastSeenAt ๊ฐฑ์ |
|
|
105
|
-
| `POST /installations/link` | ๋ก๊ทธ์ธ ํ ์ค์น๋ฅผ ๊ณ์ ์ ์ฐ๊ฒฐ |
|
|
106
|
-
| `GET /auth/github` | GitHub OAuth ์์ (login ๋ช
๋ น์ด ๋ธ๋ผ์ฐ์ ๋ก ์ฐ๋ค) |
|
|
46
|
+
## ๋ช
๋ น์ด
|
|
107
47
|
|
|
108
|
-
|
|
48
|
+
| ๋ช
๋ น | ์ค๋ช
|
|
|
49
|
+
|---|---|
|
|
50
|
+
| `pinglet install` | Claude Code / Codex ๊ฐ์ง ํ ์ฐ๊ฒฐ |
|
|
51
|
+
| `pinglet login` | GitHub ๊ณ์ ์ฐ๊ฒฐ (๋ฉ์์ง ์์ฑ์ ํ์) |
|
|
52
|
+
| `pinglet post "๋ฉ์์ง"` | Ping ๋ณด๋ด๊ธฐ |
|
|
53
|
+
| `pinglet ping` | ์ง๊ธ ํ์๋ ๋ฉ์์ง ๋ฏธ๋ฆฌ๋ณด๊ธฐ |
|
|
54
|
+
| `pinglet doctor` | ์ค์นยท์ฐ๊ฒฐ ์ํ ์ง๋จ |
|
|
55
|
+
| `pinglet uninstall` | ์ฐ๊ฒฐ ํด์ ๋ฐ ๊ธฐ์กด ์ค์ ๋ณต์ |
|
|
56
|
+
|
|
57
|
+
## ์์ฌํ๊ณ ์ฐ์ธ์
|
|
58
|
+
|
|
59
|
+
- **ํ ํฐ ์ฌ์ฉ๋ 0** โ ๋ฉ์์ง๋ Claude Code์ UI ์์ญ(statusline/spinner)์๋ง
|
|
60
|
+
ํ์๋๊ณ ๋ชจ๋ธ ์ปจํ
์คํธ์๋ ์ ํ ๋ค์ด๊ฐ์ง ์์ต๋๋ค. API ๋น์ฉ๊ณผ ์๋ต ํ์ง์
|
|
61
|
+
์ํฅ์ด ์์ต๋๋ค.
|
|
62
|
+
- **์ฝ๋๋ฅผ ์ฝ์ง ์์ต๋๋ค** โ prompt, ์๋ต, ์ฝ๋, ํ๊ฒฝ๋ณ์์ ์ ๊ทผํ์ง ์์ต๋๋ค.
|
|
63
|
+
์์งํ๋ ๊ฒ์ ์ค์น ID, OS ์ข
๋ฅ, ํด๋ผ์ด์ธํธ ๋ฒ์ , ๋ฉ์์ง ๋
ธ์ถ ์ด๋ฒคํธ๋ฟ์
๋๋ค.
|
|
64
|
+
- **ํฐ๋ฏธ๋์ด ๋๋ ค์ง์ง ์์ต๋๋ค** โ ํ์๋ ๋ก์ปฌ ์บ์๋ง ์ฝ์ด์ ๊ทธ๋ฆฌ๋ฉฐ, ๋คํธ์ํฌ๋
|
|
65
|
+
๋ฐฑ๊ทธ๋ผ์ด๋์์๋ง ์ฌ์ฉํฉ๋๋ค. ์คํ๋ผ์ธ์์๋ ๋์ํฉ๋๋ค.
|
|
66
|
+
- **๋ชจ๋ ๋ฉ์์ง๋ ๊ฒ์๋ฅผ ๊ฑฐ์นฉ๋๋ค** โ URLยท๊ฐ์ธ์ ๋ณดยท์ ์ด๋ฌธ์ยท๋ถ์ ์ ํ ํํ์
|
|
67
|
+
์๋์ผ๋ก ๊ฑธ๋ฌ์ง๋ฉฐ, ๋ฌธ์ ๊ฐ ๋๋ ๋ฉ์์ง๋ ๋ฐ๊ฒฌ ์ ๋ฐ๋ก ๋ด๋ ค์ฃผ์ธ์
|
|
68
|
+
(์๋ ๋ฌธ์ยทํผ๋๋ฐฑ ๋งํฌ).
|
|
69
|
+
|
|
70
|
+
## ์ ๊ฑฐ
|
|
109
71
|
|
|
72
|
+
```bash
|
|
73
|
+
pinglet uninstall # ์ฐ๊ฒฐ ํด์ + ๊ธฐ์กด ์ค์ ๋ณต์ (npm ์ ๊ฑฐ๋ณด๋ค ๋จผ์ !)
|
|
74
|
+
npm uninstall -g pinglet-cli
|
|
110
75
|
```
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
feed.json # Local Feed Cache
|
|
114
|
-
state.json # ํ์ฌ ํ์ ์ค ๋ฉ์์ง, seen ์นด์ดํธ, flush/refresh ํ์ด๋ฐ
|
|
115
|
-
events.jsonl # Local Event Queue (append-only)
|
|
116
|
-
```
|
|
76
|
+
|
|
77
|
+
๋ก์ปฌ ๋ฐ์ดํฐ(`~/.pinglet`)๊น์ง ์ง์ฐ๋ ค๋ฉด `pinglet uninstall --purge`.
|
|
117
78
|
|
|
118
79
|
## ์ฝ๊ด ๋ฐ ๊ฐ์ธ์ ๋ณด์ฒ๋ฆฌ๋ฐฉ์นจ
|
|
119
80
|
|
|
120
|
-
|
|
121
|
-
๋ฐฉ์ง ๋ชฉ์ ์ผ๋ก ์ฒ๋ฆฌํฉ๋๋ค. ๋ก๊ทธ์ธํ์ฌ ๋ฉ์์ง๋ฅผ ์์ฑํ๋ฉด ์๋ ๋ฌธ์์ ๋์ํ ๊ฒ์ผ๋ก
|
|
122
|
-
๊ฐ์ฃผ๋ฉ๋๋ค.
|
|
81
|
+
๋ก๊ทธ์ธํ์ฌ ๋ฉ์์ง๋ฅผ ์์ฑํ๋ฉด ์๋ ๋ฌธ์์ ๋์ํ ๊ฒ์ผ๋ก ๊ฐ์ฃผ๋ฉ๋๋ค.
|
|
123
82
|
|
|
124
|
-
- [์ด์ฉ์ฝ๊ด](https://pinglet.halluci.co.kr/terms)
|
|
125
|
-
- [๊ฐ์ธ์ ๋ณด์ฒ๋ฆฌ๋ฐฉ์นจ](https://pinglet.halluci.co.kr/privacy)
|
|
83
|
+
- [์ด์ฉ์ฝ๊ด](https://pinglet.halluci.co.kr/terms) ยท [๊ฐ์ธ์ ๋ณด์ฒ๋ฆฌ๋ฐฉ์นจ](https://pinglet.halluci.co.kr/privacy)
|
|
126
84
|
|
|
127
|
-
|
|
85
|
+
๋ฌธ์ยทํผ๋๋ฐฑ: leeyeonggyun@naver.com ยท [GitHub Issues](https://github.com/mabyko/pinglet-client/issues)
|
package/dist/commands/login.js
CHANGED
|
@@ -35,9 +35,11 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.runLogin = runLogin;
|
|
37
37
|
const child_process_1 = require("child_process");
|
|
38
|
+
const http = __importStar(require("http"));
|
|
38
39
|
const readline = __importStar(require("readline"));
|
|
39
40
|
const config_1 = require("../config");
|
|
40
41
|
const api_1 = require("../api");
|
|
42
|
+
const LOGIN_TIMEOUT_MS = 180_000;
|
|
41
43
|
function prompt(question) {
|
|
42
44
|
const rl = readline.createInterface({
|
|
43
45
|
input: process.stdin,
|
|
@@ -48,10 +50,72 @@ function prompt(question) {
|
|
|
48
50
|
resolve(answer);
|
|
49
51
|
}));
|
|
50
52
|
}
|
|
53
|
+
function openBrowser(url) {
|
|
54
|
+
const cmd = process.platform === "darwin"
|
|
55
|
+
? ["open", url]
|
|
56
|
+
: process.platform === "win32"
|
|
57
|
+
? ["cmd", "/c", "start", "", url]
|
|
58
|
+
: ["xdg-open", url];
|
|
59
|
+
try {
|
|
60
|
+
(0, child_process_1.spawn)(cmd[0], cmd.slice(1), { stdio: "ignore" }).unref();
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
const RESULT_HTML = (ok) => `<!doctype html>
|
|
68
|
+
<html lang="ko"><head><meta charset="utf-8"><title>Pinglet</title>
|
|
69
|
+
<style>body{font-family:-apple-system,sans-serif;display:flex;align-items:center;
|
|
70
|
+
justify-content:center;height:100vh;margin:0;background:#0f1115;color:#e6e9ef}
|
|
71
|
+
div{text-align:center}p{color:#8b93a3}</style></head><body><div>
|
|
72
|
+
<h1>${ok ? "๐ ๋ก๊ทธ์ธ ์๋ฃ" : "โ ๋ก๊ทธ์ธ ์คํจ"}</h1>
|
|
73
|
+
<p>${ok ? "์ด ์ฐฝ์ ๋ซ๊ณ ํฐ๋ฏธ๋๋ก ๋์๊ฐ์ธ์." : "ํฐ๋ฏธ๋์์ ๋ค์ ์๋ํด ์ฃผ์ธ์."}</p>
|
|
74
|
+
</div></body></html>`;
|
|
51
75
|
/**
|
|
52
|
-
*
|
|
53
|
-
*
|
|
76
|
+
* ๋ฃจํ๋ฐฑ ๋ก๊ทธ์ธ: ์ผํ์ฉ ๋ก์ปฌ ์๋ฒ๋ฅผ ๋์ฐ๊ณ ๋ธ๋ผ์ฐ์ ์์ OAuth๋ฅผ ๋ง์น๋ฉด
|
|
77
|
+
* ์๋ฒ๊ฐ http://127.0.0.1:{port}/callback?token=... ์ผ๋ก ํ ํฐ์ ๋๊ฒจ์ค๋ค.
|
|
78
|
+
* ํ์์์/์คํจ ์ null โ ํธ์ถ๋ถ๊ฐ ์๋ ๋ถ์ฌ๋ฃ๊ธฐ๋ก ํด๋ฐฑํ๋ค.
|
|
54
79
|
*/
|
|
80
|
+
function loginViaLoopback(apiBaseUrl) {
|
|
81
|
+
return new Promise((resolve) => {
|
|
82
|
+
let finished = false;
|
|
83
|
+
const done = (token) => {
|
|
84
|
+
if (finished)
|
|
85
|
+
return;
|
|
86
|
+
finished = true;
|
|
87
|
+
clearTimeout(timer);
|
|
88
|
+
// ๋ง์ง๋ง ์๋ต์ด flush๋ ์๊ฐ์ ์ฃผ๊ณ ๋ซ๋๋ค.
|
|
89
|
+
setTimeout(() => {
|
|
90
|
+
server.closeAllConnections?.();
|
|
91
|
+
server.close();
|
|
92
|
+
}, 200).unref();
|
|
93
|
+
resolve(token);
|
|
94
|
+
};
|
|
95
|
+
const timer = setTimeout(() => done(null), LOGIN_TIMEOUT_MS);
|
|
96
|
+
const server = http.createServer((req, res) => {
|
|
97
|
+
const url = new URL(req.url ?? "/", "http://127.0.0.1");
|
|
98
|
+
if (url.pathname !== "/callback") {
|
|
99
|
+
res.statusCode = 404;
|
|
100
|
+
res.end();
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
const token = url.searchParams.get("token");
|
|
104
|
+
res.setHeader("content-type", "text/html; charset=utf-8");
|
|
105
|
+
res.end(RESULT_HTML(Boolean(token)));
|
|
106
|
+
done(token);
|
|
107
|
+
});
|
|
108
|
+
server.on("error", () => done(null));
|
|
109
|
+
server.listen(0, "127.0.0.1", () => {
|
|
110
|
+
const port = server.address().port;
|
|
111
|
+
const url = `${apiBaseUrl}/auth/github?cli_port=${port}`;
|
|
112
|
+
console.log("๋ธ๋ผ์ฐ์ ์์ GitHub ๋ก๊ทธ์ธ์ ์๋ฃํด ์ฃผ์ธ์โฆ");
|
|
113
|
+
console.log(` ${url}\n`);
|
|
114
|
+
openBrowser(url);
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
/** GitHub OAuth ๋ก๊ทธ์ธ โ ๋ฃจํ๋ฐฑ ์๋ ์์ , ์คํจ ์ ์๋ ๋ถ์ฌ๋ฃ๊ธฐ ํด๋ฐฑ. */
|
|
55
119
|
async function runLogin(args) {
|
|
56
120
|
const config = (0, config_1.loadConfig)();
|
|
57
121
|
let token;
|
|
@@ -60,19 +124,14 @@ async function runLogin(args) {
|
|
|
60
124
|
token = args[tokenIndex + 1];
|
|
61
125
|
}
|
|
62
126
|
if (!token) {
|
|
63
|
-
const url = `${config.apiBaseUrl}/auth/github`;
|
|
64
127
|
console.log(`\n๋ก๊ทธ์ธํ๋ฉด ์ด์ฉ์ฝ๊ด(${config.apiBaseUrl}/terms)๊ณผ ๊ฐ์ธ์ ๋ณด์ฒ๋ฆฌ๋ฐฉ์นจ(${config.apiBaseUrl}/privacy)์ ๋์ํ๋ ๊ฒ์ผ๋ก ๊ฐ์ฃผ๋ฉ๋๋ค.`);
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
catch {
|
|
72
|
-
// ๋ธ๋ผ์ฐ์ ๋ฅผ ๋ชป ์ด์ด๋ URL์ ์ถ๋ ฅํ์ผ๋ฏ๋ก ์งํ
|
|
73
|
-
}
|
|
128
|
+
token = (await loginViaLoopback(config.apiBaseUrl)) ?? undefined;
|
|
129
|
+
if (!token) {
|
|
130
|
+
// SSH ๋ฑ ๋ธ๋ผ์ฐ์ ์ ํฐ๋ฏธ๋์ด ๋ค๋ฅธ ๊ธฐ๊ณ์ธ ๊ฒฝ์ฐ๋ฅผ ์ํ ํด๋ฐฑ.
|
|
131
|
+
console.log("์๋ ๋ก๊ทธ์ธ์ ์คํจํ์ต๋๋ค. ์๋ URL์์ ๋ก๊ทธ์ธ ํ ์๋ต JSON์ token ๊ฐ์ ๋ถ์ฌ๋ฃ์ด ์ฃผ์ธ์.");
|
|
132
|
+
console.log(` ${config.apiBaseUrl}/auth/github\n`);
|
|
133
|
+
token = (await prompt("token: ")).trim();
|
|
74
134
|
}
|
|
75
|
-
token = (await prompt("token: ")).trim();
|
|
76
135
|
}
|
|
77
136
|
if (!token) {
|
|
78
137
|
console.log("โ token์ด ๋น์ด ์์ต๋๋ค.");
|
package/package.json
CHANGED