@sema-agent/mods-kernel 7.55.0 → 7.56.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.
@@ -1,4 +1,4 @@
1
- import { describe, expandModPattern, MOD_SEATS, readOnSide, SEAT_TIER_TABLE, } from "./events.js";
1
+ import { describe, expandOnSide, MOD_SEATS, SEAT_TIER_TABLE, } from "./events.js";
2
2
  import { resolveModBudgetMs } from "./budget.js";
3
3
  export const MODS_INVALID_CODE = "config.mods_invalid";
4
4
  export const MODS_REGISTRATION_REFUSED_CODE = "mods.registration_refused";
@@ -44,13 +44,12 @@ function screenOne(item, seat, side, report) {
44
44
  throw modsInvalid(`${name}: provenance is ${describe(item.provenance)}; it is a label (a string)`);
45
45
  const eventsBound = new Set();
46
46
  for (const p of uses.events)
47
- for (const n of namesOf(p, name, "uses.events"))
47
+ for (const n of namesOf(p, name, "uses.events", side))
48
48
  eventsBound.add(n);
49
49
  const callsBound = new Set();
50
50
  for (const c of uses.calls)
51
- for (const n of namesOf(c, name, "uses.calls"))
52
- if (readOnSide(n, side))
53
- callsBound.add(n);
51
+ for (const n of namesOf(c, name, "uses.calls", side))
52
+ callsBound.add(n);
54
53
  return {
55
54
  registration: item,
56
55
  name,
@@ -94,8 +93,8 @@ function stringList(v, name, field) {
94
93
  }
95
94
  return Object.freeze(out);
96
95
  }
97
- function namesOf(pattern, name, field) {
98
- const expanded = expandModPattern(pattern);
96
+ function namesOf(pattern, name, field, side) {
97
+ const expanded = expandOnSide(pattern, side);
99
98
  if ("refusal" in expanded)
100
99
  throw modsInvalid(`${name}: ${field}: ${expanded.refusal}`);
101
100
  return expanded.names;
@@ -1,4 +1,5 @@
1
1
  import { type ModSeat, type ModTier } from "./events.js";
2
+ export { sealedObjects } from "./receive.js";
2
3
  export type ProxyProbe = (value: object) => boolean;
3
4
  export declare const MODS_VALUE_DEPTH = 1000;
4
5
  export declare const MOD_FAILURE_CAUSES: readonly ["threw", "timeout", "violation", "reentry"];
@@ -17,7 +18,14 @@ export interface ModAnswerer {
17
18
  export declare const NEXT_IN_FLIGHT: Readonly<{
18
19
  inFlight: true;
19
20
  }>;
20
- export type ModAnswerCheck = (answer: unknown, e: ModEventPayload, by: ModAnswerer, below: readonly unknown[]) => string | undefined;
21
+ export interface ModDispatchRun {
22
+ readonly bottomStarted: boolean;
23
+ }
24
+ export type ModAnswerCheck = (answer: unknown, e: ModEventPayload, by: ModAnswerer, below: readonly unknown[], run: ModDispatchRun) => string | undefined;
25
+ export interface ModAnswerRanks {
26
+ readonly of: (answer: unknown) => number;
27
+ readonly top: number;
28
+ }
21
29
  export type ModMatcher = Readonly<Record<string, string | number | boolean>>;
22
30
  export interface PinnedKeyBreak {
23
31
  readonly key: string;
@@ -35,7 +43,7 @@ export declare function pinnedHandOn(pinned: readonly string[], held: ModEventPa
35
43
  } | {
36
44
  readonly violation: string;
37
45
  };
38
- export declare function answerViolation(answer: unknown, check: ModAnswerCheck | undefined, e: ModEventPayload, by: ModAnswerer, below: readonly unknown[]): string | undefined;
46
+ export declare function answerViolation(answer: unknown, check: ModAnswerCheck | undefined, e: ModEventPayload, by: ModAnswerer, below: readonly unknown[], run: ModDispatchRun): string | undefined;
39
47
  export declare function methodAnswerViolation(answer: unknown, _e?: ModEventPayload, _by?: ModAnswerer, below?: readonly unknown[]): string | undefined;
40
48
  export declare function matcherViolation(m: unknown): string | undefined;
41
49
  export declare function matcherMatches(m: ModMatcher | undefined, e: ModEventPayload): boolean;
@@ -49,8 +57,11 @@ export declare function receiveEvent(e: unknown): {
49
57
  } | {
50
58
  readonly refusal: string;
51
59
  };
52
- export declare function answerUpward(v: unknown): unknown;
53
- export declare function receiveAnswer(answer: unknown, engines: ReadonlySet<object>, isProxy?: ProxyProbe): {
60
+ export declare function answerUpward(v: unknown, isProxy?: ProxyProbe): unknown;
61
+ export interface ModHeldObjects {
62
+ has(value: object): boolean;
63
+ }
64
+ export declare function receiveAnswer(answer: unknown, held: ModHeldObjects, isProxy?: ProxyProbe): {
54
65
  readonly answer: unknown;
55
66
  } | {
56
67
  readonly refusal: string;
@@ -1,5 +1,6 @@
1
1
  import { describe } from "./events.js";
2
- import { describeFault, isPlainRecord, MODS_PAYLOAD_MODE, receive } from "./receive.js";
2
+ import { describeFault, isPlainRecord, MODS_PAYLOAD_MODE, receive, sealedObjects } from "./receive.js";
3
+ export { sealedObjects } from "./receive.js";
3
4
  export const MODS_VALUE_DEPTH = 1_000;
4
5
  const HANDED_MODE = Object.freeze({ ...MODS_PAYLOAD_MODE, depth: MODS_VALUE_DEPTH + 1, past: "refuse" });
5
6
  function payloadMode(isProxy) {
@@ -190,13 +191,13 @@ function rehomed(pinned, held, passed, homes, engines) {
190
191
  Object.freeze(to);
191
192
  return twins.get(passed);
192
193
  }
193
- export function answerViolation(answer, check, e, by, below) {
194
+ export function answerViolation(answer, check, e, by, below, run) {
194
195
  if (answer === undefined)
195
196
  return "returned no answer (return next(e) to pass the event on)";
196
197
  if (check === undefined)
197
198
  return undefined;
198
199
  try {
199
- return check(answer, e, by, below);
200
+ return check(answer, e, by, below, run);
200
201
  }
201
202
  catch {
202
203
  return "returned an answer the station cannot read";
@@ -247,50 +248,31 @@ export function receiveEvent(e) {
247
248
  const r = receiveRecord(e, MODS_PAYLOAD_MODE);
248
249
  return "refusal" in r ? { refusal: r.refusal } : r;
249
250
  }
250
- export function answerUpward(v) {
251
- if (typeof v !== "object" || v === null || Object.isFrozen(v))
251
+ export function answerUpward(v, isProxy) {
252
+ if (typeof v !== "object" || v === null)
252
253
  return v;
253
- if (Array.isArray(v) && Object.getPrototypeOf(v) === Array.prototype)
254
- return Object.freeze([...v]);
255
- return isPlainRecord(v) ? Object.freeze({ ...v }) : v;
254
+ const sealed = sealedObjects([v]);
255
+ if (sealed.has(v))
256
+ return v;
257
+ const r = receive(v, payloadMode(isProxy), sealed);
258
+ if (!r.ok)
259
+ throw new TypeError(`the chain's bottom answered ${faultClause(r.fault)}`);
260
+ return r.value;
256
261
  }
257
- export function receiveAnswer(answer, engines, isProxy) {
258
- const r = receive(answer, payloadMode(isProxy), engines);
259
- return r.ok ? { answer: r.value } : { refusal: `answered ${faultClause(r.fault)}` };
262
+ function answerMode(isProxy) {
263
+ return Object.freeze({ ...payloadMode(isProxy), others: "refuse" });
260
264
  }
261
- const DETACHED_MODE = Object.freeze({ accessors: "refuse", depth: Infinity, others: "as-is" });
265
+ export function receiveAnswer(answer, held, isProxy) {
266
+ const r = receive(answer, answerMode(isProxy), held);
267
+ if (r.ok)
268
+ return { answer: r.value };
269
+ const notData = r.fault.kind === "not-data" || r.fault.kind === "cycle";
270
+ return { refusal: `answered ${faultClause(r.fault)}${notData ? " (an answer is data: strings, numbers, booleans, null, plain objects and arrays)" : ""}` };
271
+ }
272
+ const DETACHED_MODE = Object.freeze({ accessors: "refuse", depth: Infinity, others: "as-is", leaves: "cloned" });
262
273
  export function detachedCopy(e) {
263
274
  const r = receive(e, DETACHED_MODE);
264
275
  if (!r.ok)
265
276
  throw new Error(`the observer's copy of the event could not be made: ${describeFault(r.fault)}`);
266
- const copy = r.value;
267
- const clones = new Map();
268
- const walked = new Set([copy]);
269
- const stack = [copy];
270
- while (stack.length > 0) {
271
- const node = stack.pop();
272
- for (const k of Object.keys(node)) {
273
- const v = node[k];
274
- if (typeof v !== "object" || v === null)
275
- continue;
276
- if (isPlainRecord(v) || (Array.isArray(v) && Object.getPrototypeOf(v) === Array.prototype)) {
277
- if (!walked.has(v)) {
278
- walked.add(v);
279
- stack.push(v);
280
- }
281
- continue;
282
- }
283
- if (!clones.has(v)) {
284
- let own = v;
285
- try {
286
- own = structuredClone(v);
287
- }
288
- catch {
289
- }
290
- clones.set(v, own);
291
- }
292
- Object.defineProperty(node, k, { value: clones.get(v), enumerable: true, writable: true, configurable: true });
293
- }
294
- }
295
- return copy;
277
+ return r.value;
296
278
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sema-agent/mods-kernel",
3
- "version": "7.55.0",
3
+ "version": "7.56.0",
4
4
  "private": false,
5
5
  "description": "The sema mods kernel: one extension bus (registration, admission, chain, failure and budget law) shared by the engine and the shell. Zero dependencies.",
6
6
  "type": "module",