argos-scout 0.1.0__tar.gz
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.
- argos_scout-0.1.0/LICENSE +21 -0
- argos_scout-0.1.0/PKG-INFO +288 -0
- argos_scout-0.1.0/README.md +239 -0
- argos_scout-0.1.0/pyproject.toml +74 -0
- argos_scout-0.1.0/setup.cfg +4 -0
- argos_scout-0.1.0/src/argos/__init__.py +0 -0
- argos_scout-0.1.0/src/argos/brain/__init__.py +3 -0
- argos_scout-0.1.0/src/argos/brain/graph_state.py +16 -0
- argos_scout-0.1.0/src/argos/brain/llm_client.py +115 -0
- argos_scout-0.1.0/src/argos/brain/nodes/__init__.py +0 -0
- argos_scout-0.1.0/src/argos/brain/nodes/embed.py +91 -0
- argos_scout-0.1.0/src/argos/brain/nodes/genealogist.py +84 -0
- argos_scout-0.1.0/src/argos/brain/nodes/save.py +91 -0
- argos_scout-0.1.0/src/argos/brain/nodes/triage.py +194 -0
- argos_scout-0.1.0/src/argos/brain/ollama_client.py +119 -0
- argos_scout-0.1.0/src/argos/brain/pipeline.py +49 -0
- argos_scout-0.1.0/src/argos/cli.py +576 -0
- argos_scout-0.1.0/src/argos/config.py +194 -0
- argos_scout-0.1.0/src/argos/config_store.py +318 -0
- argos_scout-0.1.0/src/argos/crawler/__init__.py +21 -0
- argos_scout-0.1.0/src/argos/crawler/_robots.py +105 -0
- argos_scout-0.1.0/src/argos/crawler/dynamic_fetcher.py +179 -0
- argos_scout-0.1.0/src/argos/crawler/pipeline.py +138 -0
- argos_scout-0.1.0/src/argos/crawler/static_fetcher.py +235 -0
- argos_scout-0.1.0/src/argos/crawler/user_agents.py +15 -0
- argos_scout-0.1.0/src/argos/database.py +62 -0
- argos_scout-0.1.0/src/argos/init_wizard/__init__.py +44 -0
- argos_scout-0.1.0/src/argos/init_wizard/env_file.py +147 -0
- argos_scout-0.1.0/src/argos/init_wizard/prompts.py +252 -0
- argos_scout-0.1.0/src/argos/init_wizard/runners.py +422 -0
- argos_scout-0.1.0/src/argos/init_wizard/steps/__init__.py +8 -0
- argos_scout-0.1.0/src/argos/init_wizard/steps/healthcheck.py +97 -0
- argos_scout-0.1.0/src/argos/init_wizard/steps/infra.py +188 -0
- argos_scout-0.1.0/src/argos/init_wizard/steps/interests.py +129 -0
- argos_scout-0.1.0/src/argos/init_wizard/steps/precheck.py +49 -0
- argos_scout-0.1.0/src/argos/init_wizard/steps/schedule.py +33 -0
- argos_scout-0.1.0/src/argos/init_wizard/steps/slack.py +155 -0
- argos_scout-0.1.0/src/argos/init_wizard/wizard.py +172 -0
- argos_scout-0.1.0/src/argos/main.py +18 -0
- argos_scout-0.1.0/src/argos/models/__init__.py +7 -0
- argos_scout-0.1.0/src/argos/models/base.py +38 -0
- argos_scout-0.1.0/src/argos/models/tech_item.py +61 -0
- argos_scout-0.1.0/src/argos/models/tech_succession.py +60 -0
- argos_scout-0.1.0/src/argos/models/track_history.py +36 -0
- argos_scout-0.1.0/src/argos/models/user_asset.py +59 -0
- argos_scout-0.1.0/src/argos/scheduler.py +487 -0
- argos_scout-0.1.0/src/argos/slack/__init__.py +3 -0
- argos_scout-0.1.0/src/argos/slack/app.py +27 -0
- argos_scout-0.1.0/src/argos/slack/blocks.py +304 -0
- argos_scout-0.1.0/src/argos/slack/briefing.py +65 -0
- argos_scout-0.1.0/src/argos/slack/handlers/__init__.py +0 -0
- argos_scout-0.1.0/src/argos/slack/handlers/deep_dive.py +114 -0
- argos_scout-0.1.0/src/argos/slack/handlers/keep.py +43 -0
- argos_scout-0.1.0/src/argos/slack/handlers/pass_.py +43 -0
- argos_scout-0.1.0/src/argos/slack/handlers/portfolio.py +44 -0
- argos_scout-0.1.0/src/argos/slack/handlers/untrack.py +46 -0
- argos_scout-0.1.0/src/argos/slack/services/__init__.py +0 -0
- argos_scout-0.1.0/src/argos/slack/services/asset_transition.py +72 -0
- argos_scout-0.1.0/src/argos/slack/services/briefing_query.py +65 -0
- argos_scout-0.1.0/src/argos_scout.egg-info/PKG-INFO +288 -0
- argos_scout-0.1.0/src/argos_scout.egg-info/SOURCES.txt +68 -0
- argos_scout-0.1.0/src/argos_scout.egg-info/dependency_links.txt +1 -0
- argos_scout-0.1.0/src/argos_scout.egg-info/entry_points.txt +2 -0
- argos_scout-0.1.0/src/argos_scout.egg-info/requires.txt +27 -0
- argos_scout-0.1.0/src/argos_scout.egg-info/top_level.txt +1 -0
- argos_scout-0.1.0/tests/test_cli.py +823 -0
- argos_scout-0.1.0/tests/test_config.py +317 -0
- argos_scout-0.1.0/tests/test_config_cli.py +413 -0
- argos_scout-0.1.0/tests/test_models.py +281 -0
- argos_scout-0.1.0/tests/test_scheduler.py +1413 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 SangChu04
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: argos-scout
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Omni-Lens: Tech Scout - AI 기술 동향 자동 추적 슬랙봇
|
|
5
|
+
License: MIT
|
|
6
|
+
Project-URL: Homepage, https://github.com/james20140802/argos
|
|
7
|
+
Project-URL: Repository, https://github.com/james20140802/argos
|
|
8
|
+
Project-URL: Issues, https://github.com/james20140802/argos/issues
|
|
9
|
+
Project-URL: Changelog, https://github.com/james20140802/argos/blob/main/CHANGELOG.md
|
|
10
|
+
Keywords: slack,ai,trend-tracking,llm,crawler,pgvector
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
+
Classifier: Operating System :: MacOS
|
|
18
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
19
|
+
Classifier: Topic :: Communications :: Chat
|
|
20
|
+
Classifier: Topic :: Internet :: WWW/HTTP :: Indexing/Search
|
|
21
|
+
Requires-Python: <3.13,>=3.10
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
License-File: LICENSE
|
|
24
|
+
Requires-Dist: sqlalchemy[asyncio]>=2.0
|
|
25
|
+
Requires-Dist: asyncpg>=0.29
|
|
26
|
+
Requires-Dist: pgvector>=0.3
|
|
27
|
+
Requires-Dist: alembic>=1.13
|
|
28
|
+
Requires-Dist: pydantic-settings>=2.0
|
|
29
|
+
Requires-Dist: python-dotenv>=1.0
|
|
30
|
+
Requires-Dist: httpx>=0.27
|
|
31
|
+
Requires-Dist: playwright>=1.44
|
|
32
|
+
Requires-Dist: readability-lxml>=0.8.1
|
|
33
|
+
Requires-Dist: lxml>=5.0
|
|
34
|
+
Requires-Dist: beautifulsoup4>=4.12
|
|
35
|
+
Requires-Dist: langgraph>=0.2
|
|
36
|
+
Requires-Dist: langchain-core>=0.3
|
|
37
|
+
Requires-Dist: slack-bolt>=1.18
|
|
38
|
+
Requires-Dist: aiohttp>=3.9
|
|
39
|
+
Requires-Dist: tomli>=2.0; python_version < "3.11"
|
|
40
|
+
Requires-Dist: tomli-w>=1.0
|
|
41
|
+
Requires-Dist: questionary>=2.0
|
|
42
|
+
Provides-Extra: dev
|
|
43
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
44
|
+
Requires-Dist: pytest-asyncio>=0.23; extra == "dev"
|
|
45
|
+
Requires-Dist: pytest-mock>=3.12; extra == "dev"
|
|
46
|
+
Requires-Dist: respx>=0.21; extra == "dev"
|
|
47
|
+
Requires-Dist: ruff>=0.4; extra == "dev"
|
|
48
|
+
Dynamic: license-file
|
|
49
|
+
|
|
50
|
+
# Argos
|
|
51
|
+
|
|
52
|
+
AI 기술 동향을 자동 추적하고, 노이즈를 걸러 개인 기술 포트폴리오로 관리하는 로컬 Slack 봇.
|
|
53
|
+
M1 Max 32GB에서 완전히 로컬로 동작하며 클라우드 비용이 없습니다.
|
|
54
|
+
|
|
55
|
+
## Architecture
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
Crawler (GitHub Trending / HN / Playwright)
|
|
59
|
+
↓
|
|
60
|
+
Processing Brain (LangGraph)
|
|
61
|
+
Triage → Embed → Genealogist → Save
|
|
62
|
+
↓
|
|
63
|
+
PostgreSQL + pgvector (Docker)
|
|
64
|
+
↓
|
|
65
|
+
Slack Interface (Daily briefing + Keep/Pass/Deep Dive)
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Prerequisites
|
|
69
|
+
|
|
70
|
+
- Docker
|
|
71
|
+
- Python ≥ 3.10
|
|
72
|
+
- [uv](https://docs.astral.sh/uv/) (Python 패키지 매니저)
|
|
73
|
+
- [Ollama](https://ollama.com) (Processing Brain 실행 시 필요)
|
|
74
|
+
|
|
75
|
+
## Setup
|
|
76
|
+
|
|
77
|
+
가장 빠른 방법은 인터랙티브 부트스트랩 위저드를 쓰는 것입니다 (Docker 컨테이너 기동,
|
|
78
|
+
Alembic 마이그레이션, 필수 Ollama 모델 다운로드, Slack 토큰 검증, launchd 스케줄링,
|
|
79
|
+
헬스체크까지 한 번에 진행합니다).
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
# 1. 의존성 설치 (.venv 자동 생성)
|
|
83
|
+
uv sync --all-extras
|
|
84
|
+
|
|
85
|
+
# 2. 위저드 실행
|
|
86
|
+
uv run argos init
|
|
87
|
+
|
|
88
|
+
# 특정 섹션만 다시 설정하고 싶다면:
|
|
89
|
+
uv run argos init --reconfigure slack # infra / slack / interests / schedule
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
위저드는 idempotent 하게 동작합니다 — 기존 `~/.config/argos/.env` / `~/.config/argos/config.toml` 값을
|
|
93
|
+
다시 디폴트로 보여주고, 사용자가 바꾼 값만 atomic하게 다시 씁니다. 시크릿 값은
|
|
94
|
+
재표시 시 항상 마스킹되며 (`xoxb-***` / `***`), `.env` 파일은 항상 `chmod 600` 으로
|
|
95
|
+
잠깁니다. CI나 비-TTY 환경에서는 `ARGOS_INIT_NONINTERACTIVE=1` (또는
|
|
96
|
+
`--non-interactive`) 로 모든 디폴트를 조용히 채택할 수 있습니다.
|
|
97
|
+
|
|
98
|
+
> **기존 repo-root `.env` 사용자:** `uv run argos config migrate-env` 를 실행하면
|
|
99
|
+
> 기존 `.env`를 `~/.config/argos/.env`로 이동하고 원본은 `.env.bak`으로 백업합니다.
|
|
100
|
+
|
|
101
|
+
### 수동 설정 (선택)
|
|
102
|
+
|
|
103
|
+
위저드 대신 직접 진행하고 싶다면:
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
uv sync --all-extras
|
|
107
|
+
mkdir -p ~/.config/argos
|
|
108
|
+
cp .env.example ~/.config/argos/.env
|
|
109
|
+
chmod 600 ~/.config/argos/.env
|
|
110
|
+
|
|
111
|
+
# 비밀번호/토큰을 채워 넣은 뒤
|
|
112
|
+
docker compose up -d
|
|
113
|
+
uv run alembic upgrade head
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## Running
|
|
117
|
+
|
|
118
|
+
### 전체 파이프라인 (크롤링 → 분석 → 저장)
|
|
119
|
+
|
|
120
|
+
Ollama 실행 및 모델 준비가 필요합니다:
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
ollama pull qwen3:8b
|
|
124
|
+
ollama pull qwen3:32b
|
|
125
|
+
ollama pull nomic-embed-text
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
CLI로 실행:
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
uv run argos run
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
동적 URL을 추가로 처리하려면 `--url`을 반복해서 전달:
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
uv run argos run --url https://example.com/article --url https://example.com/another
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
상세 로그를 보려면 `-v` / `--verbose`:
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
uv run argos run -v
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Brain 파이프라인만 단독 실행
|
|
147
|
+
|
|
148
|
+
```python
|
|
149
|
+
import asyncio
|
|
150
|
+
from argos.database import AsyncSessionLocal
|
|
151
|
+
from argos.brain.pipeline import run_brain_pipeline
|
|
152
|
+
|
|
153
|
+
async def main():
|
|
154
|
+
async with AsyncSessionLocal() as session:
|
|
155
|
+
state = await run_brain_pipeline(
|
|
156
|
+
raw_text="...",
|
|
157
|
+
source_url="https://example.com",
|
|
158
|
+
session=session,
|
|
159
|
+
)
|
|
160
|
+
await session.commit()
|
|
161
|
+
print(state)
|
|
162
|
+
|
|
163
|
+
asyncio.run(main())
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## Slack Bot
|
|
167
|
+
|
|
168
|
+
Argos의 사용자 인터페이스는 Slack 봇입니다 (Socket Mode 기반, 인바운드 포트 불필요).
|
|
169
|
+
DB에 쌓인 그날의 기술 신호를 Block Kit 카드로 발송하고, 사용자가 **Keep / Pass / Deep Dive** 버튼으로 자산을 관리합니다.
|
|
170
|
+
|
|
171
|
+
### 1. Slack 앱 생성
|
|
172
|
+
|
|
173
|
+
1. <https://api.slack.com/apps> 에서 **Create New App → From scratch** 로 새 앱을 만듭니다 (워크스페이스 선택).
|
|
174
|
+
2. 좌측 메뉴 **Socket Mode** 진입 → 토글 **Enable Socket Mode** ON.
|
|
175
|
+
- 그 자리에서 발급되는 **App-Level Token** (`xapp-…`) 의 스코프에 `connections:write` 가 포함되어 있어야 합니다. → `SLACK_APP_TOKEN`.
|
|
176
|
+
3. **OAuth & Permissions → Bot Token Scopes** 에 다음 스코프를 모두 추가합니다.
|
|
177
|
+
|
|
178
|
+
| Scope | 용도 |
|
|
179
|
+
| --- | --- |
|
|
180
|
+
| `chat:write` | 브리핑 메시지 발송 |
|
|
181
|
+
| `chat:write.public` | (선택) 봇 미초대 채널에도 발송 가능 |
|
|
182
|
+
| `commands` | (선택) 슬래시 커맨드 확장 시 |
|
|
183
|
+
|
|
184
|
+
4. **Event Subscriptions** 진입 → **Enable Events** ON. Socket Mode이므로 Request URL은 비워둬도 됩니다. **Subscribe to bot events** 에서 `app_mention` 정도만 추가해도 무방합니다 (현재 코드는 인터랙티브 액션만 사용하므로 필수 아님).
|
|
185
|
+
5. **Interactivity & Shortcuts** 진입 → **Interactivity** ON. Socket Mode에서는 Request URL을 입력하지 않아도 됩니다. `action_keep` / `action_pass` / `action_deep_dive` 버튼이 이 채널을 통해 전달됩니다.
|
|
186
|
+
6. **Install App → Install to Workspace** 로 설치하고, 발급된 **Bot User OAuth Token** (`xoxb-…`) 을 복사합니다. → `SLACK_BOT_TOKEN`.
|
|
187
|
+
7. 발송할 채널 ID를 확보합니다 (Slack 채널 우클릭 → **View channel details** → 하단의 `Cxxxxxxxxxx`). 비공개 채널이면 봇을 채널에 초대 (`/invite @argos`) 해야 합니다. → `SLACK_CHANNEL_ID`.
|
|
188
|
+
|
|
189
|
+
### 2. 환경변수 설정
|
|
190
|
+
|
|
191
|
+
`~/.config/argos/.env` 에 아래 세 값을 채웁니다 (`.env.example` 참고).
|
|
192
|
+
|
|
193
|
+
```dotenv
|
|
194
|
+
SLACK_BOT_TOKEN=xoxb-...
|
|
195
|
+
SLACK_APP_TOKEN=xapp-...
|
|
196
|
+
SLACK_CHANNEL_ID=C0123456789
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
### 3. 봇 실행 — Socket Mode 데몬
|
|
200
|
+
|
|
201
|
+
별도의 웹서버 없이 한 줄로 켭니다.
|
|
202
|
+
|
|
203
|
+
```bash
|
|
204
|
+
uv run argos slack
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
이 프로세스는 Slack 게이트웨이에 WebSocket을 유지하면서 Keep / Pass / Deep Dive 버튼 이벤트를 수신·처리합니다.
|
|
208
|
+
**3초 ACK 룰**을 지키기 위해 Deep Dive 핸들러는 즉시 응답을 보낸 뒤 70B 분석은 백그라운드 태스크에서 수행합니다.
|
|
209
|
+
|
|
210
|
+
### 4. 일일 브리핑 발송
|
|
211
|
+
|
|
212
|
+
오늘 수집·분석된 항목을 Mainstream / Alpha 카테고리별 카드로 묶어 채널에 발송합니다.
|
|
213
|
+
|
|
214
|
+
```bash
|
|
215
|
+
# 기본 채널 (SLACK_CHANNEL_ID) 로 발송
|
|
216
|
+
uv run argos brief
|
|
217
|
+
|
|
218
|
+
# 다른 채널로 임시 발송
|
|
219
|
+
uv run argos brief --channel C0987654321
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
당일 처리된 항목이 없으면 자동으로 발송을 건너뜁니다 (빈 메시지 방지).
|
|
223
|
+
|
|
224
|
+
> **자동 스케줄링:** `argos init` 위저드가 macOS `launchd` 잡을 자동으로 등록합니다 (`com.argos.run`, `com.argos.brief`). 직접 관리하려면 `argos schedule` 서브커맨드를 쓰세요. 플리스트는 `~/Library/LaunchAgents/`에, 로그는 `~/Library/Logs/argos/{run,brief}.log`에 남습니다.
|
|
225
|
+
>
|
|
226
|
+
> ```bash
|
|
227
|
+
> uv run argos schedule install # config.toml 기준으로 두 잡을 등록 + 부트스트랩
|
|
228
|
+
> uv run argos schedule status # 두 라벨의 로드 여부 확인
|
|
229
|
+
> uv run argos schedule uninstall # 두 잡을 모두 해제 (이미 없어도 에러 없음)
|
|
230
|
+
> ```
|
|
231
|
+
>
|
|
232
|
+
> 스케줄 시각은 `~/.config/argos/config.toml`의 `briefing.time` / `briefing.weekdays` / `run.time`로 조정합니다 (아래 `argos config` 참고).
|
|
233
|
+
|
|
234
|
+
### 5. 일반적인 워크플로우
|
|
235
|
+
|
|
236
|
+
```bash
|
|
237
|
+
# 1) 새 데이터 수집 + 분석 (Ollama 필요)
|
|
238
|
+
uv run argos run
|
|
239
|
+
|
|
240
|
+
# 2) 결과를 Slack 으로 발송
|
|
241
|
+
uv run argos brief
|
|
242
|
+
|
|
243
|
+
# 3) 봇 데몬을 띄워두면 Keep/Pass/Deep Dive 버튼이 동작
|
|
244
|
+
uv run argos slack
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
## Configuration (`argos config`)
|
|
248
|
+
|
|
249
|
+
런타임 설정은 `~/.config/argos/config.toml`에 저장됩니다 (위저드가 생성). 시크릿(Slack 토큰, DB 비밀번호 등)은 `~/.config/argos/.env`에 두고, 동작 옵션만 config.toml에서 관리합니다. CLI로 안전하게 읽고 쓸 수 있습니다.
|
|
250
|
+
|
|
251
|
+
```bash
|
|
252
|
+
uv run argos config path # 사용 중인 config.toml 경로 출력
|
|
253
|
+
uv run argos config list # 전체 키 출력 (시크릿은 마스킹됨)
|
|
254
|
+
uv run argos config get briefing.time
|
|
255
|
+
uv run argos config set briefing.time 09:00
|
|
256
|
+
uv run argos config set briefing.weekdays "mon,tue,wed,thu,fri"
|
|
257
|
+
uv run argos config set briefing.limit_per_category 5
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
종료 코드: `0` 성공 · `1` I/O 등 일반 오류 · `2` 알 수 없는 키 · `3` 검증 실패 · `4` 시크릿 거부(`.env`에서 직접 관리).
|
|
261
|
+
|
|
262
|
+
설정을 바꾼 뒤 스케줄 시각/요일이 영향받는다면 `uv run argos schedule install`을 다시 돌려 플리스트를 갱신하세요.
|
|
263
|
+
|
|
264
|
+
## Testing
|
|
265
|
+
|
|
266
|
+
```bash
|
|
267
|
+
# 전체 테스트 (Ollama 불필요, 모두 mocked)
|
|
268
|
+
uv run pytest tests/ -v
|
|
269
|
+
|
|
270
|
+
# Brain 노드만
|
|
271
|
+
uv run pytest tests/brain/ -v
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
## Database
|
|
275
|
+
|
|
276
|
+
```bash
|
|
277
|
+
# 마이그레이션 생성
|
|
278
|
+
uv run alembic revision --autogenerate -m "description"
|
|
279
|
+
|
|
280
|
+
# 마이그레이션 적용
|
|
281
|
+
uv run alembic upgrade head
|
|
282
|
+
|
|
283
|
+
# 롤백
|
|
284
|
+
uv run alembic downgrade -1
|
|
285
|
+
|
|
286
|
+
# DB 종료
|
|
287
|
+
docker compose down
|
|
288
|
+
```
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
# Argos
|
|
2
|
+
|
|
3
|
+
AI 기술 동향을 자동 추적하고, 노이즈를 걸러 개인 기술 포트폴리오로 관리하는 로컬 Slack 봇.
|
|
4
|
+
M1 Max 32GB에서 완전히 로컬로 동작하며 클라우드 비용이 없습니다.
|
|
5
|
+
|
|
6
|
+
## Architecture
|
|
7
|
+
|
|
8
|
+
```
|
|
9
|
+
Crawler (GitHub Trending / HN / Playwright)
|
|
10
|
+
↓
|
|
11
|
+
Processing Brain (LangGraph)
|
|
12
|
+
Triage → Embed → Genealogist → Save
|
|
13
|
+
↓
|
|
14
|
+
PostgreSQL + pgvector (Docker)
|
|
15
|
+
↓
|
|
16
|
+
Slack Interface (Daily briefing + Keep/Pass/Deep Dive)
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Prerequisites
|
|
20
|
+
|
|
21
|
+
- Docker
|
|
22
|
+
- Python ≥ 3.10
|
|
23
|
+
- [uv](https://docs.astral.sh/uv/) (Python 패키지 매니저)
|
|
24
|
+
- [Ollama](https://ollama.com) (Processing Brain 실행 시 필요)
|
|
25
|
+
|
|
26
|
+
## Setup
|
|
27
|
+
|
|
28
|
+
가장 빠른 방법은 인터랙티브 부트스트랩 위저드를 쓰는 것입니다 (Docker 컨테이너 기동,
|
|
29
|
+
Alembic 마이그레이션, 필수 Ollama 모델 다운로드, Slack 토큰 검증, launchd 스케줄링,
|
|
30
|
+
헬스체크까지 한 번에 진행합니다).
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
# 1. 의존성 설치 (.venv 자동 생성)
|
|
34
|
+
uv sync --all-extras
|
|
35
|
+
|
|
36
|
+
# 2. 위저드 실행
|
|
37
|
+
uv run argos init
|
|
38
|
+
|
|
39
|
+
# 특정 섹션만 다시 설정하고 싶다면:
|
|
40
|
+
uv run argos init --reconfigure slack # infra / slack / interests / schedule
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
위저드는 idempotent 하게 동작합니다 — 기존 `~/.config/argos/.env` / `~/.config/argos/config.toml` 값을
|
|
44
|
+
다시 디폴트로 보여주고, 사용자가 바꾼 값만 atomic하게 다시 씁니다. 시크릿 값은
|
|
45
|
+
재표시 시 항상 마스킹되며 (`xoxb-***` / `***`), `.env` 파일은 항상 `chmod 600` 으로
|
|
46
|
+
잠깁니다. CI나 비-TTY 환경에서는 `ARGOS_INIT_NONINTERACTIVE=1` (또는
|
|
47
|
+
`--non-interactive`) 로 모든 디폴트를 조용히 채택할 수 있습니다.
|
|
48
|
+
|
|
49
|
+
> **기존 repo-root `.env` 사용자:** `uv run argos config migrate-env` 를 실행하면
|
|
50
|
+
> 기존 `.env`를 `~/.config/argos/.env`로 이동하고 원본은 `.env.bak`으로 백업합니다.
|
|
51
|
+
|
|
52
|
+
### 수동 설정 (선택)
|
|
53
|
+
|
|
54
|
+
위저드 대신 직접 진행하고 싶다면:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
uv sync --all-extras
|
|
58
|
+
mkdir -p ~/.config/argos
|
|
59
|
+
cp .env.example ~/.config/argos/.env
|
|
60
|
+
chmod 600 ~/.config/argos/.env
|
|
61
|
+
|
|
62
|
+
# 비밀번호/토큰을 채워 넣은 뒤
|
|
63
|
+
docker compose up -d
|
|
64
|
+
uv run alembic upgrade head
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Running
|
|
68
|
+
|
|
69
|
+
### 전체 파이프라인 (크롤링 → 분석 → 저장)
|
|
70
|
+
|
|
71
|
+
Ollama 실행 및 모델 준비가 필요합니다:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
ollama pull qwen3:8b
|
|
75
|
+
ollama pull qwen3:32b
|
|
76
|
+
ollama pull nomic-embed-text
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
CLI로 실행:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
uv run argos run
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
동적 URL을 추가로 처리하려면 `--url`을 반복해서 전달:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
uv run argos run --url https://example.com/article --url https://example.com/another
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
상세 로그를 보려면 `-v` / `--verbose`:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
uv run argos run -v
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Brain 파이프라인만 단독 실행
|
|
98
|
+
|
|
99
|
+
```python
|
|
100
|
+
import asyncio
|
|
101
|
+
from argos.database import AsyncSessionLocal
|
|
102
|
+
from argos.brain.pipeline import run_brain_pipeline
|
|
103
|
+
|
|
104
|
+
async def main():
|
|
105
|
+
async with AsyncSessionLocal() as session:
|
|
106
|
+
state = await run_brain_pipeline(
|
|
107
|
+
raw_text="...",
|
|
108
|
+
source_url="https://example.com",
|
|
109
|
+
session=session,
|
|
110
|
+
)
|
|
111
|
+
await session.commit()
|
|
112
|
+
print(state)
|
|
113
|
+
|
|
114
|
+
asyncio.run(main())
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Slack Bot
|
|
118
|
+
|
|
119
|
+
Argos의 사용자 인터페이스는 Slack 봇입니다 (Socket Mode 기반, 인바운드 포트 불필요).
|
|
120
|
+
DB에 쌓인 그날의 기술 신호를 Block Kit 카드로 발송하고, 사용자가 **Keep / Pass / Deep Dive** 버튼으로 자산을 관리합니다.
|
|
121
|
+
|
|
122
|
+
### 1. Slack 앱 생성
|
|
123
|
+
|
|
124
|
+
1. <https://api.slack.com/apps> 에서 **Create New App → From scratch** 로 새 앱을 만듭니다 (워크스페이스 선택).
|
|
125
|
+
2. 좌측 메뉴 **Socket Mode** 진입 → 토글 **Enable Socket Mode** ON.
|
|
126
|
+
- 그 자리에서 발급되는 **App-Level Token** (`xapp-…`) 의 스코프에 `connections:write` 가 포함되어 있어야 합니다. → `SLACK_APP_TOKEN`.
|
|
127
|
+
3. **OAuth & Permissions → Bot Token Scopes** 에 다음 스코프를 모두 추가합니다.
|
|
128
|
+
|
|
129
|
+
| Scope | 용도 |
|
|
130
|
+
| --- | --- |
|
|
131
|
+
| `chat:write` | 브리핑 메시지 발송 |
|
|
132
|
+
| `chat:write.public` | (선택) 봇 미초대 채널에도 발송 가능 |
|
|
133
|
+
| `commands` | (선택) 슬래시 커맨드 확장 시 |
|
|
134
|
+
|
|
135
|
+
4. **Event Subscriptions** 진입 → **Enable Events** ON. Socket Mode이므로 Request URL은 비워둬도 됩니다. **Subscribe to bot events** 에서 `app_mention` 정도만 추가해도 무방합니다 (현재 코드는 인터랙티브 액션만 사용하므로 필수 아님).
|
|
136
|
+
5. **Interactivity & Shortcuts** 진입 → **Interactivity** ON. Socket Mode에서는 Request URL을 입력하지 않아도 됩니다. `action_keep` / `action_pass` / `action_deep_dive` 버튼이 이 채널을 통해 전달됩니다.
|
|
137
|
+
6. **Install App → Install to Workspace** 로 설치하고, 발급된 **Bot User OAuth Token** (`xoxb-…`) 을 복사합니다. → `SLACK_BOT_TOKEN`.
|
|
138
|
+
7. 발송할 채널 ID를 확보합니다 (Slack 채널 우클릭 → **View channel details** → 하단의 `Cxxxxxxxxxx`). 비공개 채널이면 봇을 채널에 초대 (`/invite @argos`) 해야 합니다. → `SLACK_CHANNEL_ID`.
|
|
139
|
+
|
|
140
|
+
### 2. 환경변수 설정
|
|
141
|
+
|
|
142
|
+
`~/.config/argos/.env` 에 아래 세 값을 채웁니다 (`.env.example` 참고).
|
|
143
|
+
|
|
144
|
+
```dotenv
|
|
145
|
+
SLACK_BOT_TOKEN=xoxb-...
|
|
146
|
+
SLACK_APP_TOKEN=xapp-...
|
|
147
|
+
SLACK_CHANNEL_ID=C0123456789
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### 3. 봇 실행 — Socket Mode 데몬
|
|
151
|
+
|
|
152
|
+
별도의 웹서버 없이 한 줄로 켭니다.
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
uv run argos slack
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
이 프로세스는 Slack 게이트웨이에 WebSocket을 유지하면서 Keep / Pass / Deep Dive 버튼 이벤트를 수신·처리합니다.
|
|
159
|
+
**3초 ACK 룰**을 지키기 위해 Deep Dive 핸들러는 즉시 응답을 보낸 뒤 70B 분석은 백그라운드 태스크에서 수행합니다.
|
|
160
|
+
|
|
161
|
+
### 4. 일일 브리핑 발송
|
|
162
|
+
|
|
163
|
+
오늘 수집·분석된 항목을 Mainstream / Alpha 카테고리별 카드로 묶어 채널에 발송합니다.
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
# 기본 채널 (SLACK_CHANNEL_ID) 로 발송
|
|
167
|
+
uv run argos brief
|
|
168
|
+
|
|
169
|
+
# 다른 채널로 임시 발송
|
|
170
|
+
uv run argos brief --channel C0987654321
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
당일 처리된 항목이 없으면 자동으로 발송을 건너뜁니다 (빈 메시지 방지).
|
|
174
|
+
|
|
175
|
+
> **자동 스케줄링:** `argos init` 위저드가 macOS `launchd` 잡을 자동으로 등록합니다 (`com.argos.run`, `com.argos.brief`). 직접 관리하려면 `argos schedule` 서브커맨드를 쓰세요. 플리스트는 `~/Library/LaunchAgents/`에, 로그는 `~/Library/Logs/argos/{run,brief}.log`에 남습니다.
|
|
176
|
+
>
|
|
177
|
+
> ```bash
|
|
178
|
+
> uv run argos schedule install # config.toml 기준으로 두 잡을 등록 + 부트스트랩
|
|
179
|
+
> uv run argos schedule status # 두 라벨의 로드 여부 확인
|
|
180
|
+
> uv run argos schedule uninstall # 두 잡을 모두 해제 (이미 없어도 에러 없음)
|
|
181
|
+
> ```
|
|
182
|
+
>
|
|
183
|
+
> 스케줄 시각은 `~/.config/argos/config.toml`의 `briefing.time` / `briefing.weekdays` / `run.time`로 조정합니다 (아래 `argos config` 참고).
|
|
184
|
+
|
|
185
|
+
### 5. 일반적인 워크플로우
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
# 1) 새 데이터 수집 + 분석 (Ollama 필요)
|
|
189
|
+
uv run argos run
|
|
190
|
+
|
|
191
|
+
# 2) 결과를 Slack 으로 발송
|
|
192
|
+
uv run argos brief
|
|
193
|
+
|
|
194
|
+
# 3) 봇 데몬을 띄워두면 Keep/Pass/Deep Dive 버튼이 동작
|
|
195
|
+
uv run argos slack
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
## Configuration (`argos config`)
|
|
199
|
+
|
|
200
|
+
런타임 설정은 `~/.config/argos/config.toml`에 저장됩니다 (위저드가 생성). 시크릿(Slack 토큰, DB 비밀번호 등)은 `~/.config/argos/.env`에 두고, 동작 옵션만 config.toml에서 관리합니다. CLI로 안전하게 읽고 쓸 수 있습니다.
|
|
201
|
+
|
|
202
|
+
```bash
|
|
203
|
+
uv run argos config path # 사용 중인 config.toml 경로 출력
|
|
204
|
+
uv run argos config list # 전체 키 출력 (시크릿은 마스킹됨)
|
|
205
|
+
uv run argos config get briefing.time
|
|
206
|
+
uv run argos config set briefing.time 09:00
|
|
207
|
+
uv run argos config set briefing.weekdays "mon,tue,wed,thu,fri"
|
|
208
|
+
uv run argos config set briefing.limit_per_category 5
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
종료 코드: `0` 성공 · `1` I/O 등 일반 오류 · `2` 알 수 없는 키 · `3` 검증 실패 · `4` 시크릿 거부(`.env`에서 직접 관리).
|
|
212
|
+
|
|
213
|
+
설정을 바꾼 뒤 스케줄 시각/요일이 영향받는다면 `uv run argos schedule install`을 다시 돌려 플리스트를 갱신하세요.
|
|
214
|
+
|
|
215
|
+
## Testing
|
|
216
|
+
|
|
217
|
+
```bash
|
|
218
|
+
# 전체 테스트 (Ollama 불필요, 모두 mocked)
|
|
219
|
+
uv run pytest tests/ -v
|
|
220
|
+
|
|
221
|
+
# Brain 노드만
|
|
222
|
+
uv run pytest tests/brain/ -v
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
## Database
|
|
226
|
+
|
|
227
|
+
```bash
|
|
228
|
+
# 마이그레이션 생성
|
|
229
|
+
uv run alembic revision --autogenerate -m "description"
|
|
230
|
+
|
|
231
|
+
# 마이그레이션 적용
|
|
232
|
+
uv run alembic upgrade head
|
|
233
|
+
|
|
234
|
+
# 롤백
|
|
235
|
+
uv run alembic downgrade -1
|
|
236
|
+
|
|
237
|
+
# DB 종료
|
|
238
|
+
docker compose down
|
|
239
|
+
```
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "argos-scout"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Omni-Lens: Tech Scout - AI 기술 동향 자동 추적 슬랙봇"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
license = { text = "MIT" }
|
|
7
|
+
requires-python = ">=3.10,<3.13"
|
|
8
|
+
keywords = ["slack", "ai", "trend-tracking", "llm", "crawler", "pgvector"]
|
|
9
|
+
classifiers = [
|
|
10
|
+
"Development Status :: 3 - Alpha",
|
|
11
|
+
"Programming Language :: Python :: 3",
|
|
12
|
+
"Programming Language :: Python :: 3.10",
|
|
13
|
+
"Programming Language :: Python :: 3.11",
|
|
14
|
+
"Programming Language :: Python :: 3.12",
|
|
15
|
+
"License :: OSI Approved :: MIT License",
|
|
16
|
+
"Operating System :: MacOS",
|
|
17
|
+
"Operating System :: POSIX :: Linux",
|
|
18
|
+
"Topic :: Communications :: Chat",
|
|
19
|
+
"Topic :: Internet :: WWW/HTTP :: Indexing/Search",
|
|
20
|
+
]
|
|
21
|
+
dependencies = [
|
|
22
|
+
"sqlalchemy[asyncio]>=2.0",
|
|
23
|
+
"asyncpg>=0.29",
|
|
24
|
+
"pgvector>=0.3",
|
|
25
|
+
"alembic>=1.13",
|
|
26
|
+
"pydantic-settings>=2.0",
|
|
27
|
+
"python-dotenv>=1.0",
|
|
28
|
+
"httpx>=0.27",
|
|
29
|
+
"playwright>=1.44",
|
|
30
|
+
"readability-lxml>=0.8.1",
|
|
31
|
+
"lxml>=5.0",
|
|
32
|
+
"beautifulsoup4>=4.12",
|
|
33
|
+
"langgraph>=0.2",
|
|
34
|
+
"langchain-core>=0.3",
|
|
35
|
+
"slack-bolt>=1.18",
|
|
36
|
+
"aiohttp>=3.9",
|
|
37
|
+
"tomli>=2.0; python_version < '3.11'",
|
|
38
|
+
"tomli-w>=1.0",
|
|
39
|
+
"questionary>=2.0",
|
|
40
|
+
]
|
|
41
|
+
|
|
42
|
+
[project.urls]
|
|
43
|
+
Homepage = "https://github.com/james20140802/argos"
|
|
44
|
+
Repository = "https://github.com/james20140802/argos"
|
|
45
|
+
Issues = "https://github.com/james20140802/argos/issues"
|
|
46
|
+
Changelog = "https://github.com/james20140802/argos/blob/main/CHANGELOG.md"
|
|
47
|
+
|
|
48
|
+
[project.optional-dependencies]
|
|
49
|
+
dev = [
|
|
50
|
+
"pytest>=8.0",
|
|
51
|
+
"pytest-asyncio>=0.23",
|
|
52
|
+
"pytest-mock>=3.12",
|
|
53
|
+
"respx>=0.21",
|
|
54
|
+
"ruff>=0.4",
|
|
55
|
+
]
|
|
56
|
+
|
|
57
|
+
[project.scripts]
|
|
58
|
+
argos = "argos.cli:main"
|
|
59
|
+
|
|
60
|
+
[build-system]
|
|
61
|
+
requires = ["setuptools>=68.0"]
|
|
62
|
+
build-backend = "setuptools.build_meta"
|
|
63
|
+
|
|
64
|
+
[tool.setuptools.packages.find]
|
|
65
|
+
where = ["src"]
|
|
66
|
+
|
|
67
|
+
[tool.pytest.ini_options]
|
|
68
|
+
asyncio_mode = "auto"
|
|
69
|
+
testpaths = ["tests"]
|
|
70
|
+
pythonpath = ["src"]
|
|
71
|
+
|
|
72
|
+
[tool.ruff]
|
|
73
|
+
target-version = "py311"
|
|
74
|
+
line-length = 100
|
|
File without changes
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
from typing import TypedDict
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class BrainState(TypedDict):
|
|
6
|
+
raw_text: str
|
|
7
|
+
source_url: str
|
|
8
|
+
is_valid: bool
|
|
9
|
+
trust_score: float | None
|
|
10
|
+
summary: str | None
|
|
11
|
+
extracted_info: dict | None
|
|
12
|
+
related_tech_ids: list[str]
|
|
13
|
+
succession_result: dict | None
|
|
14
|
+
saved: bool
|
|
15
|
+
genealogy_skipped: bool
|
|
16
|
+
genealogy_skip_reason: str | None
|