@almadar/shell-node 1.1.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 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 (`createNodeOsHost` from
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-34JOE763.js';
2
- import './chunk-VQVAHUAX.js';
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-HXA6OB35.js';
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-VQVAHUAX.js';
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?.({ orbitalName, request, response, ...request.clientId !== void 0 ? { originClientId: request.clientId } : {} }),
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 = (response2) => ({
655
- ok: true,
656
- response: response2,
657
- ...stream ? { streamItems: [...streamItems, { type: "complete", data: response2, timestamp: Date.now() }] } : {}
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-LNEOE5TD.js';
2
- import './chunk-HXA6OB35.js';
3
- import './chunk-VQVAHUAX.js';
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, OsAnchors, OsGrantPort, OsHostPort, TokenEndpointPost, KernelModule, NativeMemoryPersistenceAdapter, ServiceCallContext, StepRequest, PlayedStep, ProgramValidationReport, ProgramEffectName, ProgramEffectOutcome } from '@almadar/shell-runtime';
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-cT9JGJur.js';
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, createNodeOsHost, createNodeTokenPost, credentialsFilePath, directoryKvBackend, fileCredentialRows, installNodeCredentialVault, installNodeHostPorts, loadInstalledKernel, loadKernelModule, loadNativeKernelModule, loadOrCreateDevMasterKey, memoryKvBackend, nativeMemoryOf, processAnchors, programCompose, programEval, programOsGrants, programPrint, programProve, programRead, programResolve, programResolveSchema, programStep, programValidate, resolveNativeAddon, runProgramEffect, workspaceAccessError };
301
- export type { KvBackend, KvBatchOp, KvErrorKind, KvHost, KvNamespace, KvResult, LoadKernelOptions, LoadedKernel, NodeCredentialVaultOptions, NodeOsHostOptions, NodeTokenPostOptions, ProgramCallContext, ProgramComposeOptions, ProgramEvalOptions, ProgramEvalResult, ProgramHostOptions, ProgramOsGrantsReport, ProgramProveReport, ResolvedAddress };
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-34JOE763.js';
2
- export { createProgramHandlers } from './chunk-LNEOE5TD.js';
3
- export { KernelProgram, createNodeOsHost, emitPayload, kernelWorkspaceHost, processAnchors, resolveProgramFile, workspaceBucketFromEnv, workspacesRoot } from './chunk-HXA6OB35.js';
4
- export { DEFAULT_CREDENTIALS_FILE, TokenPostRefusal, createNodeTokenPost, credentialsFilePath, fileCredentialRows, installNodeCredentialVault, installNodeHostPorts } from './chunk-VQVAHUAX.js';
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-cT9JGJur.js';
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';
@@ -1,4 +1,4 @@
1
- export { kernelWorkspaceHost, workspaceBucketFromEnv, workspacesRoot } from './chunk-HXA6OB35.js';
2
- import './chunk-VQVAHUAX.js';
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.0",
3
+ "version": "1.2.0",
4
4
  "orbRelease": {
5
5
  "severity": "normal"
6
6
  },
7
- "description": "Almadar TS shell node runtime pack: the Node os/* and program/* host of the kernel (os families, KernelProgram, workspace, program host).",
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.3.0",
41
- "@almadar/kernel": "^19.0.1",
42
- "@almadar/logger": "^2.3.0",
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.0",
45
- "@almadar/shell-runtime": "^1.1.0"
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",