Zum Hauptinhalt springen

Aus dem Quellcode builden

AISCouncil ist eine Single-File-HTML-Anwendung, die aus 80 modularen Quelldateien in src/ zusammengesetzt wird. Dieser Guide behandelt die volle Build-Pipeline, von TypeScript-Kompilierung bis zur finalen Assemblierung.

Voraussetzungen

  • Node.js 20+ und npm
  • Bash (Linux/macOS, oder WSL unter Windows)
  • Python 3.10+ (nur für Registry-Validierung)

Setup

Klonen Sie das Repository und installieren Sie Entwicklungs-Abhängigkeiten:

git clone https://github.com/nicholasgasior/bcz.git
cd bcz
npm install

Dies installiert:

  • esbuild – TypeScript-Type-Stripping (kein Bundling)
  • vitest + jsdom – Test-Framework
  • typescript – Type-Checking (tsc --noEmit)
Info

Dies sind nur Entwicklungs-Abhängigkeiten. Nichts aus node_modules wird an den Browser ausgeliefert. Der Produktions-Output ist eine einzelne index.html ohne externe Abhängigkeiten.

Build-Schritte

1. TypeScript-Kompilierung

Wenn Sie TypeScript-Module in modules/*/index.ts haben, kompilieren Sie diese zuerst:

npm run build:ts

Oder kompilieren Sie ein einzelnes Modul:

node scripts/compile-ts.js grid
Tipp

build.sh führt TypeScript-Kompilierung automatisch aus, wenn esbuild installiert ist. Sie müssen npm run build:ts nur manuell ausführen, wenn Sie ohne Assemblierung kompilieren möchten.

2. Assemblierung

Konkatenieren Sie alle 80 Quell-Teile in index.html:

./build.sh

Ausgabe:

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. Verifizierung

Prüfen Sie, ob src/ mit der aktuellen index.html übereinstimmt, ohne zu überschreiben:

./build.sh --check

Ausgabe bei Übereinstimmung:

OK: src/ matches index.html (80 parts)

Ausgabe bei Nicht-Übereinstimmung:

MISMATCH: src/ does not match index.html

TypeScript-Pipeline

Die TypeScript-Pipeline ist ein leichtgewichtiges Type-Stripping-System, kein Bundler.

Wie es funktioniert

Für jedes Modul in modules/*/:

  1. Quelle: modules/{name}/index.ts – TypeScript-Quelle mit Types
  2. Wrapper: modules/{name}/wrapper.txt – IIFE-Template mit {CODE}- und {Name}-Platzhaltern
  3. Ausgabe: src/{name}.js – Bereit-zu-konkatenierender <script>-Block

Das scripts/compile-ts.js-Skript:

  1. Liest die TypeScript-Quelle
  2. Ruft esbuild.transformSync() auf, um Types zu entfernen (kein Bundling, keine Format-Konvertierung)
  3. Entfernt alle import/export-Statements (das Modul wird in eine IIFE gewrapped)
  4. Rückt den Code ein und fügt ihn in das Wrapper-Template ein
  5. Wenn der Code __exports definiert, hängt es return __exports; an

Wrapper-Template

Jedes TypeScript-Modul hat eine wrapper.txt, die den <script>-Envelope definiert:

<script>
// ============================================================================
// MODULE: AIS.{Name} (compiled from TypeScript)
// ============================================================================
if (!AIS.{Name}) AIS.lazy('{Name}', function() {
'use strict';
{CODE}
});
</script>

Der {Name}-Platzhalter wird durch den kapitalisierten Modul-Namen ersetzt (z.B. grid wird zu Grid). Der {CODE}-Platzhalter wird durch den type-gestrippten, eingerückten Quellcode ersetzt.

TypeScript-Module schreiben

Verwenden Sie das var __exports = {...}-Muster für die öffentliche API des Moduls:

// modules/mymodule/index.ts

interface MyConfig {
name: string;
value: number;
}

function doSomething(config: MyConfig): string {
return config.name + ": " + config.value;
}

var __exports = {
doSomething,
};
Warnung

Verwenden Sie keine bloßen return-Statements – sie verursachen Fehler mit tsc --noEmit. Verwenden Sie var __exports = {...} und compile-ts.js wird return __exports; automatisch anhängen.

Warnung

Setzen Sie nicht format: 'esm' in esbuild-Optionen. Dies verursacht CommonJS-Wrapping, das das IIFE-Muster bricht. Das Kompilierungsskript lässt die format-Option absichtlich weg.

Type-Checking

Führen Sie den TypeScript-Compiler im Check-Only-Modus aus (keine Ausgabe):

npm run check

Dies verwendet tsc --noEmit mit dem Projekt-tsconfig.json. Typ-Definitionen sind in:

  • core-types/index.d.ts – Vollständige AIS-Namespace-Types
  • core-types/grid.d.ts – Grid-spezifische Types

Quelldatei-Reihenfolge

Die Reihenfolge der Dateien in build.sh ist kritisch. Das PARTS-Array definiert die exakte Konkatenations-Sequenz:

Shell (HTML/CSS/DOM):
shell-head.html # DOCTYPE, Meta-Tags, frühe Weiterleitung
shell-style.html # Klassenloses CSS
shell-body.html # HTML-Body, Layout, Dialoge, Formulare

Core-Module (einzelner <script>-Block):
core-boot.js # <script>-Tag, AIS-Namespace, Event-Bus, Lazy-Loader
core-auth-main.js # OAuth, Google Sign-In
core-auth-local.js # Lokale Konten, Geräte-Passwort
core-auth-init.js # Auth-UI-Wiring, Init, Export
core-billing.js # Abonnement-Stufe, Trial
core-ads.js # Statisches Werbesystem
core-codec.js # Base80, VLQ, Komprimierung
core-storage.js # IndexedDB + SQLite
core-providers.js # SSE-Factory, Registrierungs-API
core-providers-builtin.js # Eingebaute Anbieter-Definitionen
core-ui.js # DOM-Utils, Markdown, Toast
core-session.js # Bot-Sitzung-CRUD
core-chat.js # Nachrichten, Streaming
core-config.js # Bot-Konfigurations-Panel
core-app-botlist.js # Bot-Liste, Kontextmenü
core-app-switch.js # switchBot, createBot, Mega-Menü
core-app-events.js # bindEvents, Council-UI
core-app-search.js # Suche, Export, Import, Addons
core-app-init.js # Council-Helpers, Init, Boot
core-end.js # </script>

WASM-Ersetzbar (jedes im eigenen <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

Infrastruktur:
kernel-bootstrap.html, moduleloader.js, plugins.js,
mcp.js, channels-*.js, sandbox.js, publish.js,
perf.js, p2p.js, profiles.js, cron.js

Plattform:
settings-main.js, i18n.js, miniprograms.js,
docs.js, billing-ui.js, pwa.js

Tail:
shell-bottom.js # Willkommensbildschirm-Handler, schließende Tags
Warnung

Ordnen Sie die Dateireihenfolge nicht um. Core-Module teilen sich einen einzelnen <script>-Block, der von core-boot.js geöffnet und von core-end.js geschlossen wird. Das Einfügen einer Datei zwischen ihnen, die </script> enthält, wird den Build brechen.

Tests ausführen

Die Test-Suite verwendet Vitest mit einer jsdom-Umgebung.

# Alle Tests einmal ausführen
npm test

# Tests im Watch-Modus ausführen (erneuter Lauf bei Datei-Änderungen)
npm run test:watch

# Nur TypeScript-Modul-Tests ausführen
npm run test:modules

# Eine bestimmte Test-Suite ausführen
npm run test:settings

Worker-Tests werden separat aus dem worker/-Verzeichnis ausgeführt:

cd worker
npm test

Entwicklungs-Workflow

Der Standard Edit-Build-Test-Zyklus:

# 1. Quelldateien bearbeiten
$EDITOR src/core-chat.js

# 2. In index.html assemblieren
./build.sh

# 3. Im Browser testen
# index.html öffnen oder einen lokalen Server verwenden

# 4. Tests ausführen
npm test

# 5. Build-Integrität verifizieren
./build.sh --check

Für TypeScript-Module:

# 1. TypeScript-Quelle bearbeiten
$EDITOR modules/grid/index.ts

# 2. Type-Check
npm run check

# 3. Kompilieren + assemblieren (build.sh macht beides)
./build.sh

# 4. Testen
npm run test:modules

Ein neues Modul hinzufügen

Um ein neues Lazy-Loaded-Modul hinzuzufügen:

  1. Erstellen Sie src/mymodule.js mit dem Standard-Muster:
<script>
if (!AIS.MyModule)
AIS.lazy("MyModule", function () {
"use strict";

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

return { doWork };
});
</script>
  1. Fügen Sie die Datei zum PARTS-Array in build.sh an der entsprechenden Position hinzu.

  2. Führen Sie ./build.sh aus, um zu verifizieren, dass es korrekt assembliert.

Um ein neues TypeScript-Modul hinzuzufügen:

  1. Erstellen Sie modules/mymodule/index.ts mit dem Quellcode.
  2. Erstellen Sie modules/mymodule/wrapper.txt mit dem IIFE-Template (kopieren Sie von einem existierenden Modul wie modules/grid/wrapper.txt).
  3. Fügen Sie optional Typ-Definitionen zu core-types/index.d.ts hinzu.
  4. Fügen Sie src/mymodule.js zum PARTS-Array in build.sh hinzu.
  5. Führen Sie ./build.sh aus.

Registry-Validierung

Die Modell- und Paket-Registrys haben Validierungsskripte:

# Modell-Registry validieren
python3 registry/validate.py

# Paket-Registry validieren
python3 registry/validate.py packages

# Ein einzelnes Manifest validieren
python3 registry/validate.py manifest examples/hello-world/manifest.json

WASM-Kernel (Optional)

Der WASM-Kernel ist eine optionale Komponente. Das Builden erfordert Zig 0.14.0+:

cd kernel
../tools/zig/zig build # gibt zig-out/bin/kernel.wasm aus (~5,5 KB)

Der Kernel ist nicht erforderlich, damit die Hauptanwendung funktioniert. Alle Kernel-Features haben JavaScript-Fallbacks.