본문으로 건너뛰기

소스에서 빌드

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/*/의 각 모듈에 대해:

  1. 소스: modules/{name}/index.ts -- 타입이 있는 TypeScript 소스
  2. 래퍼: modules/{name}/wrapper.txt -- {CODE}{Name} 플레이스홀더가 있는 IIFE 템플릿
  3. 출력: src/{name}.js -- 연결 준비된 <script> 블록

scripts/compile-ts.js 스크립트:

  1. TypeScript 소스 읽기
  2. 타입을 스트립하기 위해 esbuild.transformSync() 호출 (번들링 없음, 포맷 변환 없음)
  3. import/export 문 제거 (모듈은 IIFE로 래핑됨)
  4. 코드를 들여쓰고 래퍼 템플릿에 삽입
  5. 코드가 __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} 플레이스홀더는 대문자화된 모듈 이름으로 교체됩니다 (예: gridGrid). {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

새 모듈 추가

새로운 지연 로드 모듈을 추가하려면:

  1. 표준 패턴으로 src/mymodule.js 생성:
<script>
if (!AIS.MyModule)
AIS.lazy("MyModule", function () {
"use strict";

function doWork() {
/* ... */
}

return { doWork };
});
</script>
  1. build.shPARTS 배열에 적절한 위치에 파일 추가.

  2. 올바르게 조립되는지 확인하기 위해 ./build.sh 실행.

새 TypeScript 모듈을 추가하려면:

  1. 소스 코드로 modules/mymodule/index.ts 생성.
  2. IIFE 템플릿으로 modules/mymodule/wrapper.txt 생성 (modules/grid/wrapper.txt와 같은 기존 모듈에서 복사).
  3. 선택적으로 core-types/index.d.ts에 타입 정의 추가.
  4. build.shPARTS 배열에 src/mymodule.js 추가.
  5. ./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 폴백이 있습니다.