@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.
- package/README.md +6 -4
- package/dist/dispatch.d.ts +7 -2
- package/dist/dispatch.js +140 -69
- package/dist/events.d.ts +12 -2
- package/dist/events.js +66 -42
- package/dist/index.d.ts +4 -4
- package/dist/index.js +2 -2
- package/dist/receive.d.ts +8 -1
- package/dist/receive.js +290 -17
- package/dist/registration.d.ts +24 -0
- package/dist/registration.js +6 -7
- package/dist/site-rules.d.ts +15 -4
- package/dist/site-rules.js +24 -42
- package/package.json +1 -1
package/dist/events.js
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
export const KERNEL_CONTRACT_VERSION =
|
|
1
|
+
export const KERNEL_CONTRACT_VERSION = 3;
|
|
2
2
|
export const MOD_TIERS = Object.freeze(["prepend", "user", "append", "builtin", "core"]);
|
|
3
3
|
export const MOD_SEATS = Object.freeze(["deployment", "task"]);
|
|
4
4
|
export const MOD_EVENT_SIDES = Object.freeze(["engine", "surface", "both"]);
|
|
5
|
-
export const MOD_FAILURE_ANSWERS = Object.freeze(["refuse", "skip"]);
|
|
5
|
+
export const MOD_FAILURE_ANSWERS = Object.freeze(["refuse", "skip", "refuse_until_run"]);
|
|
6
|
+
export function failureRefuses(failure) {
|
|
7
|
+
return failure !== "skip";
|
|
8
|
+
}
|
|
6
9
|
export const MOD_ABORT_POSTURES = Object.freeze(["immediate", "grace", "caller"]);
|
|
7
10
|
export const NEXT_TO_TABLE = Object.freeze({
|
|
8
11
|
prepend: Object.freeze(["append", "builtin", "core"]),
|
|
@@ -27,10 +30,19 @@ export const SEAT_TIER_TABLE = Object.freeze({
|
|
|
27
30
|
deployment: Object.freeze({ declared: "required", tiers: Object.freeze(["prepend", "user", "append"]) }),
|
|
28
31
|
task: Object.freeze({ declared: "optional", tiers: Object.freeze(["user"]) }),
|
|
29
32
|
});
|
|
30
|
-
const station = (failure, abort, pinned = []) => Object.freeze({
|
|
33
|
+
const station = (failure, abort, pinned = [], more = {}) => Object.freeze({
|
|
34
|
+
failure,
|
|
35
|
+
abort,
|
|
36
|
+
pinned: Object.freeze([...pinned]),
|
|
37
|
+
...(more.call === true ? { call: Object.freeze({ pausesCallerBudget: true }) } : {}),
|
|
38
|
+
...(more.budgetMs !== undefined ? { budgetMs: more.budgetMs } : {}),
|
|
39
|
+
});
|
|
31
40
|
const method = (pausesCallerBudget) => Object.freeze({ failure: "skip", abort: "caller", pinned: Object.freeze([]), method: Object.freeze({ pausesCallerBudget }) });
|
|
32
41
|
const engine = (s) => Object.freeze(s === undefined ? { side: "engine" } : { side: "engine", station: s });
|
|
33
|
-
const surface = Object.freeze({ side: "surface" });
|
|
42
|
+
const surface = (s) => Object.freeze(s === undefined ? { side: "surface" } : { side: "surface", station: s });
|
|
43
|
+
const RENDER_PINNED = ["surface", "component", "requestId", "viewport"];
|
|
44
|
+
const ELEMENT_PINNED = ["plugin", "element", "component", "requestId", "surface"];
|
|
45
|
+
const PROMPT_EDIT_BUDGET_MS = 50;
|
|
34
46
|
export const MOD_EVENT_TABLE = Object.freeze({
|
|
35
47
|
"classic.PreToolUse": engine(station("refuse", "immediate", ["tool", "tool_use_id", "agentId", "input"])),
|
|
36
48
|
"classic.PostToolUse": engine(station("skip", "grace")),
|
|
@@ -65,34 +77,34 @@ export const MOD_EVENT_TABLE = Object.freeze({
|
|
|
65
77
|
"classic.FileChanged": engine(),
|
|
66
78
|
"classic.DirectoryAdded": engine(),
|
|
67
79
|
"classic.MessageDisplay": engine(),
|
|
68
|
-
"tool.call": engine(),
|
|
80
|
+
"tool.call": engine(station("refuse_until_run", "immediate", ["tool", "tool_use_id", "agentId", "input"], { call: true })),
|
|
69
81
|
"tool.check": engine(station("refuse", "immediate", ["tool", "input", "tool_use_id", "agentId", "ceiling"])),
|
|
70
|
-
"ui.render": surface,
|
|
71
|
-
"ui.resolve": surface,
|
|
72
|
-
"ui.press": surface,
|
|
73
|
-
"ui.input": surface,
|
|
74
|
-
"ui.select": surface,
|
|
75
|
-
"ui.message": surface,
|
|
76
|
-
"ui.fault": surface,
|
|
77
|
-
"ui.scroll": surface,
|
|
78
|
-
"ui.focus": surface,
|
|
82
|
+
"ui.render": surface(station("skip", "grace", RENDER_PINNED)),
|
|
83
|
+
"ui.resolve": surface(station("skip", "grace", ["surface", "component"])),
|
|
84
|
+
"ui.press": surface(station("skip", "grace", ELEMENT_PINNED)),
|
|
85
|
+
"ui.input": surface(station("skip", "grace", ELEMENT_PINNED)),
|
|
86
|
+
"ui.select": surface(station("skip", "grace", ELEMENT_PINNED)),
|
|
87
|
+
"ui.message": surface(),
|
|
88
|
+
"ui.fault": surface(),
|
|
89
|
+
"ui.scroll": surface(station("skip", "grace", ["component", "requestId", "by", "bodyRows", "contentRows", "origin", "pointer"], { call: true })),
|
|
90
|
+
"ui.focus": surface(station("skip", "grace", ["component", "requestId", "plugin", "origin", "element"], { call: true })),
|
|
79
91
|
"agent.offer": engine(),
|
|
80
92
|
"agent.spawn": engine(),
|
|
81
93
|
"prompt.submit": engine(),
|
|
82
|
-
"prompt.fill": surface,
|
|
83
|
-
"prompt.suggest": surface,
|
|
84
|
-
"prompt.edit": surface,
|
|
85
|
-
"prompt.autocomplete": surface,
|
|
94
|
+
"prompt.fill": surface(station("skip", "grace", ["origin", "mode"], { call: true })),
|
|
95
|
+
"prompt.suggest": surface(station("skip", "grace", ["origin"], { call: true })),
|
|
96
|
+
"prompt.edit": surface(station("skip", "grace", ["origin", "key"], { budgetMs: PROMPT_EDIT_BUDGET_MS })),
|
|
97
|
+
"prompt.autocomplete": surface(),
|
|
86
98
|
"prompt.section": engine(station("skip", "grace", ["name", "key", "mountedTools"])),
|
|
87
99
|
"prompt.context": engine(),
|
|
88
100
|
"prompt.attachment": engine(),
|
|
89
|
-
"prompt.mention":
|
|
101
|
+
"prompt.mention": engine(station("refuse", "immediate", ["mention", "agentId"])),
|
|
90
102
|
"prompt.compose": engine(station("skip", "grace", ["model", "catalog", "selectors"])),
|
|
91
103
|
"tool.describe": engine(),
|
|
92
|
-
"command.run": surface,
|
|
93
|
-
"command.describe": surface,
|
|
94
|
-
"config.set": surface,
|
|
95
|
-
"config.describe": surface,
|
|
104
|
+
"command.run": surface(station("skip", "grace", ["command", "presentation", "origin"], { call: true })),
|
|
105
|
+
"command.describe": surface(station("skip", "grace", ["command", "immediate", "provider"])),
|
|
106
|
+
"config.set": surface(station("refuse", "immediate", ["key", "previous", "provider", "origin"], { call: true })),
|
|
107
|
+
"config.describe": surface(station("skip", "grace", ["key", "provider"])),
|
|
96
108
|
"telemetry.log": engine(),
|
|
97
109
|
"telemetry.mark": engine(),
|
|
98
110
|
"skill.prompt": engine(),
|
|
@@ -106,7 +118,7 @@ export const MOD_EVENT_TABLE = Object.freeze({
|
|
|
106
118
|
"session.detach": engine(),
|
|
107
119
|
"session.measure": engine(),
|
|
108
120
|
"session.end": engine(),
|
|
109
|
-
"plugin.register": Object.freeze({ side: "both", station: station("
|
|
121
|
+
"plugin.register": Object.freeze({ side: "both", station: station("refuse", "immediate", ["name", "seat", "tier", "uses"]) }),
|
|
110
122
|
"turn.start": engine(),
|
|
111
123
|
"turn.step": engine(),
|
|
112
124
|
"turn.complete": engine(),
|
|
@@ -114,8 +126,8 @@ export const MOD_EVENT_TABLE = Object.freeze({
|
|
|
114
126
|
"model.complete": engine(method(true)),
|
|
115
127
|
"model.classify": engine(),
|
|
116
128
|
"model.fork": engine(),
|
|
117
|
-
"audio.play": surface,
|
|
118
|
-
"audio.speak": surface,
|
|
129
|
+
"audio.play": surface(),
|
|
130
|
+
"audio.speak": surface(),
|
|
119
131
|
"mcp.call": engine(),
|
|
120
132
|
"mcp.connect": engine(),
|
|
121
133
|
"session.cwd": engine(method(true)),
|
|
@@ -131,27 +143,27 @@ export const MOD_EVENT_TABLE = Object.freeze({
|
|
|
131
143
|
"session.usage": engine(),
|
|
132
144
|
"session.version": engine(),
|
|
133
145
|
"turn.abort": engine(),
|
|
134
|
-
"prompt.read": surface,
|
|
146
|
+
"prompt.read": surface(method(true)),
|
|
135
147
|
"flag.value": engine(),
|
|
136
148
|
"tool.list": engine(method(true)),
|
|
137
149
|
"tool.register": engine(),
|
|
138
|
-
"command.list": surface,
|
|
139
|
-
"command.register": surface,
|
|
140
|
-
"config.list": surface,
|
|
150
|
+
"command.list": surface(method(true)),
|
|
151
|
+
"command.register": surface(method(true)),
|
|
152
|
+
"config.list": surface(method(true)),
|
|
141
153
|
"agent.list": engine(method(true)),
|
|
142
154
|
"agent.register": engine(),
|
|
143
|
-
"ui.toast": surface,
|
|
144
|
-
"ui.status": surface,
|
|
145
|
-
"ui.log": surface,
|
|
146
|
-
"ui.notice": surface,
|
|
147
|
-
"ui.invalidate": surface,
|
|
148
|
-
"ui.open": surface,
|
|
149
|
-
"ui.close": surface,
|
|
150
|
-
"ui.panes": surface,
|
|
151
|
-
"ui.selection": surface,
|
|
152
|
-
"ui.copy": surface,
|
|
153
|
-
"ui.notify": surface,
|
|
154
|
-
"ui.blit": surface,
|
|
155
|
+
"ui.toast": surface(method(true)),
|
|
156
|
+
"ui.status": surface(),
|
|
157
|
+
"ui.log": surface(method(true)),
|
|
158
|
+
"ui.notice": surface(method(true)),
|
|
159
|
+
"ui.invalidate": surface(method(true)),
|
|
160
|
+
"ui.open": surface(),
|
|
161
|
+
"ui.close": surface(),
|
|
162
|
+
"ui.panes": surface(),
|
|
163
|
+
"ui.selection": surface(method(true)),
|
|
164
|
+
"ui.copy": surface(method(true)),
|
|
165
|
+
"ui.notify": surface(),
|
|
166
|
+
"ui.blit": surface(),
|
|
155
167
|
"fs.read": engine(),
|
|
156
168
|
"fs.write": engine(),
|
|
157
169
|
"fs.list": engine(),
|
|
@@ -199,6 +211,18 @@ export function expandModPattern(pattern) {
|
|
|
199
211
|
}
|
|
200
212
|
return isModEventName(pattern) ? { names: [pattern] } : { refusal: `"${pattern}" is not an event` };
|
|
201
213
|
}
|
|
214
|
+
export function expandOnSide(pattern, side) {
|
|
215
|
+
const expanded = expandModPattern(pattern);
|
|
216
|
+
if ("refusal" in expanded)
|
|
217
|
+
return expanded;
|
|
218
|
+
const own = expanded.names.filter((n) => readOnSide(n, side));
|
|
219
|
+
if (own.length > 0)
|
|
220
|
+
return { names: own };
|
|
221
|
+
const named = String(pattern);
|
|
222
|
+
return named.endsWith(".*")
|
|
223
|
+
? { refusal: `"${named}" selects no event the ${side} bus reads (${expanded.names.length === 1 ? "its one name is" : "its names are"} the ${MOD_EVENT_TABLE[expanded.names[0]].side} side's)` }
|
|
224
|
+
: { refusal: `"${named}" is a ${MOD_EVENT_TABLE[expanded.names[0]].side} event, read on that side's bus only — never on the ${side} bus` };
|
|
225
|
+
}
|
|
202
226
|
export function describe(value) {
|
|
203
227
|
if (typeof value === "string")
|
|
204
228
|
return `"${value}"`;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { KERNEL_CONTRACT_VERSION, MOD_TIERS, MOD_SEATS, MOD_EVENT_SIDES, MOD_FAILURE_ANSWERS, MOD_ABORT_POSTURES, NEXT_TO_TABLE, SEAT_TIER_TABLE, MOD_EVENT_TABLE, nextToRefusal, expandModPattern, isModEventName, stationOn, readOnSide, type ModTier, type ModRegistrationTier, type ModSeat, type ModEventSide, type ModBusSide, type ModFailureAnswer, type ModAbortPosture, type ModStation, type ModEventRow, type ModEventName, } from "./events.js";
|
|
1
|
+
export { KERNEL_CONTRACT_VERSION, MOD_TIERS, MOD_SEATS, MOD_EVENT_SIDES, MOD_FAILURE_ANSWERS, MOD_ABORT_POSTURES, NEXT_TO_TABLE, SEAT_TIER_TABLE, MOD_EVENT_TABLE, nextToRefusal, expandModPattern, expandOnSide, failureRefuses, isModEventName, stationOn, readOnSide, type ModTier, type ModRegistrationTier, type ModSeat, type ModEventSide, type ModBusSide, type ModFailureAnswer, type ModAbortPosture, type ModStation, type ModEventRow, type ModEventName, } from "./events.js";
|
|
2
2
|
export { DEFAULT_MOD_BUDGET_MS, CATCH_BUDGET_MS, RUNAWAY_AFTER_MS, POST_ABORT_GRACE_MS, MAX_TIMER_MS, resolveModBudgetMs, type ModBudgetReading, } from "./budget.js";
|
|
3
|
-
export { MOD_FAILURE_CAUSES, type ModFailureCause, type ModEventPayload, type ModAnswerCheck, type ModAnswerer, type ModMatcher, type ModSkip } from "./site-rules.js";
|
|
4
|
-
export { ENGINE_ORIGIN, MODS_INVALID_CODE, MODS_REGISTRATION_REFUSED_CODE, MOD_TRACE_OUTCOMES, type ModTraceOutcome, type ModUses, type ModOrigin, type ModPluginFacts, type ModDollarBase, type ModTraceEntry, type ModCaughtError, type ModNext, type ModHandler, type ModHandlerOptions, type On, type ModRegistration, type ModAdmissionRecord, type ModSeats, } from "./registration.js";
|
|
5
|
-
export { admitMods, type ModFrame, type ModBottomContext, type ModMethodBottom, type ModMethodSeat, type ModMethodBottoms, type ModDispatchOutcome, type ModDispatchOptions, type ModBus, type ModMountedHandler, type ModBusInput, } from "./dispatch.js";
|
|
3
|
+
export { MOD_FAILURE_CAUSES, type ModFailureCause, type ModEventPayload, type ModAnswerCheck, type ModAnswerRanks, type ModDispatchRun, type ModAnswerer, type ModMatcher, type ModSkip, } from "./site-rules.js";
|
|
4
|
+
export { ENGINE_ORIGIN, MODS_INVALID_CODE, MODS_REGISTRATION_REFUSED_CODE, MOD_TRACE_OUTCOMES, type ModTraceOutcome, type ModUses, type ModOrigin, type ModPluginFacts, type ModDollarBase, type ModTraceEntry, type ModCaughtError, type ModNext, type ModHandler, type ModHandlerOptions, type ModEventPair, type ModEventMap, type ModTypedNext, type ModTypedHandler, type On, type MappedOn, type ModRegistration, type ModAdmissionRecord, type ModSeats, } from "./registration.js";
|
|
5
|
+
export { admitMods, type ModFrame, type ModBottomContext, type ModMethodBottom, type ModMethodSeat, type ModMethodBottoms, type ModCallEntry, type ModCallEntries, type ModDispatchOutcome, type ModDispatchOptions, type ModBus, type ModMountedHandler, type ModBusInput, } from "./dispatch.js";
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { KERNEL_CONTRACT_VERSION, MOD_TIERS, MOD_SEATS, MOD_EVENT_SIDES, MOD_FAILURE_ANSWERS, MOD_ABORT_POSTURES, NEXT_TO_TABLE, SEAT_TIER_TABLE, MOD_EVENT_TABLE, nextToRefusal, expandModPattern, isModEventName, stationOn, readOnSide, } from "./events.js";
|
|
1
|
+
export { KERNEL_CONTRACT_VERSION, MOD_TIERS, MOD_SEATS, MOD_EVENT_SIDES, MOD_FAILURE_ANSWERS, MOD_ABORT_POSTURES, NEXT_TO_TABLE, SEAT_TIER_TABLE, MOD_EVENT_TABLE, nextToRefusal, expandModPattern, expandOnSide, failureRefuses, isModEventName, stationOn, readOnSide, } from "./events.js";
|
|
2
2
|
export { DEFAULT_MOD_BUDGET_MS, CATCH_BUDGET_MS, RUNAWAY_AFTER_MS, POST_ABORT_GRACE_MS, MAX_TIMER_MS, resolveModBudgetMs, } from "./budget.js";
|
|
3
|
-
export { MOD_FAILURE_CAUSES } from "./site-rules.js";
|
|
3
|
+
export { MOD_FAILURE_CAUSES, } from "./site-rules.js";
|
|
4
4
|
export { ENGINE_ORIGIN, MODS_INVALID_CODE, MODS_REGISTRATION_REFUSED_CODE, MOD_TRACE_OUTCOMES, } from "./registration.js";
|
|
5
5
|
export { admitMods, } from "./dispatch.js";
|
package/dist/receive.d.ts
CHANGED
|
@@ -5,6 +5,8 @@ export interface ReceiptMode {
|
|
|
5
5
|
readonly past?: "refuse";
|
|
6
6
|
readonly contain?: true;
|
|
7
7
|
readonly freeze?: boolean;
|
|
8
|
+
readonly wire?: true;
|
|
9
|
+
readonly leaves?: "cloned";
|
|
8
10
|
readonly isProxy?: (value: object) => boolean;
|
|
9
11
|
}
|
|
10
12
|
export declare const RECEIPT_FAULTS: readonly ["proxy", "accessor", "hidden", "getter-threw", "prototype-moved", "not-data", "cycle", "too-deep", "uncopyable"];
|
|
@@ -22,6 +24,11 @@ export type Receipt = {
|
|
|
22
24
|
readonly fault: ReceiptFault;
|
|
23
25
|
};
|
|
24
26
|
export declare function isPlainRecord(v: unknown): v is Record<string, unknown>;
|
|
25
|
-
export declare function
|
|
27
|
+
export declare function dataMember(value: unknown): PropertyDescriptor;
|
|
28
|
+
export declare function appendOwn<T>(list: T[], value: T): void;
|
|
29
|
+
export declare function receive(value: unknown, mode: ReceiptMode, held?: {
|
|
30
|
+
has(value: object): boolean;
|
|
31
|
+
}): Receipt;
|
|
26
32
|
export declare const MODS_PAYLOAD_MODE: ReceiptMode;
|
|
27
33
|
export declare function describeFault(fault: ReceiptFault): string;
|
|
34
|
+
export declare function sealedObjects(roots: readonly unknown[]): ReadonlySet<object>;
|
package/dist/receive.js
CHANGED
|
@@ -5,25 +5,134 @@ export function isPlainRecord(v) {
|
|
|
5
5
|
const proto = Object.getPrototypeOf(v);
|
|
6
6
|
return proto === Object.prototype || proto === null;
|
|
7
7
|
}
|
|
8
|
+
function isIndexName(k) {
|
|
9
|
+
const n = Number(k);
|
|
10
|
+
return String(n >>> 0) === k && n !== 4_294_967_295;
|
|
11
|
+
}
|
|
8
12
|
function isOrdinaryArray(v) {
|
|
9
13
|
return Array.isArray(v) && Object.getPrototypeOf(v) === Array.prototype;
|
|
10
14
|
}
|
|
15
|
+
const DATE_TO_JSON = Date.prototype.toJSON;
|
|
16
|
+
const DATE_TIME = Date.prototype.getTime;
|
|
17
|
+
const DATE_ISO = Date.prototype.toISOString;
|
|
18
|
+
const TYPED_ARRAY_PROTO = Object.getPrototypeOf(Uint8Array.prototype);
|
|
19
|
+
const TYPED_ARRAY_NAME = Object.getOwnPropertyDescriptor(TYPED_ARRAY_PROTO, Symbol.toStringTag).get;
|
|
20
|
+
const TYPED_ARRAY_LENGTH = Object.getOwnPropertyDescriptor(TYPED_ARRAY_PROTO, "length").get;
|
|
21
|
+
const TYPED_ARRAY_SET = TYPED_ARRAY_PROTO.set;
|
|
22
|
+
const FLOAT64_ARRAY = Float64Array;
|
|
23
|
+
const ARRAY = Array;
|
|
24
|
+
const ARRAY_PROTOTYPE = Array.prototype;
|
|
25
|
+
const ARRAY_SLICE = Array.prototype.slice;
|
|
26
|
+
const OBJECT_PROTOTYPE = Object.prototype;
|
|
27
|
+
const HAS_OWN = Object.hasOwn;
|
|
28
|
+
const OWN_KEYS_ENUMERABLE = Object.keys;
|
|
29
|
+
const SET_PROTOTYPE = Object.setPrototypeOf;
|
|
30
|
+
const DEFINE = Reflect.defineProperty;
|
|
31
|
+
export function dataMember(value) {
|
|
32
|
+
const d = Object.create(null);
|
|
33
|
+
d.value = value;
|
|
34
|
+
d.writable = true;
|
|
35
|
+
d.enumerable = true;
|
|
36
|
+
d.configurable = true;
|
|
37
|
+
return d;
|
|
38
|
+
}
|
|
39
|
+
export function appendOwn(list, value) {
|
|
40
|
+
DEFINE(list, list.length, dataMember(value));
|
|
41
|
+
}
|
|
42
|
+
function listOnNoPrototype(list = []) {
|
|
43
|
+
return SET_PROTOTYPE(list, null);
|
|
44
|
+
}
|
|
45
|
+
const recordOnNoPrototype = () => Object.create(null);
|
|
46
|
+
function typedArrayIndices(v, name, length) {
|
|
47
|
+
const out = recordOnNoPrototype();
|
|
48
|
+
if (name === "BigInt64Array" || name === "BigUint64Array")
|
|
49
|
+
return out;
|
|
50
|
+
const copy = new FLOAT64_ARRAY(length);
|
|
51
|
+
Reflect.apply(TYPED_ARRAY_SET, copy, [v]);
|
|
52
|
+
for (let i = 0; i < length; i++)
|
|
53
|
+
out[i] = copy[i];
|
|
54
|
+
return out;
|
|
55
|
+
}
|
|
56
|
+
function readOwnMember(v, key, cell) {
|
|
57
|
+
try {
|
|
58
|
+
cell.value = v[key];
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
const NO_MEMBERS = Object.freeze(Object.create(null));
|
|
66
|
+
const NO_KEYS = Object.freeze([]);
|
|
67
|
+
function denseList(v, length) {
|
|
68
|
+
let holes = 0;
|
|
69
|
+
for (let i = 0; i < length; i++)
|
|
70
|
+
if (!HAS_OWN(v, i) && ++holes > 64 && holes * 2 > i + 1)
|
|
71
|
+
return false;
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
11
74
|
export function receive(value, mode, held) {
|
|
12
75
|
const seen = new Map();
|
|
13
|
-
const path =
|
|
76
|
+
const path = listOnNoPrototype();
|
|
77
|
+
const pathTo = (below) => {
|
|
78
|
+
const names = Reflect.apply(ARRAY_SLICE, path, []);
|
|
79
|
+
if (below !== undefined)
|
|
80
|
+
appendOwn(names, below);
|
|
81
|
+
return Object.freeze(names);
|
|
82
|
+
};
|
|
14
83
|
const open = new Set();
|
|
15
84
|
const heights = new Map();
|
|
16
85
|
const faults = [];
|
|
17
86
|
const refusedAt = new Map();
|
|
18
|
-
const stack =
|
|
87
|
+
const stack = listOnNoPrototype();
|
|
19
88
|
const refusals = new Set();
|
|
20
89
|
const refuse = (kind) => {
|
|
21
|
-
const fault = Object.freeze({ kind, path:
|
|
90
|
+
const fault = Object.freeze({ kind, path: pathTo() });
|
|
22
91
|
refusals.add(fault);
|
|
23
92
|
throw fault;
|
|
24
93
|
};
|
|
25
|
-
const faultOf = (err) => typeof err === "object" && err !== null && refusals.has(err) ? err : Object.freeze({ kind: "uncopyable", path:
|
|
26
|
-
const
|
|
94
|
+
const faultOf = (err) => typeof err === "object" && err !== null && refusals.has(err) ? err : Object.freeze({ kind: "uncopyable", path: pathTo() });
|
|
95
|
+
const clones = new Map();
|
|
96
|
+
const leafOf = (v) => {
|
|
97
|
+
if (!clones.has(v)) {
|
|
98
|
+
let own = v;
|
|
99
|
+
try {
|
|
100
|
+
if (typeof v !== "function")
|
|
101
|
+
own = structuredClone(v);
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
}
|
|
105
|
+
clones.set(v, own);
|
|
106
|
+
}
|
|
107
|
+
return clones.get(v);
|
|
108
|
+
};
|
|
109
|
+
const other = (v, kind) => {
|
|
110
|
+
if (mode.others !== "as-is")
|
|
111
|
+
return refuse(kind);
|
|
112
|
+
return mode.leaves !== undefined && kind === "not-data" && v !== null && (typeof v === "object" || typeof v === "function") ? leafOf(v) : v;
|
|
113
|
+
};
|
|
114
|
+
const wireForm = (v) => {
|
|
115
|
+
for (let o = v; o !== null; o = Object.getPrototypeOf(o)) {
|
|
116
|
+
if (o !== v && mode.isProxy?.(o) === true)
|
|
117
|
+
return refuse("proxy");
|
|
118
|
+
const d = Object.getOwnPropertyDescriptor(o, "toJSON");
|
|
119
|
+
if (d === undefined)
|
|
120
|
+
continue;
|
|
121
|
+
if (!Object.hasOwn(d, "value"))
|
|
122
|
+
return refuse("not-data");
|
|
123
|
+
if (typeof d.value !== "function")
|
|
124
|
+
return v;
|
|
125
|
+
if (d.value !== DATE_TO_JSON)
|
|
126
|
+
return refuse("not-data");
|
|
127
|
+
try {
|
|
128
|
+
return Number.isFinite(Reflect.apply(DATE_TIME, v, [])) ? Reflect.apply(DATE_ISO, v, []) : null;
|
|
129
|
+
}
|
|
130
|
+
catch {
|
|
131
|
+
return refuse("not-data");
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return v;
|
|
135
|
+
};
|
|
27
136
|
const refuseContainer = (v, kind) => {
|
|
28
137
|
if (mode.contain === true) {
|
|
29
138
|
refusedAt.set(v, kind);
|
|
@@ -74,12 +183,44 @@ export function receive(value, mode, held) {
|
|
|
74
183
|
return other(v, "too-deep");
|
|
75
184
|
if (mode.isProxy?.(v) === true)
|
|
76
185
|
return refuse("proxy");
|
|
186
|
+
if (mode.wire === true) {
|
|
187
|
+
const form = wireForm(v);
|
|
188
|
+
if (form !== v)
|
|
189
|
+
return form;
|
|
190
|
+
const name = Reflect.apply(TYPED_ARRAY_NAME, v, []);
|
|
191
|
+
if (typeof name === "string") {
|
|
192
|
+
const length = Reflect.apply(TYPED_ARRAY_LENGTH, v, []);
|
|
193
|
+
let out;
|
|
194
|
+
try {
|
|
195
|
+
out = typedArrayIndices(v, name, length);
|
|
196
|
+
}
|
|
197
|
+
catch {
|
|
198
|
+
out = recordOnNoPrototype();
|
|
199
|
+
}
|
|
200
|
+
const captured = Object.create(null);
|
|
201
|
+
const names = Object.keys(v);
|
|
202
|
+
let first = names.length;
|
|
203
|
+
while (first > 0 && !isIndexName(names[first - 1]))
|
|
204
|
+
first--;
|
|
205
|
+
for (const k of names.slice(first)) {
|
|
206
|
+
const d = Object.getOwnPropertyDescriptor(v, k);
|
|
207
|
+
if (d !== undefined)
|
|
208
|
+
captured[k] = d;
|
|
209
|
+
}
|
|
210
|
+
seen.set(v, out);
|
|
211
|
+
open.add(v);
|
|
212
|
+
stack[stack.length] = { v, out, list: false, proto: Object.getPrototypeOf(v), captured, keys: Object.keys(captured), level, next: 0, height: 1, key: "", member: undefined };
|
|
213
|
+
return out;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
77
216
|
const list = isOrdinaryArray(v) || (mode.others === "copy" && Array.isArray(v));
|
|
78
217
|
if (!list && !isPlainRecord(v) && mode.others !== "copy")
|
|
79
218
|
return other(v, "not-data");
|
|
219
|
+
if (mode.wire === true && (!list || denseList(v, v.length)))
|
|
220
|
+
return readInOnePass(v, list, level);
|
|
80
221
|
const proto = Object.getPrototypeOf(v);
|
|
81
222
|
const captured = Object.getOwnPropertyDescriptors(v);
|
|
82
|
-
const out = list ?
|
|
223
|
+
const out = list ? listOnNoPrototype() : recordOnNoPrototype();
|
|
83
224
|
seen.set(v, out);
|
|
84
225
|
open.add(v);
|
|
85
226
|
if (mode.accessors === "refuse") {
|
|
@@ -87,15 +228,64 @@ export function receive(value, mode, held) {
|
|
|
87
228
|
if (symbols.length > 0 && mode.contain !== true)
|
|
88
229
|
refuseContainer(v, "hidden");
|
|
89
230
|
for (const s of symbols)
|
|
90
|
-
faults
|
|
231
|
+
appendOwn(faults, Object.freeze({ kind: "hidden", path: pathTo(String(s)) }));
|
|
91
232
|
}
|
|
92
|
-
|
|
233
|
+
const names = Object.getOwnPropertyNames(captured);
|
|
234
|
+
const keys = mode.wire !== true ? names : names.filter((k) => (list ? isIndexName(k) : captured[k].enumerable === true));
|
|
235
|
+
stack[stack.length] = { v, out, list, proto, captured, keys, level, next: 0, height: 1, key: "", member: undefined };
|
|
93
236
|
return out;
|
|
94
237
|
};
|
|
238
|
+
const readInOnePass = (v, list, level) => {
|
|
239
|
+
const names = list ? undefined : OWN_KEYS_ENUMERABLE(v);
|
|
240
|
+
const count = list ? v.length : names.length;
|
|
241
|
+
const out = (list ? listOnNoPrototype(new ARRAY(count)) : recordOnNoPrototype());
|
|
242
|
+
seen.set(v, out);
|
|
243
|
+
open.add(v);
|
|
244
|
+
const f = { v, out, list, proto: Object.getPrototypeOf(v), captured: NO_MEMBERS, keys: NO_KEYS, live: { names, count, pending: undefined }, level, next: 0, height: 1, key: "", member: undefined };
|
|
245
|
+
f.live.pending = primitivesUpToAnObject(f);
|
|
246
|
+
if (f.live.pending === undefined)
|
|
247
|
+
return finish(f);
|
|
248
|
+
stack[stack.length] = f;
|
|
249
|
+
return out;
|
|
250
|
+
};
|
|
251
|
+
const read = { value: undefined };
|
|
252
|
+
const primitivesUpToAnObject = (f) => {
|
|
253
|
+
const { names, count } = f.live;
|
|
254
|
+
const v = f.v;
|
|
255
|
+
const into = f.out;
|
|
256
|
+
while (f.next < count) {
|
|
257
|
+
const key = names === undefined ? f.next : names[f.next];
|
|
258
|
+
f.next++;
|
|
259
|
+
if (!HAS_OWN(v, key))
|
|
260
|
+
continue;
|
|
261
|
+
if (!readOwnMember(v, key, read)) {
|
|
262
|
+
memberLeftOut(String(key), "getter-threw");
|
|
263
|
+
continue;
|
|
264
|
+
}
|
|
265
|
+
const member = read.value;
|
|
266
|
+
read.value = undefined;
|
|
267
|
+
if (member === null || member === undefined || typeof member === "string" || typeof member === "number" || typeof member === "boolean")
|
|
268
|
+
into[key] = member;
|
|
269
|
+
else if (typeof member === "object") {
|
|
270
|
+
into[key] = undefined;
|
|
271
|
+
return { key: String(key), member };
|
|
272
|
+
}
|
|
273
|
+
else
|
|
274
|
+
memberLeftOut(String(key), "not-data");
|
|
275
|
+
}
|
|
276
|
+
return undefined;
|
|
277
|
+
};
|
|
278
|
+
const memberLeftOut = (key, kind) => {
|
|
279
|
+
if (mode.contain !== true) {
|
|
280
|
+
path[path.length] = key;
|
|
281
|
+
refuse(kind);
|
|
282
|
+
}
|
|
283
|
+
appendOwn(faults, Object.freeze({ kind, path: pathTo(key) }));
|
|
284
|
+
};
|
|
95
285
|
const land = (f, key, copy, member) => {
|
|
96
286
|
if (measured && typeof member === "object" && member !== null)
|
|
97
287
|
f.height = Math.max(f.height, heightOf(member) + 1);
|
|
98
|
-
|
|
288
|
+
f.out[key] = copy;
|
|
99
289
|
path.length = f.level;
|
|
100
290
|
};
|
|
101
291
|
const finish = (f) => {
|
|
@@ -107,6 +297,7 @@ export function receive(value, mode, held) {
|
|
|
107
297
|
if (typeof length === "number")
|
|
108
298
|
f.out.length = length;
|
|
109
299
|
}
|
|
300
|
+
SET_PROTOTYPE(f.out, Array.isArray(f.out) ? ARRAY_PROTOTYPE : OBJECT_PROTOTYPE);
|
|
110
301
|
if (mode.freeze === true)
|
|
111
302
|
Object.freeze(f.out);
|
|
112
303
|
open.delete(f.v);
|
|
@@ -123,13 +314,34 @@ export function receive(value, mode, held) {
|
|
|
123
314
|
}
|
|
124
315
|
for (;;) {
|
|
125
316
|
const f = stack[stack.length - 1];
|
|
126
|
-
|
|
127
|
-
|
|
317
|
+
let key;
|
|
318
|
+
let captured;
|
|
319
|
+
let member;
|
|
320
|
+
if (f.live !== undefined) {
|
|
321
|
+
let next = f.live.pending;
|
|
322
|
+
f.live.pending = undefined;
|
|
323
|
+
if (next === undefined) {
|
|
324
|
+
try {
|
|
325
|
+
next = primitivesUpToAnObject(f);
|
|
326
|
+
}
|
|
327
|
+
catch (err) {
|
|
328
|
+
return { ok: false, fault: faultOf(err) };
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
if (next !== undefined)
|
|
332
|
+
({ key, member } = next);
|
|
333
|
+
}
|
|
334
|
+
else if (f.next < f.keys.length) {
|
|
335
|
+
key = f.keys[f.next++];
|
|
128
336
|
if (f.list && key === "length")
|
|
129
337
|
continue;
|
|
130
|
-
|
|
338
|
+
captured = f.captured[key];
|
|
339
|
+
}
|
|
340
|
+
if (key !== undefined) {
|
|
341
|
+
path[path.length] = key;
|
|
131
342
|
try {
|
|
132
|
-
|
|
343
|
+
if (captured !== undefined)
|
|
344
|
+
member = memberOf(f.v, captured);
|
|
133
345
|
const frames = stack.length;
|
|
134
346
|
const copy = meet(member, f.level + 1);
|
|
135
347
|
if (stack.length > frames) {
|
|
@@ -142,7 +354,8 @@ export function receive(value, mode, held) {
|
|
|
142
354
|
catch (err) {
|
|
143
355
|
if (mode.contain !== true)
|
|
144
356
|
return { ok: false, fault: faultOf(err) };
|
|
145
|
-
faults
|
|
357
|
+
appendOwn(faults, faultOf(err));
|
|
358
|
+
delete f.out[key];
|
|
146
359
|
path.length = f.level;
|
|
147
360
|
}
|
|
148
361
|
continue;
|
|
@@ -152,15 +365,16 @@ export function receive(value, mode, held) {
|
|
|
152
365
|
copy = finish(f);
|
|
153
366
|
}
|
|
154
367
|
catch (err) {
|
|
155
|
-
stack.
|
|
368
|
+
stack.length -= 1;
|
|
156
369
|
const holder = stack[stack.length - 1];
|
|
157
370
|
if (mode.contain !== true || holder === undefined)
|
|
158
371
|
return { ok: false, fault: faultOf(err) };
|
|
159
|
-
faults
|
|
372
|
+
appendOwn(faults, faultOf(err));
|
|
373
|
+
delete holder.out[holder.key];
|
|
160
374
|
path.length = holder.level;
|
|
161
375
|
continue;
|
|
162
376
|
}
|
|
163
|
-
stack.
|
|
377
|
+
stack.length -= 1;
|
|
164
378
|
const holder = stack[stack.length - 1];
|
|
165
379
|
if (holder === undefined)
|
|
166
380
|
return received(copy);
|
|
@@ -191,3 +405,62 @@ export function describeFault(fault) {
|
|
|
191
405
|
return `a value that could not be copied whole${at}`;
|
|
192
406
|
}
|
|
193
407
|
}
|
|
408
|
+
export function sealedObjects(roots) {
|
|
409
|
+
const holders = new WeakMap();
|
|
410
|
+
const met = new Set();
|
|
411
|
+
const unsealed = [];
|
|
412
|
+
const stack = [...roots];
|
|
413
|
+
while (stack.length > 0) {
|
|
414
|
+
const v = stack.pop();
|
|
415
|
+
if (typeof v !== "object" || v === null || met.has(v))
|
|
416
|
+
continue;
|
|
417
|
+
met.add(v);
|
|
418
|
+
const container = isPlainRecord(v) || (Array.isArray(v) && Object.getPrototypeOf(v) === Array.prototype);
|
|
419
|
+
if (!container) {
|
|
420
|
+
unsealed.push(v);
|
|
421
|
+
continue;
|
|
422
|
+
}
|
|
423
|
+
if (!Object.isFrozen(v))
|
|
424
|
+
unsealed.push(v);
|
|
425
|
+
const descriptors = Object.getOwnPropertyDescriptors(v);
|
|
426
|
+
if (Object.getOwnPropertySymbols(descriptors).length > 0)
|
|
427
|
+
unsealed.push(v);
|
|
428
|
+
for (const k of Object.getOwnPropertyNames(descriptors)) {
|
|
429
|
+
if (Array.isArray(v) && k === "length")
|
|
430
|
+
continue;
|
|
431
|
+
const d = descriptors[k];
|
|
432
|
+
if (!Object.hasOwn(d, "value") || d.enumerable !== true) {
|
|
433
|
+
unsealed.push(v);
|
|
434
|
+
continue;
|
|
435
|
+
}
|
|
436
|
+
const m = d.value;
|
|
437
|
+
if (typeof m === "bigint" || typeof m === "symbol" || typeof m === "function")
|
|
438
|
+
unsealed.push(v);
|
|
439
|
+
else if (typeof m === "object" && m !== null) {
|
|
440
|
+
const by = holders.get(m);
|
|
441
|
+
if (by === undefined)
|
|
442
|
+
holders.set(m, [v]);
|
|
443
|
+
else
|
|
444
|
+
by.push(v);
|
|
445
|
+
stack.push(m);
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
return withoutUnsealed(met, unsealed, holders);
|
|
450
|
+
}
|
|
451
|
+
function withoutUnsealed(objects, unsealed, holders) {
|
|
452
|
+
const bad = new Set();
|
|
453
|
+
while (unsealed.length > 0) {
|
|
454
|
+
const v = unsealed.pop();
|
|
455
|
+
if (bad.has(v))
|
|
456
|
+
continue;
|
|
457
|
+
bad.add(v);
|
|
458
|
+
for (const h of holders.get(v) ?? [])
|
|
459
|
+
unsealed.push(h);
|
|
460
|
+
}
|
|
461
|
+
const sealed = new Set();
|
|
462
|
+
for (const v of objects)
|
|
463
|
+
if (!bad.has(v))
|
|
464
|
+
sealed.add(v);
|
|
465
|
+
return sealed;
|
|
466
|
+
}
|
package/dist/registration.d.ts
CHANGED
|
@@ -47,10 +47,34 @@ export interface ModHandlerOptions<D extends ModDollarBase = ModDollarBase> {
|
|
|
47
47
|
readonly catch?: ModHandler<D>;
|
|
48
48
|
readonly observe?: boolean;
|
|
49
49
|
}
|
|
50
|
+
export interface ModEventPair {
|
|
51
|
+
readonly e: object;
|
|
52
|
+
readonly answer: unknown;
|
|
53
|
+
}
|
|
54
|
+
export type ModEventMap = {
|
|
55
|
+
readonly [name: string]: ModEventPair;
|
|
56
|
+
};
|
|
57
|
+
export interface ModTypedNext<P extends ModEventPair> {
|
|
58
|
+
(e: P["e"]): Promise<P["answer"]>;
|
|
59
|
+
to(e: P["e"], tier: ModTier): Promise<P["answer"]>;
|
|
60
|
+
readonly origin: ModOrigin;
|
|
61
|
+
readonly signal: AbortSignal;
|
|
62
|
+
readonly trace: readonly ModTraceEntry[];
|
|
63
|
+
readonly budget: ModBudgetReading;
|
|
64
|
+
readonly error?: ModCaughtError;
|
|
65
|
+
readonly called?: boolean;
|
|
66
|
+
}
|
|
67
|
+
export type ModTypedHandler<D extends ModDollarBase, P extends ModEventPair> = ($: D, e: P["e"], next: ModTypedNext<P>) => P["answer"] | Promise<P["answer"]>;
|
|
50
68
|
export interface On<D extends ModDollarBase = ModDollarBase> {
|
|
51
69
|
(pattern: string, handler: ModHandler<D>, options?: ModHandlerOptions<D>): void;
|
|
52
70
|
(pattern: string, matcher: ModMatcher, handler: ModHandler<D>, options?: ModHandlerOptions<D>): void;
|
|
53
71
|
}
|
|
72
|
+
export interface MappedOn<D extends ModDollarBase, M extends ModEventMap> {
|
|
73
|
+
<K extends keyof M & string>(pattern: K, handler: ModTypedHandler<D, M[K]>, options?: ModHandlerOptions<D>): void;
|
|
74
|
+
<K extends keyof M & string>(pattern: K, matcher: ModMatcher, handler: ModTypedHandler<D, M[K]>, options?: ModHandlerOptions<D>): void;
|
|
75
|
+
(pattern: string, handler: ModHandler<D>, options?: ModHandlerOptions<D>): void;
|
|
76
|
+
(pattern: string, matcher: ModMatcher, handler: ModHandler<D>, options?: ModHandlerOptions<D>): void;
|
|
77
|
+
}
|
|
54
78
|
export interface ModRegistration<D extends ModDollarBase = ModDollarBase> {
|
|
55
79
|
readonly name: string;
|
|
56
80
|
readonly tier?: ModRegistrationTier;
|