| .. | ||
| cmd/node | ||
| internal | ||
| README.md | ||
node — Node Agent
디바이스당 1개 실행되는 IOP 노드 에이전트.
실제 AI 모델 추론 어댑터를 관리하고, TCP + Protobuf + mTLS 소켓을 통해 요청을 처리한다.
내부 구조 (Hexagonal Architecture)
cmd/node/ — CLI 진입점 (cobra)
internal/
bootstrap/ — fx 의존성 주입 모듈
node/ — 핵심 노드 서비스 (transport.Handler 구현)
runtime/ — 도메인 타입: ExecutionSpec, RuntimeEvent, 인터페이스
router/ — RunRequest → ExecutionSpec 라우팅
transport/ — TCP 서버, 세션 관리, 프레임 코덱
adapters/
mock/ — 에코 테스트 어댑터
ollama/ — Ollama API 어댑터 (TODO)
vllm/ — vLLM OpenAI-compatible 어댑터 (TODO)
cli/ — CLI 프로세스 어댑터 (claude/gemini/codex/opencode/cline)
store/ — SQLite 실행 이력
실행
# 빌드
go build -o bin/node ./apps/node/cmd/node
# 버전 확인
./bin/node version
# 설정 확인
./bin/node config print --config configs/node.yaml
# 서버 실행
./bin/node serve --config configs/node.yaml
원격 edge에 붙는 수동 테스트는 configs/node.yaml의 transport.edge_addr와 transport.token을 먼저 맞춘 뒤 repo root에서 실행한다.
./bin/node.sh
edge의 기본 설정은 cli adapter의 claude profile을 사용한다. PATH에 claude 명령이 있어야 하며, 각 실행 요청은 claude -p --dangerously-skip-permissions --output-format stream-json --include-partial-messages --verbose <prompt> one-shot process로 처리된다 (token-level streaming).
edge에서 실행 요청을 받으면 node는 해당 입력을 Claude process의 prompt 인자로 전달하고, stream-json delta를 토큰 단위로 emit한다.
[edge-message] hello
[node-event] start run_id=manual-...
[node-event] complete run_id=manual-... detail="cli execution complete"
[node-message] <Claude 응답 텍스트 (토큰 단위로 점진적 표시)>
Logical Session (transport 1개 · session 여러 개)
edge-node transport 연결은 호스트당 1개를 유지한다. 그 연결 위에서 CLI adapter는 session_id가 다른 여러 장수 worker process를 독립적으로 관리한다.
| 개념 | 설명 |
|---|---|
| transport 연결 | edge-node 호스트 쌍당 1개 TCP 연결 |
| logical session | (adapter, agent, session_id) 로 식별되는 장수 worker process |
| run | session 위에서 실행되는 단일 요청 |
cancel vs terminate:
CancelAction_CANCEL_RUN(기본값): 현재 실행 중인 run만 중단. session process는 살아있다.CancelAction_TERMINATE_SESSION: session process를 명시적으로 종료. 이후 같은session_id로의 요청은 새 process를 만들거나(CREATE_IF_MISSING) 에러를 반환한다(REQUIRE_EXISTING).
session_mode:
RUN_SESSION_MODE_CREATE_IF_MISSING(기본값): session이 없으면 새로 생성.RUN_SESSION_MODE_REQUIRE_EXISTING: session이 없으면 에러 반환. 새 process 생성 금지.
Node Commands
node는 모델 실행(RunRequest) 외에도 edge가 보내는 NodeCommandRequest를 처리한다.
현재 구현된 command:
USAGE_STATUS: 선택된adapter/agent(예:cli/codex)의 사용량 한도와 초기화 시간을 조회한다.- Codex의 경우 TUI를 시작하고
/status명령을 전송한 뒤 출력된% left정보를 파싱해AgentUsageStatus로 반환한다.
- Codex의 경우 TUI를 시작하고
어댑터
| 어댑터 | 설명 | 상태 |
|---|---|---|
mock |
입력 에코, 스트리밍 테스트용 | 구현 완료 |
ollama |
로컬 Ollama 서버 연동 | TODO |
vllm |
vLLM OpenAI-compatible API | TODO |
cli |
claude/gemini/codex/opencode/cline CLI 실행 | 구현 완료 |
claude, gemini, codex, opencode, cline처럼 기본이 interactive TUI인 CLI는 이 파이프라인에서 non-interactive 모드로 설정해야 한다. 예: claude -p --dangerously-skip-permissions, gemini --approval-mode yolo -p <prompt>, codex exec --dangerously-bypass-approvals-and-sandbox, opencode run --model ollama-dgx/qwen3.6:35b-a3b-bf16 --format json --dangerously-skip-permissions <prompt>, cline -y --json --config /config/.cline/profiles/ollama-dgx <prompt>.
Cline은 mutable --config 디렉터리를 프로필처럼 나눈다. /config/.cline/profiles/ollama-dgx와 /config/.cline/profiles/ollama-m1는 opencode의 ollama-dgx/ollama-m1 provider 설정을 Cline의 ollama provider 설정으로 변환한 값이다.
Transport
- TCP 4-byte length-prefix framing
- JSON-encoded Envelope (TODO: protobuf 교체)
- mTLS (configs/node.yaml에서 활성화)
- 하트비트: 30초 간격