@almadar/shell-node 1.1.0 → 1.2.1
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/LICENSE +72 -0
- package/dist/OrbitalServerRuntime.d.ts +4 -3
- package/dist/OrbitalServerRuntime.js +2 -2
- package/dist/{chunk-LNEOE5TD.js → chunk-CB2RKJKB.js} +1 -1
- package/dist/{chunk-34JOE763.js → chunk-U2YFXKUN.js} +22 -11
- package/dist/chunk-WIL5CHP5.js +222 -0
- package/dist/{chunk-VQVAHUAX.js → chunk-YEC2UPB4.js} +10 -2
- package/dist/createProgramHandlers.js +3 -3
- package/dist/index.d.ts +4 -13
- package/dist/index.js +4 -4
- package/dist/{kernel-workspace-host-cT9JGJur.d.ts → kernel-workspace-host-DGAzpPX-.d.ts} +1 -3
- package/dist/kernelWorkspace.d.ts +1 -1
- package/dist/kernelWorkspace.js +2 -2
- package/package.json +7 -7
- package/dist/chunk-HXA6OB35.js +0 -2229
package/LICENSE
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
Business Source License 1.1
|
|
2
|
+
|
|
3
|
+
Parameters
|
|
4
|
+
|
|
5
|
+
Licensor: Almadar FZE
|
|
6
|
+
Licensed Work: KFlow Builder / Almadar
|
|
7
|
+
The Licensed Work is (c) 2025-2026 Almadar FZE.
|
|
8
|
+
Additional Use Grant: You may make production use of the Licensed Work for
|
|
9
|
+
non-commercial purposes and for internal evaluation.
|
|
10
|
+
Production use for commercial purposes requires a
|
|
11
|
+
commercial license from the Licensor.
|
|
12
|
+
Change Date: 2030-02-01
|
|
13
|
+
Change License: Apache License, Version 2.0
|
|
14
|
+
|
|
15
|
+
Terms
|
|
16
|
+
|
|
17
|
+
The Licensor hereby grants you the right to copy, modify, create derivative
|
|
18
|
+
works, redistribute, and make non-production use of the Licensed Work. The
|
|
19
|
+
Licensor may make an Additional Use Grant, above, permitting limited
|
|
20
|
+
production use.
|
|
21
|
+
|
|
22
|
+
Effective on the Change Date, or the fourth anniversary of the first publicly
|
|
23
|
+
available distribution of a specific version of the Licensed Work under this
|
|
24
|
+
License, whichever comes first, the Licensor hereby grants you rights under
|
|
25
|
+
the terms of the Change License, and the rights granted in the paragraph
|
|
26
|
+
above terminate.
|
|
27
|
+
|
|
28
|
+
If your use of the Licensed Work does not comply with the requirements
|
|
29
|
+
currently in effect as described in this License, you must purchase a
|
|
30
|
+
commercial license from the Licensor, its affiliated entities, or authorized
|
|
31
|
+
resellers, or you must refrain from using the Licensed Work.
|
|
32
|
+
|
|
33
|
+
All copies of the original and modified Licensed Work, and derivative works
|
|
34
|
+
of the Licensed Work, are subject to this License. This License applies
|
|
35
|
+
separately for each version of the Licensed Work and the Change Date may vary
|
|
36
|
+
for each version of the Licensed Work released by Licensor.
|
|
37
|
+
|
|
38
|
+
You must conspicuously display this License on each original or modified copy
|
|
39
|
+
of the Licensed Work. If you receive the Licensed Work in original or
|
|
40
|
+
modified form from a third party, the terms and conditions set forth in this
|
|
41
|
+
License apply to your use of that work.
|
|
42
|
+
|
|
43
|
+
Any use of the Licensed Work in violation of this License will automatically
|
|
44
|
+
terminate your rights under this License for the current and all other
|
|
45
|
+
versions of the Licensed Work.
|
|
46
|
+
|
|
47
|
+
This License does not grant you any right in any trademark or logo of
|
|
48
|
+
Licensor or its affiliates (provided that you may use a trademark or logo of
|
|
49
|
+
Licensor as expressly required by this License).
|
|
50
|
+
|
|
51
|
+
TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON
|
|
52
|
+
AN "AS IS" BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS,
|
|
53
|
+
EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF
|
|
54
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND
|
|
55
|
+
TITLE.
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
License text copyright (c) 2017 MariaDB Corporation Ab, All Rights Reserved.
|
|
60
|
+
"Business Source License" is a trademark of MariaDB Corporation Ab.
|
|
61
|
+
|
|
62
|
+
ADDITIONAL TERMS:
|
|
63
|
+
|
|
64
|
+
Documentation (builder/packages/website/docs/) is licensed under CC BY 4.0.
|
|
65
|
+
|
|
66
|
+
TRADEMARKS:
|
|
67
|
+
|
|
68
|
+
"Orbital", "KFlow", "Almadar", and the Almadar logo are trademarks of
|
|
69
|
+
Almadar FZE. You may not use these trademarks without prior written
|
|
70
|
+
permission from Almadar FZE.
|
|
71
|
+
|
|
72
|
+
For licensing inquiries: licensing@almadar.io
|
|
@@ -120,8 +120,7 @@ interface OrbitalServerRuntimeConfig {
|
|
|
120
120
|
*/
|
|
121
121
|
secretPorts?: SecretPortsOptions;
|
|
122
122
|
/**
|
|
123
|
-
* Builds the `os` host of the kernel engine from the grant port backed by the kernel (`
|
|
124
|
-
* `@almadar/shell-node`). Absent, every `os` ask is denied, as the native host does with none.
|
|
123
|
+
* Builds the `os` host of the kernel engine from the grant port backed by the kernel. Absent, the native add-on's `OsHost` answers (`orbital-core`'s `os_host`, in Rust); a wasm kernel has none and answers every `os` ask `unsupported`.
|
|
125
124
|
*/
|
|
126
125
|
osHost?: (grants: OsGrantPort) => OsHostPort;
|
|
127
126
|
/** The clock the kernel's `clock` ask is answered from, in epoch milliseconds; absent, the system clock. */
|
|
@@ -354,6 +353,8 @@ declare class OrbitalServerRuntime {
|
|
|
354
353
|
setHostDispatchSink(sink: (item: HostDispatchItem) => void): void;
|
|
355
354
|
/** Run a follow-on step's call outcome as its own dispatch, and hand its result to the host-dispatch sink. */
|
|
356
355
|
private runDeferredOutcome;
|
|
356
|
+
/** A deferred outcome for the tab that asked is what that browser is told of it: the kernel's client view and completion payload (EXEC-DIST-8, EXEC-QUEUE-10). */
|
|
357
|
+
private browserDispatchItem;
|
|
357
358
|
/**
|
|
358
359
|
* A tick-stamped dispatch is a latest-state broadcast (T6): the kernel coalesces it with the others of the window
|
|
359
360
|
* (newest per origin client, orbital and event) and says how long the window stays open; this host only runs
|
|
@@ -426,7 +427,7 @@ declare class OrbitalServerRuntime {
|
|
|
426
427
|
* runs as the session's identity, never a viewer the request names. An unknown orbital is `ORBITAL_NOT_FOUND`, an undeclared
|
|
427
428
|
* locale `LOCALE_NOT_DECLARED`; an inbound-only event and an undeclared input are the routes' refusals.
|
|
428
429
|
*/
|
|
429
|
-
dispatchEventRequest(orbital: string, parsed: EventRequest, input: boolean, stream?: boolean): Promise<DispatchRequestOutcome>;
|
|
430
|
+
dispatchEventRequest(orbital: string, parsed: EventRequest, input: boolean, stream?: boolean, wire?: boolean): Promise<DispatchRequestOutcome>;
|
|
430
431
|
dispatchExternalInput(orbitalName: string, request: ExternalInputRequest, onPush?: (item: PushItem) => void): Promise<EventResponse>;
|
|
431
432
|
/**
|
|
432
433
|
* An inbound delivery (`/api/hooks/<name>`): the runtime decides whether the name is served, runs
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { OrbitalServerRuntime, UnresolvedProgramError } from './chunk-
|
|
2
|
-
import './chunk-
|
|
1
|
+
export { OrbitalServerRuntime, UnresolvedProgramError } from './chunk-U2YFXKUN.js';
|
|
2
|
+
import './chunk-YEC2UPB4.js';
|
|
3
3
|
import './chunk-EEYGL7AB.js';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { workspacesRoot, kernelWorkspaceHost, workspaceBucketFromEnv } from './chunk-
|
|
1
|
+
import { workspacesRoot, kernelWorkspaceHost, workspaceBucketFromEnv } from './chunk-WIL5CHP5.js';
|
|
2
2
|
import { runProgramEffect } from './chunk-7QE32QQR.js';
|
|
3
3
|
import { installedWorkspaceHost, installWorkspaceHost } from './chunk-BWMLDDCL.js';
|
|
4
4
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { installNodeHostPorts, createNodeTokenPost } from './chunk-
|
|
1
|
+
import { installNodeHostPorts, createNodeTokenPost, nativeOsHost } from './chunk-YEC2UPB4.js';
|
|
2
2
|
import { nativeMemoryOf } from './chunk-EEYGL7AB.js';
|
|
3
3
|
import { EventBus, bindDeclaredCollections, createSecretPorts, defaultCallService, kernelEventRequestParser, kernelOsTls, kernelOsCompletions, stampEmitSource, eventRouteKey, kernelOsGrants, KernelEngine, dispatchDeclaredInput, dispatchInbound, createSecretStore, evaluateOnKernel, InFlightCalls } from '@almadar/shell-runtime';
|
|
4
4
|
import { installKernelEvaluator, orbitalInlineEntities, asEventId, asTraitId, inlineTraitRefs, tickEventKey, toPayloadValue } from '@almadar/core';
|
|
@@ -314,7 +314,7 @@ var OrbitalServerRuntime = class {
|
|
|
314
314
|
this.inFlightCalls.cancelAll();
|
|
315
315
|
this.kernelEngine?.dispose();
|
|
316
316
|
this.kernelOs?.close();
|
|
317
|
-
this.kernelOs = this.config.osHost?.(kernelOsGrants(kernel, () => this.requireKernelEngine()));
|
|
317
|
+
this.kernelOs = this.config.osHost?.(kernelOsGrants(kernel, () => this.requireKernelEngine())) ?? nativeOsHost(kernel, () => this.requireKernelEngine().serverHandle());
|
|
318
318
|
this.kernelEngine = KernelEngine.open(kernel, schema, this.kernelPorts(), this.lazyDir);
|
|
319
319
|
this.kernelEngine.setStateful();
|
|
320
320
|
this.programSurface = this.kernelEngine.programSurface();
|
|
@@ -496,10 +496,18 @@ var OrbitalServerRuntime = class {
|
|
|
496
496
|
/** Run a follow-on step's call outcome as its own dispatch, and hand its result to the host-dispatch sink. */
|
|
497
497
|
runDeferredOutcome(orbitalName, request) {
|
|
498
498
|
void this.processOrbitalEvent(orbitalName, request).then(
|
|
499
|
-
(response) => this.hostDispatchSink?.(
|
|
499
|
+
(response) => this.hostDispatchSink?.(this.browserDispatchItem(orbitalName, request, response)),
|
|
500
500
|
(error) => effectLog.error("deferred-outcome:failed", { orbitalName, event: request.event, trait: request.targetTrait, error: error.message })
|
|
501
501
|
);
|
|
502
502
|
}
|
|
503
|
+
/** A deferred outcome for the tab that asked is what that browser is told of it: the kernel's client view and completion payload (EXEC-DIST-8, EXEC-QUEUE-10). */
|
|
504
|
+
browserDispatchItem(orbitalName, request, response) {
|
|
505
|
+
if (request.clientId === void 0) return { orbitalName, request, response };
|
|
506
|
+
const engine = this.requireKernelEngine();
|
|
507
|
+
const payload = request.targetTrait === void 0 ? request.payload : engine.browserCompletionPayload(request.targetTrait, request.payload);
|
|
508
|
+
const { payload: _held, ...rest } = request;
|
|
509
|
+
return { orbitalName, request: payload === void 0 ? rest : { ...rest, payload }, response: engine.clientView(response), originClientId: request.clientId };
|
|
510
|
+
}
|
|
503
511
|
/**
|
|
504
512
|
* A tick-stamped dispatch is a latest-state broadcast (T6): the kernel coalesces it with the others of the window
|
|
505
513
|
* (newest per origin client, orbital and event) and says how long the window stays open; this host only runs
|
|
@@ -632,9 +640,9 @@ var OrbitalServerRuntime = class {
|
|
|
632
640
|
return this.requireKernelEngine().readRows(entity, await this.persistence.list(entity), user);
|
|
633
641
|
},
|
|
634
642
|
supportsDispatchStream: true,
|
|
635
|
-
dispatchRequest: (orbital, request, input, stream) => {
|
|
643
|
+
dispatchRequest: (orbital, request, input, stream, wire) => {
|
|
636
644
|
assertReentry?.();
|
|
637
|
-
return this.dispatchEventRequest(orbital, request, input, stream);
|
|
645
|
+
return this.dispatchEventRequest(orbital, request, input, stream, wire);
|
|
638
646
|
},
|
|
639
647
|
deliverInbound: (name, delivery) => this.deliverInbound(name, delivery),
|
|
640
648
|
resolveRows: (reference, clientId) => this.resolveRows(reference, clientId)
|
|
@@ -645,17 +653,20 @@ var OrbitalServerRuntime = class {
|
|
|
645
653
|
* runs as the session's identity, never a viewer the request names. An unknown orbital is `ORBITAL_NOT_FOUND`, an undeclared
|
|
646
654
|
* locale `LOCALE_NOT_DECLARED`; an inbound-only event and an undeclared input are the routes' refusals.
|
|
647
655
|
*/
|
|
648
|
-
async dispatchEventRequest(orbital, parsed, input, stream = false) {
|
|
656
|
+
async dispatchEventRequest(orbital, parsed, input, stream = false, wire = false) {
|
|
649
657
|
const request = parsed;
|
|
650
658
|
const streamItems = [];
|
|
651
659
|
const onPush = stream ? (item) => {
|
|
652
660
|
streamItems.push({ ...item, timestamp: item.timestamp ?? Date.now() });
|
|
653
661
|
} : void 0;
|
|
654
|
-
const answer = (
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
662
|
+
const answer = (full) => {
|
|
663
|
+
const response2 = wire ? this.requireKernelEngine().clientView(full) : full;
|
|
664
|
+
return {
|
|
665
|
+
ok: true,
|
|
666
|
+
response: response2,
|
|
667
|
+
...stream ? { streamItems: [...streamItems, { type: "complete", data: response2, timestamp: Date.now() }] } : {}
|
|
668
|
+
};
|
|
669
|
+
};
|
|
659
670
|
if (await this.resolveRegisteredOrbital(orbital) === void 0) {
|
|
660
671
|
return { ok: false, error: `Orbital not found: ${orbital}`, code: "ORBITAL_NOT_FOUND", status: 404 };
|
|
661
672
|
}
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import { installNodeHostPorts, createNodeTokenPost, nativeOsHost } from './chunk-YEC2UPB4.js';
|
|
2
|
+
import { loadNativeKernelModule, resolveNativeAddon, loadKernelModule } from './chunk-EEYGL7AB.js';
|
|
3
|
+
import { workspaceOwnerSegment } from './chunk-BWMLDDCL.js';
|
|
4
|
+
import { mkdirSync, realpathSync, mkdtempSync, writeFileSync, rmSync } from 'fs';
|
|
5
|
+
import { tmpdir } from 'os';
|
|
6
|
+
import { resolve, dirname, join } from 'path';
|
|
7
|
+
import { spawn } from 'child_process';
|
|
8
|
+
import { createRequire } from 'module';
|
|
9
|
+
import { createSecretPorts, NativeMemoryPersistenceAdapter, InFlightCalls, KernelEngine, dispatchInbound } from '@almadar/shell-runtime';
|
|
10
|
+
import { resolveOrbBinary } from '@almadar/core/behavior-package';
|
|
11
|
+
import { tickEventKey } from '@almadar/core';
|
|
12
|
+
|
|
13
|
+
function resolveKernelDir(from = process.cwd()) {
|
|
14
|
+
const named = process.env.ALMADAR_KERNEL_DIR;
|
|
15
|
+
if (named !== void 0 && named !== "") return named;
|
|
16
|
+
const entry = createRequire(join(resolve(from), "resolve.js")).resolve("@almadar/kernel");
|
|
17
|
+
return dirname(dirname(entry));
|
|
18
|
+
}
|
|
19
|
+
function emitPayload(run, event, read) {
|
|
20
|
+
const found = run.emits.find((emit) => emit.event === event);
|
|
21
|
+
return found === void 0 ? void 0 : read(found.payload ?? {});
|
|
22
|
+
}
|
|
23
|
+
async function resolveProgramFile(path, cwd = dirname(resolve(path)), orb = resolveOrbBinary(cwd)) {
|
|
24
|
+
const absolute = resolve(path);
|
|
25
|
+
return new Promise((done, fail) => {
|
|
26
|
+
const child = spawn(orb, ["resolve", absolute], { cwd, stdio: ["ignore", "pipe", "pipe"] });
|
|
27
|
+
const out = [];
|
|
28
|
+
const err = [];
|
|
29
|
+
child.stdout.on("data", (chunk) => out.push(chunk));
|
|
30
|
+
child.stderr.on("data", (chunk) => err.push(chunk));
|
|
31
|
+
child.on("error", fail);
|
|
32
|
+
child.on("close", (code) => {
|
|
33
|
+
if (code !== 0) {
|
|
34
|
+
fail(new Error(`orb resolve ${absolute} exited ${code}: ${Buffer.concat(err).toString("utf8")}`));
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
const text = Buffer.concat(out).toString("utf8");
|
|
38
|
+
done(JSON.parse(text.slice(text.indexOf("{"))));
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
var KernelProgram = class _KernelProgram {
|
|
43
|
+
constructor(engine, schema, secretPorts, persistence, os) {
|
|
44
|
+
this.engine = engine;
|
|
45
|
+
this.schema = schema;
|
|
46
|
+
this.secretPorts = secretPorts;
|
|
47
|
+
this.persistence = persistence;
|
|
48
|
+
this.os = os;
|
|
49
|
+
}
|
|
50
|
+
engine;
|
|
51
|
+
schema;
|
|
52
|
+
secretPorts;
|
|
53
|
+
persistence;
|
|
54
|
+
os;
|
|
55
|
+
static async open(schema, options) {
|
|
56
|
+
const languageFrom = { languageFrom: options.languageFrom };
|
|
57
|
+
const native = options.engine === "native";
|
|
58
|
+
const addon = native ? await loadNativeKernelModule(options.nativeAddon ?? resolveNativeAddon(options.languageFrom), languageFrom) : void 0;
|
|
59
|
+
const kernelDir = addon === void 0 ? options.kernelDir ?? resolveKernelDir() : "";
|
|
60
|
+
const kernel = addon ?? await loadKernelModule(kernelDir, languageFrom);
|
|
61
|
+
installNodeHostPorts();
|
|
62
|
+
let engine;
|
|
63
|
+
const requireEngine = () => {
|
|
64
|
+
if (engine === void 0) throw new Error("KernelProgram: an ask arrived before the program opened");
|
|
65
|
+
return engine;
|
|
66
|
+
};
|
|
67
|
+
const tokenPost = createNodeTokenPost({ egressAllows: (url) => requireEngine().egressAllows(url), isPublicAddress: (ip) => kernel.isPublicAddress(ip) });
|
|
68
|
+
const secretPorts = createSecretPorts({ tokenPost, ...options.secretPorts });
|
|
69
|
+
const persistence = new NativeMemoryPersistenceAdapter(new kernel.MemoryStore());
|
|
70
|
+
for (const [entityType, rows] of Object.entries(options.seed ?? {})) {
|
|
71
|
+
for (const row of rows) await persistence.writeWhere({ kind: "upsert", entityType, data: row });
|
|
72
|
+
}
|
|
73
|
+
const ports = {
|
|
74
|
+
persistence,
|
|
75
|
+
callService: async () => null,
|
|
76
|
+
programEffect: () => void 0,
|
|
77
|
+
inFlightCalls: new InFlightCalls(),
|
|
78
|
+
servicePorts: (caller, _user, message) => ({ caller, message, inputs: () => [], readableEntities: () => [], dispatchInput: async () => {
|
|
79
|
+
throw new Error("KernelProgram has no input channel");
|
|
80
|
+
}, read: async () => [] }),
|
|
81
|
+
deliverLive: () => void 0,
|
|
82
|
+
deferCallOutcome: () => void 0,
|
|
83
|
+
secretPorts
|
|
84
|
+
};
|
|
85
|
+
const os = nativeOsHost(kernel, () => requireEngine().serverHandle());
|
|
86
|
+
if (os !== void 0) ports.os = os;
|
|
87
|
+
engine = KernelEngine.open(kernel, schema, ports);
|
|
88
|
+
return new _KernelProgram(engine, schema, secretPorts, persistence, os);
|
|
89
|
+
}
|
|
90
|
+
/** Fire `event` at the orbital as `user` (the program's `@user`), wait for its whole cascade (every secret ask included), and return what it emitted. */
|
|
91
|
+
async dispatch(orbital, event, payload = {}, targetTrait, user) {
|
|
92
|
+
const response = await this.engine.evaluate(
|
|
93
|
+
orbital,
|
|
94
|
+
{ event, payload, ...targetTrait !== void 0 ? { targetTrait } : {}, ...user !== void 0 ? { user } : {} },
|
|
95
|
+
{ orbital }
|
|
96
|
+
);
|
|
97
|
+
return {
|
|
98
|
+
success: response.success,
|
|
99
|
+
emits: response.emittedEvents,
|
|
100
|
+
rejections: response.rejections ?? [],
|
|
101
|
+
...response.error !== void 0 ? { error: response.error } : {}
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
/** Fire `trait`'s tick `name` once, as a host timer would; the kernel evaluates the tick's guard and effects. */
|
|
105
|
+
async tick(orbital, trait, name) {
|
|
106
|
+
const response = await this.engine.evaluate(orbital, { event: tickEventKey(name), runTick: { trait, tick: name }, targetTrait: trait }, { orbital });
|
|
107
|
+
return {
|
|
108
|
+
success: response.success,
|
|
109
|
+
emits: response.emittedEvents,
|
|
110
|
+
rejections: response.rejections ?? [],
|
|
111
|
+
...response.error !== void 0 ? { error: response.error } : {}
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
/** Deliver an `/api/hooks/<name>` request to the program and return the answer it gave (EXEC-INBOUND-1). */
|
|
115
|
+
async deliverInbound(name, delivery) {
|
|
116
|
+
return dispatchInbound(this.engine, name, delivery, (orbital, request) => this.engine.evaluate(orbital, request, { orbital }), (credential) => this.secretPorts.secrets.get(credential, void 0));
|
|
117
|
+
}
|
|
118
|
+
/** The rows the host's in-memory store holds for `entity` (empty when the native kernel keeps its own `store`). */
|
|
119
|
+
async rows(entity) {
|
|
120
|
+
return this.persistence.list(entity);
|
|
121
|
+
}
|
|
122
|
+
close() {
|
|
123
|
+
this.os?.close();
|
|
124
|
+
this.engine.dispose();
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
// src/program/kernel-workspace-host.ts
|
|
129
|
+
var GCS_ENDPOINT = "https://storage.googleapis.com";
|
|
130
|
+
var WORKSPACE_HMAC_KEY_ID = "ALMADAR_WORKSPACE_HMAC_KEY_ID";
|
|
131
|
+
var WORKSPACE_HMAC_SECRET = "ALMADAR_WORKSPACE_HMAC_SECRET";
|
|
132
|
+
function workspaceBucketFromEnv(env) {
|
|
133
|
+
const name = env.ALMADAR_WORKSPACE_BUCKET;
|
|
134
|
+
if (name === void 0 || name === "") return void 0;
|
|
135
|
+
return { name, endpoint: GCS_ENDPOINT, region: "auto", accessKeyId: WORKSPACE_HMAC_KEY_ID, secretAccessKey: WORKSPACE_HMAC_SECRET };
|
|
136
|
+
}
|
|
137
|
+
var ORBITAL = "Workspaces";
|
|
138
|
+
var TRAIT = `${ORBITAL}WorkspaceClient`;
|
|
139
|
+
function workspacesRoot(projectRoot) {
|
|
140
|
+
return join(projectRoot, "workspaces");
|
|
141
|
+
}
|
|
142
|
+
function programText(root, bucket) {
|
|
143
|
+
const egress = bucket === void 0 ? "" : `
|
|
144
|
+
egress: [${JSON.stringify(bucket.endpoint)}],`;
|
|
145
|
+
return `app kernel-workspace-host [
|
|
146
|
+
version: "1.0.0",
|
|
147
|
+
description: "The program host's workspaces, run by std-workspace.",${egress}
|
|
148
|
+
fs: { ${JSON.stringify(`${root}/**`)}: [read, write, create, remove] },
|
|
149
|
+
exec: ["git"]
|
|
150
|
+
]
|
|
151
|
+
uses Ws from "std/behaviors/std-workspace"
|
|
152
|
+
orbital ${ORBITAL} = Ws.orbitals.WorkspaceOrbital {${bucket === void 0 ? `
|
|
153
|
+
traits { WorkspaceClient { config { root: ${JSON.stringify(root)} } } }` : `
|
|
154
|
+
traits {
|
|
155
|
+
WorkspaceClient { config { root: ${JSON.stringify(root)}, store: bucket, bucket: ${JSON.stringify(bucket.name)} } }
|
|
156
|
+
WorkspaceStore { config { endpoint: ${JSON.stringify(bucket.endpoint)}, region: ${JSON.stringify(bucket.region)}, bucket: ${JSON.stringify(bucket.name)}, accessKeyId: ${JSON.stringify(bucket.accessKeyId)}, secretAccessKey: ${JSON.stringify(bucket.secretAccessKey)} } }
|
|
157
|
+
}`}
|
|
158
|
+
}
|
|
159
|
+
`;
|
|
160
|
+
}
|
|
161
|
+
function failure(run, failed, what) {
|
|
162
|
+
const detail = emitPayload(run, failed, (p) => typeof p.message === "string" ? p.message : "");
|
|
163
|
+
return new Error(`workspace ${what} failed: ${detail ?? run.error ?? "no answer"}`);
|
|
164
|
+
}
|
|
165
|
+
function snapshots(payload) {
|
|
166
|
+
const rows = payload.snapshots;
|
|
167
|
+
if (!Array.isArray(rows)) return [];
|
|
168
|
+
return rows.flatMap(
|
|
169
|
+
(row) => typeof row === "object" && row !== null && !Array.isArray(row) && typeof row.id === "string" && typeof row.timestamp === "number" && typeof row.reason === "string" ? [{ id: row.id, timestamp: row.timestamp, reason: row.reason }] : []
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
function kernelWorkspaceHost(options) {
|
|
173
|
+
const root = workspacesRoot(options.projectRoot);
|
|
174
|
+
let program;
|
|
175
|
+
let tail = Promise.resolve();
|
|
176
|
+
const open = () => {
|
|
177
|
+
program ??= (async () => {
|
|
178
|
+
mkdirSync(root, { recursive: true });
|
|
179
|
+
const granted = realpathSync(root);
|
|
180
|
+
const dir = mkdtempSync(join(tmpdir(), "almadar-workspace-host-"));
|
|
181
|
+
try {
|
|
182
|
+
const file = join(dir, "workspace-host.lolo");
|
|
183
|
+
writeFileSync(file, programText(granted, options.bucket));
|
|
184
|
+
const schema = await resolveProgramFile(file, options.projectRoot, options.orb);
|
|
185
|
+
return await KernelProgram.open(schema, { ...options.kernel, languageFrom: options.projectRoot });
|
|
186
|
+
} finally {
|
|
187
|
+
rmSync(dir, { recursive: true, force: true });
|
|
188
|
+
}
|
|
189
|
+
})();
|
|
190
|
+
return program;
|
|
191
|
+
};
|
|
192
|
+
const run = (principal, event, payload, read) => {
|
|
193
|
+
const next = tail.then(async () => read(await (await open()).dispatch(ORBITAL, event, payload, TRAIT, { id: principal })));
|
|
194
|
+
tail = next.catch(() => void 0);
|
|
195
|
+
return next;
|
|
196
|
+
};
|
|
197
|
+
return {
|
|
198
|
+
root,
|
|
199
|
+
async open(workspace, context) {
|
|
200
|
+
const principal = context.principal;
|
|
201
|
+
if (principal === void 0 || principal === "") throw new Error("A workspace needs a signed-in caller");
|
|
202
|
+
return {
|
|
203
|
+
workDir: join(root, workspaceOwnerSegment(principal), workspaceOwnerSegment(workspace)),
|
|
204
|
+
writeFile: (path, content) => run(principal, "WORKSPACE_WRITE_FILE", { workspace, path, content }, (r) => {
|
|
205
|
+
if (emitPayload(r, "WORKSPACE_FILE_WRITTEN", (p) => p.written) !== true) throw failure(r, "WORKSPACE_WRITE_FAILED", `write of ${path}`);
|
|
206
|
+
}),
|
|
207
|
+
snapshot: (reason) => run(principal, "WORKSPACE_SNAPSHOT", { workspace, reason }, (r) => {
|
|
208
|
+
const taken = emitPayload(r, "WORKSPACE_SNAPSHOT_TAKEN", (p) => ({ committed: p.committed === true, oid: typeof p.oid === "string" ? p.oid : "" }));
|
|
209
|
+
if (taken === void 0) throw failure(r, "WORKSPACE_SNAPSHOT_FAILED", "snapshot");
|
|
210
|
+
return taken.committed ? { oid: taken.oid } : null;
|
|
211
|
+
}),
|
|
212
|
+
listSnapshots: (opts) => run(principal, "WORKSPACE_HISTORY", { workspace, ...opts?.limit !== void 0 ? { limit: opts.limit } : {} }, (r) => {
|
|
213
|
+
const found = emitPayload(r, "WORKSPACE_HISTORY_LOADED", snapshots);
|
|
214
|
+
if (found === void 0) throw failure(r, "WORKSPACE_HISTORY_FAILED", "history");
|
|
215
|
+
return found;
|
|
216
|
+
})
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
export { KernelProgram, emitPayload, kernelWorkspaceHost, resolveProgramFile, workspaceBucketFromEnv, workspacesRoot };
|
|
@@ -2,10 +2,11 @@ import { readFile, mkdir, writeFile, rename } from 'fs/promises';
|
|
|
2
2
|
import { join, dirname } from 'path';
|
|
3
3
|
import { EntityRowSchema, runRowWrite } from '@almadar/core';
|
|
4
4
|
import { AsyncLocalStorage } from 'async_hooks';
|
|
5
|
-
import { installCredentialScopeStorage, CREDENTIAL_MASTER_KEY_ENV, CREDENTIAL_PREVIOUS_MASTER_KEY_ENV, CredentialVault, installCredentialStore } from '@almadar/shell-runtime';
|
|
5
|
+
import { installCredentialScopeStorage, CREDENTIAL_MASTER_KEY_ENV, CREDENTIAL_PREVIOUS_MASTER_KEY_ENV, CredentialVault, installCredentialStore, createNativeOsPort } from '@almadar/shell-runtime';
|
|
6
6
|
import { lookup } from 'dns/promises';
|
|
7
7
|
import { request } from 'https';
|
|
8
8
|
import { isIP } from 'net';
|
|
9
|
+
import { homedir } from 'os';
|
|
9
10
|
|
|
10
11
|
// src/credential-rows.ts
|
|
11
12
|
var CREDENTIALS_FILE_ENV = "ALMADAR_CREDENTIALS_FILE";
|
|
@@ -179,5 +180,12 @@ function createNodeTokenPost(options) {
|
|
|
179
180
|
});
|
|
180
181
|
};
|
|
181
182
|
}
|
|
183
|
+
function nodeOsAnchors() {
|
|
184
|
+
const env = Object.fromEntries(Object.entries(process.env).flatMap(([name, value]) => value === void 0 ? [] : [[name, value]]));
|
|
185
|
+
return { home: homedir(), start: process.cwd(), exeDir: dirname(process.execPath), exe: process.execPath, env };
|
|
186
|
+
}
|
|
187
|
+
function nativeOsHost(kernel, server) {
|
|
188
|
+
return kernel.OsHost === void 0 ? void 0 : createNativeOsPort(kernel.OsHost, nodeOsAnchors(), server);
|
|
189
|
+
}
|
|
182
190
|
|
|
183
|
-
export { DEFAULT_CREDENTIALS_FILE, TokenPostRefusal, createNodeTokenPost, credentialsFilePath, fileCredentialRows, installNodeCredentialVault, installNodeHostPorts };
|
|
191
|
+
export { DEFAULT_CREDENTIALS_FILE, TokenPostRefusal, createNodeTokenPost, credentialsFilePath, fileCredentialRows, installNodeCredentialVault, installNodeHostPorts, nativeOsHost };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export { createProgramHandlers } from './chunk-
|
|
2
|
-
import './chunk-
|
|
3
|
-
import './chunk-
|
|
1
|
+
export { createProgramHandlers } from './chunk-CB2RKJKB.js';
|
|
2
|
+
import './chunk-WIL5CHP5.js';
|
|
3
|
+
import './chunk-YEC2UPB4.js';
|
|
4
4
|
import './chunk-EEYGL7AB.js';
|
|
5
5
|
import './chunk-7QE32QQR.js';
|
|
6
6
|
import './chunk-BWMLDDCL.js';
|
package/dist/index.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { CredentialVaultModule, CredentialVault, CredentialRowsPort,
|
|
1
|
+
import { CredentialVaultModule, CredentialVault, CredentialRowsPort, TokenEndpointPost, KernelModule, NativeMemoryPersistenceAdapter, ServiceCallContext, StepRequest, PlayedStep, ProgramValidationReport, ProgramEffectName, ProgramEffectOutcome } from '@almadar/shell-runtime';
|
|
2
2
|
import { JsonValue, KernelMemoryStoreExports, OrbitalSchema, EvaluatedProgram, ProgramValidationIssue, CatalogScope, CatalogEntry, DependencyGraph, TraitValue, TraitDescription, DescribeTarget, BehaviorDescription } from '@almadar/core';
|
|
3
3
|
export { ClientEffectTuple, ClientNavigateBackTuple, ClientNavigateTuple, ClientRenderUITuple, EventRequest, EventResponse, TransitionRejection } from '@almadar/core';
|
|
4
4
|
import { RequestOptions } from 'node:https';
|
|
5
5
|
import { IncomingMessage, ClientRequest } from 'node:http';
|
|
6
6
|
import { OsGrantsReport, ProveReport, StepRefusal } from '@almadar/core/kernel-wire';
|
|
7
7
|
import { LayoutStrategy } from '@almadar/core/builders';
|
|
8
|
-
export { K as KernelProgram, a as KernelProgramOptions, b as KernelWorkspaceBucket, c as KernelWorkspaceHostOptions, P as ProgramRun, W as WorkspaceHost, d as WorkspacePort, e as emitPayload, i as installWorkspaceHost, f as installedWorkspaceHost, k as kernelWorkspaceHost, r as resolveProgramFile, u as uninstallWorkspaceHost, w as workspaceBucketFromEnv, g as workspaceOwnerSegment, h as workspacesRoot } from './kernel-workspace-host-
|
|
8
|
+
export { K as KernelProgram, a as KernelProgramOptions, b as KernelWorkspaceBucket, c as KernelWorkspaceHostOptions, P as ProgramRun, W as WorkspaceHost, d as WorkspacePort, e as emitPayload, i as installWorkspaceHost, f as installedWorkspaceHost, k as kernelWorkspaceHost, r as resolveProgramFile, u as uninstallWorkspaceHost, w as workspaceBucketFromEnv, g as workspaceOwnerSegment, h as workspacesRoot } from './kernel-workspace-host-DGAzpPX-.js';
|
|
9
9
|
export { HostDispatchItem, LiveBroadcastItem, LoaderConfig, OrbitalServerRuntime, OrbitalServerRuntimeConfig, PushItem, RegisterOptions, RegisteredOrbital, RuntimeOrbital, RuntimeOrbitalSchema, UnresolvedProgramError } from './OrbitalServerRuntime.js';
|
|
10
10
|
export { ProgramHandlers, ProgramHostConfig, createProgramHandlers } from './createProgramHandlers.js';
|
|
11
11
|
|
|
@@ -47,15 +47,6 @@ declare function fileCredentialRows(path: string): CredentialRowsPort;
|
|
|
47
47
|
*/
|
|
48
48
|
declare function loadOrCreateDevMasterKey(dir: string): string;
|
|
49
49
|
|
|
50
|
-
/** One program instance's `os` host: its own handle tables, closed by `close`. */
|
|
51
|
-
interface NodeOsHostOptions {
|
|
52
|
-
/** Where `~/` and `./` and the declared grant anchors are placed; absent, the process's own (`OsAnchors::of_process`). */
|
|
53
|
-
anchors?: OsAnchors;
|
|
54
|
-
}
|
|
55
|
-
/** The process's home, working directory, executable directory and environment, read once (`OsAnchors::of_process`). */
|
|
56
|
-
declare function processAnchors(): OsAnchors;
|
|
57
|
-
declare function createNodeOsHost(grants: OsGrantPort, options?: NodeOsHostOptions): OsHostPort;
|
|
58
|
-
|
|
59
50
|
type KvErrorKind = 'denied' | 'invalid' | 'io' | 'timeout' | 'unsupported' | 'closed';
|
|
60
51
|
type KvResult<T> = {
|
|
61
52
|
ok: true;
|
|
@@ -297,5 +288,5 @@ type EffectArg = JsonValue;
|
|
|
297
288
|
*/
|
|
298
289
|
declare function runProgramEffect(op: ProgramEffectName, args: readonly EffectArg[], opts: ProgramHostOptions, context?: ProgramCallContext): Promise<ProgramEffectOutcome>;
|
|
299
290
|
|
|
300
|
-
export { DEFAULT_CREDENTIALS_FILE, KvFailure, TokenPostRefusal, behaviorCatalog, behaviorCatalogSync, behaviorDependencies, behaviorDescribe, behaviorResolve, behaviorSource, createKvHost,
|
|
301
|
-
export type { KvBackend, KvBatchOp, KvErrorKind, KvHost, KvNamespace, KvResult, LoadKernelOptions, LoadedKernel, NodeCredentialVaultOptions,
|
|
291
|
+
export { DEFAULT_CREDENTIALS_FILE, KvFailure, TokenPostRefusal, behaviorCatalog, behaviorCatalogSync, behaviorDependencies, behaviorDescribe, behaviorResolve, behaviorSource, createKvHost, createNodeTokenPost, credentialsFilePath, directoryKvBackend, fileCredentialRows, installNodeCredentialVault, installNodeHostPorts, loadInstalledKernel, loadKernelModule, loadNativeKernelModule, loadOrCreateDevMasterKey, memoryKvBackend, nativeMemoryOf, programCompose, programEval, programOsGrants, programPrint, programProve, programRead, programResolve, programResolveSchema, programStep, programValidate, resolveNativeAddon, runProgramEffect, workspaceAccessError };
|
|
292
|
+
export type { KvBackend, KvBatchOp, KvErrorKind, KvHost, KvNamespace, KvResult, LoadKernelOptions, LoadedKernel, NodeCredentialVaultOptions, NodeTokenPostOptions, ProgramCallContext, ProgramComposeOptions, ProgramEvalOptions, ProgramEvalResult, ProgramHostOptions, ProgramOsGrantsReport, ProgramProveReport, ResolvedAddress };
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export { OrbitalServerRuntime, UnresolvedProgramError } from './chunk-
|
|
2
|
-
export { createProgramHandlers } from './chunk-
|
|
3
|
-
export { KernelProgram,
|
|
4
|
-
export { DEFAULT_CREDENTIALS_FILE, TokenPostRefusal, createNodeTokenPost, credentialsFilePath, fileCredentialRows, installNodeCredentialVault, installNodeHostPorts } from './chunk-
|
|
1
|
+
export { OrbitalServerRuntime, UnresolvedProgramError } from './chunk-U2YFXKUN.js';
|
|
2
|
+
export { createProgramHandlers } from './chunk-CB2RKJKB.js';
|
|
3
|
+
export { KernelProgram, emitPayload, kernelWorkspaceHost, resolveProgramFile, workspaceBucketFromEnv, workspacesRoot } from './chunk-WIL5CHP5.js';
|
|
4
|
+
export { DEFAULT_CREDENTIALS_FILE, TokenPostRefusal, createNodeTokenPost, credentialsFilePath, fileCredentialRows, installNodeCredentialVault, installNodeHostPorts } from './chunk-YEC2UPB4.js';
|
|
5
5
|
export { loadInstalledKernel, loadKernelModule, loadNativeKernelModule, nativeMemoryOf, resolveNativeAddon } from './chunk-EEYGL7AB.js';
|
|
6
6
|
export { behaviorCatalog, behaviorCatalogSync, behaviorDependencies, behaviorDescribe, behaviorResolve, behaviorSource, programCompose, programEval, programOsGrants, programPrint, programProve, programRead, programResolve, programResolveSchema, programStep, programValidate, runProgramEffect, workspaceAccessError } from './chunk-7QE32QQR.js';
|
|
7
7
|
export { installWorkspaceHost, installedWorkspaceHost, uninstallWorkspaceHost, workspaceOwnerSegment } from './chunk-BWMLDDCL.js';
|
|
@@ -56,8 +56,6 @@ interface KernelProgramOptions {
|
|
|
56
56
|
secretPorts?: Pick<SecretPortsOptions, 'secrets' | 'random'>;
|
|
57
57
|
/** Rows the program's in-memory store starts with, by entity name (a catalog the host already holds). */
|
|
58
58
|
seed?: Record<string, EntityRow[]>;
|
|
59
|
-
/** Answer the program's `os` effects with the Node host (its grants are the program's own); absent, every `os` ask is denied. */
|
|
60
|
-
os?: boolean;
|
|
61
59
|
}
|
|
62
60
|
interface ProgramRun {
|
|
63
61
|
success: boolean;
|
|
@@ -76,10 +74,10 @@ declare function emitPayload<T>(run: ProgramRun, event: string, read: (payload:
|
|
|
76
74
|
declare function resolveProgramFile(path: string, cwd?: string, orb?: string): Promise<OrbitalSchema>;
|
|
77
75
|
declare class KernelProgram {
|
|
78
76
|
private readonly engine;
|
|
79
|
-
private readonly os;
|
|
80
77
|
private readonly schema;
|
|
81
78
|
private readonly secretPorts;
|
|
82
79
|
private readonly persistence;
|
|
80
|
+
private readonly os;
|
|
83
81
|
private constructor();
|
|
84
82
|
static open(schema: OrbitalSchema, options: KernelProgramOptions): Promise<KernelProgram>;
|
|
85
83
|
/** Fire `event` at the orbital as `user` (the program's `@user`), wait for its whole cascade (every secret ask included), and return what it emitted. */
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { b as KernelWorkspaceBucket, c as KernelWorkspaceHostOptions, k as kernelWorkspaceHost, w as workspaceBucketFromEnv, h as workspacesRoot } from './kernel-workspace-host-
|
|
1
|
+
export { b as KernelWorkspaceBucket, c as KernelWorkspaceHostOptions, k as kernelWorkspaceHost, w as workspaceBucketFromEnv, h as workspacesRoot } from './kernel-workspace-host-DGAzpPX-.js';
|
|
2
2
|
import '@almadar/shell-runtime';
|
|
3
3
|
import '@almadar/core';
|
package/dist/kernelWorkspace.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { kernelWorkspaceHost, workspaceBucketFromEnv, workspacesRoot } from './chunk-
|
|
2
|
-
import './chunk-
|
|
1
|
+
export { kernelWorkspaceHost, workspaceBucketFromEnv, workspacesRoot } from './chunk-WIL5CHP5.js';
|
|
2
|
+
import './chunk-YEC2UPB4.js';
|
|
3
3
|
import './chunk-EEYGL7AB.js';
|
|
4
4
|
import './chunk-BWMLDDCL.js';
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@almadar/shell-node",
|
|
3
|
-
"version": "1.1
|
|
3
|
+
"version": "1.2.1",
|
|
4
4
|
"orbRelease": {
|
|
5
5
|
"severity": "normal"
|
|
6
6
|
},
|
|
7
|
-
"description": "Almadar TS shell node runtime pack: the Node
|
|
7
|
+
"description": "Almadar TS shell node runtime pack: the Node program host of the kernel (KernelProgram, workspace, program host); os asks are answered only by the native add-on.",
|
|
8
8
|
"license": "BUSL-1.1",
|
|
9
9
|
"type": "module",
|
|
10
10
|
"main": "./dist/index.js",
|
|
@@ -37,12 +37,12 @@
|
|
|
37
37
|
"access": "public"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@almadar/core": "^11.
|
|
41
|
-
"@almadar/kernel": "^19.0
|
|
42
|
-
"@almadar/logger": "^2.
|
|
40
|
+
"@almadar/core": "^11.4.0",
|
|
41
|
+
"@almadar/kernel": "^19.2.0",
|
|
42
|
+
"@almadar/logger": "^2.4.0",
|
|
43
43
|
"zod": "^4.6.7",
|
|
44
|
-
"@almadar/std": "^17.1
|
|
45
|
-
"@almadar/shell-runtime": "^1.1
|
|
44
|
+
"@almadar/std": "^17.2.1",
|
|
45
|
+
"@almadar/shell-runtime": "^1.2.1"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"@types/node": "^20.0.0",
|