@almadar/shell-node 1.0.0 → 1.2.0
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-7QG7JGKQ.js → chunk-CB2RKJKB.js} +1 -1
- package/dist/{chunk-3PNZYEZQ.js → chunk-U2YFXKUN.js} +23 -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-YLFK5OJN.js +0 -2225
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';
|
|
@@ -262,6 +262,7 @@ var OrbitalServerRuntime = class {
|
|
|
262
262
|
deferCallOutcome: () => this.hostDispatchSink === null ? void 0 : (call) => this.runDeferredOutcome(call.orbital, {
|
|
263
263
|
event: call.event,
|
|
264
264
|
...call.payload !== void 0 ? { payload: call.payload } : {},
|
|
265
|
+
...call.heldPayload !== void 0 ? { heldPayload: call.heldPayload } : {},
|
|
265
266
|
targetTrait: call.traitName,
|
|
266
267
|
...call.entityId !== void 0 ? { entityId: call.entityId } : {},
|
|
267
268
|
...call.originClientId !== void 0 ? { clientId: call.originClientId } : {},
|
|
@@ -313,7 +314,7 @@ var OrbitalServerRuntime = class {
|
|
|
313
314
|
this.inFlightCalls.cancelAll();
|
|
314
315
|
this.kernelEngine?.dispose();
|
|
315
316
|
this.kernelOs?.close();
|
|
316
|
-
this.kernelOs = this.config.osHost?.(kernelOsGrants(kernel, () => this.requireKernelEngine()));
|
|
317
|
+
this.kernelOs = this.config.osHost?.(kernelOsGrants(kernel, () => this.requireKernelEngine())) ?? nativeOsHost(kernel, () => this.requireKernelEngine().serverHandle());
|
|
317
318
|
this.kernelEngine = KernelEngine.open(kernel, schema, this.kernelPorts(), this.lazyDir);
|
|
318
319
|
this.kernelEngine.setStateful();
|
|
319
320
|
this.programSurface = this.kernelEngine.programSurface();
|
|
@@ -495,10 +496,18 @@ var OrbitalServerRuntime = class {
|
|
|
495
496
|
/** Run a follow-on step's call outcome as its own dispatch, and hand its result to the host-dispatch sink. */
|
|
496
497
|
runDeferredOutcome(orbitalName, request) {
|
|
497
498
|
void this.processOrbitalEvent(orbitalName, request).then(
|
|
498
|
-
(response) => this.hostDispatchSink?.(
|
|
499
|
+
(response) => this.hostDispatchSink?.(this.browserDispatchItem(orbitalName, request, response)),
|
|
499
500
|
(error) => effectLog.error("deferred-outcome:failed", { orbitalName, event: request.event, trait: request.targetTrait, error: error.message })
|
|
500
501
|
);
|
|
501
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
|
+
}
|
|
502
511
|
/**
|
|
503
512
|
* A tick-stamped dispatch is a latest-state broadcast (T6): the kernel coalesces it with the others of the window
|
|
504
513
|
* (newest per origin client, orbital and event) and says how long the window stays open; this host only runs
|
|
@@ -631,9 +640,9 @@ var OrbitalServerRuntime = class {
|
|
|
631
640
|
return this.requireKernelEngine().readRows(entity, await this.persistence.list(entity), user);
|
|
632
641
|
},
|
|
633
642
|
supportsDispatchStream: true,
|
|
634
|
-
dispatchRequest: (orbital, request, input, stream) => {
|
|
643
|
+
dispatchRequest: (orbital, request, input, stream, wire) => {
|
|
635
644
|
assertReentry?.();
|
|
636
|
-
return this.dispatchEventRequest(orbital, request, input, stream);
|
|
645
|
+
return this.dispatchEventRequest(orbital, request, input, stream, wire);
|
|
637
646
|
},
|
|
638
647
|
deliverInbound: (name, delivery) => this.deliverInbound(name, delivery),
|
|
639
648
|
resolveRows: (reference, clientId) => this.resolveRows(reference, clientId)
|
|
@@ -644,17 +653,20 @@ var OrbitalServerRuntime = class {
|
|
|
644
653
|
* runs as the session's identity, never a viewer the request names. An unknown orbital is `ORBITAL_NOT_FOUND`, an undeclared
|
|
645
654
|
* locale `LOCALE_NOT_DECLARED`; an inbound-only event and an undeclared input are the routes' refusals.
|
|
646
655
|
*/
|
|
647
|
-
async dispatchEventRequest(orbital, parsed, input, stream = false) {
|
|
656
|
+
async dispatchEventRequest(orbital, parsed, input, stream = false, wire = false) {
|
|
648
657
|
const request = parsed;
|
|
649
658
|
const streamItems = [];
|
|
650
659
|
const onPush = stream ? (item) => {
|
|
651
660
|
streamItems.push({ ...item, timestamp: item.timestamp ?? Date.now() });
|
|
652
661
|
} : void 0;
|
|
653
|
-
const answer = (
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
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
|
+
};
|
|
658
670
|
if (await this.resolveRegisteredOrbital(orbital) === void 0) {
|
|
659
671
|
return { ok: false, error: `Orbital not found: ${orbital}`, code: "ORBITAL_NOT_FOUND", status: 404 };
|
|
660
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.
|
|
3
|
+
"version": "1.2.0",
|
|
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.
|
|
45
|
-
"@almadar/shell-runtime": "^1.
|
|
44
|
+
"@almadar/std": "^17.2.0",
|
|
45
|
+
"@almadar/shell-runtime": "^1.2.0"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"@types/node": "^20.0.0",
|