@telorun/kernel 0.26.1 → 0.27.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.
Files changed (49) hide show
  1. package/dist/cel-handlers.d.ts +14 -0
  2. package/dist/cel-handlers.d.ts.map +1 -0
  3. package/dist/cel-handlers.js +22 -0
  4. package/dist/cel-handlers.js.map +1 -0
  5. package/dist/dependency-injection.d.ts +10 -0
  6. package/dist/dependency-injection.d.ts.map +1 -0
  7. package/dist/dependency-injection.js +95 -0
  8. package/dist/dependency-injection.js.map +1 -0
  9. package/dist/eval-paths.d.ts +10 -0
  10. package/dist/eval-paths.d.ts.map +1 -0
  11. package/dist/eval-paths.js +35 -0
  12. package/dist/eval-paths.js.map +1 -0
  13. package/dist/evaluation-context.d.ts.map +1 -1
  14. package/dist/evaluation-context.js +60 -0
  15. package/dist/evaluation-context.js.map +1 -1
  16. package/dist/index.d.ts +2 -2
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js +2 -2
  19. package/dist/index.js.map +1 -1
  20. package/dist/invoke-dispatch.d.ts +11 -0
  21. package/dist/invoke-dispatch.d.ts.map +1 -0
  22. package/dist/invoke-dispatch.js +37 -0
  23. package/dist/invoke-dispatch.js.map +1 -0
  24. package/dist/kernel.d.ts +0 -31
  25. package/dist/kernel.d.ts.map +1 -1
  26. package/dist/kernel.js +7 -291
  27. package/dist/kernel.js.map +1 -1
  28. package/dist/resource-context.d.ts.map +1 -1
  29. package/dist/resource-context.js +2 -15
  30. package/dist/resource-context.js.map +1 -1
  31. package/dist/schema-compiled-values.d.ts +7 -0
  32. package/dist/schema-compiled-values.d.ts.map +1 -0
  33. package/dist/schema-compiled-values.js +72 -0
  34. package/dist/schema-compiled-values.js.map +1 -0
  35. package/package.json +1 -1
  36. package/src/cel-handlers.ts +24 -0
  37. package/src/dependency-injection.ts +96 -0
  38. package/src/eval-paths.ts +44 -0
  39. package/src/evaluation-context.ts +58 -0
  40. package/src/index.ts +2 -2
  41. package/src/invoke-dispatch.ts +43 -0
  42. package/src/kernel.ts +6 -323
  43. package/src/resource-context.ts +1 -13
  44. package/src/schema-compiled-values.ts +85 -0
  45. package/dist/event-stream.d.ts +0 -45
  46. package/dist/event-stream.d.ts.map +0 -1
  47. package/dist/event-stream.js +0 -98
  48. package/dist/event-stream.js.map +0 -1
  49. package/src/event-stream.ts +0 -121
@@ -0,0 +1,7 @@
1
+ /** Replaces CompiledValue wrappers with schema-appropriate placeholders for schema validation.
2
+ * Template strings were compiled from YAML at load time; this restores a shape
3
+ * that AJV can validate without evaluating expressions. When no schema is
4
+ * supplied every compiled value collapses to `""` (the `default` branch of
5
+ * `placeholderForSchema`), matching the schema-unaware strip. */
6
+ export declare function stripCompiledValues(v: unknown, schema?: Record<string, unknown>, rootSchema?: Record<string, unknown>): unknown;
7
+ //# sourceMappingURL=schema-compiled-values.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-compiled-values.d.ts","sourceRoot":"","sources":["../src/schema-compiled-values.ts"],"names":[],"mappings":"AAyDA;;;;kEAIkE;AAClE,wBAAgB,mBAAmB,CACjC,CAAC,EAAE,OAAO,EACV,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,EACpC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACnC,OAAO,CAkBT"}
@@ -0,0 +1,72 @@
1
+ import { isCompiledValue } from "@telorun/sdk";
2
+ /** Returns a schema-appropriate placeholder value for a CompiledValue field. */
3
+ function placeholderForSchema(schema) {
4
+ if (schema.default !== undefined)
5
+ return schema.default;
6
+ switch (schema.type) {
7
+ case "integer":
8
+ case "number":
9
+ return schema.minimum ?? 0;
10
+ case "boolean":
11
+ return false;
12
+ case "array":
13
+ return [];
14
+ case "object":
15
+ return {};
16
+ default:
17
+ return "";
18
+ }
19
+ }
20
+ /** Resolve a `$ref` (only `#/$defs/...` form) against the root schema. */
21
+ function resolveSchemaRef(schema, root) {
22
+ if (schema.$ref &&
23
+ typeof schema.$ref === "string" &&
24
+ schema.$ref.startsWith("#/$defs/")) {
25
+ const defName = schema.$ref.slice("#/$defs/".length);
26
+ const defs = root.$defs;
27
+ const resolved = defs?.[defName];
28
+ if (resolved)
29
+ return resolved;
30
+ }
31
+ return schema;
32
+ }
33
+ /** Collect property schemas from top-level `properties` and all `oneOf`/`anyOf` sub-schemas. */
34
+ function collectSchemaProperties(schema) {
35
+ const props = {
36
+ ...(schema.properties ?? {}),
37
+ };
38
+ for (const sub of (schema.oneOf ?? schema.anyOf ?? [])) {
39
+ if (sub && typeof sub === "object" && sub.properties) {
40
+ for (const [k, v] of Object.entries(sub.properties)) {
41
+ if (!(k in props))
42
+ props[k] = v;
43
+ }
44
+ }
45
+ }
46
+ return props;
47
+ }
48
+ /** Replaces CompiledValue wrappers with schema-appropriate placeholders for schema validation.
49
+ * Template strings were compiled from YAML at load time; this restores a shape
50
+ * that AJV can validate without evaluating expressions. When no schema is
51
+ * supplied every compiled value collapses to `""` (the `default` branch of
52
+ * `placeholderForSchema`), matching the schema-unaware strip. */
53
+ export function stripCompiledValues(v, schema = {}, rootSchema) {
54
+ const root = rootSchema ?? schema;
55
+ const resolved = resolveSchemaRef(schema, root);
56
+ if (isCompiledValue(v))
57
+ return placeholderForSchema(resolved);
58
+ if (Array.isArray(v)) {
59
+ const itemSchema = resolveSchemaRef((resolved.items ?? {}), root);
60
+ return v.map((item) => stripCompiledValues(item, itemSchema, root));
61
+ }
62
+ if (v !== null && typeof v === "object") {
63
+ const props = collectSchemaProperties(resolved);
64
+ const out = {};
65
+ for (const [k, val] of Object.entries(v)) {
66
+ out[k] = stripCompiledValues(val, props[k] ?? {}, root);
67
+ }
68
+ return out;
69
+ }
70
+ return v;
71
+ }
72
+ //# sourceMappingURL=schema-compiled-values.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-compiled-values.js","sourceRoot":"","sources":["../src/schema-compiled-values.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@telorun/kernel",
3
- "version": "0.26.1",
3
+ "version": "0.27.0",
4
4
  "description": "Telo Runtime - A lightweight, polyglot execution host.",
5
5
  "keywords": [
6
6
  "telo",
@@ -0,0 +1,24 @@
1
+ import { createHash, createHmac } from "node:crypto";
2
+
3
+ /** Node implementations of the host-injected CEL functions (`crypto` / `Buffer`).
4
+ * The kernel wires these into the analyzer + loader; the CLI reuses them for
5
+ * `telo cel eval` so its results match a real run. */
6
+ export const nodeCelHandlers = {
7
+ sha256: (s: string) => createHash("sha256").update(s).digest("hex"),
8
+ md5: (s: string) => createHash("md5").update(s).digest("hex"),
9
+ sha1: (s: string) => createHash("sha1").update(s).digest("hex"),
10
+ sha512: (s: string) => createHash("sha512").update(s).digest("hex"),
11
+ hmac: (algorithm: string, key: string, message: string) =>
12
+ createHmac(algorithm, key).update(message).digest("hex"),
13
+ base64Encode: (s: string) => Buffer.from(s, "utf8").toString("base64"),
14
+ base64Decode: (s: string) => Buffer.from(s, "base64").toString("utf8"),
15
+ // cel-js represents int / uint as BigInt — JSON.stringify throws on BigInts,
16
+ // so coerce them down to Number unconditionally. CEL int is i64 and JS Number
17
+ // is f64, so values outside ±2^53 lose precision; that's accepted behaviour
18
+ // for Telo manifests, which never carry > 2^53 integer values in practice.
19
+ // JSON.stringify returns undefined for top-level undefined / function / symbol
20
+ // — the CEL signature is `json(dyn): string`, so coerce that to "null" rather
21
+ // than break the contract. (CEL `null` already serializes to "null".)
22
+ json: (value: unknown) =>
23
+ JSON.stringify(value, (_k, v) => (typeof v === "bigint" ? Number(v) : v)) ?? "null",
24
+ };
@@ -0,0 +1,96 @@
1
+ import { ResourceInstance, ResourceManifest, RuntimeError } from "@telorun/sdk";
2
+
3
+ /**
4
+ * Walks `resource` following `fieldPath` (dot notation, `[]` = array traversal,
5
+ * `{}` = map traversal). For each leaf value that looks like a {kind, name}
6
+ * reference, calls getInstance(name) and replaces the value in-place with the
7
+ * returned live ResourceInstance. Values where getInstance returns undefined are
8
+ * left unchanged.
9
+ */
10
+ export function injectAtPath(
11
+ resource: ResourceManifest,
12
+ fieldPath: string,
13
+ getInstance: (name: string, alias?: string) => ResourceInstance | undefined,
14
+ ): void {
15
+ const parts = fieldPath.split(".");
16
+
17
+ // Resolve a {kind, name, alias?} reference to its live instance. A non-`Self` alias is a
18
+ // cross-module reference into an import's published exports; if that import hasn't
19
+ // finished init() yet the instance is absent, so we throw to defer this resource to a
20
+ // later pass of the multi-pass init loop (which catches and retries) rather than leaving
21
+ // the ref unresolved. Local refs (no alias) that miss are left for topo ordering / later
22
+ // diagnostics, matching prior behaviour.
23
+ function resolveInto(ref: Record<string, unknown>): ResourceInstance | undefined {
24
+ const alias = typeof ref.alias === "string" ? ref.alias : undefined;
25
+ const instance = getInstance(ref.name as string, alias);
26
+ if (!instance && alias && alias !== "Self") {
27
+ throw new RuntimeError(
28
+ "ERR_CROSS_MODULE_REF_PENDING",
29
+ `Cross-module reference '${alias}.${String(ref.name)}' is not available yet (import not initialized)`,
30
+ );
31
+ }
32
+ return instance;
33
+ }
34
+
35
+ function traverse(obj: unknown, partsLeft: string[]): void {
36
+ if (!obj || typeof obj !== "object" || partsLeft.length === 0) return;
37
+ const [head, ...rest] = partsLeft;
38
+
39
+ // Map iteration: descend into every value of the current object (used for
40
+ // schema fields with `additionalProperties` like `content[mime]`).
41
+ if (head === "{}") {
42
+ const container = obj as Record<string, unknown>;
43
+ for (const mapKey of Object.keys(container)) {
44
+ const elem = container[mapKey];
45
+ if (!elem || typeof elem !== "object") continue;
46
+ if (rest.length === 0) {
47
+ const ref = elem as Record<string, unknown>;
48
+ if (typeof ref.kind === "string" && typeof ref.name === "string") {
49
+ const instance = resolveInto(ref);
50
+ if (instance) container[mapKey] = instance;
51
+ }
52
+ } else {
53
+ traverse(elem, rest);
54
+ }
55
+ }
56
+ return;
57
+ }
58
+
59
+ const isArr = head.endsWith("[]");
60
+ const key = isArr ? head.slice(0, -2) : head;
61
+ const container = obj as Record<string, unknown>;
62
+ const val = container[key];
63
+ if (val == null) return;
64
+
65
+ if (isArr) {
66
+ if (!Array.isArray(val)) return;
67
+ for (let i = 0; i < val.length; i++) {
68
+ const elem = val[i];
69
+ if (!elem || typeof elem !== "object") continue;
70
+ if (rest.length === 0) {
71
+ const ref = elem as Record<string, unknown>;
72
+ if (typeof ref.kind === "string" && typeof ref.name === "string") {
73
+ const instance = resolveInto(ref);
74
+ if (instance) val[i] = instance;
75
+ }
76
+ } else {
77
+ traverse(elem, rest);
78
+ }
79
+ }
80
+ } else {
81
+ if (rest.length === 0) {
82
+ if (val && typeof val === "object" && !Array.isArray(val)) {
83
+ const ref = val as Record<string, unknown>;
84
+ if (typeof ref.kind === "string" && typeof ref.name === "string") {
85
+ const instance = resolveInto(ref);
86
+ if (instance) container[key] = instance;
87
+ }
88
+ }
89
+ } else {
90
+ traverse(val, rest);
91
+ }
92
+ }
93
+ }
94
+
95
+ traverse(resource, parts);
96
+ }
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Traverses a definition schema and collects all paths annotated with `x-telo-eval`.
3
+ * Root-level `x-telo-eval` produces the `"**"` wildcard (expand all fields).
4
+ * Property-level annotations produce the dot-notation path to that property.
5
+ */
6
+ export function buildEvalPaths(schema: Record<string, any>): {
7
+ compile: string[];
8
+ runtime: string[];
9
+ } {
10
+ const compile: string[] = [];
11
+ const runtime: string[] = [];
12
+
13
+ if (schema["x-telo-eval"] === "compile") compile.push("**");
14
+ else if (schema["x-telo-eval"] === "runtime") runtime.push("**");
15
+
16
+ if (schema.properties) {
17
+ for (const [key, propSchema] of Object.entries(schema.properties as Record<string, any>)) {
18
+ collectEvalPathsNode(propSchema, key, compile, runtime);
19
+ }
20
+ }
21
+
22
+ return { compile, runtime };
23
+ }
24
+
25
+ function collectEvalPathsNode(
26
+ node: Record<string, any>,
27
+ path: string,
28
+ compile: string[],
29
+ runtime: string[],
30
+ ): void {
31
+ if (node["x-telo-eval"] === "compile") {
32
+ compile.push(path);
33
+ return;
34
+ }
35
+ if (node["x-telo-eval"] === "runtime") {
36
+ runtime.push(path);
37
+ return;
38
+ }
39
+ if (node.properties) {
40
+ for (const [key, propSchema] of Object.entries(node.properties as Record<string, any>)) {
41
+ collectEvalPathsNode(propSchema, `${path}.${key}`, compile, runtime);
42
+ }
43
+ }
44
+ }
@@ -22,6 +22,53 @@ import { RuntimeError } from "@telorun/sdk";
22
22
 
23
23
  export { resourceKey };
24
24
 
25
+ /** An edge in the resource dependency graph: a resolved `!ref` target. */
26
+ type ResourceRef = { kind: string; name: string; alias?: string };
27
+
28
+ /** A pure resolved reference is a `{ kind, name, alias? }` object and nothing
29
+ * else — the shape `resolveRefSentinels` produces (Phase 2.5). An inline
30
+ * definition (`{ kind, ...config }`) carries extra keys and is its own node, so
31
+ * it is not an edge here; a live `ResourceInstance` (injected at Phase 5) has
32
+ * methods, never this exact key set. */
33
+ function isResolvedRef(value: unknown): value is ResourceRef {
34
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
35
+ const v = value as Record<string, unknown>;
36
+ if (typeof v.kind !== "string" || typeof v.name !== "string") return false;
37
+ return Object.keys(v).every((k) => k === "kind" || k === "name" || k === "alias");
38
+ }
39
+
40
+ /**
41
+ * Walk a resource manifest's config and collect every resolved `{kind, name,
42
+ * alias?}` reference it points at — the outbound edges for the dependency graph.
43
+ * Called at create time, before Phase-5 injection swaps refs for live instances,
44
+ * so the targets are still inspectable plain objects (and there are no instance
45
+ * cycles to guard against). `metadata` is skipped (it holds the resource's own
46
+ * identity, never refs); ref leaves are not descended into. Deduped by alias+name.
47
+ */
48
+ function collectResourceRefs(resource: ResourceManifest): ResourceRef[] {
49
+ const found = new Map<string, ResourceRef>();
50
+ const visit = (value: unknown): void => {
51
+ if (isResolvedRef(value)) {
52
+ const key = `${value.alias ?? ""}::${value.name}`;
53
+ if (!found.has(key)) found.set(key, { kind: value.kind, name: value.name, ...(value.alias ? { alias: value.alias } : {}) });
54
+ return;
55
+ }
56
+ if (Array.isArray(value)) {
57
+ for (const item of value) visit(item);
58
+ } else if (value && typeof value === "object") {
59
+ for (const [k, v] of Object.entries(value as Record<string, unknown>)) {
60
+ if (k === "metadata") continue;
61
+ visit(v);
62
+ }
63
+ }
64
+ };
65
+ for (const [k, v] of Object.entries(resource as Record<string, unknown>)) {
66
+ if (k === "kind" || k === "metadata") continue;
67
+ visit(v);
68
+ }
69
+ return [...found.values()];
70
+ }
71
+
25
72
  /**
26
73
  * Kernel-internal propagation of the current invocation tree's cancellation
27
74
  * scope. NEVER the controller-facing contract — controllers always receive the
@@ -270,6 +317,14 @@ export class EvaluationContext implements IEvaluationContext {
270
317
  if (idx >= 0) this.pendingResources.splice(idx, 1);
271
318
  errors.delete(name);
272
319
  progress = true;
320
+ await this.emit(`${created.resource.kind}.${created.resource.metadata.name}.Created`, {
321
+ resource: {
322
+ kind: created.resource.kind,
323
+ name: created.resource.metadata.name,
324
+ module: created.resource.metadata.module,
325
+ },
326
+ dependencies: collectResourceRefs(created.resource),
327
+ });
273
328
  }
274
329
  } catch (error) {
275
330
  if (error instanceof RuntimeError && (error.code === "ERR_VISIBILITY_DENIED" || error.code === "ERR_FATAL")) throw error;
@@ -297,6 +352,9 @@ export class EvaluationContext implements IEvaluationContext {
297
352
  this.createdInstances.delete(name);
298
353
  errors.delete(name);
299
354
  progress = true;
355
+ await this.emit(`${resource.kind}.${resource.metadata.name}.Initialized`, {
356
+ resource: { kind: resource.kind, name: resource.metadata.name },
357
+ });
300
358
  } catch (error) {
301
359
  if (error instanceof RuntimeError && (error.code === "ERR_VISIBILITY_DENIED" || error.code === "ERR_FATAL")) throw error;
302
360
  errors.set(name, formatErrorForDiagnostic(error));
package/src/index.ts CHANGED
@@ -10,9 +10,9 @@ export {
10
10
  writeManifestCache,
11
11
  } from "./manifest-sources/local-manifest-cache-source.js";
12
12
  export { MemorySource } from "./manifest-sources/memory-source.js";
13
- export { EventStream } from "./event-stream.js";
14
13
  export { ExecutionContext } from "./execution-context.js";
15
- export { Kernel, type KernelOptions, nodeCelHandlers } from "./kernel.js";
14
+ export { Kernel, type KernelOptions } from "./kernel.js";
15
+ export { nodeCelHandlers } from "./cel-handlers.js";
16
16
  export { ModuleContext } from "./module-context.js";
17
17
  export { ManifestRegistry as Registry } from "./registry.js";
18
18
  export { ResourceURI } from "./resource-uri.js";
@@ -0,0 +1,43 @@
1
+ import {
2
+ createCancellationSource,
3
+ RuntimeError,
4
+ type CancellationSource,
5
+ type InvokeOptions,
6
+ } from "@telorun/sdk";
7
+
8
+ /** Translate embedder `InvokeOptions` (external signal / absolute deadline)
9
+ * into a seeded cancellation source, or `undefined` when nothing was requested
10
+ * so the dispatch path stays on its allocation-free sentinel. The caller
11
+ * disposes the returned source once the invoke settles. */
12
+ export function seedInvokeSource(opts?: InvokeOptions): CancellationSource | undefined {
13
+ if (!opts?.signal && opts?.deadlineAt === undefined) return undefined;
14
+ const source = createCancellationSource();
15
+ if (opts.deadlineAt !== undefined) source.cancelAt(opts.deadlineAt);
16
+ const signal = opts.signal;
17
+ if (signal && !signal.aborted) {
18
+ const onAbort = () => source.cancel(String(signal.reason ?? "aborted"));
19
+ signal.addEventListener("abort", onAbort, { once: true });
20
+ // Detach from the (possibly long-lived) external signal on dispose so the
21
+ // listener — which captures the source — doesn't pin it until the signal
22
+ // eventually aborts (or forever if it never does).
23
+ const baseDispose = source.dispose.bind(source);
24
+ source.dispose = () => {
25
+ signal.removeEventListener("abort", onAbort);
26
+ baseDispose();
27
+ };
28
+ } else if (signal?.aborted) {
29
+ source.cancel(String(signal.reason ?? "aborted"));
30
+ }
31
+ return source;
32
+ }
33
+
34
+ export function parseRef(ref: string): { kind: string; name: string } {
35
+ const lastDot = ref.lastIndexOf(".");
36
+ if (lastDot <= 0 || lastDot === ref.length - 1) {
37
+ throw new RuntimeError(
38
+ "ERR_INVALID_VALUE",
39
+ `Invalid resource reference '${ref}': expected '<Kind>.<Name>' (e.g. 'Http.Server.Main') or pass { kind, name } directly.`,
40
+ );
41
+ }
42
+ return { kind: ref.slice(0, lastDot), name: ref.slice(lastDot + 1) };
43
+ }