diff --git a/agent-client/claude/README.md b/agent-client/claude/README.md index fc87d68..80bc4fa 100644 --- a/agent-client/claude/README.md +++ b/agent-client/claude/README.md @@ -3,10 +3,11 @@ 기존 Seulgivibe Claude 설정이 되어 있는 macOS 환경에서 Claude TUI `/model`에 아래 모델을 함께 노출한다. ```text -claude-seulgivibe-sonnet-4-5 -claude-seulgivibe-opus-4-8 -claude-seulgivibe-mythos-5 -claude-dev-corp-gemma4-26b +claude-seulgivibe-sonnet-4-5 Claude Sonnet 4.5 - coding agents +claude-seulgivibe-opus-4-8 Claude Opus 4.8 - browser agents +claude-seulgivibe-mythos-5 Claude Fable 5 - autonomous work +claude-dev-corp-gemma4-26b Gemma4 26B - gemma4:26b +claude-dev-corp-ornith35b Ornith 35B - ornith35b ``` ## 설치 @@ -26,5 +27,7 @@ cd agent-client/claude - `~/.claude/dev-corp-openai-api-key` - `~/.pi/agent/dev-corp-openai-api-key` - 없으면 `~/.claude/anthropic_key.sh` 출력값을 fallback으로 사용한다. +- `claude-dev-corp-gemma4-26b`는 Claude 표시용 alias이며 upstream 호출 모델은 `gemma4:26b`다. +- `claude-dev-corp-ornith35b`는 Claude 표시용 alias이며 upstream 호출 모델은 `ornith:35b`다. JWT/API key 원문은 이 폴더에 포함하지 않는다. diff --git a/agent-client/claude/install.sh b/agent-client/claude/install.sh index 84d346d..565e727 100755 --- a/agent-client/claude/install.sh +++ b/agent-client/claude/install.sh @@ -107,7 +107,7 @@ models = [ "claude-seulgivibe-sonnet-4-5", "claude-seulgivibe-opus-4-8", "claude-seulgivibe-mythos-5", - "claude-dev-corp-gemma4-26b", + "gemma4:26b", ] settings["apiKeyHelper"] = settings.get("apiKeyHelper") or "~/.claude/anthropic_key.sh" @@ -125,6 +125,8 @@ for key in [ ]: env.pop(key, None) +if settings.get("model") == "claude-dev-corp-gemma4-26b": + settings["model"] = "gemma4:26b" if settings.get("model") not in models: settings["model"] = "claude-seulgivibe-mythos-5" settings["availableModels"] = models @@ -141,7 +143,7 @@ cache = { {"id": "claude-seulgivibe-sonnet-4-5", "display_name": "Seulgivibe Sonnet 4.5"}, {"id": "claude-seulgivibe-opus-4-8", "display_name": "Seulgivibe Opus 4.8"}, {"id": "claude-seulgivibe-mythos-5", "display_name": "Seulgivibe Fable 5"}, - {"id": "claude-dev-corp-gemma4-26b", "display_name": "dev-corp gemma4:26b"}, + {"id": "gemma4:26b", "display_name": "dev-corp gemma4:26b"}, ], } cache_path.write_text(json.dumps(cache, ensure_ascii=False, separators=(",", ":")) + "\n") diff --git a/agent-client/claude/iop-claude-gateway.py b/agent-client/claude/iop-claude-gateway.py index f380d55..f63448e 100755 --- a/agent-client/claude/iop-claude-gateway.py +++ b/agent-client/claude/iop-claude-gateway.py @@ -17,7 +17,7 @@ SEULGIVIBE_HOST = os.environ.get("SEULGIVIBE_HOST", "seulgivibe.lgudax.cool") SEULGIVIBE_PREFIX = os.environ.get("SEULGIVIBE_ANTHROPIC_PREFIX", "/anthropic") SEULGIVIBE_KEY_HELPER = os.path.expanduser("~/.claude/anthropic_key.sh") -DEV_CORP_OPENAI_BASE_URL = os.environ.get( +DEFAULT_DEV_CORP_OPENAI_BASE_URL = os.environ.get( "DEV_CORP_OPENAI_BASE_URL", "http://digitalplatform.iop.ai.kr:18086/v1", ).rstrip("/") @@ -26,9 +26,37 @@ DEV_CORP_TOKEN_FILES = [ os.path.expanduser("~/.claude/dev-corp-openai-api-key"), os.path.expanduser("~/.pi/agent/dev-corp-openai-api-key"), ] -DEV_CORP_MODEL = "claude-dev-corp-gemma4-26b" -DEV_CORP_UPSTREAM_MODEL = "gemma4:26b" DEV_CORP_MIN_MAX_TOKENS = int(os.environ.get("DEV_CORP_UPSTREAM_MIN_MAX_TOKENS", "1024")) +GEMMA_MODEL = "gemma4:26b" +ORNITH_MODEL = "ornith35b" +CLAUDE_GEMMA_MODEL = "claude-dev-corp-gemma4-26b" +CLAUDE_ORNITH_MODEL = "claude-dev-corp-ornith35b" +GEMMA_OPENAI_BASE_URL = os.environ.get( + "DEV_CORP_GEMMA_OPENAI_BASE_URL", + DEFAULT_DEV_CORP_OPENAI_BASE_URL, +).rstrip("/") +ORNITH_OPENAI_BASE_URL = os.environ.get( + "DEV_CORP_ORNITH_OPENAI_BASE_URL", + "http://172.24.63.178:18003/v1", +).rstrip("/") +DEV_CORP_MODEL_CONFIGS = { + GEMMA_MODEL: { + "upstream_model": "gemma4:26b", + "base_url": GEMMA_OPENAI_BASE_URL, + }, + CLAUDE_GEMMA_MODEL: { + "upstream_model": "gemma4:26b", + "base_url": GEMMA_OPENAI_BASE_URL, + }, + ORNITH_MODEL: { + "upstream_model": "ornith:35b", + "base_url": ORNITH_OPENAI_BASE_URL, + }, + CLAUDE_ORNITH_MODEL: { + "upstream_model": "ornith:35b", + "base_url": ORNITH_OPENAI_BASE_URL, + }, +} SEULGIVIBE_ALIASES = { "claude-seulgivibe-sonnet-4-5": "claude-sonnet-4-5-20250929", @@ -40,29 +68,36 @@ MODELS = [ { "id": "claude-seulgivibe-sonnet-4-5", "type": "model", - "display_name": "Seulgivibe Sonnet 4.5", - "description": "Seulgivibe Sonnet 4.5", + "display_name": "Claude Sonnet 4.5 - coding agents", + "description": "Seulgivibe Claude Sonnet 4.5 for coding, complex agents, computer use, and long-horizon tasks.", "created_at": "2026-05-13T00:00:00Z", }, { "id": "claude-seulgivibe-opus-4-8", "type": "model", - "display_name": "Seulgivibe Opus 4.8", - "description": "Seulgivibe Opus 4.8", + "display_name": "Claude Opus 4.8 - browser agents", + "description": "Seulgivibe Claude Opus 4.8 for deeper agent work, browser and computer-use tasks, and long-session collaboration.", "created_at": "2026-05-13T00:00:00Z", }, { "id": "claude-seulgivibe-mythos-5", "type": "model", - "display_name": "Seulgivibe Fable 5", - "description": "Fable 5 · Most capable for your hardest and longest-running tasks · $10/$50 per Mtok", + "display_name": "Claude Fable 5 - autonomous work", + "description": "Seulgivibe Claude Fable 5 for complex knowledge work, coding, multi-day autonomous tasks, staged planning, delegation, and self-verification.", "created_at": "2026-05-13T00:00:00Z", }, { - "id": DEV_CORP_MODEL, + "id": CLAUDE_GEMMA_MODEL, "type": "model", - "display_name": "dev-corp gemma4:26b", - "description": "dev-corp gemma4:26b via OpenAI-compatible gateway", + "display_name": "Gemma4 26B - gemma4:26b", + "description": "dev-corp Gemma 4 26B A4B IT NVFP4 via MLX/OpenAI-compatible, tuned here for image-text and local code workflows.", + "created_at": "2026-07-10T00:00:00Z", + }, + { + "id": CLAUDE_ORNITH_MODEL, + "type": "model", + "display_name": "Ornith 35B - ornith35b", + "description": "dev-corp Ornith 1.0 35B 8-bit MLX open coding agent, routed to upstream ornith:35b.", "created_at": "2026-07-10T00:00:00Z", }, ] @@ -328,9 +363,9 @@ def anthropic_tools_to_openai(payload): return tools -def build_openai_payload(payload): +def build_openai_payload(payload, model_config): body = { - "model": DEV_CORP_UPSTREAM_MODEL, + "model": model_config["upstream_model"], "messages": anthropic_messages_to_openai(payload), "temperature": payload.get("temperature", 0.2), "top_p": payload.get("top_p", 0.95), @@ -347,8 +382,8 @@ def build_openai_payload(payload): return body -def parse_openai_url(path): - parsed = urlsplit(DEV_CORP_OPENAI_BASE_URL) +def parse_openai_url(base_url, path): + parsed = urlsplit(base_url) scheme = parsed.scheme or "http" host = parsed.hostname or "" port = parsed.port @@ -356,8 +391,8 @@ def parse_openai_url(path): return scheme, host, port, f"{prefix}{path}" -def call_dev_corp(openai_payload, inbound_headers): - scheme, host, port, path = parse_openai_url("/chat/completions") +def call_dev_corp(openai_payload, inbound_headers, model_config): + scheme, host, port, path = parse_openai_url(model_config["base_url"], "/chat/completions") body = json.dumps(openai_payload, ensure_ascii=False, separators=(",", ":")).encode("utf-8") headers = { "content-type": "application/json", @@ -427,7 +462,7 @@ def openai_to_anthropic(openai_payload, requested_model): "id": openai_payload.get("id") or f"msg_{uuid.uuid4().hex}", "type": "message", "role": "assistant", - "model": requested_model or DEV_CORP_MODEL, + "model": requested_model or GEMMA_MODEL, "content": content or [{"type": "text", "text": ""}], "stop_reason": stop_reason, "stop_sequence": None, @@ -585,12 +620,13 @@ class Handler(BaseHTTPRequestHandler): return headers = {key.lower(): value for key, value in self.headers.items()} - if payload.get("model") == DEV_CORP_MODEL: + model_config = DEV_CORP_MODEL_CONFIGS.get(payload.get("model")) + if model_config: if is_count_tokens: self.write_json(200, {"input_tokens": estimate_tokens(payload)}) return - openai_payload = build_openai_payload(payload) - status, _, body = call_dev_corp(openai_payload, headers) + openai_payload = build_openai_payload(payload, model_config) + status, _, body = call_dev_corp(openai_payload, headers, model_config) if status < 200 or status >= 300: try: detail = json.loads(body.decode("utf-8")) diff --git a/agent-ops/skills/project/dev-corp-runtime-deploy/SKILL.md b/agent-ops/skills/project/dev-corp-runtime-deploy/SKILL.md index 97c69bf..ea6be58 100644 --- a/agent-ops/skills/project/dev-corp-runtime-deploy/SKILL.md +++ b/agent-ops/skills/project/dev-corp-runtime-deploy/SKILL.md @@ -61,7 +61,7 @@ dev-corp provider pool을 현재 dev-runtime과 같은 구조로 배포한다. - 2026-07-13 기준 Spark Gemma4 `8002`/`8004` runtime은 내린 상태로 보고, Spark 01/02는 Ornith `8003`/`8005`를 IOP provider로 둔다. Gemma4는 Mac Studio `192.168.2.3:8004` provider만 기본 대상으로 둔다. - 2026-07-13 재확인 기준 DGX Spark 01 Ornith는 Docker `iop-vllm-ornith35b-fp8`, host `8003`, `--gpu-memory-utilization 0.47`로 동작하며 startup log에서 GPU KV cache `783,347` tokens, full-context concurrency `2.99x`를 확인했다. DGX Spark 02 Ornith는 host `8005`, `--gpu-memory-utilization 0.50`으로 동작하며 GPU KV cache `1,074,276` tokens, full-context concurrency `4.10x`를 확인했다. - 2026-07-02 mac-mini native Control Plane `18002/19004/19005` 관측값은 historical evidence다. 2026-07-09 현재 dev-corp Edge source of truth는 public `iop.ai.kr`이고, current runner에서 public host SSH와 public Control Plane status 접근은 확인되지 않았다. -- 2026-07-13 기준 dev-corp provider-pool Edge OpenAI-compatible capacity smoke 표준은 public `http://digitalplatform.iop.ai.kr:18086/v1/chat/completions`에서 `ornith:35b` 9/6, `gemma4:26b` 9/6 동시 요청이다. `/v1/responses`는 OpenAI-compatible provider model group raw passthrough parity 전까지 미지원이므로 성공 기준에서 제외한다. +- 2026-07-13 기준 dev-corp provider-pool Edge OpenAI-compatible capacity smoke 표준은 public `https://digitalplatform.iop.ai.kr/v1/chat/completions`에서 `ornith:35b` 9/6, `gemma4:26b` 9/6 동시 요청이다. Direct Edge listener `http://digitalplatform.iop.ai.kr:18086/v1`도 같은 backend로 동작하지만 사용자-facing 기본값으로 쓰지 않는다. `/v1/responses`는 OpenAI-compatible provider model group raw passthrough parity 전까지 미지원이므로 성공 기준에서 제외한다. - 2026-07-13 live status 기준 DGX Spark 01/02와 Mac Studio node는 `iop.ai.kr:18087`로 연결되어 있으며, provider snapshot은 Spark01 Ornith capacity `4`, Spark02 Ornith capacity `4`, Mac Studio Gemma4 capacity `5`이다. 같은 날 model-specific smoke에서 `ornith:35b` 9/6, `gemma4:26b` 9/6 요청이 모두 성공했고 완료 후 `in_flight=0`, `queued=0`, `healthy`로 회복했다. ## 실행 절차 diff --git a/agent-test/dev-corp/edge-smoke.md b/agent-test/dev-corp/edge-smoke.md index fa11b4a..8c8a1fe 100644 --- a/agent-test/dev-corp/edge-smoke.md +++ b/agent-test/dev-corp/edge-smoke.md @@ -40,7 +40,7 @@ last_rule_updated_at: 2026-07-13 - package manager: Go modules / Makefile - docker: unit/smoke quick check는 Docker를 요구하지 않는다. compose dev-corp 검증은 mac-mini에서 `.env.dev-corp.example` 기준으로 수행한다. - external service: dev-corp artifact/base URL 기본 후보 `http://iop.ai.kr:18085`, dev-corp Edge runtime 기본 후보 `iop.ai.kr:18087`; mac-mini local endpoint는 dev-corp Edge 경로로 사용하지 않는다. -- model endpoint: dev-corp OpenAI-compatible base URL 기본 후보 `http://digitalplatform.iop.ai.kr:18086/v1` +- model endpoint: dev-corp OpenAI-compatible base URL 기본 후보 `https://digitalplatform.iop.ai.kr/v1`; direct Edge listener 확인이 필요할 때만 `http://digitalplatform.iop.ai.kr:18086/v1` - credential: token/secret/API key 원문은 문서에 기록하지 않는다. ## dev-corp provider pool 인벤토리 @@ -53,7 +53,7 @@ dev-corp provider pool과 3-node 연결 상태를 점검할 때는 `agent-test/d - Control Plane HTTP/status 후보: `http://iop.ai.kr:18002`, `http://iop.ai.kr:18002/edges/dev-corp-edge/status` when the public port is enabled - Control Plane-Edge wire 후보: `iop.ai.kr:19005` when the public port is enabled - bootstrap HTTP 기본 후보: `http://iop.ai.kr:18085` -- Edge OpenAI-compatible base URL 기본 후보: `http://digitalplatform.iop.ai.kr:18086/v1` +- Edge OpenAI-compatible base URL 기본 후보: `https://digitalplatform.iop.ai.kr/v1` - Edge-Node TCP transport 기본 후보: `iop.ai.kr:18087` - mac-mini/internal 후보는 dev-corp Edge 경로가 아니다. Node `edge_addr`는 `iop.ai.kr:18087`이어야 한다. - model alias 후보: `gemma4:26b`, `ornith:35b` @@ -113,7 +113,7 @@ Mac Studio의 `http://192.168.2.3:8005/v1` mlx-vlm DiffusionGemma endpoint는 - On 2026-07-09 after rebuilding the public Edge from the current passthrough source, default streaming `/v1/chat/completions` preserved provider reasoning deltas for 15/15 historical aggregate concurrent requests; transformed `chatcmpl-manual` IDs were 0/15. Evidence: `build/dev-corp-runtime/logs/public_passthrough_chat_15_20260709_180115.json`. - On 2026-07-09 after deploying latest node binaries to DGX Spark 01/02 and Mac Studio, public streaming `/v1/chat/completions` again passed 15/15 historical aggregate concurrency with provider reasoning deltas preserved and transformed `chatcmpl-manual` IDs 0/15. Evidence: `build/dev-corp-runtime/logs/public_latest_edge_node_chat_15_20260709_181222.json`. - Mac Studio provider catalog `type`은 최신 config validator 기준으로 `openai_compat`를 사용한다. 실제 provider runtime은 vLLM-MLX이고 `runtime_type: vllm-mlx`로 추적한다. -- `/v1/chat/completions` capacity smoke 표준: public `http://digitalplatform.iop.ai.kr:18086/v1`에서 `ornith:35b`는 9개/6개 동시 요청, `gemma4:26b`는 9개/6개 동시 요청을 확인한다. 2026-07-13 live smoke에서는 네 시나리오 모두 성공했고 완료 후 provider `in_flight=0`, `queued=0`, `healthy`로 회복했다. +- `/v1/chat/completions` capacity smoke 표준: public `https://digitalplatform.iop.ai.kr/v1`에서 `ornith:35b`는 9개/6개 동시 요청, `gemma4:26b`는 9개/6개 동시 요청을 확인한다. Direct Edge listener `http://digitalplatform.iop.ai.kr:18086/v1`도 같은 backend로 동작하지만 사용자-facing 기본값으로 쓰지 않는다. 2026-07-13 live smoke에서는 네 시나리오 모두 성공했고 완료 후 provider `in_flight=0`, `queued=0`, `healthy`로 회복했다. - `/v1/responses`는 OpenAI-compatible provider model group raw passthrough parity 전까지 미지원이므로 provider-pool capacity 성공 기준에서 제외한다. ## 명령 @@ -123,7 +123,7 @@ Mac Studio의 `http://192.168.2.3:8005/v1` mlx-vlm DiffusionGemma endpoint는 - unit: `go test ./apps/edge/...` - smoke: `./scripts/e2e-smoke.sh`는 기본 포트 임시 설정을 쓰는 보조 smoke이므로 dev-corp 포트 override 필요 여부를 먼저 확인한다. - e2e: `make test-e2e`는 보조 smoke이며 full-cycle 실제 구동을 대체하지 않는다. -- model: dev-corp OpenAI-compatible profile을 띄운 경우 `gemma4:26b`와 `ornith:35b`를 각각 public `http://digitalplatform.iop.ai.kr:18086/v1/chat/completions`로 확인한다. +- model: dev-corp OpenAI-compatible profile을 띄운 경우 `gemma4:26b`와 `ornith:35b`를 각각 public `https://digitalplatform.iop.ai.kr/v1/chat/completions`로 확인한다. - direct-provider: mac-mini에서 `curl -fsS http://192.168.2.2:8003/v1/models`, `curl -fsS http://192.168.2.4:8005/v1/models`, `curl -fsS http://192.168.2.3:8004/v1/models` - full-cycle: repo 내부 edge-node 진단, `iop-edge smoke openai`, OpenAI-compatible 입력 표면 수동 검증 diff --git a/agent-test/dev-corp/inventory.yaml b/agent-test/dev-corp/inventory.yaml index 62ac163..d53635a 100644 --- a/agent-test/dev-corp/inventory.yaml +++ b/agent-test/dev-corp/inventory.yaml @@ -35,9 +35,11 @@ edge: control_plane_client_ws_public: ws://iop.ai.kr:19004/client bootstrap_http_public: http://iop.ai.kr:18085 bootstrap_http_node_internal: http://iop.ai.kr:18085 - openai_base_url_public: http://digitalplatform.iop.ai.kr:18086/v1 + openai_base_url_public: https://digitalplatform.iop.ai.kr/v1 + openai_base_url_public_http: http://digitalplatform.iop.ai.kr/v1 + openai_base_url_direct_edge_listener: http://digitalplatform.iop.ai.kr:18086/v1 openai_base_url_node_internal: http://digitalplatform.iop.ai.kr:18086/v1 - openai_base_url_runner: http://digitalplatform.iop.ai.kr:18086/v1 + openai_base_url_runner: https://digitalplatform.iop.ai.kr/v1 openai_api_key_required_current_runtime: true openai_api_key_secret_path_remote: build/dev-corp-runtime/.secrets/openai_api_key openai_api_key_value_tracked: false diff --git a/agent-test/dev-corp/node-smoke.md b/agent-test/dev-corp/node-smoke.md index c7a51df..0b0235f 100644 --- a/agent-test/dev-corp/node-smoke.md +++ b/agent-test/dev-corp/node-smoke.md @@ -39,7 +39,7 @@ last_rule_updated_at: 2026-07-13 - package manager: Go modules / Makefile - docker: unit/smoke quick check는 Docker를 요구하지 않는다. compose dev-corp 검증은 mac-mini에서 수행한다. - external service: dev-corp Edge runtime 후보는 `iop.ai.kr:18087`이다. mac-mini local endpoint와 reverse tunnel은 dev-corp Edge 경로로 사용하지 않는다. -- model endpoint: dev-corp OpenAI-compatible base URL 기본 후보 `http://digitalplatform.iop.ai.kr:18086/v1` +- model endpoint: dev-corp OpenAI-compatible base URL 기본 후보 `https://digitalplatform.iop.ai.kr/v1`; direct Edge listener 확인이 필요할 때만 `http://digitalplatform.iop.ai.kr:18086/v1` - credential: token/secret/API key 원문은 문서에 기록하지 않는다. ## dev-corp Node 접속 기준 @@ -108,7 +108,7 @@ Mac Studio의 secondary `http://192.168.2.3:8005/v1` endpoint는 기본 Node/pro ## 2026-07-09 연결/용량 검증 상태 - DGX Spark 01, DGX Spark 02, Mac Studio Node는 각 host의 `~/iop-dev-corp-field/node.yaml`에서 `edge_addr: "iop.ai.kr:18087"`로 실행된다. -- 2026-07-13 live status 기준 세 Node 모두 connected이며 provider snapshot은 Spark01 Ornith capacity `4`, Spark02 Ornith capacity `4`, Mac Studio Gemma4 capacity `5`이다. Public `http://digitalplatform.iop.ai.kr:18086/v1/chat/completions`에서 `ornith:35b` 9/6, `gemma4:26b` 9/6 동시 요청이 모두 성공했고 완료 후 `in_flight=0`, `queued=0`, `healthy`로 회복했다. +- 2026-07-13 live status 기준 세 Node 모두 connected이며 provider snapshot은 Spark01 Ornith capacity `4`, Spark02 Ornith capacity `4`, Mac Studio Gemma4 capacity `5`이다. Public OpenAI-compatible route에서 `ornith:35b` 9/6, `gemma4:26b` 9/6 동시 요청이 모두 성공했고 완료 후 `in_flight=0`, `queued=0`, `healthy`로 회복했다. 사용자-facing 기본 base URL은 `https://digitalplatform.iop.ai.kr/v1`이다. - `/v1/responses`는 OpenAI-compatible provider model group raw passthrough parity 전까지 미지원이므로 provider-pool capacity 성공 기준에서 제외한다. ## 명령 diff --git a/agent-test/dev-corp/platform-common-smoke.md b/agent-test/dev-corp/platform-common-smoke.md index 5d05aab..80d2e44 100644 --- a/agent-test/dev-corp/platform-common-smoke.md +++ b/agent-test/dev-corp/platform-common-smoke.md @@ -35,7 +35,7 @@ last_rule_updated_at: 2026-07-11 - package manager: Go modules / Makefile - docker: unit/codegen quick check는 Docker를 요구하지 않는다. compose dev-corp 검증은 mac-mini에서 수행한다. - external service: dev-corp artifact/base URL 기본 후보 `http://iop.ai.kr:18085`; mac-mini runner/local legacy 경로는 bootstrap 기본 URL로 쓰지 않는다. -- model endpoint: dev-corp OpenAI-compatible base URL 기본 후보 `http://digitalplatform.iop.ai.kr:18086/v1` +- model endpoint: dev-corp OpenAI-compatible base URL 기본 후보 `https://digitalplatform.iop.ai.kr/v1`; direct Edge listener 확인이 필요할 때만 `http://digitalplatform.iop.ai.kr:18086/v1` - credential: token/secret/API key 원문은 문서에 기록하지 않는다. ## 명령 diff --git a/agent-test/dev-corp/rules.md b/agent-test/dev-corp/rules.md index 82ee1eb..b0f18f1 100644 --- a/agent-test/dev-corp/rules.md +++ b/agent-test/dev-corp/rules.md @@ -40,8 +40,8 @@ last_rule_updated_at: 2026-07-13 - runtime: Go quick check는 local toolchain을 우선한다. Docker/Flutter/client/field/bootstrap/provider-pool evidence는 mac-mini와 내부 provider nodes를 사용한다. - package manager: Go modules / Makefile / Flutter pub - docker: 현재 작업 컨테이너에서는 Docker-in-Docker를 사용하지 않는다. Docker compose 검증은 mac-mini checkout에서 수행한다. -- external service: dev-corp Edge 후보는 `http://iop.ai.kr:18085`, `http://digitalplatform.iop.ai.kr:18086/v1`, `iop.ai.kr:18087`이다. Control Plane/Client public 후보는 해당 public host 포트가 실제로 열려 있을 때만 검증 대상으로 삼는다. -- model endpoint: Edge 배포 후 기본 외부 후보 `http://digitalplatform.iop.ai.kr:18086/v1`; 직접 provider 확인은 `agent-test/dev-corp/inventory.yaml`의 provider endpoint를 따른다. +- external service: dev-corp Edge 후보는 `http://iop.ai.kr:18085`, `https://digitalplatform.iop.ai.kr/v1`, `iop.ai.kr:18087`이다. Control Plane/Client public 후보는 해당 public host 포트가 실제로 열려 있을 때만 검증 대상으로 삼는다. +- model endpoint: Edge 배포 후 기본 외부 후보 `https://digitalplatform.iop.ai.kr/v1`; `http://digitalplatform.iop.ai.kr:18086/v1`은 direct Edge listener 확인용으로만 쓴다. 직접 provider 확인은 `agent-test/dev-corp/inventory.yaml`의 provider endpoint를 따른다. - credential: secret/token/API key 원문은 문서에 기록하지 않는다. ## 포트 매핑 diff --git a/agent-test/dev-corp/testing-smoke.md b/agent-test/dev-corp/testing-smoke.md index 487b16b..93616fd 100644 --- a/agent-test/dev-corp/testing-smoke.md +++ b/agent-test/dev-corp/testing-smoke.md @@ -33,13 +33,12 @@ last_rule_updated_at: 2026-07-13 ## 환경 - host: local checkout. Flutter client 포함 검증, Docker compose, field/bootstrap, artifact server, external provider evidence가 필요하면 mac-mini runner를 사용한다. -- port: web/dev preview `13002`, artifact/bootstrap HTTP 후보 `18085`, Edge OpenAI-compatible HTTP 후보 `18086`, Client WS `19004`, CP-Edge wire `19005`, compose Edge-Node TCP transport `19006`, native Edge-Node TCP 후보 `18087`, Edge metrics 후보 `19102`, Control Plane metrics `19104`, Prometheus `19112`, Grafana `19122`. +- port: web/dev preview `13002`, artifact/bootstrap HTTP 후보 `18085`, Edge OpenAI-compatible HTTP 후보 `18086`, Client WS `19004`, CP-Edge wire `19005`, compose Edge-Node TCP transport `19006`, native Edge-Node TCP 후보 `18087`, Edge metrics 후보 `19102`. - runtime: Go `1.24` - package manager: Go modules / Makefile - docker: quick check는 Docker를 요구하지 않는다. 현재 작업 컨테이너에서는 Docker-in-Docker를 사용하지 않으며, Docker compose 검증은 mac-mini 환경에서 수행한다. - external service: dev-corp Control Plane 후보는 mac-mini local 기준 `http://127.0.0.1:18002`, 기본 외부 후보 `http://iop.ai.kr:18002`이다. Client wire 후보는 mac-mini local 기준 `ws://127.0.0.1:19004/client`, 기본 외부 후보 `ws://iop.ai.kr:19004/client`이다. dev-corp Edge runtime 기본 후보는 `iop.ai.kr:18087`이며, mac-mini runner/local legacy 경로를 Edge runtime 또는 Node `edge_addr`로 쓰지 않는다. -- model endpoint: dev-corp OpenAI-compatible base URL 기본 후보 `http://digitalplatform.iop.ai.kr:18086/v1` -- operator notice: 기존 dev-corp 사용자-facing URL은 변경하지 않는다. 현재 세션에서는 dev-corp runner 접근이 불가하므로 이 문서는 port/profile 정의와 향후 검증 절차만 기록한다. +- model endpoint: dev-corp OpenAI-compatible base URL 기본 후보 `https://digitalplatform.iop.ai.kr/v1`; direct Edge listener 확인이 필요할 때만 `http://digitalplatform.iop.ai.kr:18086/v1` - credential: token/secret/API key 원문은 문서에 기록하지 않는다. ## 명령 @@ -48,7 +47,7 @@ last_rule_updated_at: 2026-07-13 - lint: - unit: `make test` - smoke: `./scripts/e2e-smoke.sh` -- compose-smoke: mac-mini 환경에서 `IOP_EDGE_NODE_TOKEN`을 안전하게 주입한 뒤 `docker compose --env-file .env.dev-corp.example up -d postgres redis control-plane web prometheus grafana` +- compose-smoke: mac-mini 환경에서 `IOP_EDGE_NODE_TOKEN`을 안전하게 주입한 뒤 `docker compose --env-file .env.dev-corp.example up -d postgres redis control-plane edge web` - compose-health: `curl -fsS http://127.0.0.1:18002/healthz` - control-plane-status: mac-mini에서 `curl -fsS http://127.0.0.1:18002/edges/dev-corp-edge/status` - provider-health: mac-mini에서 `curl -fsS http://192.168.2.2:8003/health`, `curl -fsS http://192.168.2.4:8005/health`, `curl -fsS http://192.168.2.3:8004/health` @@ -74,9 +73,8 @@ last_rule_updated_at: 2026-07-13 ## 판정 기준 -- dev-corp compose는 `COMPOSE_PROJECT_NAME=iop-dev-corp-agent`, `IOP_COMPOSE_NETWORK=iop-dev-corp-agent-net`, `IOP_COMPOSE_SUBNET=10.89.2.0/24`를 사용한다. +- dev-corp compose는 `COMPOSE_PROJECT_NAME=iop-dev-corp-agent`와 `IOP_COMPOSE_NETWORK=iop-dev-corp-agent-net`을 사용한다. - dev-corp compose가 local/test/dev 포트를 점유하지 않는다. -- dev-corp Control Plane 관측 그룹은 `control-plane`, `web`, `postgres`, `redis`, `prometheus`, `grafana`를 한 compose project로 묶고, Edge는 연결 검증이 필요할 때 같은 compose의 인접 service로 붙인다. - edge console에서 메시지 2회가 각각 기대 payload를 포함한 `[node-*-message]`로 표시되고, command 결과가 edge 화면에 도착한다. - node 로컬 `[node-message]` payload 라인 목록과 edge `[node-*-message]` payload 라인 목록이 run별로 내용/순서까지 동일해야 한다. - Node bootstrap UX는 Edge가 출력한 완성된 bootstrap URL과 실제 positional token 값 하나만 포함하는 한 줄 명령 형태를 유지한다. diff --git a/docs/edge-local-dev-guide.md b/docs/edge-local-dev-guide.md index f644e76..c8f30e2 100644 --- a/docs/edge-local-dev-guide.md +++ b/docs/edge-local-dev-guide.md @@ -137,7 +137,7 @@ http://:18081/v1 - 현재 dev-corp provider-pool device mapping은 `gemma4:26b` -> Mac Studio provider capacity `5`, `ornith:35b` -> DGX Spark 01/02 provider 합산 capacity `8`이다. 세부 endpoint와 runtime args는 `agent-test/dev-corp/inventory.yaml`을 기준으로 한다. - dev-corp provider-pool 안정 smoke: `think`, `reasoning_effort`, `thinking_token_budget`을 생략하고 현재 provider 기본값을 유지한다. -- 현재 dev-corp public capacity smoke 표준은 public OpenAI-compatible base `http://digitalplatform.iop.ai.kr:18086/v1`의 `/chat/completions`에서 `ornith:35b` 9/6 동시 요청과 `gemma4:26b` 9/6 동시 요청을 각각 확인하는 방식이다. +- 현재 dev-corp public capacity smoke 표준은 public OpenAI-compatible base `https://digitalplatform.iop.ai.kr/v1`의 `/chat/completions`에서 `ornith:35b` 9/6 동시 요청과 `gemma4:26b` 9/6 동시 요청을 각각 확인하는 방식이다. - 일반 표준 caller의 `stream=false` 측정은 `/v1/chat/completions`에서 요청 파라미터만으로 확인한다. - `include_reasoning=false`는 non-provider normalized route의 hide 동작 기준이다. dev-corp provider-pool pure `passthrough`에서는 client가 reasoning field를 선택적으로 무시/제거한다. - `think=false` 또는 `reasoning_effort=none`은 hide-only 옵션이 아니라 thinking disable 요청이다. dev-corp 기본 안정 smoke에서는 쓰지 않는다. @@ -145,7 +145,7 @@ http://:18081/v1 예시 (dev-corp `gemma4:26b` provider-pool non-stream 측정, think 생략): -아래 `18081` 포트는 local Edge 예시다. dev-corp public smoke에서는 base URL을 `http://digitalplatform.iop.ai.kr:18086/v1`로 바꾼다. +아래 `18081` 포트는 local Edge 예시다. dev-corp public smoke에서는 base URL을 `https://digitalplatform.iop.ai.kr/v1`로 바꾼다. Direct Edge listener `http://digitalplatform.iop.ai.kr:18086/v1`도 동작하지만 사용자-facing 기본값은 포트 없는 public URL이다. ```bash curl -fsS http://:18081/v1/chat/completions \