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.
Files changed (70) hide show
  1. argos_scout-0.1.0/LICENSE +21 -0
  2. argos_scout-0.1.0/PKG-INFO +288 -0
  3. argos_scout-0.1.0/README.md +239 -0
  4. argos_scout-0.1.0/pyproject.toml +74 -0
  5. argos_scout-0.1.0/setup.cfg +4 -0
  6. argos_scout-0.1.0/src/argos/__init__.py +0 -0
  7. argos_scout-0.1.0/src/argos/brain/__init__.py +3 -0
  8. argos_scout-0.1.0/src/argos/brain/graph_state.py +16 -0
  9. argos_scout-0.1.0/src/argos/brain/llm_client.py +115 -0
  10. argos_scout-0.1.0/src/argos/brain/nodes/__init__.py +0 -0
  11. argos_scout-0.1.0/src/argos/brain/nodes/embed.py +91 -0
  12. argos_scout-0.1.0/src/argos/brain/nodes/genealogist.py +84 -0
  13. argos_scout-0.1.0/src/argos/brain/nodes/save.py +91 -0
  14. argos_scout-0.1.0/src/argos/brain/nodes/triage.py +194 -0
  15. argos_scout-0.1.0/src/argos/brain/ollama_client.py +119 -0
  16. argos_scout-0.1.0/src/argos/brain/pipeline.py +49 -0
  17. argos_scout-0.1.0/src/argos/cli.py +576 -0
  18. argos_scout-0.1.0/src/argos/config.py +194 -0
  19. argos_scout-0.1.0/src/argos/config_store.py +318 -0
  20. argos_scout-0.1.0/src/argos/crawler/__init__.py +21 -0
  21. argos_scout-0.1.0/src/argos/crawler/_robots.py +105 -0
  22. argos_scout-0.1.0/src/argos/crawler/dynamic_fetcher.py +179 -0
  23. argos_scout-0.1.0/src/argos/crawler/pipeline.py +138 -0
  24. argos_scout-0.1.0/src/argos/crawler/static_fetcher.py +235 -0
  25. argos_scout-0.1.0/src/argos/crawler/user_agents.py +15 -0
  26. argos_scout-0.1.0/src/argos/database.py +62 -0
  27. argos_scout-0.1.0/src/argos/init_wizard/__init__.py +44 -0
  28. argos_scout-0.1.0/src/argos/init_wizard/env_file.py +147 -0
  29. argos_scout-0.1.0/src/argos/init_wizard/prompts.py +252 -0
  30. argos_scout-0.1.0/src/argos/init_wizard/runners.py +422 -0
  31. argos_scout-0.1.0/src/argos/init_wizard/steps/__init__.py +8 -0
  32. argos_scout-0.1.0/src/argos/init_wizard/steps/healthcheck.py +97 -0
  33. argos_scout-0.1.0/src/argos/init_wizard/steps/infra.py +188 -0
  34. argos_scout-0.1.0/src/argos/init_wizard/steps/interests.py +129 -0
  35. argos_scout-0.1.0/src/argos/init_wizard/steps/precheck.py +49 -0
  36. argos_scout-0.1.0/src/argos/init_wizard/steps/schedule.py +33 -0
  37. argos_scout-0.1.0/src/argos/init_wizard/steps/slack.py +155 -0
  38. argos_scout-0.1.0/src/argos/init_wizard/wizard.py +172 -0
  39. argos_scout-0.1.0/src/argos/main.py +18 -0
  40. argos_scout-0.1.0/src/argos/models/__init__.py +7 -0
  41. argos_scout-0.1.0/src/argos/models/base.py +38 -0
  42. argos_scout-0.1.0/src/argos/models/tech_item.py +61 -0
  43. argos_scout-0.1.0/src/argos/models/tech_succession.py +60 -0
  44. argos_scout-0.1.0/src/argos/models/track_history.py +36 -0
  45. argos_scout-0.1.0/src/argos/models/user_asset.py +59 -0
  46. argos_scout-0.1.0/src/argos/scheduler.py +487 -0
  47. argos_scout-0.1.0/src/argos/slack/__init__.py +3 -0
  48. argos_scout-0.1.0/src/argos/slack/app.py +27 -0
  49. argos_scout-0.1.0/src/argos/slack/blocks.py +304 -0
  50. argos_scout-0.1.0/src/argos/slack/briefing.py +65 -0
  51. argos_scout-0.1.0/src/argos/slack/handlers/__init__.py +0 -0
  52. argos_scout-0.1.0/src/argos/slack/handlers/deep_dive.py +114 -0
  53. argos_scout-0.1.0/src/argos/slack/handlers/keep.py +43 -0
  54. argos_scout-0.1.0/src/argos/slack/handlers/pass_.py +43 -0
  55. argos_scout-0.1.0/src/argos/slack/handlers/portfolio.py +44 -0
  56. argos_scout-0.1.0/src/argos/slack/handlers/untrack.py +46 -0
  57. argos_scout-0.1.0/src/argos/slack/services/__init__.py +0 -0
  58. argos_scout-0.1.0/src/argos/slack/services/asset_transition.py +72 -0
  59. argos_scout-0.1.0/src/argos/slack/services/briefing_query.py +65 -0
  60. argos_scout-0.1.0/src/argos_scout.egg-info/PKG-INFO +288 -0
  61. argos_scout-0.1.0/src/argos_scout.egg-info/SOURCES.txt +68 -0
  62. argos_scout-0.1.0/src/argos_scout.egg-info/dependency_links.txt +1 -0
  63. argos_scout-0.1.0/src/argos_scout.egg-info/entry_points.txt +2 -0
  64. argos_scout-0.1.0/src/argos_scout.egg-info/requires.txt +27 -0
  65. argos_scout-0.1.0/src/argos_scout.egg-info/top_level.txt +1 -0
  66. argos_scout-0.1.0/tests/test_cli.py +823 -0
  67. argos_scout-0.1.0/tests/test_config.py +317 -0
  68. argos_scout-0.1.0/tests/test_config_cli.py +413 -0
  69. argos_scout-0.1.0/tests/test_models.py +281 -0
  70. 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
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
File without changes
@@ -0,0 +1,3 @@
1
+ from argos.brain.pipeline import run_brain_pipeline
2
+
3
+ __all__ = ["run_brain_pipeline"]
@@ -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