@wenathlan/saddle 2.0.150 → 2.0.152
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Dockerfile +43 -23
- package/README.md +4 -4
- package/biome.jsonc +134 -0
- package/dist/App.d.ts +3 -0
- package/dist/App.js +50 -0
- package/dist/Sol/Sol.d.ts +3 -0
- package/dist/Sol/Sol.js +46 -0
- package/dist/Sol/agentbrowser/agentbrowser.d.ts +9 -0
- package/dist/Sol/agentbrowser/agentbrowser.js +121 -0
- package/dist/Sol/architecture/architecture.d.ts +9 -0
- package/dist/Sol/architecture/architecture.js +93 -0
- package/dist/Sol/compute/compute.d.ts +9 -0
- package/dist/Sol/compute/compute.js +22 -0
- package/dist/Sol/console/console.d.ts +15 -0
- package/dist/Sol/console/console.js +292 -0
- package/dist/Sol/dashboard/dashboard.d.ts +10 -0
- package/dist/Sol/dashboard/dashboard.js +181 -0
- package/dist/Sol/docs/docs.d.ts +9 -0
- package/dist/Sol/docs/docs.js +28 -0
- package/dist/Sol/home/home.d.ts +35 -0
- package/dist/Sol/home/home.js +239 -0
- package/dist/Sol/integrations/integrations.d.ts +9 -0
- package/dist/Sol/integrations/integrations.js +83 -0
- package/dist/Sol/intro/intro.d.ts +7 -0
- package/dist/Sol/intro/intro.js +102 -0
- package/dist/Sol/login/login.d.ts +16 -0
- package/dist/Sol/login/login.js +49 -0
- package/dist/Sol/notfound/notfound.d.ts +9 -0
- package/dist/Sol/notfound/notfound.js +15 -0
- package/dist/Sol/onboarding/onboarding.d.ts +25 -0
- package/dist/Sol/onboarding/onboarding.js +60 -0
- package/dist/Sol/playground/playground.d.ts +9 -0
- package/dist/Sol/playground/playground.js +127 -0
- package/dist/Sol/register/register.d.ts +16 -0
- package/dist/Sol/register/register.js +193 -0
- package/dist/Sol/shell/Shell.d.ts +124 -0
- package/dist/Sol/shell/Shell.js +335 -0
- package/dist/Sol/wingets/ComputeBootladder.d.ts +6 -0
- package/dist/Sol/wingets/ComputeBootladder.js +71 -0
- package/dist/Sol/wingets/ComputeModalitycatalog.d.ts +7 -0
- package/dist/Sol/wingets/ComputeModalitycatalog.js +71 -0
- package/dist/Sol/wingets/ConsoleApibadge.d.ts +7 -0
- package/dist/Sol/wingets/ConsoleApibadge.js +5 -0
- package/dist/Sol/wingets/ConsoleEdgelaw.d.ts +6 -0
- package/dist/Sol/wingets/ConsoleEdgelaw.js +36 -0
- package/dist/Sol/wingets/ConsoleEventstimeline.d.ts +19 -0
- package/dist/Sol/wingets/ConsoleEventstimeline.js +12 -0
- package/dist/Sol/wingets/ConsoleSnapshotcontrols.d.ts +8 -0
- package/dist/Sol/wingets/ConsoleSnapshotcontrols.js +8 -0
- package/dist/Sol/wingets/ConsoleSpecpanel.d.ts +21 -0
- package/dist/Sol/wingets/ConsoleSpecpanel.js +75 -0
- package/dist/Sol/wingets/ConsoleTerminal.d.ts +22 -0
- package/dist/Sol/wingets/ConsoleTerminal.js +77 -0
- package/dist/Sol/wingets/DashboardAccountpanel.d.ts +18 -0
- package/dist/Sol/wingets/DashboardAccountpanel.js +65 -0
- package/dist/Sol/wingets/DashboardAdminpanel.d.ts +6 -0
- package/dist/Sol/wingets/DashboardAdminpanel.js +90 -0
- package/dist/Sol/wingets/DashboardAuditlog.d.ts +8 -0
- package/dist/Sol/wingets/DashboardAuditlog.js +50 -0
- package/dist/Sol/wingets/DashboardCreatesandboxform.d.ts +10 -0
- package/dist/Sol/wingets/DashboardCreatesandboxform.js +71 -0
- package/dist/Sol/wingets/DashboardEventstimeline.d.ts +8 -0
- package/dist/Sol/wingets/DashboardEventstimeline.js +83 -0
- package/dist/Sol/wingets/DashboardGlobalsandboxestable.d.ts +8 -0
- package/dist/Sol/wingets/DashboardGlobalsandboxestable.js +57 -0
- package/dist/Sol/wingets/DashboardMeshnodestable.d.ts +8 -0
- package/dist/Sol/wingets/DashboardMeshnodestable.js +103 -0
- package/dist/Sol/wingets/DashboardSandboxlist.d.ts +10 -0
- package/dist/Sol/wingets/DashboardSandboxlist.js +163 -0
- package/dist/Sol/wingets/DashboardUserstable.d.ts +8 -0
- package/dist/Sol/wingets/DashboardUserstable.js +78 -0
- package/dist/Sol/wingets/HomeEntrygate.d.ts +23 -0
- package/dist/Sol/wingets/HomeEntrygate.js +73 -0
- package/dist/Sol/wingets/HomeMetricstrip.d.ts +9 -0
- package/dist/Sol/wingets/HomeMetricstrip.js +4 -0
- package/dist/Sol/wingets/HomeRuntimediagram.d.ts +1 -0
- package/dist/Sol/wingets/HomeRuntimediagram.js +22 -0
- package/dist/Sol/wingets/LoginForm.d.ts +19 -0
- package/dist/Sol/wingets/LoginForm.js +141 -0
- package/dist/Sol/wingets/RegisterPasswordconfirm.d.ts +13 -0
- package/dist/Sol/wingets/RegisterPasswordconfirm.js +16 -0
- package/dist/Sol/wingets/RegisterPasswordmeter.d.ts +19 -0
- package/dist/Sol/wingets/RegisterPasswordmeter.js +65 -0
- package/dist/Sol/wingets/RegisterUsernamerules.d.ts +11 -0
- package/dist/Sol/wingets/RegisterUsernamerules.js +16 -0
- package/dist/Sol/wingets/index.d.ts +39 -0
- package/dist/Sol/wingets/index.js +39 -0
- package/dist/alternatives.d.ts +508 -0
- package/dist/alternatives.js +950 -0
- package/dist/api.d.ts +154 -0
- package/dist/api.js +174 -0
- package/dist/auth.d.ts +268 -0
- package/dist/auth.js +476 -0
- package/dist/automation.d.ts +425 -0
- package/dist/automation.js +566 -0
- package/dist/browser.d.ts +561 -0
- package/dist/browser.js +1058 -0
- package/dist/capacitor.config.d.ts +45 -0
- package/dist/capacitor.config.js +48 -0
- package/dist/catalog.d.ts +43 -0
- package/dist/catalog.js +44 -0
- package/dist/cli.d.ts +16 -0
- package/dist/cli.js +168 -0
- package/dist/communication.d.ts +181 -0
- package/dist/communication.js +376 -0
- package/dist/compute.d.ts +1160 -0
- package/dist/compute.js +2272 -0
- package/dist/dashboardlib.d.ts +58 -0
- package/dist/dashboardlib.js +161 -0
- package/dist/db.d.ts +569 -0
- package/dist/db.js +1080 -0
- package/dist/distribution.d.ts +528 -0
- package/dist/distribution.js +810 -0
- package/dist/drizzle.config.d.ts +20 -0
- package/dist/drizzle.config.js +18 -0
- package/dist/edgelandes.d.ts +70 -0
- package/dist/edgelandes.host.d.ts +26 -0
- package/dist/edgelandes.host.js +1089 -0
- package/dist/edgelandes.inproc.d.ts +27 -0
- package/dist/edgelandes.inproc.js +952 -0
- package/dist/edgelandes.js +1133 -0
- package/dist/edgelandes.ninety.d.ts +31 -0
- package/dist/edgelandes.ninety.js +174 -0
- package/dist/edgelandes.virtual.d.ts +25 -0
- package/dist/edgelandes.virtual.js +629 -0
- package/dist/edgeplane.d.ts +114 -0
- package/dist/edgeplane.js +305 -0
- package/dist/examplelocaljob.d.ts +1 -0
- package/{docs/example-localjob.ts → dist/examplelocaljob.js} +0 -1
- package/dist/execution.d.ts +529 -0
- package/dist/execution.js +760 -0
- package/dist/family.d.ts +16 -0
- package/dist/family.js +42 -0
- package/dist/familyurl.d.ts +21 -0
- package/dist/familyurl.js +24 -0
- package/dist/format.d.ts +18 -0
- package/dist/format.js +59 -0
- package/dist/foundation.d.ts +172 -0
- package/dist/foundation.js +312 -0
- package/dist/index.d.ts +735 -0
- package/dist/index.js +1020 -0
- package/dist/integration.d.ts +235 -0
- package/dist/integration.js +228 -0
- package/dist/intelligence.d.ts +93 -0
- package/dist/intelligence.js +144 -0
- package/dist/isolation.d.ts +128 -0
- package/dist/isolation.js +95 -0
- package/dist/labels.d.ts +665 -0
- package/dist/labels.js +751 -0
- package/dist/localauth.d.ts +127 -0
- package/dist/localauth.js +413 -0
- package/dist/media.d.ts +343 -0
- package/dist/media.js +985 -0
- package/dist/mesh.d.ts +177 -0
- package/dist/mesh.js +468 -0
- package/dist/modalityregistry.d.ts +109 -0
- package/dist/modalityregistry.js +1386 -0
- package/dist/modes.d.ts +358 -0
- package/dist/modes.js +133 -0
- package/dist/onboardingstate.d.ts +79 -0
- package/dist/onboardingstate.js +282 -0
- package/dist/orchestrator.d.ts +1338 -0
- package/dist/orchestrator.js +4310 -0
- package/dist/packager/targetcli.js +4 -0
- package/dist/paths.d.ts +2 -0
- package/dist/paths.js +14 -0
- package/dist/performance.d.ts +415 -0
- package/dist/performance.js +826 -0
- package/dist/quantum.d.ts +809 -0
- package/dist/quantum.js +2072 -0
- package/dist/render.d.ts +380 -0
- package/dist/render.js +1072 -0
- package/dist/runall.d.ts +2 -0
- package/dist/runall.js +39 -0
- package/dist/runtimeprobe.d.ts +4 -0
- package/dist/runtimeprobe.js +8 -0
- package/dist/sandbox.d.ts +355 -0
- package/dist/sandbox.js +1721 -0
- package/dist/sandboxenvprofile.d.ts +29 -0
- package/dist/sandboxenvprofile.js +89 -0
- package/dist/sandboxprofile.d.ts +137 -0
- package/dist/sandboxprofile.js +241 -0
- package/dist/sandboxqueue.d.ts +108 -0
- package/dist/sandboxqueue.js +201 -0
- package/dist/sandboxquota.d.ts +121 -0
- package/dist/sandboxquota.js +236 -0
- package/dist/scheduler.d.ts +595 -0
- package/dist/scheduler.js +1258 -0
- package/dist/scriptlanes.d.ts +182 -0
- package/dist/scriptlanes.js +660 -0
- package/dist/scripts.buildengine.d.ts +1 -0
- package/dist/scripts.buildengine.js +39 -0
- package/dist/scripts.securitygate.d.ts +1 -0
- package/dist/scripts.securitygate.js +68 -0
- package/dist/scripts.validateflatnative.d.ts +1 -0
- package/dist/scripts.validateflatnative.js +72 -0
- package/dist/security.d.ts +500 -0
- package/dist/security.js +1169 -0
- package/dist/seedcatalog.d.ts +13 -0
- package/dist/seedcatalog.js +46 -0
- package/dist/server.d.ts +20 -0
- package/dist/server.js +53 -0
- package/dist/speccatalog.d.ts +31 -0
- package/dist/speccatalog.js +163 -0
- package/dist/tiers.d.ts +1001 -0
- package/dist/tiers.js +2169 -0
- package/dist/utils.d.ts +2 -0
- package/dist/utils.js +5 -0
- package/dist/vaulthandoff.d.ts +141 -0
- package/dist/vaulthandoff.js +444 -0
- package/dist/virtual.d.ts +640 -0
- package/dist/virtual.js +1284 -0
- package/dist/virtualcpu.d.ts +315 -0
- package/dist/virtualcpu.js +1180 -0
- package/dist/virtualgpu.d.ts +344 -0
- package/dist/virtualgpu.js +1000 -0
- package/dist/virtualization.d.ts +606 -0
- package/dist/virtualization.js +1186 -0
- package/dist/virtualmemory.d.ts +817 -0
- package/dist/virtualmemory.js +1795 -0
- package/dist/vite.config.d.ts +3 -0
- package/dist/vite.config.js +43 -0
- package/dist/vitest.config.d.ts +2 -0
- package/dist/vitest.config.js +25 -0
- package/dist/webserver.d.ts +166 -0
- package/dist/webserver.js +2226 -0
- package/dist/workloadlaw.d.ts +133 -0
- package/dist/workloadlaw.js +193 -0
- package/docker.config +13 -6
- package/docs/artifactavailability.md +2 -2
- package/docs/{containerplatforms-2.1.0.md → containerplatforms.2.1.0.md} +1 -1
- package/docs/{documentmap-1.8.12.md → documentmap.1.8.12.md} +1 -1
- package/docs/ninety.modalities.md +108 -0
- package/docs/planning.ninety.md +391 -0
- package/docs/{releasenotes-1.8.13.md → releasenotes.1.8.13.md} +2 -2
- package/docs/{releasenotes-1.8.14.md → releasenotes.1.8.14.md} +1 -1
- package/docs/{repo-synthesis-1.8.16.md → repo.synthesis.1.8.16.md} +1 -1
- package/docs/{todo-1.8.15.md → todo.1.8.15.md} +1 -1
- package/docs/{todo-1.8.16.md → todo.1.8.16.md} +5 -5
- package/docs/todo.md +2 -2
- package/docs/workloadlaw.md +104 -0
- package/index.ts +4 -3
- package/manifest.json +1 -1
- package/modalityregistry.ts +1493 -0
- package/orchestrator.ts +1 -1
- package/package.json +76 -37
- package/docs/CONVERSA.txt +0 -1523
- package/docs/architecture-1.8.19.png +0 -0
- package/docs/assets/architecture.svg +0 -45
- package/docs/assets/saddle-browser-trace.webp +0 -0
- package/docs/assets/saddle-hero-bridge.webp +0 -0
- package/docs/assets/saddle-mark.webp +0 -0
- package/docs/assets/saddle-runtime-map.webp +0 -0
- package/docs/assets/saddlemark.svg +0 -13
- package/docs/example-publicapi.ts +0 -7
- package/docs/saddle.archive.1.8.17.tar.gz.gpg +0 -0
- /package/docs/{architecture-1.8.19.md → architecture.1.8.19.md} +0 -0
- /package/docs/{architecture-1.8.19.mmd → architecture.1.8.19.mmd} +0 -0
- /package/docs/{artifactresearch-1.8.9.md → artifactresearch.1.8.9.md} +0 -0
- /package/docs/{batches-1816-1820.md → batches.1816.to.1820.md} +0 -0
- /package/docs/{brancharchive-2026-08-18.md → brancharchive.2026.08.18.md} +0 -0
- /package/docs/{containerplatforms-1.8.17.md → containerplatforms.1.8.17.md} +0 -0
- /package/docs/{e2ugh-engine.md → e2ugh.engine.md} +0 -0
- /package/docs/{flatbuildresearch-1.8.11.md → flatbuildresearch.1.8.11.md} +0 -0
- /package/docs/{licenseaudit-1.8.12.md → licenseaudit.1.8.12.md} +0 -0
- /package/docs/{mobileconversionresearch-1.8.10.md → mobileconversionresearch.1.8.10.md} +0 -0
- /package/docs/{native-wrappers.md → native.wrappers.md} +0 -0
- /package/docs/{nativeidentityresearch-1.8.11.md → nativeidentityresearch.1.8.11.md} +0 -0
- /package/docs/{releasenotes-1.8.12.md → releasenotes.1.8.12.md} +0 -0
- /package/docs/{releasenotes-1.8.15.md → releasenotes.1.8.15.md} +0 -0
- /package/docs/{releasenotes-1.8.16.md → releasenotes.1.8.16.md} +0 -0
- /package/docs/{releasenotes-1.8.17.md → releasenotes.1.8.17.md} +0 -0
- /package/docs/{releasenotes-1.8.18.md → releasenotes.1.8.18.md} +0 -0
- /package/docs/{releasenotes-1.8.19.md → releasenotes.1.8.19.md} +0 -0
- /package/docs/{reorganization-1.8.8.md → reorganization.1.8.8.md} +0 -0
- /package/docs/{reorganization-1.8.9.md → reorganization.1.8.9.md} +0 -0
- /package/docs/{repo-analysis-1.8.21.json → repo.analysis.1.8.21.json} +0 -0
- /package/docs/{repo-candidates-1.8.21.jsonl → repo.candidates.1.8.21.jsonl} +0 -0
- /package/docs/{repo-research-1.8.16.md → repo.research.1.8.16.md} +0 -0
- /package/docs/{repo-research-1.8.21.md → repo.research.1.8.21.md} +0 -0
- /package/docs/{repo-selected-1.8.21.json → repo.selected.1.8.21.json} +0 -0
- /package/docs/{repo-synthesis-1.8.21.md → repo.synthesis.1.8.21.md} +0 -0
- /package/docs/{research-1.8.18-isolation.md → research.1.8.18.isolation.md} +0 -0
- /package/docs/{research-1.8.19-virtual-browser.md → research.1.8.19.virtual.browser.md} +0 -0
- /package/docs/{scanningresearch-1.8.11.md → scanningresearch.1.8.11.md} +0 -0
- /package/docs/{securityaudit-1.8.7.md → securityaudit.1.8.7.md} +0 -0
- /package/docs/{securityreferences-1.8.11.md → securityreferences.1.8.11.md} +0 -0
- /package/docs/{securityresearch-1.8.11.md → securityresearch.1.8.11.md} +0 -0
- /package/docs/{signingresearch-1.8.12.md → signingresearch.1.8.12.md} +0 -0
- /package/docs/{tauri-glib-risk-1.8.11.md → tauri.glib.risk.1.8.11.md} +0 -0
- /package/docs/{todo-1.8.18.md → todo.1.8.18.md} +0 -0
- /package/docs/{todo-1.8.19.md → todo.1.8.19.md} +0 -0
- /package/docs/{toolchainresearch-1.8.9.md → toolchainresearch.1.8.9.md} +0 -0
- /package/docs/{web-duplicatecleanup.md → web.duplicatecleanup.md} +0 -0
- /package/docs/{web-ideas.md → web.ideas.md} +0 -0
- /package/docs/{workflowimprovements-2026-08-19.md → workflowimprovements.2026.08.19.md} +0 -0
package/Dockerfile
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
# compute service published as ghcr.io/wenathlan/saddle:<version>
|
|
14
14
|
# across the four-arch family standard (amd64, arm64, ppc64le, s390x
|
|
15
15
|
# — the trixie slim base line; the stage also builds the web SPA so
|
|
16
|
-
# the image serves the self-hosted console via `node /app/
|
|
16
|
+
# the image serves the self-hosted console via `node /app/webserver.ts`).
|
|
17
17
|
#
|
|
18
18
|
# saddle v2 (grand merge) - virtual hardware engine, multi-stage, multi-arch image.
|
|
19
19
|
#
|
|
@@ -641,17 +641,20 @@ ENTRYPOINT ["/usr/bin/tini", "--", "qemu-system-x86_64"]
|
|
|
641
641
|
# ---------------------------------------------------------------------------
|
|
642
642
|
# saddle-build: the node-engine build stage (defined here, before the
|
|
643
643
|
# vhe runtime, so BOTH container surfaces can consume its output: the
|
|
644
|
-
# vhe runtime copies the built web SPA
|
|
645
|
-
# the saddle-runtime stage copies the engine dist plus the
|
|
646
|
-
#
|
|
647
|
-
# QEMU): its outputs are platform-independent static/js
|
|
644
|
+
# vhe runtime copies the built web SPA beside the console server at
|
|
645
|
+
# /engine and the saddle-runtime stage copies the engine dist plus the
|
|
646
|
+
# same staged SPA - one build, two consumers). The stage runs native
|
|
647
|
+
# (never under QEMU): its outputs are platform-independent static/js
|
|
648
|
+
# payloads.
|
|
648
649
|
|
|
649
650
|
# the build stage pins to the native build platform ($BUILDPLATFORM): its
|
|
650
651
|
# outputs (the engine dist, pure js, and the web SPA, static assets) are
|
|
651
652
|
# architecture-independent, while the tailwind/lightningcss pipeline only
|
|
652
653
|
# ships native bindings for the builder platforms - the per-arch legs never
|
|
653
|
-
# run it under QEMU.
|
|
654
|
-
|
|
654
|
+
# run it under QEMU. The base rides the family tag contract (tags only,
|
|
655
|
+
# never a @sha256: digest - a single digest cannot serve the
|
|
656
|
+
# four-architecture matrix the registry resolves per platform).
|
|
657
|
+
FROM --platform=$BUILDPLATFORM node:26.8.1-slim AS saddle-build
|
|
655
658
|
|
|
656
659
|
ARG SADDLE_VERSION
|
|
657
660
|
WORKDIR /app
|
|
@@ -663,7 +666,16 @@ RUN npm ci --ignore-scripts --legacy-peer-deps
|
|
|
663
666
|
COPY . .
|
|
664
667
|
RUN npm run build:engine \
|
|
665
668
|
&& node --check dist/cli.js \
|
|
666
|
-
&& npm run web:build:pages
|
|
669
|
+
&& npm run web:build:pages \
|
|
670
|
+
# the theme build emits the hashed SPA bundles straight at the app
|
|
671
|
+
# root (the family static-first vite contract): stage them into a
|
|
672
|
+
# clean folder so the runtime stages copy exactly the console
|
|
673
|
+
# surface - the shell, the hashed js/css bundles and the icon and
|
|
674
|
+
# manifest assets the shell references. the extension popup
|
|
675
|
+
# stylesheet is the one root css that never belongs to the spa.
|
|
676
|
+
&& mkdir -p /out/spa \
|
|
677
|
+
&& cp index.html *.js *.css *.svg *.webmanifest /out/spa/ \
|
|
678
|
+
&& rm -f /out/spa/popup.css
|
|
667
679
|
|
|
668
680
|
FROM ${UBUNTU} AS runtime
|
|
669
681
|
ARG TARGETARCH
|
|
@@ -895,19 +907,24 @@ COPY --from=python-bridge /bridge/qemubridge.py /engine/qemubridge.py
|
|
|
895
907
|
# the engine sources and the specification files consumed at runtime
|
|
896
908
|
# (docker.config "final" stage copies the whole tree; the flat layout
|
|
897
909
|
# keeps that a single COPY layer).
|
|
898
|
-
COPY *.ts package.json tsconfig.json biome.
|
|
910
|
+
COPY *.ts package.json tsconfig.json biome.jsonc jsdom.d.ts /engine/
|
|
899
911
|
COPY processors.json gpus.json cores.json boards.json vm.config.json virtualhardware.json /engine/
|
|
900
|
-
COPY qemu.config mttg.config passage.config docker.config /engine/
|
|
912
|
+
COPY qemu.config mttg.config passage.config docker.config mime.types /engine/
|
|
901
913
|
|
|
902
914
|
# the web node ships inside the main container: the mesh edition (auth,
|
|
903
915
|
# sqlite database, dashboard and the browser sandbox pages) runs from the
|
|
904
916
|
# same image, so one container serves the engine AND the web surface.
|
|
905
|
-
# run it with: docker run ghcr.io/wenathlan/saddle node /engine/
|
|
906
|
-
COPY
|
|
907
|
-
#
|
|
908
|
-
#
|
|
909
|
-
#
|
|
910
|
-
|
|
917
|
+
# run it with: docker run ghcr.io/wenathlan/saddle node /engine/webserver.ts
|
|
918
|
+
# (the console server is a root engine source - the COPY *.ts line above
|
|
919
|
+
# already lands it at /engine together with its console stack, and the
|
|
920
|
+
# extension denylist of its static resolver keeps every .ts/.json/.sql
|
|
921
|
+
# source unreachable).
|
|
922
|
+
# the built web SPA (vite, staged by saddle-build): the theme build emits
|
|
923
|
+
# the hashed bundles straight at the app root, so the staged spa lands
|
|
924
|
+
# beside the console server at /engine and webserver.ts serves it from
|
|
925
|
+
# its own module directory - the unified React interface that absorbed
|
|
926
|
+
# the former static pages.
|
|
927
|
+
COPY --from=saddle-build /out/spa /engine/
|
|
911
928
|
|
|
912
929
|
RUN set -eux; \
|
|
913
930
|
chmod 0755 /usr/local/bin/nvidia-smi /usr/local/bin/aetherforge; \
|
|
@@ -1310,7 +1327,7 @@ ENTRYPOINT ["/entrypoint.sh"]
|
|
|
1310
1327
|
# docker build --target saddle-runtime -t saddle:<version> .
|
|
1311
1328
|
# ══════════════════════════════════════════════════════════════════════
|
|
1312
1329
|
|
|
1313
|
-
FROM node:26.8.1-slim
|
|
1330
|
+
FROM node:26.8.1-slim AS saddle-runtime
|
|
1314
1331
|
|
|
1315
1332
|
ARG SADDLE_VERSION
|
|
1316
1333
|
LABEL org.opencontainers.image.title="Saddle" \
|
|
@@ -1357,12 +1374,15 @@ RUN apt-get update \
|
|
|
1357
1374
|
&& rm -rf node_modules/cpu-features/deps \
|
|
1358
1375
|
&& find node_modules -type f -name Dockerfile -delete
|
|
1359
1376
|
COPY --from=saddle-build /app/dist ./dist
|
|
1360
|
-
# the web service surface (self-hosted console): the
|
|
1361
|
-
#
|
|
1362
|
-
#
|
|
1363
|
-
# mime.types, init.sql, schema.prisma) - zero npm
|
|
1364
|
-
# node 26 runtime carries everything (node:sqlite,
|
|
1365
|
-
|
|
1377
|
+
# the web service surface (self-hosted console): the staged spa plus the
|
|
1378
|
+
# pure-node server stack (webserver.ts, db.ts, labels.ts, auth.ts,
|
|
1379
|
+
# mesh.ts, sandbox.ts, sandboxprofile.ts, sandboxenvprofile.ts,
|
|
1380
|
+
# sandboxquota.ts, mime.types, init.sql, schema.prisma) - zero npm
|
|
1381
|
+
# dependencies, the node 26 runtime carries everything (node:sqlite,
|
|
1382
|
+
# node:crypto, native type stripping for the .ts sources).
|
|
1383
|
+
# run the console with: docker run saddle:<version> node webserver.ts
|
|
1384
|
+
COPY --from=saddle-build /app/webserver.ts /app/db.ts /app/labels.ts /app/auth.ts /app/mesh.ts /app/sandbox.ts /app/sandboxprofile.ts /app/sandboxenvprofile.ts /app/sandboxquota.ts /app/mime.types /app/init.sql /app/schema.prisma ./
|
|
1385
|
+
COPY --from=saddle-build /out/spa ./
|
|
1366
1386
|
|
|
1367
1387
|
USER node
|
|
1368
1388
|
|
package/README.md
CHANGED
|
@@ -31,12 +31,12 @@ domain modules land beside the saddle domains:
|
|
|
31
31
|
| `media.ts`, `render.ts`, `quantum.ts`, `tiers.ts` | media pipeline, GPU registry, quantum simulation, tier policy |
|
|
32
32
|
| `security.ts`, `alternatives.ts` | hardening gates and the alternative-stack catalog |
|
|
33
33
|
| `index.html`, `App.tsx`, `Sol/` | the single SPA shell and the Sol theme (one tsx app with one stylesheet per theme) |
|
|
34
|
-
| `server.ts`, `sandbox.ts` | the zero-dependency self-hosted API of the 2.0.
|
|
34
|
+
| `server.ts`, `sandbox.ts` | the zero-dependency self-hosted API of the 2.0.152 grand-merge envelope (`node server.ts`; the api answers its version at `/api/v1/health`) and the browser-pure engine port |
|
|
35
35
|
| `vercel.json`, `netlify.toml` | the platform deploy adapters beside the surface they publish (the caddy ghost stays out of the tree) |
|
|
36
36
|
| `specs/*` package exports | processors, gpus, cores, boards and the qemu/mttg/passage/docker envelopes |
|
|
37
37
|
|
|
38
38
|
The full pre-merge documentation of the engine lives in
|
|
39
|
-
[docs/e2ugh
|
|
39
|
+
[docs/e2ugh.engine.md](docs/e2ugh.engine.md) and its release history in
|
|
40
40
|
[CHANGELOG.md (the e2ugh lineage sections)](CHANGELOG.md (the e2ugh lineage sections)).
|
|
41
41
|
|
|
42
42
|
## Start here
|
|
@@ -223,7 +223,7 @@ Saddle is applying to the SignPath Foundation for open-source code signing. Unti
|
|
|
223
223
|
|
|
224
224
|
The requested policy is: **Free code signing provided by SignPath.io, certificate by SignPath Foundation**. Committers and reviewers are maintainers with write access to the public repository. Approvers are repository owners or release approvers recorded in `governance.md`. Every signed release must be built from repository source, pass the security and packaging gates, and receive manual signing approval.
|
|
225
225
|
|
|
226
|
-
The core program will not transfer information to other networked systems unless specifically requested by the user or the person installing or operating it. Browser sessions, storage adapters, runners and external services remain caller-configured and subject to their own policies. See [`privacy
|
|
226
|
+
The core program will not transfer information to other networked systems unless specifically requested by the user or the person installing or operating it. Browser sessions, storage adapters, runners and external services remain caller-configured and subject to their own policies. See [`privacy.policy.md`](privacy.policy.md) and [`SECURITY.md`](SECURITY.md).
|
|
227
227
|
|
|
228
228
|
## GitHub Pages web surface
|
|
229
229
|
|
|
@@ -234,7 +234,7 @@ npm run web:check
|
|
|
234
234
|
VITE_BASE_PATH=/saddle npm run web:build:pages
|
|
235
235
|
```
|
|
236
236
|
|
|
237
|
-
Small public configuration and visual assets live under `web/public/`. The development collector
|
|
237
|
+
Small public configuration and visual assets live under `web/public/`. The obsolete `web/public/__manus__` directory is intentionally absent; the development debug collector (the visitor-browser telemetry hook at the former `web/debugcollector.ts`) left the saddle together with the scrape lanes — the engine keeps no surface that watches the user's browser.
|
|
238
238
|
|
|
239
239
|
## Development
|
|
240
240
|
|
package/biome.jsonc
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
// the family biome baseline: identical across the apps, the identity only names the app.
|
|
2
|
+
{
|
|
3
|
+
"$schema": "https://biomejs.dev/schemas/2.6.4/schema.json",
|
|
4
|
+
"vcs": {
|
|
5
|
+
"enabled": true,
|
|
6
|
+
"clientKind": "git",
|
|
7
|
+
"useIgnoreFile": false
|
|
8
|
+
},
|
|
9
|
+
"files": {
|
|
10
|
+
"includes": [
|
|
11
|
+
"**/*.ts",
|
|
12
|
+
"**/*.tsx",
|
|
13
|
+
"**/*.js",
|
|
14
|
+
"**/*.mjs",
|
|
15
|
+
"**/*.cjs",
|
|
16
|
+
"**/*.json",
|
|
17
|
+
"!**/dist",
|
|
18
|
+
"!**/distpackage",
|
|
19
|
+
"!**/target",
|
|
20
|
+
"!**/node_modules",
|
|
21
|
+
"!**/bun.lock",
|
|
22
|
+
"!**/*.min.js",
|
|
23
|
+
"!**/docs",
|
|
24
|
+
"!**/tests/tmp",
|
|
25
|
+
"!**/tests/code",
|
|
26
|
+
"!**/Sol/dist",
|
|
27
|
+
"!**/Sol/.vite",
|
|
28
|
+
"!**/Sol/node_modules",
|
|
29
|
+
"!**/coverage",
|
|
30
|
+
"!**/android",
|
|
31
|
+
"!**/releasecheck",
|
|
32
|
+
"!**/build",
|
|
33
|
+
"!**/release",
|
|
34
|
+
"!index-*.js"
|
|
35
|
+
]
|
|
36
|
+
},
|
|
37
|
+
"formatter": {
|
|
38
|
+
"enabled": true,
|
|
39
|
+
"indentStyle": "space",
|
|
40
|
+
"indentWidth": 2,
|
|
41
|
+
"lineWidth": 120,
|
|
42
|
+
"lineEnding": "lf"
|
|
43
|
+
},
|
|
44
|
+
"linter": {
|
|
45
|
+
"enabled": true,
|
|
46
|
+
"rules": {
|
|
47
|
+
"preset": "recommended",
|
|
48
|
+
"correctness": {
|
|
49
|
+
"noUnusedVariables": "warn",
|
|
50
|
+
"noUnsafeOptionalChaining": "warn",
|
|
51
|
+
"useExhaustiveDependencies": "warn",
|
|
52
|
+
"noUnusedImports": "warn",
|
|
53
|
+
"noUnusedPrivateClassMembers": "warn",
|
|
54
|
+
"noUnusedFunctionParameters": "warn",
|
|
55
|
+
"noConstantCondition": "warn",
|
|
56
|
+
"noVoidTypeReturn": "warn"
|
|
57
|
+
},
|
|
58
|
+
"a11y": {
|
|
59
|
+
"useButtonType": "warn",
|
|
60
|
+
"noStaticElementInteractions": "warn",
|
|
61
|
+
"useSemanticElements": "warn",
|
|
62
|
+
"useAriaPropsSupportedByRole": "warn"
|
|
63
|
+
},
|
|
64
|
+
"suspicious": {
|
|
65
|
+
"noExplicitAny": "warn",
|
|
66
|
+
"noArrayIndexKey": "warn",
|
|
67
|
+
"noControlCharactersInRegex": "warn",
|
|
68
|
+
"noRedeclare": "warn",
|
|
69
|
+
"noAssignInExpressions": "warn",
|
|
70
|
+
"noShadowRestrictedNames": "warn",
|
|
71
|
+
"noDuplicateElseIf": "warn",
|
|
72
|
+
"noImplicitAnyLet": "warn",
|
|
73
|
+
"noTsIgnore": "warn",
|
|
74
|
+
"noGlobalIsNan": "warn"
|
|
75
|
+
},
|
|
76
|
+
"style": {
|
|
77
|
+
"noNonNullAssertion": "warn",
|
|
78
|
+
"useTemplate": "warn",
|
|
79
|
+
"useExponentiationOperator": "warn",
|
|
80
|
+
"useConst": "warn"
|
|
81
|
+
},
|
|
82
|
+
"complexity": {
|
|
83
|
+
"useLiteralKeys": "warn",
|
|
84
|
+
"useOptionalChain": "warn",
|
|
85
|
+
"noUselessContinue": "warn",
|
|
86
|
+
"noUselessUndefinedInitialization": "warn",
|
|
87
|
+
"noUselessEscapeInRegex": "warn"
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
"javascript": {
|
|
92
|
+
"formatter": {
|
|
93
|
+
"quoteStyle": "double",
|
|
94
|
+
"semicolons": "always",
|
|
95
|
+
"trailingCommas": "all",
|
|
96
|
+
"arrowParentheses": "always"
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
"css": {
|
|
100
|
+
"parser": {
|
|
101
|
+
"tailwindDirectives": true
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
"overrides": [
|
|
105
|
+
{
|
|
106
|
+
"includes": ["**/*"],
|
|
107
|
+
"linter": {
|
|
108
|
+
"rules": {
|
|
109
|
+
"suspicious": {
|
|
110
|
+
"noDebugger": "off"
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
"includes": ["tests/workflowcheck.ts", "tests/publishlanes.test.ts"],
|
|
117
|
+
"linter": {
|
|
118
|
+
"rules": {
|
|
119
|
+
"suspicious": {
|
|
120
|
+
"noTemplateCurlyInString": "off"
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
],
|
|
126
|
+
"assist": {
|
|
127
|
+
"enabled": true,
|
|
128
|
+
"actions": {
|
|
129
|
+
"source": {
|
|
130
|
+
"useSortedKeys": "off"
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
package/dist/App.d.ts
ADDED
package/dist/App.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* App — the global anchor (layer 1 of the anchor architecture) and the only
|
|
4
|
+
* TSX outside the theme. The root manages the themes as single files: it
|
|
5
|
+
* imports only the theme anchor (Sol/Sol.tsx — the file named after the theme
|
|
6
|
+
* folder, beside Sol/sol.css) and the theme stylesheet, wraps the anchor in
|
|
7
|
+
* the global concerns it owns (the error boundary, the theme and tooltip
|
|
8
|
+
* providers, the toaster and the wouter router provider) and renders it. The
|
|
9
|
+
* whole route tree lives behind the theme anchor; no page or component of the
|
|
10
|
+
* theme is ever imported here.
|
|
11
|
+
*/
|
|
12
|
+
import { createRoot } from 'react-dom/client';
|
|
13
|
+
import { Router as WouterRouter } from 'wouter';
|
|
14
|
+
import Sol from './Sol/Sol';
|
|
15
|
+
import { ErrorBoundary, ThemeProvider, Toaster, TooltipProvider } from './Sol/shell/Shell.tsx';
|
|
16
|
+
import './Sol/sol.css';
|
|
17
|
+
import { seedlabels } from './labels';
|
|
18
|
+
// the copy law rides the boot: the seed refreshes the label store rows
|
|
19
|
+
// (translated rows protected) before the first paint answers
|
|
20
|
+
if (typeof window !== 'undefined')
|
|
21
|
+
void seedlabels().catch(() => { });
|
|
22
|
+
// NOTE: About Theme
|
|
23
|
+
// - First choose a default theme according to your design style (dark or light bg), than change color palette in Sol/sol.css
|
|
24
|
+
// to keep consistent foreground/background color across components
|
|
25
|
+
// - If you want to make theme switchable, pass `switchable` ThemeProvider and use `useTheme` hook
|
|
26
|
+
/** The router base derives from the declared base path so the same build serves
|
|
27
|
+
* every host. A relative base ("./") cannot name the folder it lands in, but the
|
|
28
|
+
* dispatcher always boots cold links at the application root first — so the
|
|
29
|
+
* folder prefix of the boot pathname is exactly the router base (absolute, so
|
|
30
|
+
* wouter never has to match against a relative prefix). The absolute bases
|
|
31
|
+
* carry through unchanged. */
|
|
32
|
+
function routerBase() {
|
|
33
|
+
const declaredBase = import.meta.env.BASE_URL;
|
|
34
|
+
if (declaredBase !== '/' && declaredBase !== './')
|
|
35
|
+
return declaredBase.replace(/\/$/, '');
|
|
36
|
+
const bootPath = window.location.pathname.replace(/index\.html$/, '').replace(/\/$/, '');
|
|
37
|
+
return bootPath === '' ? '' : bootPath;
|
|
38
|
+
}
|
|
39
|
+
function App() {
|
|
40
|
+
return (_jsx(ErrorBoundary, { children: _jsx(ThemeProvider, { defaultTheme: "dark", children: _jsxs(TooltipProvider, { children: [_jsx(Toaster, {}), _jsx(WouterRouter, { base: routerBase(), children: _jsx(Sol, {}) })] }) }) }));
|
|
41
|
+
}
|
|
42
|
+
/* The self-mount: the app owns its bootstrap — the retired main.tsx
|
|
43
|
+
* wrapper is gone, so this module is the single entry the html loads
|
|
44
|
+
* (the doctrine of the 2.1.0 universal interface: one tsx app, the
|
|
45
|
+
* router and the mount live together). */
|
|
46
|
+
const rootmount = typeof document !== 'undefined' ? document.getElementById('root') : null;
|
|
47
|
+
if (rootmount) {
|
|
48
|
+
createRoot(rootmount).render(_jsx(App, {}));
|
|
49
|
+
}
|
|
50
|
+
export default App;
|
package/dist/Sol/Sol.js
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* Sol theme anchor — layer 2 of the anchor architecture.
|
|
4
|
+
* The file carrying the theme folder's own name (Sol/Sol.tsx, beside
|
|
5
|
+
* Sol/sol.css) is the path manager of the pages: it imports one anchor per
|
|
6
|
+
* page folder (`folder/folder.tsx`, each beside the loose components its
|
|
7
|
+
* folder keeps) and mounts every route and subroute of the theme. App.tsx
|
|
8
|
+
* consumes only this file and the theme stylesheet; no page component is
|
|
9
|
+
* ever imported outside this layer. When a theme folder changes its name
|
|
10
|
+
* (Moon, Aqua), this file follows the new name and App.tsx keeps importing
|
|
11
|
+
* the anchor by the folder path. Since the family window conversion the
|
|
12
|
+
* theme is an APPLICATION: the entry flow opens the route table — /intro
|
|
13
|
+
* (the akash-floor splash) and /onboarding (the first-run frames) — and
|
|
14
|
+
* every other route renders as the content of the ONE application window
|
|
15
|
+
* (the page anchors carry no chrome of their own; the window rail is the
|
|
16
|
+
* only nav). The flow contract rides the home anchor's entry gate
|
|
17
|
+
* (Sol/home/entrygate.tsx): "/" consults the seen flags (onboardingstate.ts)
|
|
18
|
+
* before anything shows, the intro hands straight to /onboarding and the
|
|
19
|
+
* onboarding lands home.
|
|
20
|
+
*/
|
|
21
|
+
import { Route, Switch } from 'wouter';
|
|
22
|
+
import AgentBrowserAnchor from './agentbrowser/agentbrowser';
|
|
23
|
+
import ArchitectureAnchor from './architecture/architecture';
|
|
24
|
+
import ComputeAnchor from './compute/compute';
|
|
25
|
+
import ConsoleAnchor from './console/console';
|
|
26
|
+
import DashboardAnchor from './dashboard/dashboard';
|
|
27
|
+
import DocsAnchor from './docs/docs';
|
|
28
|
+
import HomeAnchor from './home/home';
|
|
29
|
+
import IntegrationsAnchor from './integrations/integrations';
|
|
30
|
+
import IntroAnchor from './intro/intro';
|
|
31
|
+
import LoginAnchor from './login/login';
|
|
32
|
+
import NotFoundAnchor from './notfound/notfound';
|
|
33
|
+
import OnboardingAnchor from './onboarding/onboarding';
|
|
34
|
+
import PlaygroundAnchor from './playground/playground';
|
|
35
|
+
import RegisterAnchor from './register/register';
|
|
36
|
+
import { Shell } from './shell/Shell.tsx';
|
|
37
|
+
/** The window stage: the ONE application window wrapping the whole page
|
|
38
|
+
* route table — every existing route stays alive inside the stage. */
|
|
39
|
+
function WindowStage() {
|
|
40
|
+
return (_jsx(Shell, { children: _jsxs(Switch, { children: [_jsx(Route, { path: '/', component: HomeAnchor }), _jsx(Route, { path: '/architecture', component: ArchitectureAnchor }), _jsx(Route, { path: '/agent-browser', component: AgentBrowserAnchor }), _jsx(Route, { path: '/compute', component: ComputeAnchor }), _jsx(Route, { path: '/integrations', component: IntegrationsAnchor }), _jsx(Route, { path: '/playground', component: PlaygroundAnchor }), _jsx(Route, { path: '/console', component: ConsoleAnchor }), _jsx(Route, { path: '/login', component: LoginAnchor }), _jsx(Route, { path: '/register', component: RegisterAnchor }), _jsx(Route, { path: '/dashboard', component: DashboardAnchor }), _jsx(Route, { path: '/docs', component: DocsAnchor }), _jsx(Route, { path: '/404', component: NotFoundAnchor }), _jsx(Route, { component: NotFoundAnchor })] }) }));
|
|
41
|
+
}
|
|
42
|
+
/** The route tree of the theme: the entry flow (intro, onboarding) before
|
|
43
|
+
* the catch-all that mounts the window over every page route. */
|
|
44
|
+
export default function Sol() {
|
|
45
|
+
return (_jsxs(Switch, { children: [_jsx(Route, { path: '/intro', component: IntroAnchor }), _jsx(Route, { path: '/onboarding', component: OnboardingAnchor }), _jsx(Route, { component: WindowStage })] }));
|
|
46
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* agent browser page anchor — layer 3 of the anchor architecture.
|
|
3
|
+
* The file carrying the folder's own name is the path manager of the page:
|
|
4
|
+
* it imports the loose components beside it, mounts the page and re-exports
|
|
5
|
+
* the public component surface. Only the theme anchor (Sol/Sol.tsx) consumes
|
|
6
|
+
* this file. This anchor carries the former main component of the folder,
|
|
7
|
+
* which now lives here as the page mount itself.
|
|
8
|
+
*/
|
|
9
|
+
export default function AgentBrowser(): import("react").JSX.Element;
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* agent browser page anchor — layer 3 of the anchor architecture.
|
|
4
|
+
* The file carrying the folder's own name is the path manager of the page:
|
|
5
|
+
* it imports the loose components beside it, mounts the page and re-exports
|
|
6
|
+
* the public component surface. Only the theme anchor (Sol/Sol.tsx) consumes
|
|
7
|
+
* this file. This anchor carries the former main component of the folder,
|
|
8
|
+
* which now lives here as the page mount itself.
|
|
9
|
+
*/
|
|
10
|
+
import { PulseRegular as Activity, ProhibitedRegular as Ban, CameraRegular as Camera, CheckmarkCircleRegular as CheckCircle2, KeyboardRegular as Keyboard, CursorRegular as MousePointer2, PlayRegular as Play, ArrowCounterclockwiseRegular as RotateCcw, DocumentTextRegular as ScrollText, WindowConsoleRegular as Terminal, } from '@fluentui/react-icons';
|
|
11
|
+
// Signal & Ledger: agent browser as an event trail, evidence and deterministic replay.
|
|
12
|
+
// The session console renders the rows the sessions catalog serves — the
|
|
13
|
+
// documented example log of docs/logs/examplesession.json offline, the paired
|
|
14
|
+
// database rows over HTTPS — never invented coordinates or counts. Every
|
|
15
|
+
// word of the page itself rides the label store (labels.ts — the copy law).
|
|
16
|
+
import { useEffect, useState } from 'react';
|
|
17
|
+
import { PageShell } from '../shell/Shell.tsx';
|
|
18
|
+
import { label, labelfill } from '../../labels.ts';
|
|
19
|
+
import { agentsessions, mediaSlots, } from '../../catalog';
|
|
20
|
+
/** the glyph of one event kind of the session trail. */
|
|
21
|
+
function eventicon(type) {
|
|
22
|
+
if (type === 'scroll')
|
|
23
|
+
return ScrollText;
|
|
24
|
+
if (type === 'type')
|
|
25
|
+
return Keyboard;
|
|
26
|
+
return MousePointer2;
|
|
27
|
+
}
|
|
28
|
+
/** the value line of one event: exactly the fields the row carries. */
|
|
29
|
+
function eventvalue(event) {
|
|
30
|
+
if (event.type === 'scroll')
|
|
31
|
+
return `dy ${event.dy ?? 0}`;
|
|
32
|
+
if (event.type === 'type')
|
|
33
|
+
return `key ${event.key ?? ''}`;
|
|
34
|
+
return `x ${event.x ?? 0} / y ${event.y ?? 0}`;
|
|
35
|
+
}
|
|
36
|
+
/** the elapsed label of one event from its relative time. */
|
|
37
|
+
const eventtime = (event) => `+${event.t} ms`;
|
|
38
|
+
/** one rendered event row: the glyph, the relative time, the kind and the fields. */
|
|
39
|
+
function SessionEventRow({ event }) {
|
|
40
|
+
const Icon = eventicon(event.type);
|
|
41
|
+
return (_jsxs("div", { className: "console-row", children: [_jsx(Icon, { fontSize: 16 }), _jsx("span", { className: "console-time", children: eventtime(event) }), _jsx("strong", { children: event.type }), _jsx("span", { children: eventvalue(event) })] }));
|
|
42
|
+
}
|
|
43
|
+
/** the event trail of one session: one row per captured event. */
|
|
44
|
+
function SessionTrail({ events }) {
|
|
45
|
+
return (_jsx(_Fragment, { children: events.map((event) => (_jsx(SessionEventRow, { event: event }, `${event.t}-${event.type}`))) }));
|
|
46
|
+
}
|
|
47
|
+
/** the captcha verdict badge of one session: the honest outcome of the run. */
|
|
48
|
+
function CaptchaBadge({ verdict }) {
|
|
49
|
+
return (_jsxs("span", { className: verdict.passed ? 'console-pass' : 'console-denied', children: [verdict.passed ? _jsx(CheckCircle2, { fontSize: 14 }) : _jsx(Ban, { fontSize: 13 }), " ", verdict.kind, ' ', label(verdict.passed ? 'agentbrowser.captcha.passed' : 'agentbrowser.captcha.failed')] }));
|
|
50
|
+
}
|
|
51
|
+
/** the principle cards beside the console: the glyph is presentation code,
|
|
52
|
+
* the words ride the store (agentbrowser.principle.*). */
|
|
53
|
+
const principles = [
|
|
54
|
+
{ icon: Camera, titlekey: 'agentbrowser.principle.dom.title', bodykey: 'agentbrowser.principle.dom.body' },
|
|
55
|
+
{
|
|
56
|
+
icon: RotateCcw,
|
|
57
|
+
titlekey: 'agentbrowser.principle.replay.title',
|
|
58
|
+
bodykey: 'agentbrowser.principle.replay.body',
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
icon: Play,
|
|
62
|
+
titlekey: 'agentbrowser.principle.evidence.title',
|
|
63
|
+
bodykey: 'agentbrowser.principle.evidence.body',
|
|
64
|
+
},
|
|
65
|
+
];
|
|
66
|
+
export default function AgentBrowser() {
|
|
67
|
+
const [media, setMedia] = useState(undefined);
|
|
68
|
+
const [sessions, setSessions] = useState(null);
|
|
69
|
+
useEffect(() => {
|
|
70
|
+
void mediaSlots().then((rows) => setMedia(rows.find((slot) => slot.id === 'media.agentbrowser.trace')));
|
|
71
|
+
}, []);
|
|
72
|
+
useEffect(() => {
|
|
73
|
+
let live = true;
|
|
74
|
+
agentsessions()
|
|
75
|
+
.then((rows) => {
|
|
76
|
+
if (live)
|
|
77
|
+
setSessions(rows);
|
|
78
|
+
})
|
|
79
|
+
.catch(() => {
|
|
80
|
+
if (live)
|
|
81
|
+
setSessions([]);
|
|
82
|
+
});
|
|
83
|
+
return () => {
|
|
84
|
+
live = false;
|
|
85
|
+
};
|
|
86
|
+
}, []);
|
|
87
|
+
const session = sessions?.[0] ?? null;
|
|
88
|
+
const lastt = session ? session.events[session.events.length - 1]?.t ?? 0 : 0;
|
|
89
|
+
const sessionlabel = session ? session.session.id : label('agentbrowser.console.reading');
|
|
90
|
+
/** the trimmed json projection of the served row (the docs/logs shape). */
|
|
91
|
+
const sessionsummary = session
|
|
92
|
+
? JSON.stringify({
|
|
93
|
+
version: session.version,
|
|
94
|
+
session: {
|
|
95
|
+
id: session.session.id,
|
|
96
|
+
browser: session.session.browser,
|
|
97
|
+
},
|
|
98
|
+
events: session.events.map((event) => event.type),
|
|
99
|
+
captcha: session.captcha,
|
|
100
|
+
}, null, 2)
|
|
101
|
+
: label('agentbrowser.console.waitingSession');
|
|
102
|
+
return (_jsxs(PageShell, { section: label('agentbrowser.shell.section'), label: label('agentbrowser.shell.label'), title: label('agentbrowser.shell.title'), intro: label('agentbrowser.shell.intro'), media: media, children: [_jsxs("section", { className: "content-section split-content", children: [_jsxs("div", { children: [_jsx("p", { className: "eyebrow", children: label('agentbrowser.split.eyebrow') }), _jsx("h2", { className: "section-title", children: label('agentbrowser.split.title') })] }), _jsxs("div", { className: "prose-copy", children: [_jsx("p", { children: label('agentbrowser.split.body1') }), _jsx("p", { children: label('agentbrowser.split.body2') })] })] }), _jsxs("section", { className: "content-section browser-grid", children: [_jsxs("div", { className: "session-console", children: [_jsxs("div", { className: "console-head", children: [_jsxs("span", { children: [_jsx(Terminal, { fontSize: 14 }), ' ', labelfill('agentbrowser.console.session', {
|
|
103
|
+
id: sessionlabel,
|
|
104
|
+
})] }), session ? _jsx(CaptchaBadge, { verdict: session.captcha }) : null] }), _jsx("div", { className: "console-rows", children: session === null ? (_jsxs("div", { className: "console-row", "aria-live": "polite", children: [_jsx(Activity, { fontSize: 16 }), _jsx("span", { className: "console-time" }), _jsx("strong", { children: label('agentbrowser.console.catalog') }), _jsx("span", { children: label('agentbrowser.console.waiting') })] })) : session.events.length === 0 ? (_jsxs("div", { className: "console-row", "aria-live": "polite", children: [_jsx(Activity, { fontSize: 16 }), _jsx("span", { className: "console-time" }), _jsx("strong", { children: label('agentbrowser.console.catalog') }), _jsx("span", { children: label('agentbrowser.console.empty') })] })) : (_jsxs(_Fragment, { children: [_jsx(SessionTrail, { events: session.events }), _jsxs("div", { className: "console-row", children: [_jsx(Activity, { fontSize: 16 }), _jsxs("span", { className: "console-time", children: ["+", lastt, " ms"] }), _jsx("strong", { children: label('agentbrowser.console.metrics') }), _jsx("span", { children: labelfill('agentbrowser.console.events', {
|
|
105
|
+
n: String(session.events.length),
|
|
106
|
+
s: (lastt / 1000).toFixed(1),
|
|
107
|
+
}) })] })] })) }), _jsxs("div", { className: "console-footer", children: [_jsx("span", { children: labelfill('agentbrowser.console.seed', {
|
|
108
|
+
seed: session
|
|
109
|
+
? session.session.seed
|
|
110
|
+
: label('agentbrowser.console.na'),
|
|
111
|
+
}) }), _jsx("span", { children: labelfill('agentbrowser.console.browser', {
|
|
112
|
+
browser: session
|
|
113
|
+
? session.session.browser
|
|
114
|
+
: label('agentbrowser.console.na'),
|
|
115
|
+
}) })] })] }), _jsx("div", { className: "browser-principles", children: principles.map((principle) => {
|
|
116
|
+
const Icon = principle.icon;
|
|
117
|
+
return (_jsxs("div", { className: "principle-card", children: [_jsx(Icon, { fontSize: 19 }), _jsxs("div", { children: [_jsx("strong", { children: label(principle.titlekey) }), _jsx("span", { children: label(principle.bodykey) })] })] }, principle.titlekey));
|
|
118
|
+
}) })] }), _jsxs("section", { className: "content-section", children: [_jsxs("div", { className: "content-section-heading", children: [_jsx("p", { className: "eyebrow", children: labelfill('agentbrowser.json.eyebrow', {
|
|
119
|
+
version: String(session ? session.version : 1),
|
|
120
|
+
}) }), _jsx("span", { className: "mono-label", children: label('agentbrowser.json.mono') })] }), _jsx("pre", { className: "code-block", children: _jsx("code", { children: sessionsummary }) })] })] }));
|
|
121
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* architecture page anchor — layer 3 of the anchor architecture.
|
|
3
|
+
* The file carrying the folder's own name is the path manager of the page:
|
|
4
|
+
* it imports the loose components beside it, mounts the page and re-exports
|
|
5
|
+
* the public component surface. Only the theme anchor (Sol/Sol.tsx) consumes
|
|
6
|
+
* this file. This anchor carries the former main component of the folder,
|
|
7
|
+
* which now lives here as the page mount itself.
|
|
8
|
+
*/
|
|
9
|
+
export default function Architecture(): import("react").JSX.Element;
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* architecture page anchor — layer 3 of the anchor architecture.
|
|
4
|
+
* The file carrying the folder's own name is the path manager of the page:
|
|
5
|
+
* it imports the loose components beside it, mounts the page and re-exports
|
|
6
|
+
* the public component surface. Only the theme anchor (Sol/Sol.tsx) consumes
|
|
7
|
+
* this file. This anchor carries the former main component of the folder,
|
|
8
|
+
* which now lives here as the page mount itself.
|
|
9
|
+
*/
|
|
10
|
+
import { ArrowUpRightRegular as ArrowUpRight, BrainCircuitRegular as Cpu, DatabaseRegular as Database, BranchForkRegular as GitBranch, GlobeRegular as Globe2, ShieldTaskRegular as ShieldCheck, } from '@fluentui/react-icons';
|
|
11
|
+
// Signal & Ledger: the architecture as a diagram-as-ledger — layered hairline
|
|
12
|
+
// rows (the runtime forms of sandboxprofile: runtime/packages, full/docker,
|
|
13
|
+
// published/registries) with mono annotations and connector dashes, then the
|
|
14
|
+
// four layers, the provider chain and the physical limit band. No floating
|
|
15
|
+
// boxes: every layer is a ruled row on the same spine. The page ships zero
|
|
16
|
+
// fixed data of its own: the runtime forms ride the declared vocabulary of
|
|
17
|
+
// sandboxprofile, the provider chain and the layer words ride the label
|
|
18
|
+
// store (labels.ts — the seed mirrors the rows into the labels table), and
|
|
19
|
+
// every word reads through the typed accessor — the copy law.
|
|
20
|
+
import { useEffect, useState } from 'react';
|
|
21
|
+
import { PageShell } from '../shell/Shell.tsx';
|
|
22
|
+
import { mediaSlots } from '../../catalog';
|
|
23
|
+
import { label } from '../../labels.ts';
|
|
24
|
+
import { SANDBOXFORMS } from '../../sandboxprofile.ts';
|
|
25
|
+
/** the ledger annotations of the three runtime forms: the copy rides the
|
|
26
|
+
* store under the architecture.form.* family, keyed by the declared form
|
|
27
|
+
* ids of sandboxprofile (the ids are data, the words are copy). */
|
|
28
|
+
const formlabels = {
|
|
29
|
+
'runtime-node': {
|
|
30
|
+
name: label('architecture.form.runtimeNode.name'),
|
|
31
|
+
pkg: label('architecture.form.runtimeNode.pkg'),
|
|
32
|
+
note: label('architecture.form.runtimeNode.note'),
|
|
33
|
+
},
|
|
34
|
+
'full-docker': {
|
|
35
|
+
name: label('architecture.form.fullDocker.name'),
|
|
36
|
+
pkg: label('architecture.form.fullDocker.pkg'),
|
|
37
|
+
note: label('architecture.form.fullDocker.note'),
|
|
38
|
+
},
|
|
39
|
+
published: {
|
|
40
|
+
name: label('architecture.form.published.name'),
|
|
41
|
+
pkg: label('architecture.form.published.pkg'),
|
|
42
|
+
note: label('architecture.form.published.note'),
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
/** the four layers of the map: the glyph is presentation code, every word
|
|
46
|
+
* rides the store (the home surfaces() precedent). */
|
|
47
|
+
function layers() {
|
|
48
|
+
return [
|
|
49
|
+
{
|
|
50
|
+
icon: GitBranch,
|
|
51
|
+
name: label('architecture.layer.repository.name'),
|
|
52
|
+
sub: label('architecture.layer.repository.sub'),
|
|
53
|
+
body: label('architecture.layer.repository.body'),
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
icon: Cpu,
|
|
57
|
+
name: label('architecture.layer.runner.name'),
|
|
58
|
+
sub: label('architecture.layer.runner.sub'),
|
|
59
|
+
body: label('architecture.layer.runner.body'),
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
icon: Database,
|
|
63
|
+
name: label('architecture.layer.memory.name'),
|
|
64
|
+
sub: label('architecture.layer.memory.sub'),
|
|
65
|
+
body: label('architecture.layer.memory.body'),
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
icon: Globe2,
|
|
69
|
+
name: label('architecture.layer.surface.name'),
|
|
70
|
+
sub: label('architecture.layer.surface.sub'),
|
|
71
|
+
body: label('architecture.layer.surface.body'),
|
|
72
|
+
},
|
|
73
|
+
];
|
|
74
|
+
}
|
|
75
|
+
/** the provider chain as config: the ordered ids ride the label store
|
|
76
|
+
* (architecture.chain.providers — the seed ingests the row into the labels
|
|
77
|
+
* table like every other string) and the page only splits the row; no fixed
|
|
78
|
+
* provider array survives inside the component. */
|
|
79
|
+
function providerchain() {
|
|
80
|
+
return label('architecture.chain.providers').split(' · ');
|
|
81
|
+
}
|
|
82
|
+
export default function Architecture() {
|
|
83
|
+
const [media, setMedia] = useState(undefined);
|
|
84
|
+
useEffect(() => {
|
|
85
|
+
void mediaSlots().then((rows) => setMedia(rows.find((slot) => slot.id === 'media.runtime.map')));
|
|
86
|
+
}, []);
|
|
87
|
+
return (_jsxs(PageShell, { section: label('architecture.shell.section'), label: label('architecture.shell.label'), title: label('architecture.shell.title'), intro: label('architecture.shell.intro'), media: media, children: [_jsxs("section", { className: "content-section split-content", children: [_jsxs("div", { children: [_jsx("p", { className: "eyebrow", children: label('architecture.model.eyebrow') }), _jsx("h2", { className: "section-title", children: label('architecture.model.title') })] }), _jsxs("div", { className: "prose-copy", children: [_jsx("p", { children: label('architecture.model.body1') }), _jsx("p", { children: label('architecture.model.body2') })] })] }), _jsxs("section", { className: "content-section", "aria-label": label('architecture.forms.aria'), children: [_jsxs("div", { className: "content-section-heading", children: [_jsx("p", { className: "eyebrow", children: label('architecture.forms.eyebrow') }), _jsx("span", { className: "mono-label", children: label('architecture.forms.mono') })] }), _jsx("ol", { className: "r3-forms", children: SANDBOXFORMS.map((form, index) => (_jsxs("li", { className: "r3-form-row", children: [_jsx("span", { className: "r3-form-index", children: `0${index + 1}` }), _jsx("span", { className: "r3-form-name", children: formlabels[form].name }), _jsx("span", { className: "r3-form-pkg", children: formlabels[form].pkg }), _jsx("span", { className: "r3-form-note", children: formlabels[form].note })] }, form))) })] }), _jsxs("section", { className: "content-section", children: [_jsxs("div", { className: "content-section-heading", children: [_jsx("p", { className: "eyebrow", children: label('architecture.layers.eyebrow') }), _jsx("span", { className: "mono-label", children: label('architecture.layers.mono') })] }), _jsx("div", { className: "layer-stack", children: layers().map((layer, index) => {
|
|
88
|
+
const Icon = layer.icon;
|
|
89
|
+
return (_jsxs("div", { className: "layer-row", children: [_jsxs("span", { className: "layer-index", children: ["0", index + 1] }), _jsx(Icon, { fontSize: 20, strokeWidth: 1.5, "aria-hidden": "true" }), _jsxs("div", { className: "layer-name", children: [_jsx("strong", { children: layer.name }), _jsx("span", { children: layer.sub })] }), _jsx("p", { children: layer.body }), _jsx(ArrowUpRight, { fontSize: 16, "aria-hidden": "true" })] }, layer.name));
|
|
90
|
+
}) })] }), _jsxs("section", { className: "content-section", children: [_jsxs("div", { className: "content-section-heading", children: [_jsx("p", { className: "eyebrow", children: label('architecture.chain.eyebrow') }), _jsx("span", { className: "mono-label", children: label('architecture.chain.mono') })] }), _jsx("div", { className: "provider-grid", children: providerchain().map((name, index) => (_jsxs("div", { className: `provider-cell ${index === 0 ? 'is-active' : ''}`, children: [_jsxs("span", { className: "provider-index", children: ["0", index + 1] }), _jsx("strong", { children: name }), _jsx("small", { children: label(index === 0
|
|
91
|
+
? 'architecture.chain.preferred'
|
|
92
|
+
: 'architecture.chain.fallback') })] }, name))) })] }), _jsxs("section", { className: "content-section architecture-note", children: [_jsx(ShieldCheck, { fontSize: 21, "aria-hidden": "true" }), _jsxs("div", { children: [_jsx("p", { className: "eyebrow", children: label('architecture.limit.eyebrow') }), _jsx("p", { children: label('architecture.limit.body') })] })] })] }));
|
|
93
|
+
}
|