12 KiB
12 KiB
| domain | last_rule_review_commit | last_rule_updated_at |
|---|---|---|
| node | 7ca329ac9e |
2026-07-14 |
node
목적 / 책임
Edge에 연결되어 실제 adapter execution을 수행하는 IOP 노드 에이전트 영역이다. edge에서 들어온 실행·취소·조회성 명령을 runtime 요청으로 변환하고, 라우팅된 어댑터를 실행하며, 실행 이벤트와 현재 단계의 로컬 실행 이력을 관리한다.
포함 경로
apps/node/cmd/node/— node CLI 진입점과 서브커맨드apps/node/internal/bootstrap/— fx 의존성 주입과 adapter registry 구성apps/node/internal/node/— transport handler 구현과 실행 오케스트레이션apps/node/internal/runtime/— node 도메인 타입과 핵심 인터페이스apps/node/internal/router/— RunRequest를 ExecutionSpec으로 해석하는 라우팅apps/node/internal/transport/— edge와의 TCP/protobuf 세션 및 메시지 처리apps/node/internal/adapters/— mock/ollama/vllm/cli 실행 어댑터apps/node/internal/store/— SQLite 실행 이력 저장apps/node/internal/terminal/— persistent terminal session과 tail buffer helperapps/node/README.md— node 실행 흐름과 adapter/session 경계 설명
제외 경로
apps/edge/— Node를 관리하는 실행 그룹 컨트롤러 영역apps/control-plane/— 여러 Edge 연결 관리와 운영 제어 API 제공 영역apps/worker/— 비동기 작업 처리 예정 영역packages/go/— 여러 앱이 공유하는 Go 공통 패키지proto/— 앱 간 메시지 계약
주요 구성 요소
runtime.Adapter— adapter target 실행 계약runtime.Router— 실행 요청을 구체적인ExecutionSpec으로 변환하는 계약runtime.CommandHandler— adapter별NodeCommandRequest처리 optional 계약runtime.SessionTerminator— logical session 종료를 지원하는 optional 계약runtime.ProviderProber/runtime.ProviderProbeResult— provider endpoint와 target availability probe optional 계약runtime.ProviderTunnelAdapter/ProviderTunnelRequest/ProviderTunnelFrame— OpenAI-compatible provider raw HTTP/SSE tunnel optional 계약node.Node—transport.Handler구현체이자 실행 파이프라인 조정자node.runManager— run ID 기준runHandle(cancel, done) 등록/해제/취소 관리;node.Node내부에서만 사용node.Node.OnConfigRefresh()— Edge가 보낸NodeConfigRefreshRequest를 적용하고 adapter registry를 live swapnode.Node.OnProviderTunnelRequest()— provider tunnel 요청을 지원 adapter에 전달하고 tunnel frame을 edge session으로 반환node.sessionSink— adapterRuntimeEvent를 protoRunEvent로 변환해 edge session으로 보내는 sinktransport.Session— edge와 연결된 node 세션 및 메시지 처리adapters.Registry— 어댑터 등록/조회 및LifecycleAdapterstart/stop lifecycle 관리 (실패 시 역순 롤백)adapters.LifecycleAdapter— start/stop lifecycle이 필요한 어댑터의 optional 인터페이스adapters.ConfigSet/adapters.DiffConfigSets()— Edge config payload에서 adapter registry/runtime snapshot을 만들고 refresh diff를 산출adapters.BuildFromPayload()— edge에서 받은NodeConfigPayload로Registry를 초기화하는 factoryadapters/cli.CLI— one-shot, persistent TUI, persistent-lazy, codex-exec, antigravity-print, opencode-sse profile을 실행하는 CLI adapteradapters/cli.clineJSONEmitter— Cline JSON output을RuntimeEventdelta/error로 변환하는 emitteradapters/cli.executeAntigravityPrint()— Antigravity print mode conversation id를 IOP logical session별로 보관하고 resume_args로 후속 요청을 재개adapters/cli.executeOpencodeSSE()— opencode serve HTTP/SSE session을 실행하거나--attach로 외부 server에 연결해 delta를 relayadapters/cli.executePersistent()— terminal/persistent profile의 completion marker, idle timeout, output filter를 처리adapters/cli/status— claude/codex/antigravity CLI 상태 파서 (사용량 한도, reset 시각 등)adapters/cli.lineEmitter— stdout 한 줄을 파싱해RuntimeEvent를 반환하는 내부 인터페이스;emitters.go에서 format별로 등록adapters/ollama.Ollama— Ollama/api/chatstreaming,/api/tagscapabilities,/api/*command passthrough를 처리하는 adapteradapters/openai_compat.Adapter— OpenAI-compatible/v1/models, chat completions, provider label/header/options passthrough, provider tunnel을 처리하는 adapteradapters/vllm.Vllm— vLLM/SGLang류 OpenAI-compatible endpoint를 직접 호출하고 provider tunnel을 처리하는 adapterterminal.Session/terminal.TailBuffer— persistent TUI session I/O, resize/signal/close, visible output buffer helperstore.Store— 실행 상태와 결과 저장
유지할 패턴
runtime패키지에는 도메인 타입과 인터페이스를 두고 구체 구현 의존성을 넣지 않는다.- transport/proto 타입은
node.Node경계에서 runtime 타입으로 변환한다. - 내부 실행 식별자는
adapter + target을 사용한다. 외부 OpenAI-compatible API나 legacy placeholder를 제외하고model을 내부 실행 대표 용어로 되돌리지 않는다. - Edge-Node runtime wire와 Edge가 내려주는 config payload 계약 상세는
agent-contract/inner/edge-node-runtime-wire.md와agent-contract/inner/edge-config-runtime-refresh.md를 기준으로 확인한다. - 어댑터 추가 시
runtime.Adapter를 구현하고adapters.BuildFromPayload()또는 bootstrap registry에 등록한다. - 여러 adapter instance는
adapters.Registry.RegisterKeyed(instanceKey, typeName, adapter)로 등록하고, router lookup은 instance key를 우선한다. legacy type-name lookup은 단일 instance일 때만 안전하다. - field Node의 기본 시작 경로는 Edge bootstrap script가 만든 최소 config와 Edge가 RegisterResponse로 내려주는 adapter/runtime payload다. 사용자가 기본 경로에서 node config를 직접 작성하거나 adapter/provider 세부값을 명령줄에 넣는 흐름을 만들지 않는다.
- Node runtime 작업 디렉터리나 store/workspace 경로는 대상 OS에서 쓰기 가능한 기본값이어야 한다. Edge가 특정 node에
workspace_root를 내려줄 때 macOS/dev host 절대 경로(/Users/...) 같은 값을 Linux/Windows node에 재사용하지 않으며, OS별 경로가 필요하면 Edge 설정에 미리 굽는다. - 실행 취소는 run ID 기준으로
runManager에 등록하고 실행 종료 시 반드시deregister로 해제한다. CancelAction_CANCEL_RUN은 현재 run 취소,CancelAction_TERMINATE_SESSION은 logical session 종료로 구분한다.ProviderTunnelRequest는 run ID/tunnel ID 기준으로runManager에 등록하고,ProviderTunnelFrame은 RunEvent stream과 별도 proto message로 edge에 반환한다. tunnel 지원은runtime.ProviderTunnelAdapter를 구현한 adapter에만 허용한다.NodeCommandRequest는 실행 요청과 분리해USAGE_STATUS,CAPABILITIES,SESSION_LIST,TRANSPORT_STATUS같은 조회/제어성 명령으로 처리한다.OLLAMA_APIcommand는 Ollama adapter 내부의 제한된/api/*passthrough로 처리하고, Edge/OpenAI surface가 node HTTP client를 우회해 직접 Ollama에 붙는 구조로 확장하지 않는다.adapters.Registry의 start/stop은 bootstrap lifecycle에서만 호출하고 개별 adapter에서 직접 호출하지 않는다.- cli adapter의 출력 format별 파싱 로직은
lineEmitter구현체로 분리하고node.Node에 분기문으로 박지 않는다. - CLI profile mode별 세부 실행(
persistent-lazy,codex-exec,antigravity-print,opencode-sse)은adapters/cli내부에 두고,runtime.Adapter계약 밖으로 새 transport를 노출하지 않는다. cline-json,opencode-json,codex-json,claude-json같은 provider별 stdout parser는adapters/cliemitter로 등록하고 runtime 공통 이벤트로만 외부에 노출한다.- CLI logical session은
(target, session_id)로 식별한다. Antigravity conversation id, Codex external id, opencode session/server 상태를 전역 target 단위로 공유하지 않는다. response_idle_timeout_ms,startup_idle_timeout_ms,completion_marker,resume_args,mode같은 CLI profile 설정은 edge config/proto payload를 통해 주입하고 node 코드에 target별 상수를 늘리지 않는다.- config refresh는
adapters.BuildConfigSet()로 next registry를 만들고 start 성공 후 router registry를 live swap한다. 기존 in-flight run은 old adapter snapshot으로 마무리하고, old registry stop은 active run drain 뒤에 처리한다. - Node-wide runtime concurrency는 admission source로 되살리지 않는다. per-adapter
Capabilities().MaxConcurrency가 adapter gate capacity의 기준이다. - Ollama adapter는 내부 target을 model 이름으로 사용하고,
context_size는options.num_ctx의 강제 소유값으로 주입한다. 요청 input에 명시된options.num_ctx가 있어도 Edge-ownedcontext_size가 항상 우선한다.context_size가 0이면 request 값을 그대로 사용한다. - vLLM/openai_compat adapter는 OpenAI-compatible provider endpoint를 호출하되, Edge가 선택한 served model target과 provider header/auth/passthrough 정책을 보존한다.
RuntimeEvent는 start/delta/reasoning_delta/complete/error/cancelled 타입을 유지하고, adapter별 streaming 표현을 node 외부로 새 이벤트 체계로 노출하지 않는다.- node 내부 변경은 가능한 대상 패키지 테스트를 먼저 추가하거나 갱신한다.
apps/node/cmd/node/**,apps/node/internal/bootstrap/**,apps/node/internal/transport/**,apps/node/internal/node/**,apps/node/internal/router/**,apps/node/internal/adapters/**,apps/node/internal/terminal/**,apps/node/internal/store/**의 실행 요청/응답/stream/cancel/status/session/config-refresh/provider-tunnel 경로를 바꾼 뒤에는testingdomain rule의 작업 후 검증 기준을 따른다.
다른 도메인과의 경계
- edge: edge는 node 연결 등록, adapter/runtime 설정 전달, 라우팅 진입, stream relay를 담당한다. node는 edge가 보낸 실행/취소/명령 요청을 처리하고 이벤트와 명령 응답을 돌려준다.
- platform-common: node는
packages/go/config,packages/go/events,packages/go/observability,proto/gen/iop등을 사용하지만 공통 타입/설정/event helper 자체의 소유자는 platform-common이다. - control-plane: control-plane은 Node가 아니라 Edge를 통해 시스템을 제어한다. node는 control-plane 직접 연결/직접 스케줄링을 전제로 하지 않는다.
금지 사항
- node 도메인 내부에서 gRPC, WebSocket 기본 transport, actor/FSM/plugin framework를 새 기본 구조로 도입하지 않는다.
proto/gen/iop/*.pb.go생성 파일을 직접 수정하지 않는다.- 새 어댑터 구현을
node.Node에 직접 분기문으로 박아 넣지 않는다. - provider tunnel 지원을 RunEvent delta에 섞거나 OpenAI-compatible raw response를 node stdout parser처럼 취급하지 않는다.
- config refresh 중 old registry를 in-flight run이 끝나기 전에 stop해 기존 실행을 끊지 않는다.
- edge-local console, OpenAI-compatible HTTP, A2A 같은 입력 표면 책임을 node로 끌어오지 않는다.
- placeholder 상태인 control-plane/worker 책임을 node에 임시로 흡수하지 않는다.
- CLI provider별 session/conversation 상태를
runtime공통 인터페이스로 성급히 승격하지 않는다. provider 세부 상태는adapters/cli내부에 둔다. - field bootstrap 기본 안내에서 사용자가
IOP_HOME,IOP_NODE_CONFIG,IOP_NODE_METRICS_PORT같은 환경 변수를 먼저 선언해야만 동작하는 형태를 요구하지 않는다. 필요한 값은 bootstrap 기본값 또는 Edge-provided config로 처리하고, 환경 변수는 optional override로만 둔다.