From e3dd2db3586bde0f21ee36fd762df13685c4f312 Mon Sep 17 00:00:00 2001 From: LeeJhin Date: Mon, 8 Jun 2026 18:00:14 +0900 Subject: [PATCH] Change default ports to math constants MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit agent 3000 → 31415 (π) web 3001 → 27182 (e) math-engine 8000 → 16180 (φ) 영향: - 코드 default 5곳: PORT/MATH_ENGINE_URL Zod default, CORS allowlist, SSE hook fallback, uvicorn port, next dev/start port - 활성 config: agent/.env.example - 활성 문서 4종: README, AGENTS, web README, rag-integration spec 핸드오프 스냅샷(deliverables/openmath_handoff_*)은 의도적으로 보존. Note: AGENTS.md, README.md 등 일부 파일은 working tree에 존재하던 다른 in-progress 작업(D-11/D-12 mapping, §9 진입점 현황 재작성 등)도 함께 묶여 들어감 (사용자 승인). --- AGENTS.md | 32 ++++++++++--------- README.md | 26 +++++++-------- docs/specs/rag-integration.md | 4 +-- packages/agent/.env.example | 6 ++-- packages/agent/src/config/env.ts | 4 +-- packages/agent/src/server/app.ts | 2 +- packages/math-engine/run.py | 2 +- packages/web/README.md | 19 +++++------ packages/web/hooks/use-verification-stream.ts | 6 ++-- packages/web/package.json | 4 +-- 10 files changed, 54 insertions(+), 51 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 563328e..f626769 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -29,6 +29,8 @@ | D-7 (RagClient) | `packages/agent/src/tools/rag-client.ts` | | D-8 (.md frontmatter) | `packages/agent/src/tools/prompt-loader.ts`, `packages/agent/prompts/*.md` | | D-9 (Next.js 14 + 듀얼-서피스 디자인) | `packages/web/`, `packages/web/DESIGN.md` | +| D-11 (I-G4 투명 노출 정책) | `packages/agent/src/server/routes/generate.ts`, `packages/web/DESIGN.md` `{component.result-card-failed}` | +| D-12 (S0-B OCR v2 보류) | `packages/web/` S0 카드 disabled 상태 | | [`docs/specs/domain.md`](docs/specs/domain.md) §2 도메인 | `packages/agent/src/schemas/*.schema.ts` | | 불변식 I-V1 ~ I-V5 | `assertVerificationInvariants` | | 불변식 I-I1 ~ I-I3 | `IntentSchema.regex` + `assertIntentInvariants` | @@ -42,9 +44,9 @@ |---|---| | 의존성 설치 + git hooks | `pnpm install` | | 세 서비스 동시 dev | `pnpm dev:all` | -| agent만 dev | `pnpm dev` (`:3000`) | -| math-engine만 dev | `pnpm dev:math` (`:8000`) | -| web만 dev | `pnpm dev:web` (`:3001`) | +| agent만 dev | `pnpm dev` (`:31415`) | +| math-engine만 dev | `pnpm dev:math` (`:16180`) | +| web만 dev | `pnpm dev:web` (`:27182`) | | Node typecheck (agent + web) | `pnpm typecheck` | | Node unit test (agent) | `pnpm -F @openmath/agent test` | | Node integration test | `pnpm -F @openmath/agent test:integration` | @@ -147,21 +149,21 @@ agent 코드를 *건드리지 않고* 동작이 바뀌는 영역. --- -## 9. 진입점 우선순위 (현재 미구현) +## 9. 진입점 현황 (구현 완료) -`grep -rn "not implemented yet" packages/agent/src` 로 14곳 확인 가능. +`grep -rn "not implemented yet" packages/agent/src` 로 0곳 — 아래 진입점 모두 구현 완료. | Priority | 파일 | 비고 | |---|---|---| -| P0 | `tools/math-engine-client.ts` `createMathEngineClient` | math-engine은 작동 중. 첫 통합 | -| P0 | `tools/prompt-loader.ts` `createFsPromptLoader` | gray-matter + handlebars | -| P0 | `tools/llm-provider.ts` `resolveLanguageModel` | CLIProxyAPI 우선 | -| P1 | `tools/rag-client.ts` `createInMemoryRagClient` | JSONL + filter | -| P1 | `agents/*-agent.ts` (4개) | `generateObject` + prompt 로드 | -| P1 | `steps/*.ts` (6개) | agents/tools 얇은 wrapper | -| P2 | `workflows/verification-workflow.ts` | async generator + I-V invariant assert | -| P2 | `server/routes/generate.ts` + `sse/progress-stream.ts` | streamSSE 흘리기 | -| P3 | `src/index.ts` `main` | dep wiring (10줄) | +| P0 | `tools/math-engine-client.ts` `createMathEngineClient` | 구현 완료 | +| P0 | `tools/prompt-loader.ts` `createFsPromptLoader` | 구현 완료 (gray-matter + handlebars) | +| P0 | `tools/llm-provider.ts` `resolveLanguageModel` | 구현 완료 (CLIProxyAPI 우선) | +| P1 | `tools/rag-client.ts` `createInMemoryRagClient` | 구현 완료 (JSONL + filter) | +| P1 | `agents/*-agent.ts` (4개) | 구현 완료 | +| P1 | `steps/*.ts` (6개) | 구현 완료 | +| P2 | `workflows/verification-workflow.ts` | 구현 완료 | +| P2 | `server/routes/generate.ts` + `sse/progress-stream.ts` | 구현 완료 | +| P3 | `src/index.ts` `main` | 구현 완료 | --- @@ -169,7 +171,7 @@ agent 코드를 *건드리지 않고* 동작이 바뀌는 영역. - [`README.md`](README.md) — 프로젝트 무엇·왜·누구 - [`CONTRIBUTING.md`](CONTRIBUTING.md) — 브랜치·hook·커밋·CI 규칙 -- [`docs/specs/architecture.md`](docs/specs/architecture.md) — L0 시스템 경계, 결정 8개, Open Questions 4개 +- [`docs/specs/architecture.md`](docs/specs/architecture.md) — L0 시스템 경계, 결정 12개, Open Questions 4개 - [`docs/specs/domain.md`](docs/specs/domain.md) — L1 도메인 개념 + 불변식 17개 - [`docs/product/`](docs/product/) — 사용자 측 기획 5종 + HTML preview (2026-05-07 핸드오프) - [`docs/PROGRESS.md`](docs/PROGRESS.md) — 데이터 파이프라인 + 에이전트 실험 보고 (2026-04-03) diff --git a/README.md b/README.md index 15ed4fd..ed5c2c8 100644 --- a/README.md +++ b/README.md @@ -40,10 +40,10 @@ LLM access is pluggable: direct OpenAI/Anthropic, or via [CLIProxyAPI](https://g ## Status -- **`math-engine`** — operational. 5 endpoints (`/solve`, `/verify`, `/simplify`, `/differentiate`, `/limit`) + 19 pytest passing. -- **`agent`** — scaffolded per spec; 42 TS files with stable interfaces + Zod schemas. Implementations pending (search `throw new Error(".*: not implemented yet")`). -- **`web`** — Landing page + DESIGN.md spec scaffolded. `pnpm build` green, static prerender. 추가 화면 (S0~S6) 마이그레이션은 FE 담당. -- **L0 architecture** — Proposed (D-1 ~ D-9). **L1 domain** — Draft. L2 contracts·L3 modules: TBD. +- **`math-engine`** — operational. 5 endpoints (`/solve`, `/verify`, `/simplify`, `/differentiate`, `/limit`) + 20 pytest passing. +- **`agent`** — implemented per spec; 48 TS source files with stable interfaces + Zod schemas. No stubs remain (`grep "not implemented yet" packages/agent/src` returns 0 matches). +- **`web`** — Landing + S0~S6 workflow screens + DESIGN.md spec implemented. `pnpm build` green. S5/S6 (결과·출력)은 현재 mock 데이터 기반 — agent SSE 연동 진행 중. +- **L0 architecture** — Proposed (D-1 ~ D-12). **L1 domain** — Draft. L2 contracts·L3 modules: TBD. ## Development @@ -55,9 +55,9 @@ pnpm typecheck # tsc --noEmit on agent + web pnpm build # production build (agent + web) ``` -- Agent: `http://localhost:3000` (SSE at `POST /api/generate`) -- Math Engine: `http://localhost:8000` -- Web: `http://localhost:3001` (landing) +- Agent: `http://localhost:31415` (SSE at `POST /api/generate`) +- Math Engine: `http://localhost:16180` +- Web: `http://localhost:27182` (landing) ### LLM 환경 설정 (필수) @@ -101,11 +101,11 @@ LLM_MODEL=claude-3-5-sonnet-20241022 ### 포트 충돌 회피 -다른 프로세스(Mantis, 별도 Next.js 서버 등)가 3000번을 점유하면 `pnpm dev:all` 시 agent가 `EADDRINUSE`로 실패. 다음 단계로 회피: +다른 프로세스(Mantis, 별도 Next.js 서버 등)가 31415번을 점유하면 `pnpm dev:all` 시 agent가 `EADDRINUSE`로 실패. 다음 단계로 회피: ```bash # 1. 충돌 확인 -lsof -i :3000 +lsof -i :31415 # 2. agent 포트 변경 PORT=3002 pnpm dev @@ -118,7 +118,7 @@ echo "NEXT_PUBLIC_AGENT_URL=http://localhost:3002" > packages/web/.env.local pnpm -F @openmath/web dev ``` -`NEXT_PUBLIC_AGENT_URL`이 미설정이면 web은 `http://localhost:3000`을 호출하므로 포트 변경 시 반드시 `.env.local` 갱신. +`NEXT_PUBLIC_AGENT_URL`이 미설정이면 web은 `http://localhost:31415`를 호출하므로 포트 변경 시 반드시 `.env.local` 갱신. ### 데모 실행 절차 (캡스톤) @@ -133,7 +133,7 @@ cp packages/agent/.env.example packages/agent/.env # 2. (매 시연) 세 서비스 기동 pnpm dev:all -# 3. (브라우저) http://localhost:3001 → S0 → 학년(중3) → 단원(이차방정식) +# 3. (브라우저) http://localhost:27182 → S0 → 학년(중3) → 단원(이차방정식) # → 평가 차원(인수분해 또는 근의 공식 사용 + 판별식) → 생성 # 4. (검증) S4 6단계 ✓ → S5 결과 3문항 → S6 PDF @@ -142,7 +142,7 @@ pnpm dev:all 또는 직접 SSE: ```bash -curl -sN -X POST http://localhost:3000/api/generate \ +curl -sN -X POST http://localhost:31415/api/generate \ -H "Content-Type: application/json" \ -d '{"grade":3,"topic":"9수02-09","mode":"structural","dims":["인수분해 또는 근의 공식 사용","판별식으로 해의 종류 해석"]}' ``` @@ -163,7 +163,7 @@ packages/ │ └── data/ # corpus JSONL + strategy YAML — hand-off slot ├── math-engine/ # Python — SymPy verification HTTP │ ├── src/ # FastAPI app + routers -│ └── tests/ # pytest (19 tests) +│ └── tests/ # pytest (20 tests) └── web/ # Node 22 — Next.js 14 App Router + Tailwind v4 ├── DESIGN.md # 디자인 시스템 spec (editorial + productivity 듀얼-서피스) ├── app/ diff --git a/docs/specs/rag-integration.md b/docs/specs/rag-integration.md index 98e8e75..9621189 100644 --- a/docs/specs/rag-integration.md +++ b/docs/specs/rag-integration.md @@ -62,8 +62,8 @@ CORPUS_JSONL=/absolute/path/to/rag_problem_generation_dataset/openmath_rag_recor 예시 로컬 `.env`: ```env -PORT=3000 -MATH_ENGINE_URL=http://localhost:8000 +PORT=31415 +MATH_ENGINE_URL=http://localhost:16180 CORPUS_JSONL=/Users//dev/AI_HUB_data/rag_problem_generation_dataset/openmath_rag_records.jsonl ``` diff --git a/packages/agent/.env.example b/packages/agent/.env.example index afaf8e4..a8795dc 100644 --- a/packages/agent/.env.example +++ b/packages/agent/.env.example @@ -2,10 +2,10 @@ # 모두 optional. 미설정 시 src/config/env.ts 기본값 또는 src/index.ts fallback 사용. # --- 서버 --- -# 다른 프로세스(예: Mantis 등)가 3000 점유 시 PORT 변경 + 동시에 +# 기본 31415 (π). 다른 프로세스 점유 시 PORT 변경 + 동시에 # packages/web/.env.local 의 NEXT_PUBLIC_AGENT_URL 도 같이 갱신해야 web↔agent 연결됨. -PORT=3000 -MATH_ENGINE_URL=http://localhost:8000 +PORT=31415 +MATH_ENGINE_URL=http://localhost:16180 # --- RAG --- # 미설정 시 ./data/corpus/math-sample-unified-v1.jsonl (repo 동봉) 사용. diff --git a/packages/agent/src/config/env.ts b/packages/agent/src/config/env.ts index c962e1f..2ff32e4 100644 --- a/packages/agent/src/config/env.ts +++ b/packages/agent/src/config/env.ts @@ -4,9 +4,9 @@ import { z } from "zod"; export const EnvSchema = z.object({ NODE_ENV: z.enum(["development", "test", "production"]).default("development"), - PORT: z.coerce.number().int().min(1).max(65535).default(3000), + PORT: z.coerce.number().int().min(1).max(65535).default(31415), - MATH_ENGINE_URL: z.string().url().default("http://localhost:8000"), + MATH_ENGINE_URL: z.string().url().default("http://localhost:16180"), LLM_PROVIDER: z .enum(["openai", "openai-compatible", "anthropic-via-compatible", "cliproxy"]) diff --git a/packages/agent/src/server/app.ts b/packages/agent/src/server/app.ts index 9cd963b..e60c631 100644 --- a/packages/agent/src/server/app.ts +++ b/packages/agent/src/server/app.ts @@ -20,7 +20,7 @@ export function createApp(deps: AppDeps): Hono { app.use( "*", cors({ - origin: ["http://localhost:3001", "http://127.0.0.1:3001"], + origin: ["http://localhost:27182", "http://127.0.0.1:27182"], allowHeaders: ["Content-Type", "Accept"], allowMethods: ["GET", "POST", "OPTIONS"], }), diff --git a/packages/math-engine/run.py b/packages/math-engine/run.py index 6202761..19415be 100644 --- a/packages/math-engine/run.py +++ b/packages/math-engine/run.py @@ -4,6 +4,6 @@ uvicorn.run( "src.main:app", host="0.0.0.0", - port=8000, + port=16180, reload=True, ) diff --git a/packages/web/README.md b/packages/web/README.md index f88a348..d22d107 100644 --- a/packages/web/README.md +++ b/packages/web/README.md @@ -2,7 +2,7 @@ OpenMath 프론트엔드 (Next.js 14 App Router + Tailwind v4). -랜딩 페이지 보일러플레이트 + [DESIGN.md](./DESIGN.md) 디자인 시스템 spec. 1차 핸드오프 시점에는 `/` 랜딩 1 화면만 작동. +랜딩 페이지 보일러플레이트 + [DESIGN.md](./DESIGN.md) 디자인 시스템 spec. 현재 `/`, `/login`, `/samples`, `/app/*` (S0~S6) 가 작동. --- @@ -10,10 +10,10 @@ OpenMath 프론트엔드 (Next.js 14 App Router + Tailwind v4). ```bash pnpm install # 루트에서 1회 -pnpm -F @openmath/web dev # http://localhost:3001 +pnpm -F @openmath/web dev # http://localhost:27182 ``` -`agent` 서비스 (포트 3000) 가 동시에 떠 있어야 SSE 엔드포인트를 호출할 수 있다. `pnpm dev:all` 사용 권장. +`agent` 서비스 (포트 31415) 가 동시에 떠 있어야 SSE 엔드포인트를 호출할 수 있다. `pnpm dev:all` 사용 권장. ## 디렉토리 @@ -54,25 +54,26 @@ npx @google/design.md lint DESIGN.md `broken-ref` 는 error, 나머지는 warning. lint 통과 = front matter 와 prose 의 토큰 참조가 모두 resolve 됨. -## SSE Consumption (후속 PR) +## SSE Consumption -`agent` 의 `POST /api/generate` 가 6 단계 검증 progress 를 SSE 로 흘림. 1차 핸드오프에는 미포함. +`agent` 의 `POST /api/generate` 가 6 단계 검증 progress 를 SSE 로 흘림. 현재 구현됨 (`hooks/use-verification-stream.ts`). **중요**: 브라우저 `EventSource` 는 GET 전용. `POST /api/generate` 와 호환되지 않음. 두 가지 선택지: - (A) **`@microsoft/fetch-event-source`** 사용 — production 패턴 (OpenDerisk, Openinary, Kodus AI 채택). custom hook `hooks/use-verification-stream.ts` 안에 `fetchEventSource` 래핑 + `AbortController` cleanup. - (B) `agent` 측에서 `GET /api/generate?…` 로 변경 — 표준 `EventSource` 사용 가능. -후속 PR 에서 (A) 채택 잠정. `useChat` (Vercel AI SDK) 은 AI SDK 의 `data-*` 메시지 스트림 프로토콜 전용이라 임의 SSE 이벤트 이름 (`step_started`, `pipeline_completed`) 과 호환 안 됨. +현재 구현은 (A) `@microsoft/fetch-event-source` 채택. `useChat` (Vercel AI SDK) 은 AI SDK 의 `data-*` 메시지 스트림 프로토콜 전용이라 임의 SSE 이벤트 이름 (`step_started`, `pipeline_completed`) 과 호환 안 됨. 이벤트 종류 (`docs/specs/architecture.md` D-6): - `step` — `{ index: 1-6, name: string, status: 'started' | 'completed' | 'failed' }` +- `preview` — `{ latex: string }` (중간 후보 LaTeX 미리보기) - `result` — `GeneratedProblem[]` (검증 통과한 문항 묶음) - `error` — `{ stage: string, message: string }` -후속 PR scope: -- `lib/sse-client.ts` + `hooks/use-verification-stream.ts` (`fetchEventSource` + `AbortController` cleanup) +구현 내역: +- `hooks/use-verification-stream.ts` (`fetchEventSource` + `AbortController` cleanup) — 구현 완료 - React 18 strict-mode 더블 마운트 방어 (cleanup 함수) -- `agent` 측 CORS 설정 (`Access-Control-Allow-Origin: http://localhost:3001`) +- `agent` 측 CORS 설정 (`Access-Control-Allow-Origin: http://localhost:27182`) - `@openmath/agent` 워크스페이스 dep 추가 + Zod 스키마 import (`@openmath/agent/schemas`) ## 폰트 로딩 diff --git a/packages/web/hooks/use-verification-stream.ts b/packages/web/hooks/use-verification-stream.ts index ec4ef7d..42bee5b 100644 --- a/packages/web/hooks/use-verification-stream.ts +++ b/packages/web/hooks/use-verification-stream.ts @@ -17,7 +17,7 @@ import { useEffect, useReducer, useRef } from "react"; * 로컬 타입을 사용한다. 추후 zod 스키마 import 로 검증을 강화한다. * ──────────────────────────────────────────────────────────── */ -export const STEP_NAMES: readonly string[] = [ +const STEP_NAMES: readonly string[] = [ "RAG 검색", "의도 추출", "문제 생성", @@ -67,7 +67,7 @@ export type StreamInput = { mode: "structural" | "conceptual"; dims: readonly string[]; sourceProblemText?: string; - /** override agent endpoint. defaults to NEXT_PUBLIC_AGENT_URL or localhost:3000 */ + /** override agent endpoint. defaults to NEXT_PUBLIC_AGENT_URL or localhost:31415 */ endpoint?: string; }; @@ -236,7 +236,7 @@ class FatalStreamError extends Error {} function defaultEndpoint(): string { const env = typeof process !== "undefined" ? process.env.NEXT_PUBLIC_AGENT_URL : undefined; - return env ?? "http://localhost:3000"; + return env ?? "http://localhost:31415"; } function verificationStorageKey(input: StreamInput): string { diff --git a/packages/web/package.json b/packages/web/package.json index 8c557aa..97df121 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -4,9 +4,9 @@ "private": true, "type": "module", "scripts": { - "dev": "next dev --port 3001", + "dev": "next dev --port 27182", "build": "next build", - "start": "next start --port 3001", + "start": "next start --port 27182", "lint": "next lint", "typecheck": "tsc --noEmit" },