@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
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/** one edge execution request: the modality lane to ride, the program
|
|
2
|
+
* payload (or the base64 wasm bytes, or the vfs payload), the optional
|
|
3
|
+
* inputs and the optional deadline budget in milliseconds. */
|
|
4
|
+
export type EdgeRequest = {
|
|
5
|
+
/** the modality id of the lane to ride (the registry id). */
|
|
6
|
+
modality: string;
|
|
7
|
+
/** the program payload the lane interprets (code, bytes or script). */
|
|
8
|
+
code: string;
|
|
9
|
+
/** the caller inputs the lane surfaces to the program when given. */
|
|
10
|
+
inputs?: unknown;
|
|
11
|
+
/** the run deadline in milliseconds (clamped between 250 and 60000). */
|
|
12
|
+
deadlinems?: number;
|
|
13
|
+
};
|
|
14
|
+
/** one lane of the edge plane as the report answers it: the modality it
|
|
15
|
+
* wires, whether the lane executes (live) or probes (host), the runtime
|
|
16
|
+
* surface it rides, and the honest probed presence of that runtime. */
|
|
17
|
+
export type EdgeLaneReport = {
|
|
18
|
+
/** the modality id the lane wires. */
|
|
19
|
+
modality: string;
|
|
20
|
+
/** live lanes execute, host lanes probe the runtime (the next rung). */
|
|
21
|
+
kind: "live" | "host";
|
|
22
|
+
/** the runtime surface the lane rides ("node:vm", "bun", "docker"...). */
|
|
23
|
+
runtime: string;
|
|
24
|
+
/** whether this report row reflects a probe performed now (always true —
|
|
25
|
+
* every lane probes its runtime surface when the table is read). */
|
|
26
|
+
probed: boolean;
|
|
27
|
+
/** whether the probed runtime surface is present on this engine host. */
|
|
28
|
+
present: boolean;
|
|
29
|
+
};
|
|
30
|
+
/** one edge run result: the run identity, the lane it rode, the honest
|
|
31
|
+
* status, the captured streams, the committed artifact manifest and the
|
|
32
|
+
* coded error when the run failed. */
|
|
33
|
+
export type EdgeRunResult = {
|
|
34
|
+
/** the run id the engine minted. */
|
|
35
|
+
runid: string;
|
|
36
|
+
/** the modality id that was requested. */
|
|
37
|
+
modality: string;
|
|
38
|
+
/** the runtime surface the run rode (empty when no lane rode it). */
|
|
39
|
+
lane: string;
|
|
40
|
+
/** the honest status of the run. */
|
|
41
|
+
status: "succeeded" | "failed";
|
|
42
|
+
/** the captured stdout when the run produced any. */
|
|
43
|
+
stdout?: string;
|
|
44
|
+
/** the captured stderr when the run produced any. */
|
|
45
|
+
stderr?: string;
|
|
46
|
+
/** the artifact the run committed (mime, byte count, storage ref). */
|
|
47
|
+
artifact?: {
|
|
48
|
+
mime: string;
|
|
49
|
+
bytes: number;
|
|
50
|
+
storageref?: string;
|
|
51
|
+
};
|
|
52
|
+
/** the coded error when the run failed. */
|
|
53
|
+
error?: {
|
|
54
|
+
code: string;
|
|
55
|
+
message: string;
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
/** the storage surface the edge plane commits artifacts through: the
|
|
59
|
+
* duck-typed shape of the virtual.ts storageadapter products
|
|
60
|
+
* (localstorage, memorystorage, the pools), so any adapter the engine
|
|
61
|
+
* already carries slots in without importing the root domain graph. */
|
|
62
|
+
export interface EdgeStorageAdapter {
|
|
63
|
+
/** writes one artifact and answers its manifest. */
|
|
64
|
+
put(input: {
|
|
65
|
+
key: string;
|
|
66
|
+
data: Uint8Array | ArrayBuffer | string;
|
|
67
|
+
contenttype?: string;
|
|
68
|
+
metadata?: Record<string, unknown>;
|
|
69
|
+
}): Promise<unknown>;
|
|
70
|
+
/** reads one artifact back as bytes. */
|
|
71
|
+
get(key: string): Promise<Uint8Array | ArrayBuffer>;
|
|
72
|
+
/** answers the manifest of one artifact when present. */
|
|
73
|
+
head(key: string): Promise<unknown>;
|
|
74
|
+
/** removes one artifact. */
|
|
75
|
+
delete(key: string): Promise<unknown>;
|
|
76
|
+
/** lists the manifests under one prefix. */
|
|
77
|
+
list(prefix?: string): Promise<readonly unknown[]>;
|
|
78
|
+
}
|
|
79
|
+
/** edgelanes — the lane table with every runtime probed now: the report
|
|
80
|
+
* never lies, a lane whose runtime is absent says absent (an ops
|
|
81
|
+
* surface, not a hot path — the probes walk PATH and the module
|
|
82
|
+
* resolver synchronously). */
|
|
83
|
+
export declare function edgelanes(): EdgeLaneReport[];
|
|
84
|
+
/** edgelandesreport — the same probed lane table keyed by modality id
|
|
85
|
+
* for the api surface (GET /api/v1/edge/lanes answers {lanes: this}). */
|
|
86
|
+
export declare function edgelandesreport(): Record<string, EdgeLaneReport>;
|
|
87
|
+
/** assertvisitorfree — the law guard of the edge plane: throws
|
|
88
|
+
* {code: "VISITOR_CONTEXT_REFUSED"} when the scope carries
|
|
89
|
+
* browser-shaped globals, because the engine executes server-side only
|
|
90
|
+
* and never as the visitor browser. Every runonedge entry calls it on
|
|
91
|
+
* globalThis before a single instruction rides a lane.
|
|
92
|
+
*
|
|
93
|
+
* @param scope the scope to inspect (duck-typed, works in node).
|
|
94
|
+
* @throws the coded refusal when the scope is browser-shaped.
|
|
95
|
+
*/
|
|
96
|
+
export declare function assertvisitorfree(scope: unknown): void;
|
|
97
|
+
/** runonedge — the dispatch law of the edge plane: the visitor guard
|
|
98
|
+
* refuses any browser scope, the registry resolves the modality, the
|
|
99
|
+
* lane executor rides the runtime server-side, the output is captured,
|
|
100
|
+
* and the artifact (the lane artifact, or the stdout when the lane
|
|
101
|
+
* produced none) is committed through the caller's storage adapter when
|
|
102
|
+
* given. A planned or unknown modality answers MODALITY_NOT_LIVE; a
|
|
103
|
+
* lane whose host runtime is absent answers HOST_RUNTIME_ABSENT naming
|
|
104
|
+
* the runtime; a storage commit failure fails the run honestly
|
|
105
|
+
* (STORAGE_FAILURE — an unpersisted artifact is a failed commit, the
|
|
106
|
+
* engine law).
|
|
107
|
+
*
|
|
108
|
+
* @param request the edge run request (modality, code, inputs, deadline).
|
|
109
|
+
* @param options the caller surfaces (the storage adapter for artifacts).
|
|
110
|
+
* @returns the honest EdgeRunResult of the dispatch.
|
|
111
|
+
*/
|
|
112
|
+
export declare function runonedge(request: EdgeRequest, options?: {
|
|
113
|
+
storage?: EdgeStorageAdapter;
|
|
114
|
+
}): Promise<EdgeRunResult>;
|
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
// # edgeplane.ts — the edge execution law of the saddle engine: every
|
|
2
|
+
// pass of the system rides one modality lane of the engine, server-side,
|
|
3
|
+
// and the visitor browser never executes anything (the owner's law: the
|
|
4
|
+
// interface never uses the visitor browser, gpu or cpu; the sandbox and
|
|
5
|
+
// the saddle modalities act for the system over the internet). The plane
|
|
6
|
+
// owns the lane table — the ten live lanes the engine drives today and
|
|
7
|
+
// the six host lanes it probes — the visitor guard that refuses any
|
|
8
|
+
// browser-shaped scope before a single instruction rides, and the
|
|
9
|
+
// dispatcher that resolves the modality through the registry, rides the
|
|
10
|
+
// lane executor, captures the output and commits the artifact through
|
|
11
|
+
// the caller's storage adapter. The lane table is the wiring truth of
|
|
12
|
+
// this plane: the sv1 catalog declared most of these lanes planned
|
|
13
|
+
// before the edge wave wired them, and the report states what the engine
|
|
14
|
+
// drives today, honestly probed per runtime. The imports stay node-safe
|
|
15
|
+
// on purpose: the webserver's plain node host strips types and resolves
|
|
16
|
+
// only .ts specifiers, so the plane imports the pure registry and
|
|
17
|
+
// foundation modules directly and leaves the root domain graph
|
|
18
|
+
// (virtual.ts and its .js specifiers) to the lazy lane loads.
|
|
19
|
+
import { edgelaneexecutorsall, edgelanespecsall } from "./edgelandes.ninety.ts";
|
|
20
|
+
import { probedocker, probehostbinary, probemodule, probenodevm, probevirtualmodule, probewasm } from "./edgelandes.ts";
|
|
21
|
+
import { idfactory } from "./foundation.ts";
|
|
22
|
+
import { getmodality } from "./modalityregistry.ts";
|
|
23
|
+
/** the lane table of the edge plane: the ten live lanes (the execution
|
|
24
|
+
* lanes the engine drives today) and the six host lanes (the runtimes
|
|
25
|
+
* the engine probes, the execution wiring the next rung) of the base
|
|
26
|
+
* contract, then the sixty-three lanes of the ninety modalities wave
|
|
27
|
+
* merged in through edgelandes.ninety.ts (the twenty-five host binary
|
|
28
|
+
* lanes, the nineteen in-process lanes, the seven virtual hardware
|
|
29
|
+
* lanes and the six heavyweight probes). The ids are pinned — parallel
|
|
30
|
+
* waves and the api routes read them exactly. */
|
|
31
|
+
const EDGELANES = Object.freeze([
|
|
32
|
+
...edgelanespecsall,
|
|
33
|
+
// the live lanes: the engine executes through these today
|
|
34
|
+
{ modality: "container-docker", kind: "live", runtime: "docker", present: probedocker },
|
|
35
|
+
{ modality: "fs-vfs", kind: "live", runtime: "virtual-vfs", present: probevirtualmodule },
|
|
36
|
+
{ modality: "runner-node", kind: "live", runtime: "node:vm", present: probenodevm },
|
|
37
|
+
{ modality: "runner-bun", kind: "live", runtime: "bun", present: () => probehostbinary("bun") },
|
|
38
|
+
{ modality: "runner-wasm", kind: "live", runtime: "webassembly", present: probewasm },
|
|
39
|
+
{ modality: "runner-babel", kind: "live", runtime: "@babel/core", present: () => probemodule("@babel/core") },
|
|
40
|
+
{ modality: "runner-webpack", kind: "live", runtime: "webpack", present: () => probemodule("webpack") },
|
|
41
|
+
{ modality: "runner-universal", kind: "live", runtime: "bash", present: () => probehostbinary("bash") },
|
|
42
|
+
{ modality: "language-python", kind: "live", runtime: "python3", present: () => probehostbinary("python3") },
|
|
43
|
+
{ modality: "language-java", kind: "live", runtime: "java", present: () => probehostbinary("java") },
|
|
44
|
+
// the host lanes: the engine probes the runtime, execution is the next rung
|
|
45
|
+
{ modality: "container-runsc", kind: "host", runtime: "runsc", present: () => probehostbinary("runsc") },
|
|
46
|
+
{
|
|
47
|
+
modality: "emulator-qemu",
|
|
48
|
+
kind: "host",
|
|
49
|
+
runtime: "qemu-system-x86_64",
|
|
50
|
+
present: () => probehostbinary("qemu-system-x86_64"),
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
modality: "microvm-firecracker",
|
|
54
|
+
kind: "host",
|
|
55
|
+
runtime: "firecracker",
|
|
56
|
+
present: () => probehostbinary("firecracker"),
|
|
57
|
+
},
|
|
58
|
+
{ modality: "runtime-jvm", kind: "host", runtime: "java", present: () => probehostbinary("java") },
|
|
59
|
+
{ modality: "language-go", kind: "host", runtime: "go", present: () => probehostbinary("go") },
|
|
60
|
+
{ modality: "language-ruby", kind: "host", runtime: "ruby", present: () => probehostbinary("ruby") },
|
|
61
|
+
]);
|
|
62
|
+
/** edgelanes — the lane table with every runtime probed now: the report
|
|
63
|
+
* never lies, a lane whose runtime is absent says absent (an ops
|
|
64
|
+
* surface, not a hot path — the probes walk PATH and the module
|
|
65
|
+
* resolver synchronously). */
|
|
66
|
+
export function edgelanes() {
|
|
67
|
+
return EDGELANES.map((lane) => ({
|
|
68
|
+
modality: lane.modality,
|
|
69
|
+
kind: lane.kind,
|
|
70
|
+
runtime: lane.runtime,
|
|
71
|
+
probed: true,
|
|
72
|
+
present: lane.present(),
|
|
73
|
+
}));
|
|
74
|
+
}
|
|
75
|
+
/** edgelandesreport — the same probed lane table keyed by modality id
|
|
76
|
+
* for the api surface (GET /api/v1/edge/lanes answers {lanes: this}). */
|
|
77
|
+
export function edgelandesreport() {
|
|
78
|
+
const report = {};
|
|
79
|
+
for (const lane of edgelanes())
|
|
80
|
+
report[lane.modality] = lane;
|
|
81
|
+
return report;
|
|
82
|
+
}
|
|
83
|
+
/* ════════════════════════════════════════════════════════════════════ */
|
|
84
|
+
/* Section 3: the visitor law guard — the engine refuses browser scopes. */
|
|
85
|
+
/* ════════════════════════════════════════════════════════════════════ */
|
|
86
|
+
/** the browser shells and storage surfaces that mark a visitor scope
|
|
87
|
+
* (window, document, localStorage, sessionStorage, indexedDB): a scope
|
|
88
|
+
* carrying any of them is a browser, and the engine refuses to execute
|
|
89
|
+
* as one. navigator alone is not a marker — node itself ships a
|
|
90
|
+
* vestigial navigator since v21 — the shells and the storages are the
|
|
91
|
+
* law. */
|
|
92
|
+
const VISITORMARKERS = Object.freeze([
|
|
93
|
+
"window",
|
|
94
|
+
"document",
|
|
95
|
+
"localStorage",
|
|
96
|
+
"sessionStorage",
|
|
97
|
+
"indexedDB",
|
|
98
|
+
]);
|
|
99
|
+
/** assertvisitorfree — the law guard of the edge plane: throws
|
|
100
|
+
* {code: "VISITOR_CONTEXT_REFUSED"} when the scope carries
|
|
101
|
+
* browser-shaped globals, because the engine executes server-side only
|
|
102
|
+
* and never as the visitor browser. Every runonedge entry calls it on
|
|
103
|
+
* globalThis before a single instruction rides a lane.
|
|
104
|
+
*
|
|
105
|
+
* @param scope the scope to inspect (duck-typed, works in node).
|
|
106
|
+
* @throws the coded refusal when the scope is browser-shaped.
|
|
107
|
+
*/
|
|
108
|
+
export function assertvisitorfree(scope) {
|
|
109
|
+
if (scope === null || typeof scope !== "object")
|
|
110
|
+
return;
|
|
111
|
+
const record = scope;
|
|
112
|
+
for (const marker of VISITORMARKERS) {
|
|
113
|
+
if (record[marker] !== undefined) {
|
|
114
|
+
const error = new Error(`the visitor context is refused: the scope carries the browser global ${marker} and the edge plane executes server-side only`);
|
|
115
|
+
error.name = "edgeplaneerror";
|
|
116
|
+
error.code = "VISITOR_CONTEXT_REFUSED";
|
|
117
|
+
throw error;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
/* ════════════════════════════════════════════════════════════════════ */
|
|
122
|
+
/* Section 4: the dispatch — runonedge rides one lane, honestly. */
|
|
123
|
+
/* ════════════════════════════════════════════════════════════════════ */
|
|
124
|
+
/** the default deadline of one edge run. */
|
|
125
|
+
const DEFAULTDEADLINEMS = 10000;
|
|
126
|
+
/** the deadline floor and ceiling: no run rides under 250 ms or over 60 s. */
|
|
127
|
+
const MINDEADLINEMS = 250;
|
|
128
|
+
const MAXDEADLINEMS = 60000;
|
|
129
|
+
/** the artifact extension of one mime type (the storage key suffix). */
|
|
130
|
+
function extensionfor(mime) {
|
|
131
|
+
const base = mime.split(";")[0]?.trim() ?? "";
|
|
132
|
+
const extensions = {
|
|
133
|
+
"text/plain": ".txt",
|
|
134
|
+
"application/json": ".json",
|
|
135
|
+
"application/javascript": ".js",
|
|
136
|
+
"application/wasm": ".wasm",
|
|
137
|
+
"application/octet-stream": ".bin",
|
|
138
|
+
};
|
|
139
|
+
return extensions[base] ?? ".bin";
|
|
140
|
+
}
|
|
141
|
+
/** clamps the caller deadline into the honest budget window. */
|
|
142
|
+
function clampdeadline(deadlinems) {
|
|
143
|
+
const requested = typeof deadlinems === "number" && Number.isFinite(deadlinems) ? deadlinems : DEFAULTDEADLINEMS;
|
|
144
|
+
return Math.min(Math.max(Math.round(requested), MINDEADLINEMS), MAXDEADLINEMS);
|
|
145
|
+
}
|
|
146
|
+
/** the safe message of an unknown thrown value (no stack rides a result). */
|
|
147
|
+
function errormessage(error) {
|
|
148
|
+
return error instanceof Error ? error.message : String(error ?? "unknown edge failure");
|
|
149
|
+
}
|
|
150
|
+
/** the lane error code of an unknown thrown value: coded lane errors keep
|
|
151
|
+
* their code, timeouts answer RUN_DEADLINE_EXCEEDED, the rest is honest
|
|
152
|
+
* EDGE_LANE_FAILURE. */
|
|
153
|
+
function lanecode(error) {
|
|
154
|
+
const code = error?.code;
|
|
155
|
+
if (typeof code === "string" && code.length > 0)
|
|
156
|
+
return code;
|
|
157
|
+
if (/timed out|timeout/i.test(errormessage(error)))
|
|
158
|
+
return "RUN_DEADLINE_EXCEEDED";
|
|
159
|
+
return "EDGE_LANE_FAILED";
|
|
160
|
+
}
|
|
161
|
+
/** the id factory of the edge plane (one run id per dispatch). */
|
|
162
|
+
const ids = idfactory();
|
|
163
|
+
/** runonedge — the dispatch law of the edge plane: the visitor guard
|
|
164
|
+
* refuses any browser scope, the registry resolves the modality, the
|
|
165
|
+
* lane executor rides the runtime server-side, the output is captured,
|
|
166
|
+
* and the artifact (the lane artifact, or the stdout when the lane
|
|
167
|
+
* produced none) is committed through the caller's storage adapter when
|
|
168
|
+
* given. A planned or unknown modality answers MODALITY_NOT_LIVE; a
|
|
169
|
+
* lane whose host runtime is absent answers HOST_RUNTIME_ABSENT naming
|
|
170
|
+
* the runtime; a storage commit failure fails the run honestly
|
|
171
|
+
* (STORAGE_FAILURE — an unpersisted artifact is a failed commit, the
|
|
172
|
+
* engine law).
|
|
173
|
+
*
|
|
174
|
+
* @param request the edge run request (modality, code, inputs, deadline).
|
|
175
|
+
* @param options the caller surfaces (the storage adapter for artifacts).
|
|
176
|
+
* @returns the honest EdgeRunResult of the dispatch.
|
|
177
|
+
*/
|
|
178
|
+
export async function runonedge(request, options = {}) {
|
|
179
|
+
const runid = ids.next("edgerun");
|
|
180
|
+
const modality = typeof request?.modality === "string" ? request.modality : "";
|
|
181
|
+
let lanename = "";
|
|
182
|
+
try {
|
|
183
|
+
assertvisitorfree(globalThis);
|
|
184
|
+
if (modality.length === 0 || typeof request?.code !== "string") {
|
|
185
|
+
return {
|
|
186
|
+
runid,
|
|
187
|
+
modality,
|
|
188
|
+
lane: lanename,
|
|
189
|
+
status: "failed",
|
|
190
|
+
error: { code: "INVALID_EDGE_REQUEST", message: "an edge run requires a modality id and a code payload" },
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
const lane = EDGELANES.find((entry) => entry.modality === modality);
|
|
194
|
+
if (lane === undefined) {
|
|
195
|
+
const record = getmodality(modality);
|
|
196
|
+
if (record === undefined) {
|
|
197
|
+
return {
|
|
198
|
+
runid,
|
|
199
|
+
modality,
|
|
200
|
+
lane: lanename,
|
|
201
|
+
status: "failed",
|
|
202
|
+
error: { code: "MODALITY_NOT_LIVE", message: `the modality id ${modality} is unknown to the registry` },
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
// a record the registry already drives live through another engine
|
|
206
|
+
// surface (the envelope sandbox lane) is never lied about here: the
|
|
207
|
+
// modality is live, this plane simply wires no lane for it yet.
|
|
208
|
+
if (record.state === "planned") {
|
|
209
|
+
return {
|
|
210
|
+
runid,
|
|
211
|
+
modality,
|
|
212
|
+
lane: lanename,
|
|
213
|
+
status: "failed",
|
|
214
|
+
error: {
|
|
215
|
+
code: "MODALITY_NOT_LIVE",
|
|
216
|
+
message: `the modality ${modality} is planned: no engine surface drives it yet`,
|
|
217
|
+
},
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
return {
|
|
221
|
+
runid,
|
|
222
|
+
modality,
|
|
223
|
+
lane: lanename,
|
|
224
|
+
status: "failed",
|
|
225
|
+
error: {
|
|
226
|
+
code: "LANE_NOT_WIRED_IN_PLANE",
|
|
227
|
+
message: `the modality ${modality} is ${record.state} in the registry, but this edge plane wires no lane for it yet — the other engine surfaces drive it`,
|
|
228
|
+
},
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
lanename = lane.runtime;
|
|
232
|
+
const executor = edgelaneexecutorsall[lane.modality];
|
|
233
|
+
if (executor === undefined) {
|
|
234
|
+
return {
|
|
235
|
+
runid,
|
|
236
|
+
modality,
|
|
237
|
+
lane: lanename,
|
|
238
|
+
status: "failed",
|
|
239
|
+
error: { code: "EDGE_PLANE_MISWIRED", message: `no executor is wired for the lane ${lanename}` },
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
const deadline = clampdeadline(request.deadlinems);
|
|
243
|
+
const output = await executor(request.code, request.inputs, deadline);
|
|
244
|
+
const payload = output.artifact ??
|
|
245
|
+
(output.stdout.length > 0
|
|
246
|
+
? { mime: "text/plain;charset=utf-8", bytes: new TextEncoder().encode(output.stdout) }
|
|
247
|
+
: undefined);
|
|
248
|
+
let artifact;
|
|
249
|
+
if (payload !== undefined) {
|
|
250
|
+
artifact = { mime: payload.mime, bytes: payload.bytes.byteLength };
|
|
251
|
+
if (options.storage !== undefined) {
|
|
252
|
+
try {
|
|
253
|
+
const key = `edge/runs/${runid}/output${extensionfor(payload.mime)}`;
|
|
254
|
+
const manifest = (await options.storage.put({
|
|
255
|
+
key,
|
|
256
|
+
data: payload.bytes,
|
|
257
|
+
contenttype: payload.mime,
|
|
258
|
+
metadata: { runid, modality },
|
|
259
|
+
}));
|
|
260
|
+
artifact.storageref = typeof manifest?.key === "string" ? manifest.key : key;
|
|
261
|
+
}
|
|
262
|
+
catch (error) {
|
|
263
|
+
return {
|
|
264
|
+
runid,
|
|
265
|
+
modality,
|
|
266
|
+
lane: lanename,
|
|
267
|
+
status: "failed",
|
|
268
|
+
stderr: output.stderr,
|
|
269
|
+
error: {
|
|
270
|
+
code: "STORAGE_FAILURE",
|
|
271
|
+
message: `the artifact of the edge run ${runid} failed to persist: ${errormessage(error)}`,
|
|
272
|
+
},
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
return {
|
|
278
|
+
runid,
|
|
279
|
+
modality,
|
|
280
|
+
lane: lanename,
|
|
281
|
+
status: "succeeded",
|
|
282
|
+
stdout: output.stdout,
|
|
283
|
+
stderr: output.stderr,
|
|
284
|
+
artifact,
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
catch (error) {
|
|
288
|
+
return {
|
|
289
|
+
runid,
|
|
290
|
+
modality,
|
|
291
|
+
lane: lanename,
|
|
292
|
+
status: "failed",
|
|
293
|
+
stderr: error.stderr,
|
|
294
|
+
error: { code: lanecode(error), message: errormessage(error) },
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
/* the wiring self-check: the plane refuses to load over a lane it
|
|
299
|
+
* cannot wire (a table entry without an executor is a miswired plane,
|
|
300
|
+
* and miswiring must fail loud at boot, never silently at run time). */
|
|
301
|
+
for (const lane of EDGELANES) {
|
|
302
|
+
if (edgelaneexecutorsall[lane.modality] === undefined) {
|
|
303
|
+
throw new Error(`the edge plane is miswired: no executor for the lane ${lane.modality}`);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -7,7 +7,6 @@ import { join } from "node:path";
|
|
|
7
7
|
import { eventbus, engine, inprocess, scheduler } from "../index.js";
|
|
8
8
|
import { localmemory } from "../virtual.js";
|
|
9
9
|
import { localstorage } from "../virtual.js";
|
|
10
|
-
|
|
11
10
|
const root = await mkdtemp(join(tmpdir(), "saddleexample"));
|
|
12
11
|
const events = eventbus();
|
|
13
12
|
const run = engine({ storage: localstorage(root), memory: localmemory(), scheduler: scheduler([inprocess()]), events });
|