Skip to content

Commit f402257

Browse files
committed
docs(Clone_ex): finalize STUDENT_TEST_GUIDE.md with simulation tutorials and code snippets. feat(Clone_ex): update simulated entry point handling.
1 parent f172dd4 commit f402257

6 files changed

Lines changed: 2334 additions & 3 deletions

File tree

CLONE_MANUAL_DETAILED.md

Lines changed: 1996 additions & 0 deletions
Large diffs are not rendered by default.

Clone_ex/IMPLEMENTATION_PLAN.md

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# OpenClaw Clone_ex Implementation Plan (Chapters 1-5)
2+
3+
본 문서는 OpenClaw(Moltbot)의 핵심 아키텍처를 `Clone_ex` 폴더에 클론하고 구현한 상세 과정과 실행 방법을 설명합니다. 모든 코드는 '해부학적 관점'에서 설계되어 시스템의 각 부분이 인간의 장기처럼 유기적으로 작동하도록 구성되었습니다.
4+
5+
---
6+
7+
## 🚀 1. 프로젝트 개요 (Anatomical Architecture)
8+
9+
`Clone_ex`는 OpenClaw의 복잡한 로직을 5개의 챕터로 나누어 단계별로 구현한 교육용 클론 프로젝트입니다.
10+
11+
| 파일/폴더 | 해부학적 역할 | 기능 설명 |
12+
| :--- | :--- | :--- |
13+
| `src/gateway/server.ts` | **얼굴 (Face)** | 외부 모듈이 서버를 호출하는 공식 Entry Point |
14+
| `src/gateway/server.impl.ts` | **뇌 (Brain)** | 모든 장기(HTTP, WS, Channel)를 연결하고 통합 제어 |
15+
| `src/gateway/server-http.ts` | **입 (Mouth)** | HTTP 요청 처리 및 관리 UI(Dashboard) 서빙 |
16+
| `src/gateway/server-ws-runtime.ts` | **귀 (Ears)** | WebSocket을 통한 실시간 데이터 경청 |
17+
| `src/gateway/server-channels.ts` | **팔다리 (Limbs)** | WhatsApp, Slack 등 외부 메신저와의 연결 관리 |
18+
| `src/channels/whatsapp.ts` | **눈과 귀 (Senses)** | 실제 외부 메시지를 수집하고 표준 형식으로 변환 |
19+
| `src/agents/pi-embedded-runner.ts` | **지능 (Intelligence)** | LLM을 사용하여 의도를 분석하고 답변을 생성 |
20+
| `src/narrator.ts` | **신경계 (Nerve)** | 시스템의 모든 움직임을 기록하고 보고 (Logging) |
21+
22+
---
23+
24+
## 🛠 2. 구현 방법 및 기술 스택
25+
26+
### 핵심 기술 (Tech Stack)
27+
- **Runtime**: Node.js (v22+)
28+
- **Language**: TypeScript (엄격한 타입 체크 및 인터페이스 기반 설계)
29+
- **Framework**: Hono (경량 고속 웹 서버)
30+
- **Messenger API**: Baileys (WhatsApp Web 리버스 엔지니어링)
31+
- **Architecture**: Micro-Kernel & Event-Driven (중앙 Gateway 중심 설계)
32+
33+
### 단계별 구현 로직
34+
1. **Chapter 1 (기초)**: `tsconfig.json``package.json` 설정으로 현대적 ESM 환경 구축.
35+
2. **Chapter 2 (신경망)**: `narrator.ts`를 통해 시스템의 모든 로그를 추적 가능하게 만듦.
36+
3. **Chapter 3 (오감)**: WhatsApp 어댑터를 구현하여 외부 메시지를 수신하는 '눈'을 장착.
37+
4. **Chapter 4 (지능)**: AI 에이전트 러너를 구현하여 메시지에 대한 지능적 답변 생성.
38+
5. **Chapter 5 (얼굴)**: `ui/` 폴더 내의 HTML/JS를 통해 시스템 상태를 시각화하는 대시보드 구축.
39+
40+
---
41+
42+
## 🏃 3. 실행 방법 (Execution Guide)
43+
44+
현재 환경의 보안 정책(EPERM) 및 패키지 설치 제한을 고려하여 두 가지 실행 방법을 제공합니다.
45+
46+
### 방법 A: 전체 통합 시뮬레이션 (추천)
47+
외부 라이브러리 설치 없이 모든 챕터의 로직이 연결되는 것을 터미널에서 즉시 확인할 수 있습니다.
48+
```bash
49+
node run_simulation.js
50+
```
51+
- **작동 방식**: 가상의 WhatsApp 메시지 발생 -> 브레인 분석 -> AI 답변 생성 -> 전송 완료 과정을 시각화하여 보여줍니다.
52+
53+
### 방법 B: 실제 서버 가동 (로컬 환경 필요)
54+
사용자님의 로컬 컴퓨터에서 실제 서버를 띄우고 UI에 접속하는 방법입니다.
55+
```bash
56+
cd Clone_ex
57+
pnpm install
58+
pnpm run dev
59+
```
60+
- **접속**: 브라우저에서 `http://localhost:18789`로 접속하여 제어 패널 확인 가능.
61+
62+
---
63+
64+
## 📅 4. 향후 실행 및 확장 계획 (Forward Plan)
65+
66+
1. **실제 API 연동**: 현재 시뮬레이션된 AI/메신저 부분을 실제 OpenAI/Baileys API 키와 연결.
67+
2. **데이터베이스 영속화**: SQLite를 사용하여 대화 내역 및 사용자 세션을 파일로 영구 저장.
68+
3. **도구 호출(Tool Calling) 확장**: 날씨 조회 외에 일정 예약, 이메일 전송 등의 실제 기능을 에이전트에 추가.
69+
4. **모바일 최적화**: 대시보드 UI를 반응형으로 개선하여 스마트폰에서도 모니터링 가능하도록 개선.
70+
71+
---
72+
**작성일**: 2026-02-21
73+
**상태**: Chapters 1-5 구현 완료 및 검증 성공

Clone_ex/STUDENT_TEST_GUIDE.md

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
# 🎓 OpenClaw Clone_ex: 학생용 테스트 및 학습 가이드
2+
3+
이 문서는 우리가 구현한 `Clone_ex` 프로젝트의 작동 원리를 직접 확인하고, 소스 코드를 분석하며 시스템의 **'해부학적 구조(Anatomy)'**를 깊이 있게 이해하기 위해 작성되었습니다.
4+
5+
---
6+
7+
## 🧪 테스트 목표
8+
1. **시뮬레이션**을 통해 시스템이 유기적으로 살아 움직이는 과정을 확인합니다.
9+
2. **로그(Log)**를 분석하여 데이터가 어떤 **'프로세스 - 장기'**를 거쳐가는지 추적하는 능력을 배양합니다.
10+
3. **코드**를 직접 수정해 보며 시스템의 반응을 통해 설계자의 의도를 파악합니다.
11+
12+
---
13+
14+
## 🚀 Step 1: 시스템 가동 (The Big Bang)
15+
16+
가상 시스템 전체가 어떻게 연결되어 작동하는지 직접 구동해 보시기 바랍니다.
17+
18+
1. VS Code 하단의 **터미널(Terminal)**을 엽니다.
19+
2. 아래 명령어를 입력하여 시뮬레이션을 실행합니다.
20+
```bash
21+
cd Clone_ex
22+
node interactive_run_ex.js
23+
```
24+
25+
> **💡 잠깐! 시뮬레이션 코드는 어떻게 만드나요?**
26+
>
27+
> 코드를 완성한 뒤, 전체 흐름을 테스트하기 위해 AI(몰트봇)에게 **시뮬레이션 코드** 작성을 요청하는 방법을 익혀 두십시오. 실제 환경(예: WhatsApp 연동)을 꾸리기 전에 핵심 로직만 검증할 때 매우 유용합니다.
28+
>
29+
> **[AI 프롬프트 작성 공식]**
30+
> 1. **목적 선언**: "지금까지 작성한 전체 코드가 유기적으로 동작하는지 터미널에서 확인하고 싶어."
31+
> 2. **조건 명시 (가상화)**: "실제 외부 연결(WhatsApp, HTTP 포트 바인딩 등)은 모두 `console.log``setTimeout`으로 가상화(Mocking) 처리해 줘."
32+
> 3. **단계별 출력 요구**: "초기화 -> 메시지 수신 -> 분석 -> 응답 등 전체 과정을 Step별로 보기 좋게 출력하는 하나의 실행 파일(`interactive_run.js`)을 만들어 줘."
33+
3. **관찰 및 분석 포인트**:
34+
- 터미널에 출력되는 **[STEP 1] 기초 공사 및 신경망 초기화** 로그에서 어떤 신경망이 초기화되는지 확인하십시오. (힌트: `EventEmitter`)
35+
- 터미널에 출력되는 **[STEP 5] 브레인 가동** 단계에서 AI가 대화를 이해할 때 발생하는 로그의 흐름을 분석해 보시기 바랍니다.
36+
37+
---
38+
39+
## 🧠 Step 2: 뇌와 오감의 연결 구조 확인 (Anatomical Study)
40+
41+
코드를 직접 열어 우리가 정의한 '해부학적 역할'이 실제 구현과 어떻게 일치하는지 대조해 보시기 바랍니다.
42+
43+
| 확인할 파일 | 해부학적 역할 | 분석 포인트 (Focus) |
44+
| :--- | :--- | :--- |
45+
| `src/gateway/server.impl.ts` | **뇌 (Brain)** | `gateway.on("incoming_message", ...)` 로직이 메시지 수신 시 어떻게 반응하는지 파악하십시오. |
46+
| `src/narrator.ts` | **신경망 (Nerve)** | `narrate` 함수가 시스템 전반의 정보를 어떻게 포맷팅하여 출력을 표준화하는지 연구하십시오. |
47+
| `src/agents/pi-embedded-runner.ts` | **지능 (Intelligence)** | `runAgent` 함수 내에서 AI의 답변 생성 로직이 어떻게 구성되어 있는지 추론해 보시기 바랍니다. |
48+
49+
### 1. 뇌 (Brain) - `src/gateway/server.impl.ts`
50+
> **분석 포인트**: `gateway.on("incoming_message", ...)` 로직이 메시지 수신 시 어떻게 반응하는지 파악하십시오.
51+
52+
```typescript
53+
import { narrate } from "../narrator.js";
54+
import { runAgent } from "../agents/pi-embedded-runner.js";
55+
import EventEmitter from "events";
56+
57+
// ... (생략)
58+
59+
export async function startGatewayServer() {
60+
// 1. 게이트웨이 이벤트 허브 생성 (신경 중추)
61+
const gateway = new EventEmitter();
62+
63+
// ... (중략)
64+
65+
// [신경망 핵심] 메시지 유입 시 AI 에이전트 실행 로직
66+
gateway.on("incoming_message", async (msg: any) => {
67+
narrate({
68+
who: "Brain",
69+
role: "지휘소",
70+
action: "WhatsApp 메시지 수신 -> AI 분석 의뢰",
71+
friend: msg.from
72+
});
73+
74+
// AI 에이전트 실행 (지능에게 판단 의뢰)
75+
const reply = await runAgent(msg.text);
76+
77+
// AI의 답변을 다시 WhatsApp으로 전송 (팔다리에게 명령)
78+
await whatsapp.sendMessage(msg.from, reply);
79+
});
80+
}
81+
```
82+
83+
### 2. 신경망 (Nerve) - `src/narrator.ts`
84+
> **분석 포인트**: `narrate` 함수가 시스템 전반의 정보를 어떻게 포맷팅하여 출력을 표준화하는지 연구하십시오.
85+
86+
```typescript
87+
import fs from 'fs';
88+
89+
// "해설자" 함수: 시스템의 모든 움직임을 기록합니다.
90+
export function narrate(info: {
91+
who: string; // 함수 이름
92+
role: string; // 역할
93+
action: string; // 하는 일
94+
friend?: string; // 연결 대상
95+
}) {
96+
const logMessage = `[${new Date().toISOString()}]
97+
👤 WHO: ${info.who}
98+
🛡️ ROLE: ${info.role}
99+
🎬 ACTION: ${info.action}
100+
${info.friend ? `🔗 CONTACT: ${info.friend}` : ""}
101+
--------------------------------------------------\n`;
102+
103+
// 1. 화면(Terminal)에 실시간 출력
104+
console.log(logMessage);
105+
106+
// 2. 파일(learning.log)에 영구 기록
107+
try {
108+
fs.appendFileSync('learning.log', logMessage);
109+
} catch (err) {
110+
console.error('Failed to write to learning.log:', err);
111+
}
112+
}
113+
```
114+
115+
### 3. 지능 (Intelligence) - `src/agents/pi-embedded-runner.ts`
116+
> **분석 포인트**: `runAgent` 함수 내에서 AI의 답변 생성 로직이 어떻게 구성되어 있는지 추론해 보시기 바랍니다.
117+
118+
```typescript
119+
import { narrate } from "../narrator.js";
120+
121+
/**
122+
* AI 에이전트 실행기: 사용자의 입력을 이해하고 답변을 생성합니다.
123+
*/
124+
export async function runAgent(userInput: string) {
125+
narrate({
126+
who: "runAgent",
127+
role: "지능형 뇌 (AI Agent)",
128+
action: "사용자 요청 추론 시작",
129+
friend: userInput
130+
});
131+
132+
// 1. [추론 시작] LLM 호출 시뮬레이션
133+
console.log(`[Agent] Thinking about: "${userInput}"...`);
134+
await new Promise(resolve => setTimeout(resolve, 1500));
135+
136+
// 2. [행동 판단] 도구 사용 여부 체크
137+
if (userInput.includes("날씨")) {
138+
narrate({ who: "Agent", role: "지능", action: "도구 선택: WeatherAPI" });
139+
const weatherInfo = "서울은 현재 맑음, 기온은 15도입니다.";
140+
return `요청하신 날씨 정보입니다: ${weatherInfo}`;
141+
}
142+
143+
// 3. [일반 응답]
144+
return "안녕하세요! 저는 몰트봇입니다. 무엇을 도와드릴까요?";
145+
}
146+
```
147+
148+
---
149+
150+
## 🛠 Step 3: 시스템 '신경' 수정 실험 (Experiments)
151+
152+
이론으로 배운 것을 바탕으로 직접 코드를 수정하여 시스템의 변화를 관찰해 보십시오.
153+
154+
### 실험 A: 시스템의 '응답 스타일' 변경
155+
1. `interactive_run_ex.js` 파일을 엽니다.
156+
2. `Step 5` 조각에 정의된 `aiReply` 변수의 내용을 본인만의 스타일로 수정합니다.
157+
3. 다시 `node interactive_run_ex.js`를 실행하여 수정된 응답이 정상적으로 출력되는지 확인하십시오.
158+
159+
### 실험 B: 새로운 '신경 로그' 추가
160+
1. `src/gateway/server-http.ts` 파일을 엽니다.
161+
2. `app.get("/health", ...)` 핸들러 내에 새로운 `narrate` 로그를 추가해 보십시오. (예: `action: "상태 점검 중"`)
162+
3. 저장 후 시뮬레이션을 다시 구동하여 본인이 추가한 로그가 출력되는지 확인하십시오.
163+
164+
---
165+
166+
## 📋 자가 진단 체크리스트 (Self-Check)
167+
168+
테스트를 마치신 후, 다음 질문에 명확하게 답할 수 있는지 본인의 실력을 점검해 보시기 바랍니다.
169+
170+
- [ ] 메시지 수신 시 가장 먼저 반응하는 **'프로세스 - 장기'**의 명칭과 역할을 이해했습니까?
171+
- [ ] AI 에이전트와 메신저 사이를 연결하는 '중재자'의 개념을 파악했습니까?
172+
- [ ] 터미널에 출력되는 로그 시스템이 전체 아키텍처 이해에 어떤 도움을 주는지 체득했습니까?
173+
174+
---
175+
**Happy Coding!** 기술적 궁금증이 생기면 주저하지 말고 질문하시기 바랍니다. 여러분의 성장을 끝까지 지원하겠습니다. 🚀

Clone_ex/interactive_run_ex.js

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import EventEmitter from "events";
2+
3+
/**
4+
* [OpenClaw Clone_ex 대화형 시뮬레이터]
5+
* 각 단계별로 시스템의 작동 원리를 설명하며 실행됩니다.
6+
*/
7+
8+
const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
9+
10+
async function stepHeader(stepNum, title, description) {
11+
console.log("\n" + "=".repeat(60));
12+
console.log(`[STEP ${stepNum}] ${title}`);
13+
console.log("-".repeat(60));
14+
console.log(`💡 목적: ${description}`);
15+
console.log("=".repeat(60) + "\n");
16+
await sleep(2000);
17+
}
18+
19+
function narrate(info) {
20+
console.log(` [Log] 👤 ${info.who.padEnd(10)} | 🛡️ ${info.role.padEnd(12)} | 🎬 ${info.action}`);
21+
}
22+
23+
async function runInteractiveSimulation() {
24+
console.log("\n" + "★".repeat(60));
25+
console.log(" OpenClaw(Moltbot) 통합 시스템 단계별 시연 시작");
26+
console.log(" 본 시연은 Chapters 1-5의 모든 핵심 로직을 포함합니다.");
27+
console.log("★".repeat(60) + "\n");
28+
await sleep(2000);
29+
30+
// --- Step 1: Foundation ---
31+
await stepHeader(1, "기초 공사 및 신경망 초기화 (Core & Nerve)", "시스템의 뼈대와 로그를 기록할 신경망을 구축합니다.");
32+
const gateway = new EventEmitter();
33+
narrate({ who: "System", role: "Infrastructure", action: "EventEmitter(신경망) 생성 완료" });
34+
narrate({ who: "Narrator", role: "신경계", action: "로그 추적 시스템 가동" });
35+
await sleep(2000);
36+
37+
// --- Step 2: Mouth & Ears ---
38+
await stepHeader(2, "입(HTTP)과 귀(WS) 개방", "외부 세계(브라우저, 관리자)와 소통할 통로를 엽니다.");
39+
narrate({ who: "HTTP Server", role: "입 (Mouth)", action: "Port 18789 리스닝 시작 (Hono 기반)" });
40+
narrate({ who: "WS Runtime", role: "귀 (Ears)", action: "실시간 대시보드 연결 대기 상태 진입" });
41+
await sleep(2000);
42+
43+
// --- Step 3: Eyes & Ears (WhatsApp) ---
44+
await stepHeader(3, "오감(Sensors) 활성화: WhatsApp 연동", "실제 외부 사용자의 메시지를 감지할 센서를 가동합니다.");
45+
narrate({ who: "WhatsApp", role: "눈과 귀", action: "메신저 인증 정보 로드 및 서버 연결 성공" });
46+
console.log(" [알림] 이제 시스템은 외부로부터의 자극(메시지)을 기다립니다...");
47+
await sleep(3000);
48+
49+
// --- Step 4: Incoming Message ---
50+
await stepHeader(4, "자극 발생: 메시지 수신 (Input)", "외부 사용자로부터 실제 질문이 도착했습니다.");
51+
const incomingMsg = {
52+
from: "821012345678@s.whatsapp.net",
53+
text: "안녕 몰트봇! 오늘 서울 날씨가 어때?",
54+
platform: "whatsapp"
55+
};
56+
narrate({ who: "WhatsApp", role: "감각 센서", action: "새 메시지 감지 및 표준화(Normalization)" });
57+
narrate({ who: "Gateway", role: "신경 경로", action: "브레인(Brain)으로 데이터 패킷 전송" });
58+
await sleep(2000);
59+
60+
// --- Step 5: Brain Processing ---
61+
await stepHeader(5, "브레인 가동: AI 에이전트 추론 (Think)", "수신된 텍스트의 의도를 분석하고 답변을 설계합니다.");
62+
narrate({ who: "AI Agent", role: "지능형 뇌", action: "의도 분석 중... [서울], [날씨] 키워드 포착" });
63+
await sleep(1500);
64+
narrate({ who: "AI Agent", role: "지능형 뇌", action: "내부 날씨 도구(Tool) 호출 및 결과 생성" });
65+
const aiReply = "현재 서울의 기온은 15도이며 맑은 하늘입니다. 산책하기 아주 좋은 날씨네요! ☀️";
66+
await sleep(1500);
67+
68+
// --- Step 6: Limbs Action ---
69+
await stepHeader(6, "운동 기능: 답변 전송 (Output)", "뇌의 명령을 받아 팔다리가 실제로 응답을 보냅니다.");
70+
narrate({ who: "ChannelMgr", role: "운동 신경", action: "답변 패킷을 WhatsApp 팔로 전달" });
71+
console.log(`\n >>> [WhatsApp 전송 완료] To: ${incomingMsg.from}`);
72+
console.log(` >>> [내용]: ${aiReply}\n`);
73+
narrate({ who: "WhatsApp", role: "팔 (Limbs)", action: "메시지 발송 성공 시그널 확인" });
74+
await sleep(2000);
75+
76+
// --- Final Summary ---
77+
console.log("\n" + "=".repeat(60));
78+
console.log(" 🎉 OpenClaw Clone_ex 시연 완료!");
79+
console.log("-".repeat(60));
80+
console.log(" 1. 기초(Nerve) -> 2. 통로(Gateway) -> 3. 인지(Sensor)");
81+
console.log(" 4. 추론(Brain) -> 5. 실행(Limbs)의 전 과정이 검증되었습니다.");
82+
console.log("=".repeat(60) + "\n");
83+
}
84+
85+
runInteractiveSimulation().catch(console.error);

Clone_ex/src/server.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/// <reference types="node" />
12
import { startGatewayServer } from "./gateway/server.js";
23
import { narrate } from "./narrator.js";
34

@@ -20,10 +21,10 @@ async function run() {
2021
`);
2122

2223
// 프로세스 종료 시 서버 안전 종료
23-
process.on('SIGINT', async () => {
24+
(process as any).on('SIGINT', async () => {
2425
console.log("\n종료 신호를 받았습니다...");
2526
await server.close({ reason: "Process interrupted" });
26-
process.exit(0);
27+
(process as any).exit(0);
2728
});
2829
}
2930

Clone_ex/tsconfig.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
"skipLibCheck": true,
1212
"resolveJsonModule": true,
1313
"noEmitOnError": true,
14-
"allowSyntheticDefaultImports": true
14+
"allowSyntheticDefaultImports": true,
15+
"types": ["node"]
1516
},
1617
"include": ["src/**/*"],
1718
"exclude": [

0 commit comments

Comments
 (0)