ai-chatbot/docs/pascal-editor-integration.md

141 lines
5.1 KiB
Markdown

# Pascal Editor Integration
## Current Shape
The app exposes a Pascal Editor workspace at `/pascal-editor`. Its customized
source is versioned with the main repository under `services/pascal-editor`,
while it remains an independently built Next app embedded through an iframe.
This keeps Pascal's Bun workspace and `@pascal-app/nodes` dependency graph out
of the host application's pnpm dependency graph.
The wrapper route is protected by the host application's existing login system.
Unauthenticated users are redirected to `/login?callbackUrl=/pascal-editor`.
The embedded Pascal app is self-hosted and does not use Pascal's official hosted
sign-in flow.
The page resolves the editor source in this order:
1. `NEXT_PUBLIC_PASCAL_EDITOR_URL`
2. `PASCAL_EDITOR_URL`
3. `/vendor/pascal-editor/index.html` when that file exists
4. `http://localhost:3002` when that self-hosted Pascal service is reachable in
local development
If none is available, the page shows an explicit configuration state instead of
loading a broken iframe.
## Why Iframe First
`@pascal-app/core`, `@pascal-app/viewer`, and `@pascal-app/editor` are published
on npm, but the standalone app also depends on its monorepo workspace packages.
Keeping the complete Pascal source tree below `services/pascal-editor` preserves
the built-in walls, doors, windows, levels, roofs, stairs, MCP tools, and our AI
Agent customization without coupling the host build to those packages.
## Deployment Options
### Local Self-Hosted Dev Service
Run Pascal Editor as a local standalone service:
```bash
pnpm pascal:dev
```
The helper uses `services/pascal-editor`, installs its dependencies when needed,
and starts `apps/editor` on `http://localhost:3002`. Set `PASCAL_EDITOR_DIR` only
when deliberately testing a different Pascal checkout.
Then open:
```text
http://localhost:3000/pascal-editor
```
The host app auto-detects `http://localhost:3002` in development, so no env var
is required for the default local setup.
### Same-Origin Static Bundle
Build Pascal Editor as a static bundle and place it here:
```text
public/vendor/pascal-editor/index.html
```
Then leave `NEXT_PUBLIC_PASCAL_EDITOR_URL` empty or set it explicitly:
```env
NEXT_PUBLIC_PASCAL_EDITOR_URL=/vendor/pascal-editor/index.html
```
### Separate Pascal Service
Run Pascal Editor as its own service, then set:
```env
NEXT_PUBLIC_PASCAL_EDITOR_URL=https://pascal-editor.example.com
```
`next.config.ts` reads this value and allows that origin in `frame-src` so the
iframe is not blocked by our Content Security Policy.
`PASCAL_EDITOR_URL` is also supported for server-side configuration. The final
iframe URL is visible to the browser either way, so do not place secrets in it.
The integration no longer falls back to `editor.pascal.app`, because the
official hosted app can require Pascal sign-in for create, fork, and save
actions. Use a local or self-hosted Pascal service for an auth-independent POC.
Keep any separately deployed Pascal service behind the same private network,
reverse proxy, or SSO boundary if direct access to that service must also be
restricted.
### Same-domain authenticated service
The production integration can expose Pascal below `/pascal-service` while the
service itself only listens on a loopback port. Configure:
```env
PASCAL_EDITOR_URL=/pascal-service/scenes
PASCAL_PROXY_SECRET=replace_with_a_long_random_value
```
Nginx must use `auth_request` against `/api/internal/pascal/access`, strip any
client-supplied Pascal identity or secret headers, and inject the authenticated
`X-Pascal-User-Id` into the upstream request. The Pascal scene store uses that
id as `ownerId`, so scene listing and every scene mutation remain user-scoped.
The reviewed configuration is kept in
`deploy/nginx/pascal-service.conf.template`; render its secret placeholder and
include it inside the main HTTPS `server` block.
The private Pascal service points its OpenAI-compatible model base URL to
`/api/internal/pascal-agent/v1` on this application and authenticates with
`PASCAL_PROXY_SECRET`. On every request, that gateway resolves the enabled
model explicitly marked as `multimodalModel` and its provider from system
settings. It does not fall back to the Agent Auto model. OpenAI-compatible
`openai`, `custom`, `alibaba`, and `zhipu` providers work without copying their
API keys into the Pascal service.
For repeatable deployment and upgrades on additional servers, use
`scripts/deploy-pascal-production.sh`. The complete defaults, override
variables, health check, real-model smoke test, and rollback behavior are
documented in `docs/pascal-production-deployment.md`.
## Source Maintenance
`services/pascal-editor` was imported with Git subtree so its upstream history
can still be refreshed deliberately. Apply and test upstream updates in a
dedicated branch before merging them with our localization, host authentication,
scene storage, and AI Agent changes:
```bash
git subtree pull \
--prefix=services/pascal-editor \
https://github.com/pascalorg/editor.git main \
--squash
```
Production servers do not run this command. They only pull the reviewed main
repository and let `pnpm pascal:deploy` sync the vendored source into the
isolated runtime directory.