소스에서 빌드
AISCouncil는 src/의 80개 모듈식 소스 파일로 조립된 단일 파일 HTML 애플리케이션입니다. 이 가이드는 TypeScript 컴파일에서 최종 조립까지 전체 빌드 파이프라인을 다룹니다.
사전 요구사항
- Node.js 20+ 및 npm
- Bash (Linux/macOS, 또는 Windows의 WSL)
- Python 3.10+ (레지스트리 검증만)
설정
저장소를 클론하고 개발 의존성을 설치합니다:
git clone https://github.com/nicholasgasior/bcz.git
cd bcz
npm install
다음이 설치됩니다:
- esbuild -- TypeScript 타입 스트리핑 (번들링 없음)
- vitest + jsdom -- 테스트 프레임워크
- typescript -- 타입 체킹 (
tsc --noEmit)
이것들은 개발 의존성만입니다. node_modules의 어떤 것도 브라우저로 전송되지 않습니다. 프로덕션 출력은 외부 의존성이 없는 단일 index.html입니다.
빌드 단계
1. TypeScript 컴파일
modules/*/index.ts에 TypeScript 모듈이 있는 경우 먼저 컴파일합니다:
npm run build:ts
또는 단일 모듈 컴파일:
node scripts/compile-ts.js grid
build.sh는 esbuild가 설치되어 있으면 자동으로 TypeScript 컴파일을 실행합니다. 조립 없이 컴파일만 하려면 npm run build:ts를 수동으로 실행하세요.
2. 조립
80개의 모든 소스 파트를 index.html로 연결합니다:
./build.sh
출력:
Compiling TypeScript modules...
grid: modules/grid/index.ts -> src/grid.js
Compiled 1 module.
Built index.html (15432 lines, 982451 bytes) from 80 parts
3. 검증
덮어쓰지 않고 src/가 현재 index.html과 일치하는지 확인합니다:
./build.sh --check
일치 시 출력:
OK: src/ matches index.html (80 parts)
불일치 시 출력:
MISMATCH: src/ does not match index.html
TypeScript 파이프라인
TypeScript 파이프라인은 번들러가 아닌 경량 타입 스트리핑 시스템입니다.
작동 방식
modules/*/의 각 모듈에 대해:
- 소스:
modules/{name}/index.ts-- 타입이 있는 TypeScript 소스 - 래퍼:
modules/{name}/wrapper.txt--{CODE}와{Name}플레이스홀더가 있는 IIFE 템플릿 - 출력:
src/{name}.js-- 연결 준비된<script>블록
scripts/compile-ts.js 스크립트:
- TypeScript 소스 읽기
- 타입을 스트립하기 위해
esbuild.transformSync()호출 (번들링 없음, 포맷 변환 없음) import/export문 제거 (모듈은 IIFE로 래핑됨)- 코드를 들여쓰고 래퍼 템플릿에 삽입
- 코드가
__exports를 정의하면return __exports;추가
래퍼 템플릿
각 TypeScript 모듈은 <script> 봉투를 정의하는 wrapper.txt를 가집니다:
<script>
// ============================================================================
// MODULE: AIS.{Name} (compiled from TypeScript)
// ============================================================================
if (!AIS.{Name}) AIS.lazy('{Name}', function() {
'use strict';
{CODE}
});
</script>
{Name} 플레이스홀더는 대문자화된 모듈 이름으로 교체됩니다 (예: grid → Grid). {CODE} 플레이스홀더는 타입이 스트립되고 들여쓰기된 소스로 교체됩니다.
TypeScript 모듈 작성
모듈의 공개 API에 var __exports = {...} 패턴을 사용하세요:
// modules/mymodule/index.ts
interface MyConfig {
name: string;
value: number;
}
function doSomething(config: MyConfig): string {
return config.name + ": " + config.value;
}
var __exports = {
doSomething,
};
베어 return 문을 사용하지 마세요. tsc --noEmit에서 에러를 유발합니다. var __exports = {...}를 사용하면 compile-ts.js가 자동으로 return __exports;를 추가합니다.
esbuild 옵션에서 format: 'esm'을 설정하지 마세요. IIFE 패턴을 깨는 CommonJS 래핑을 유발합니다. 컴파일 스크립트는 의도적으로 format 옵션을 생략합니다.
타입 체킹
출력 없이 체크 전용 모드에서 TypeScript 컴파일러를 실행합니다:
npm run check
이것은 프로젝트 tsconfig.json으로 tsc --noEmit을 사용합니다. 타입 정의는 다음에 있습니다:
core-types/index.d.ts-- 전체AIS네임스페이스 타입core-types/grid.d.ts-- Grid 관련 타입
소스 파일 순서
build.sh의 파일 순서가 중요합니다. PARTS 배열이 정확한 연결 순서를 정의합니다:
Shell (HTML/CSS/DOM):
shell-head.html # DOCTYPE, meta 태그, 초기 리다이렉트
shell-style.html # 클래스 없는 CSS 스타일
shell-body.html # HTML 본문, 레이아웃, 대화상자, 폼
Core Modules (단일 <script> 블록):
core-boot.js # <script> 태그, AIS 네임스페이스, 이벤트 버스, 지연 로더
core-auth-main.js # OAuth, Google Sign-In
core-auth-local.js # 로컬 계정, 기기 비밀번호
core-auth-init.js # 인증 UI 연결, 초기화, 내보내기
core-billing.js # 구독 등급, 평가판
core-ads.js # 정적 광고 시스템
core-codec.js # Base80, VLQ, 압축
core-storage.js # IndexedDB + SQLite
core-providers.js # SSE 팩토리, 등록 API
core-providers-builtin.js # 내장 제공자 정의
core-ui.js # DOM 유틸, 마크다운, 토스트
core-session.js # 봇 세션 CRUD
core-chat.js # 메시지, 스트리밍
core-config.js # 봇 설정 패널
core-app-botlist.js # 봇 목록, 컨텍스트 메뉴
core-app-switch.js # switchBot, createBot, 메가 메뉴
core-app-events.js # bindEvents, 카운실 UI
core-app-search.js # 검색, 내보내기, 가져오기, 애드온
core-app-init.js # 카운실 헬퍼, 초기화, 부팅
core-end.js # </script>
WASM 교체 가능 (각각 자체 <script>):
registry.js, grid.js, council.js, wizard.js,
vision.js, memory.js, imagegen.js, tools.js,
reminders.js, themes.js, templates-registry.js,
model-picker.js
인프라:
kernel-bootstrap.html, moduleloader.js, plugins.js,
mcp.js, channels-*.js, sandbox.js, publish.js,
perf.js, p2p.js, profiles.js, cron.js
플랫폼:
settings-main.js, i18n.js, miniprograms.js,
docs.js, billing-ui.js, pwa.js
Tail:
shell-bottom.js # 환영 화면 핸들러, 닫는 태그
파일 순서를 재배열하지 마세요. 코어 모듈은 core-boot.js에서 열리고 core-end.js에서 닫히는 단일 <script> 블록을 공유합니다. 그 사이에 </script>가 포함된 파일을 삽입하면 빌드가 깨집니다.
테스트 실행
테스트 스위트는 jsdom 환경에서 Vitest를 사용합니다.
# 모든 테스트 한 번 실행
npm test
# 감시 모드로 테스트 실행 (파일 변경 시 재실행)
npm run test:watch
# TypeScript 모듈 테스트만 실행
npm run test:modules
# 특정 테스트 스위트 실행
npm run test:settings
Worker 테스트는 worker/ 디렉토리 내에서 별도로 실행됩니다:
cd worker
npm test
개발 워크플로
표준 편집-빌드-테스트 주기:
# 1. 소스 파일 편집
$EDITOR src/core-chat.js
# 2. index.html로 조립
./build.sh
# 3. 브라우저에서 테스트
# index.html 열기 또는 로컬 서버 사용
# 4. 테스트 실행
npm test
# 5. 빌드 무결성 검증
./build.sh --check
TypeScript 모듈의 경우:
# 1. TypeScript 소스 편집
$EDITOR modules/grid/index.ts
# 2. 타입 체크
npm run check
# 3. 컴파일 + 조립 (build.sh가 둘 다 수행)
./build.sh
# 4. 테스트
npm run test:modules
새 모듈 추가
새로운 지연 로드 모듈을 추가하려면:
- 표준 패턴으로
src/mymodule.js생성:
<script>
if (!AIS.MyModule)
AIS.lazy("MyModule", function () {
"use strict";
function doWork() {
/* ... */
}
return { doWork };
});
</script>
-
build.sh의PARTS배열에 적절한 위치에 파일 추가. -
올바르게 조립되는지 확인하기 위해
./build.sh실행.
새 TypeScript 모듈을 추가하려면:
- 소스 코드로
modules/mymodule/index.ts생성. - IIFE 템플릿으로
modules/mymodule/wrapper.txt생성 (modules/grid/wrapper.txt와 같은 기존 모듈에서 복사). - 선택적으로
core-types/index.d.ts에 타입 정의 추가. build.sh의PARTS배열에src/mymodule.js추가../build.sh실행.
레지스트리 검증
모델과 패키지 레지스트리에는 검증 스크립트가 있습니다:
# 모델 레지스트리 검증
python3 registry/validate.py
# 패키지 레지스트리 검증
python3 registry/validate.py packages
# 단일 매니페스트 검증
python3 registry/validate.py manifest examples/hello-world/manifest.json
WASM 커널 (선택)
WASM 커널은 선택적 구성 요소입니다. 빌드하려면 Zig 0.14.0+이 필요합니다:
cd kernel
../tools/zig/zig build # zig-out/bin/kernel.wasm 출력 (~5.5 KB)
커널은 메인 애플리케이션이 작동하는 데 필요하지 않습니다. 모든 커널 기능에는 JavaScript 폴백이 있습니다.