@rcrsr/rill 0.16.0 → 0.18.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 +37 -21
- package/dist/ast-nodes.d.ts +14 -4
- package/dist/ast-unions.d.ts +1 -1
- package/dist/constants.d.ts +1 -1
- package/dist/constants.js +1 -0
- package/dist/error-registry.js +228 -0
- package/dist/ext/crypto/index.d.ts +3 -3
- package/dist/ext/crypto/index.js +62 -59
- package/dist/ext/exec/index.d.ts +3 -3
- package/dist/ext/exec/index.js +15 -9
- package/dist/ext/fetch/index.d.ts +3 -3
- package/dist/ext/fetch/index.js +17 -12
- package/dist/ext/fetch/request.js +1 -1
- package/dist/ext/fs/index.d.ts +3 -3
- package/dist/ext/fs/index.js +256 -266
- package/dist/ext/fs/sandbox.d.ts +18 -0
- package/dist/ext/fs/sandbox.js +33 -0
- package/dist/ext/kv/index.d.ts +3 -3
- package/dist/ext/kv/index.js +198 -196
- package/dist/ext/kv/store.d.ts +1 -1
- package/dist/ext/kv/store.js +2 -1
- package/dist/ext-parse-bridge.d.ts +10 -0
- package/dist/ext-parse-bridge.js +10 -0
- package/dist/generated/introspection-data.d.ts +1 -1
- package/dist/generated/introspection-data.js +385 -296
- package/dist/generated/version-data.d.ts +1 -1
- package/dist/generated/version-data.js +2 -2
- package/dist/highlight-map.js +1 -0
- package/dist/index.d.ts +1 -4
- package/dist/index.js +1 -5
- package/dist/lexer/operators.js +1 -0
- package/dist/parser/helpers.js +1 -0
- package/dist/parser/parser-expr.js +44 -5
- package/dist/parser/parser-literals.js +111 -4
- package/dist/parser/parser-shape.js +2 -2
- package/dist/parser/parser-types.js +12 -0
- package/dist/parser/parser-use.js +26 -3
- package/dist/parser/parser.d.ts +2 -0
- package/dist/parser/parser.js +2 -0
- package/dist/runtime/core/callable.d.ts +24 -13
- package/dist/runtime/core/callable.js +71 -38
- package/dist/runtime/core/context.d.ts +2 -13
- package/dist/runtime/core/context.js +80 -79
- package/dist/runtime/core/eval/base.d.ts +2 -2
- package/dist/runtime/core/eval/base.js +2 -0
- package/dist/runtime/core/eval/evaluator.d.ts +1 -1
- package/dist/runtime/core/eval/index.d.ts +3 -3
- package/dist/runtime/core/eval/index.js +11 -0
- package/dist/runtime/core/eval/mixins/closures.js +381 -41
- package/dist/runtime/core/eval/mixins/collections.js +81 -6
- package/dist/runtime/core/eval/mixins/control-flow.js +1 -1
- package/dist/runtime/core/eval/mixins/conversion.js +61 -115
- package/dist/runtime/core/eval/mixins/core.js +17 -4
- package/dist/runtime/core/eval/mixins/expressions.js +36 -27
- package/dist/runtime/core/eval/mixins/extraction.js +2 -3
- package/dist/runtime/core/eval/mixins/list-dispatch.js +1 -1
- package/dist/runtime/core/eval/mixins/literals.js +17 -6
- package/dist/runtime/core/eval/mixins/types.js +73 -54
- package/dist/runtime/core/eval/mixins/variables.js +12 -8
- package/dist/runtime/core/execute.d.ts +1 -1
- package/dist/runtime/core/field-descriptor.d.ts +3 -3
- package/dist/runtime/core/field-descriptor.js +2 -1
- package/dist/runtime/core/introspection.d.ts +2 -2
- package/dist/runtime/core/introspection.js +7 -6
- package/dist/runtime/core/resolvers.d.ts +1 -1
- package/dist/runtime/core/signals.d.ts +6 -1
- package/dist/runtime/core/signals.js +9 -0
- package/dist/runtime/core/types/constructors.d.ts +54 -0
- package/dist/runtime/core/types/constructors.js +201 -0
- package/dist/runtime/core/types/guards.d.ts +42 -0
- package/dist/runtime/core/types/guards.js +88 -0
- package/dist/runtime/core/types/index.d.ts +18 -0
- package/dist/runtime/core/types/index.js +19 -0
- package/dist/runtime/core/types/markers.d.ts +12 -0
- package/dist/runtime/core/types/markers.js +7 -0
- package/dist/runtime/core/types/operations.d.ts +98 -0
- package/dist/runtime/core/types/operations.js +804 -0
- package/dist/runtime/core/types/registrations.d.ts +126 -0
- package/dist/runtime/core/types/registrations.js +751 -0
- package/dist/runtime/core/{types.d.ts → types/runtime.d.ts} +22 -10
- package/dist/runtime/core/types/structures.d.ts +146 -0
- package/dist/runtime/core/types/structures.js +12 -0
- package/dist/runtime/core/values.d.ts +29 -209
- package/dist/runtime/core/values.js +56 -968
- package/dist/runtime/ext/builtins.js +88 -68
- package/dist/runtime/ext/extensions.d.ts +31 -125
- package/dist/runtime/ext/extensions.js +2 -94
- package/dist/runtime/ext/test-context.d.ts +28 -0
- package/dist/runtime/ext/test-context.js +155 -0
- package/dist/runtime/index.d.ts +12 -12
- package/dist/runtime/index.js +13 -5
- package/dist/signature-parser.d.ts +2 -2
- package/dist/signature-parser.js +14 -14
- package/dist/token-types.d.ts +1 -0
- package/dist/token-types.js +1 -0
- package/package.json +1 -1
- /package/dist/runtime/core/{types.js → types/runtime.js} +0 -0
|
@@ -9,8 +9,11 @@
|
|
|
9
9
|
import { callable, isCallable, isDict } from '../core/callable.js';
|
|
10
10
|
import { RuntimeError } from '../../types.js';
|
|
11
11
|
import { parseSignatureRegistration } from '../../signature-parser.js';
|
|
12
|
-
import {
|
|
12
|
+
import { deepEquals, formatValue, inferType, serializeValue, } from '../core/types/registrations.js';
|
|
13
|
+
import { isIterator, isVector } from '../core/types/guards.js';
|
|
14
|
+
import { anyTypeValue, isEmpty, structureToTypeValue } from '../core/values.js';
|
|
13
15
|
import { invokeCallable } from '../core/eval/index.js';
|
|
16
|
+
import { populateBuiltinMethods } from '../core/types/registrations.js';
|
|
14
17
|
// ============================================================
|
|
15
18
|
// ITERATOR HELPERS
|
|
16
19
|
// ============================================================
|
|
@@ -70,7 +73,7 @@ export const BUILTIN_FUNCTIONS = {
|
|
|
70
73
|
params: [
|
|
71
74
|
{
|
|
72
75
|
name: 'value',
|
|
73
|
-
type: {
|
|
76
|
+
type: { kind: 'any' },
|
|
74
77
|
defaultValue: undefined,
|
|
75
78
|
annotations: {},
|
|
76
79
|
},
|
|
@@ -83,7 +86,7 @@ export const BUILTIN_FUNCTIONS = {
|
|
|
83
86
|
params: [
|
|
84
87
|
{
|
|
85
88
|
name: 'message',
|
|
86
|
-
type: {
|
|
89
|
+
type: { kind: 'any' },
|
|
87
90
|
defaultValue: undefined,
|
|
88
91
|
annotations: {},
|
|
89
92
|
},
|
|
@@ -103,21 +106,20 @@ export const BUILTIN_FUNCTIONS = {
|
|
|
103
106
|
params: [
|
|
104
107
|
{
|
|
105
108
|
name: 'value',
|
|
106
|
-
type: {
|
|
109
|
+
type: { kind: 'any' },
|
|
107
110
|
defaultValue: undefined,
|
|
108
111
|
annotations: {},
|
|
109
112
|
},
|
|
110
113
|
],
|
|
111
|
-
returnType:
|
|
114
|
+
returnType: structureToTypeValue({ kind: 'string' }),
|
|
112
115
|
fn: (args, _ctx, location) => {
|
|
113
116
|
const value = args['value'] ?? null;
|
|
114
117
|
try {
|
|
115
|
-
const jsonValue =
|
|
118
|
+
const jsonValue = serializeValue(value);
|
|
116
119
|
return JSON.stringify(jsonValue);
|
|
117
120
|
}
|
|
118
121
|
catch (err) {
|
|
119
|
-
|
|
120
|
-
throw err;
|
|
122
|
+
// Wrap serialization errors (RILL-R067 from protocol) as RILL-R004
|
|
121
123
|
if (err instanceof Error) {
|
|
122
124
|
throw new RuntimeError('RILL-R004', err.message, location);
|
|
123
125
|
}
|
|
@@ -135,14 +137,14 @@ export const BUILTIN_FUNCTIONS = {
|
|
|
135
137
|
{
|
|
136
138
|
name: 'items',
|
|
137
139
|
type: {
|
|
138
|
-
|
|
139
|
-
members: [{
|
|
140
|
+
kind: 'union',
|
|
141
|
+
members: [{ kind: 'list' }, { kind: 'dict' }, { kind: 'string' }],
|
|
140
142
|
},
|
|
141
143
|
defaultValue: undefined,
|
|
142
144
|
annotations: {},
|
|
143
145
|
},
|
|
144
146
|
],
|
|
145
|
-
returnType:
|
|
147
|
+
returnType: structureToTypeValue({ kind: 'list' }),
|
|
146
148
|
fn: (args) => {
|
|
147
149
|
const input = args['items'] ?? null;
|
|
148
150
|
if (Array.isArray(input)) {
|
|
@@ -167,19 +169,19 @@ export const BUILTIN_FUNCTIONS = {
|
|
|
167
169
|
params: [
|
|
168
170
|
{
|
|
169
171
|
name: 'start',
|
|
170
|
-
type: {
|
|
172
|
+
type: { kind: 'number' },
|
|
171
173
|
defaultValue: undefined,
|
|
172
174
|
annotations: {},
|
|
173
175
|
},
|
|
174
176
|
{
|
|
175
177
|
name: 'stop',
|
|
176
|
-
type: {
|
|
178
|
+
type: { kind: 'number' },
|
|
177
179
|
defaultValue: undefined,
|
|
178
180
|
annotations: {},
|
|
179
181
|
},
|
|
180
182
|
{
|
|
181
183
|
name: 'step',
|
|
182
|
-
type: {
|
|
184
|
+
type: { kind: 'number' },
|
|
183
185
|
defaultValue: 1,
|
|
184
186
|
annotations: {},
|
|
185
187
|
},
|
|
@@ -217,13 +219,13 @@ export const BUILTIN_FUNCTIONS = {
|
|
|
217
219
|
params: [
|
|
218
220
|
{
|
|
219
221
|
name: 'value',
|
|
220
|
-
type: {
|
|
222
|
+
type: { kind: 'any' },
|
|
221
223
|
defaultValue: undefined,
|
|
222
224
|
annotations: {},
|
|
223
225
|
},
|
|
224
226
|
{
|
|
225
227
|
name: 'count',
|
|
226
|
-
type: {
|
|
228
|
+
type: { kind: 'number' },
|
|
227
229
|
defaultValue: undefined,
|
|
228
230
|
annotations: {},
|
|
229
231
|
},
|
|
@@ -262,13 +264,13 @@ export const BUILTIN_FUNCTIONS = {
|
|
|
262
264
|
params: [
|
|
263
265
|
{
|
|
264
266
|
name: 'value',
|
|
265
|
-
type: {
|
|
267
|
+
type: { kind: 'any' },
|
|
266
268
|
defaultValue: undefined,
|
|
267
269
|
annotations: {},
|
|
268
270
|
},
|
|
269
271
|
{
|
|
270
272
|
name: 'transform',
|
|
271
|
-
type: {
|
|
273
|
+
type: { kind: 'any' },
|
|
272
274
|
defaultValue: undefined,
|
|
273
275
|
annotations: {},
|
|
274
276
|
},
|
|
@@ -311,20 +313,10 @@ export const BUILTIN_FUNCTIONS = {
|
|
|
311
313
|
// ============================================================
|
|
312
314
|
// BUILT-IN METHODS
|
|
313
315
|
// ============================================================
|
|
314
|
-
/** Factory for comparison methods (lt, gt, le, ge) */
|
|
315
|
-
function createComparisonMethod(compare) {
|
|
316
|
-
return (receiver, args) => {
|
|
317
|
-
const arg = args[0];
|
|
318
|
-
if (typeof receiver === 'number' && typeof arg === 'number') {
|
|
319
|
-
return compare(receiver, arg);
|
|
320
|
-
}
|
|
321
|
-
return compare(formatValue(receiver), formatValue(arg ?? ''));
|
|
322
|
-
};
|
|
323
|
-
}
|
|
324
316
|
/** Receiver param prepended to every method's param list */
|
|
325
317
|
const RECEIVER_PARAM = {
|
|
326
318
|
name: 'receiver',
|
|
327
|
-
type: {
|
|
319
|
+
type: { kind: 'any' },
|
|
328
320
|
defaultValue: undefined,
|
|
329
321
|
annotations: {},
|
|
330
322
|
};
|
|
@@ -337,7 +329,7 @@ const RECEIVER_PARAM = {
|
|
|
337
329
|
*
|
|
338
330
|
* EC-4: Receiver missing from record raises RILL-R044.
|
|
339
331
|
*/
|
|
340
|
-
function buildMethodEntry(name, signature, method) {
|
|
332
|
+
function buildMethodEntry(name, signature, method, skipReceiverValidation) {
|
|
341
333
|
const parsed = parseSignatureRegistration(signature, name);
|
|
342
334
|
const methodParams = parsed.params;
|
|
343
335
|
return {
|
|
@@ -359,8 +351,9 @@ function buildMethodEntry(name, signature, method) {
|
|
|
359
351
|
? { description: parsed.description }
|
|
360
352
|
: {},
|
|
361
353
|
returnType: parsed.returnType !== undefined
|
|
362
|
-
?
|
|
354
|
+
? structureToTypeValue(parsed.returnType)
|
|
363
355
|
: anyTypeValue,
|
|
356
|
+
...(skipReceiverValidation ? { skipReceiverValidation: true } : {}),
|
|
364
357
|
};
|
|
365
358
|
}
|
|
366
359
|
export const BUILTIN_METHODS = {
|
|
@@ -423,7 +416,7 @@ const mTail = (receiver, _args, _ctx, location) => {
|
|
|
423
416
|
};
|
|
424
417
|
/** Get iterator at first position for any collection */
|
|
425
418
|
const mFirst = (receiver, _args, _ctx, location) => {
|
|
426
|
-
if (
|
|
419
|
+
if (isIterator(receiver))
|
|
427
420
|
return receiver;
|
|
428
421
|
if (Array.isArray(receiver))
|
|
429
422
|
return makeListIterator(receiver, 0);
|
|
@@ -552,10 +545,34 @@ const mPadEnd = (receiver, args) => {
|
|
|
552
545
|
const mEq = (receiver, args) => deepEquals(receiver, args[0] ?? null);
|
|
553
546
|
/** Inequality check (deep structural comparison) */
|
|
554
547
|
const mNe = (receiver, args) => !deepEquals(receiver, args[0] ?? null);
|
|
555
|
-
|
|
556
|
-
const
|
|
557
|
-
const
|
|
558
|
-
|
|
548
|
+
/** Less-than comparison (number or string) */
|
|
549
|
+
const mLt = (receiver, args) => {
|
|
550
|
+
const arg = args[0];
|
|
551
|
+
if (typeof receiver === 'number' && typeof arg === 'number')
|
|
552
|
+
return receiver < arg;
|
|
553
|
+
return formatValue(receiver) < formatValue(arg ?? '');
|
|
554
|
+
};
|
|
555
|
+
/** Greater-than comparison (number or string) */
|
|
556
|
+
const mGt = (receiver, args) => {
|
|
557
|
+
const arg = args[0];
|
|
558
|
+
if (typeof receiver === 'number' && typeof arg === 'number')
|
|
559
|
+
return receiver > arg;
|
|
560
|
+
return formatValue(receiver) > formatValue(arg ?? '');
|
|
561
|
+
};
|
|
562
|
+
/** Less-than-or-equal comparison (number or string) */
|
|
563
|
+
const mLe = (receiver, args) => {
|
|
564
|
+
const arg = args[0];
|
|
565
|
+
if (typeof receiver === 'number' && typeof arg === 'number')
|
|
566
|
+
return receiver <= arg;
|
|
567
|
+
return formatValue(receiver) <= formatValue(arg ?? '');
|
|
568
|
+
};
|
|
569
|
+
/** Greater-than-or-equal comparison (number or string) */
|
|
570
|
+
const mGe = (receiver, args) => {
|
|
571
|
+
const arg = args[0];
|
|
572
|
+
if (typeof receiver === 'number' && typeof arg === 'number')
|
|
573
|
+
return receiver >= arg;
|
|
574
|
+
return formatValue(receiver) >= formatValue(arg ?? '');
|
|
575
|
+
};
|
|
559
576
|
/** Get all keys of a dict as a list */
|
|
560
577
|
const mKeys = (receiver) => isDict(receiver) ? Object.keys(receiver) : [];
|
|
561
578
|
/** Get all values of a dict as a list */
|
|
@@ -757,10 +774,10 @@ const SIG_CMP = '|other: any|:bool';
|
|
|
757
774
|
BUILTIN_METHODS.string = Object.freeze({
|
|
758
775
|
len: buildMethodEntry('len', SIG_LEN, mLen),
|
|
759
776
|
trim: buildMethodEntry('trim', '||:string', mTrim),
|
|
760
|
-
head: buildMethodEntry('head', SIG_HEAD, mHead),
|
|
761
|
-
tail: buildMethodEntry('tail', SIG_TAIL, mTail),
|
|
762
|
-
first: buildMethodEntry('first', SIG_FIRST, mFirst),
|
|
763
|
-
at: buildMethodEntry('at', SIG_AT, mAt),
|
|
777
|
+
head: buildMethodEntry('head', SIG_HEAD, mHead, true),
|
|
778
|
+
tail: buildMethodEntry('tail', SIG_TAIL, mTail, true),
|
|
779
|
+
first: buildMethodEntry('first', SIG_FIRST, mFirst, true),
|
|
780
|
+
at: buildMethodEntry('at', SIG_AT, mAt, true),
|
|
764
781
|
split: buildMethodEntry('split', '|separator: string = "\\n"|:list', mSplit),
|
|
765
782
|
lines: buildMethodEntry('lines', '||:list', mLines),
|
|
766
783
|
empty: buildMethodEntry('empty', SIG_EMPTY, mEmpty),
|
|
@@ -777,8 +794,8 @@ BUILTIN_METHODS.string = Object.freeze({
|
|
|
777
794
|
repeat: buildMethodEntry('repeat', '|count: number|:string', mRepeat),
|
|
778
795
|
pad_start: buildMethodEntry('pad_start', '|length: number, fill: string = " "|:string', mPadStart),
|
|
779
796
|
pad_end: buildMethodEntry('pad_end', '|length: number, fill: string = " "|:string', mPadEnd),
|
|
780
|
-
eq: buildMethodEntry('eq', SIG_EQ, mEq),
|
|
781
|
-
ne: buildMethodEntry('ne', SIG_NE, mNe),
|
|
797
|
+
eq: buildMethodEntry('eq', SIG_EQ, mEq, true),
|
|
798
|
+
ne: buildMethodEntry('ne', SIG_NE, mNe, true),
|
|
782
799
|
lt: buildMethodEntry('lt', SIG_CMP, mLt),
|
|
783
800
|
gt: buildMethodEntry('gt', SIG_CMP, mGt),
|
|
784
801
|
le: buildMethodEntry('le', SIG_CMP, mLe),
|
|
@@ -786,32 +803,32 @@ BUILTIN_METHODS.string = Object.freeze({
|
|
|
786
803
|
});
|
|
787
804
|
BUILTIN_METHODS.list = Object.freeze({
|
|
788
805
|
len: buildMethodEntry('len', SIG_LEN, mLen),
|
|
789
|
-
head: buildMethodEntry('head', SIG_HEAD, mHead),
|
|
790
|
-
tail: buildMethodEntry('tail', SIG_TAIL, mTail),
|
|
791
|
-
first: buildMethodEntry('first', SIG_FIRST, mFirst),
|
|
792
|
-
at: buildMethodEntry('at', SIG_AT, mAt),
|
|
806
|
+
head: buildMethodEntry('head', SIG_HEAD, mHead, true),
|
|
807
|
+
tail: buildMethodEntry('tail', SIG_TAIL, mTail, true),
|
|
808
|
+
first: buildMethodEntry('first', SIG_FIRST, mFirst, true),
|
|
809
|
+
at: buildMethodEntry('at', SIG_AT, mAt, true),
|
|
793
810
|
join: buildMethodEntry('join', '|separator: string = ","|:string', mJoin),
|
|
794
811
|
empty: buildMethodEntry('empty', SIG_EMPTY, mEmpty),
|
|
795
|
-
eq: buildMethodEntry('eq', SIG_EQ, mEq),
|
|
796
|
-
ne: buildMethodEntry('ne', SIG_NE, mNe),
|
|
797
|
-
has: buildMethodEntry('has', '|value: any|:bool', mHas),
|
|
798
|
-
has_any: buildMethodEntry('has_any', '|candidates: list|:bool', mHasAny),
|
|
799
|
-
has_all: buildMethodEntry('has_all', '|candidates: list|:bool', mHasAll),
|
|
812
|
+
eq: buildMethodEntry('eq', SIG_EQ, mEq, true),
|
|
813
|
+
ne: buildMethodEntry('ne', SIG_NE, mNe, true),
|
|
814
|
+
has: buildMethodEntry('has', '|value: any|:bool', mHas, true),
|
|
815
|
+
has_any: buildMethodEntry('has_any', '|candidates: list|:bool', mHasAny, true),
|
|
816
|
+
has_all: buildMethodEntry('has_all', '|candidates: list|:bool', mHasAll, true),
|
|
800
817
|
});
|
|
801
818
|
BUILTIN_METHODS.dict = Object.freeze({
|
|
802
819
|
len: buildMethodEntry('len', SIG_LEN, mLen),
|
|
803
|
-
first: buildMethodEntry('first', SIG_FIRST, mFirst),
|
|
820
|
+
first: buildMethodEntry('first', SIG_FIRST, mFirst, true),
|
|
804
821
|
empty: buildMethodEntry('empty', SIG_EMPTY, mEmpty),
|
|
805
|
-
eq: buildMethodEntry('eq', SIG_EQ, mEq),
|
|
806
|
-
ne: buildMethodEntry('ne', SIG_NE, mNe),
|
|
807
|
-
keys: buildMethodEntry('keys', '||:list', mKeys),
|
|
808
|
-
values: buildMethodEntry('values', '||:list', mValues),
|
|
809
|
-
entries: buildMethodEntry('entries', '||:list', mEntries),
|
|
822
|
+
eq: buildMethodEntry('eq', SIG_EQ, mEq, true),
|
|
823
|
+
ne: buildMethodEntry('ne', SIG_NE, mNe, true),
|
|
824
|
+
keys: buildMethodEntry('keys', '||:list', mKeys, true),
|
|
825
|
+
values: buildMethodEntry('values', '||:list', mValues, true),
|
|
826
|
+
entries: buildMethodEntry('entries', '||:list', mEntries, true),
|
|
810
827
|
});
|
|
811
828
|
BUILTIN_METHODS.number = Object.freeze({
|
|
812
829
|
empty: buildMethodEntry('empty', SIG_EMPTY, mEmpty),
|
|
813
|
-
eq: buildMethodEntry('eq', SIG_EQ, mEq),
|
|
814
|
-
ne: buildMethodEntry('ne', SIG_NE, mNe),
|
|
830
|
+
eq: buildMethodEntry('eq', SIG_EQ, mEq, true),
|
|
831
|
+
ne: buildMethodEntry('ne', SIG_NE, mNe, true),
|
|
815
832
|
lt: buildMethodEntry('lt', SIG_CMP, mLt),
|
|
816
833
|
gt: buildMethodEntry('gt', SIG_CMP, mGt),
|
|
817
834
|
le: buildMethodEntry('le', SIG_CMP, mLe),
|
|
@@ -819,18 +836,21 @@ BUILTIN_METHODS.number = Object.freeze({
|
|
|
819
836
|
});
|
|
820
837
|
BUILTIN_METHODS.bool = Object.freeze({
|
|
821
838
|
empty: buildMethodEntry('empty', SIG_EMPTY, mEmpty),
|
|
822
|
-
eq: buildMethodEntry('eq', SIG_EQ, mEq),
|
|
823
|
-
ne: buildMethodEntry('ne', SIG_NE, mNe),
|
|
839
|
+
eq: buildMethodEntry('eq', SIG_EQ, mEq, true),
|
|
840
|
+
ne: buildMethodEntry('ne', SIG_NE, mNe, true),
|
|
824
841
|
});
|
|
825
842
|
// [ASSUMPTION] vector is a 6th group beyond the 5 specified basic types.
|
|
826
843
|
// The 7 vector methods do not belong to string/list/dict/number/bool.
|
|
827
844
|
// Adding this group ensures all 42 methods are accessible (AC-36).
|
|
828
845
|
BUILTIN_METHODS.vector = Object.freeze({
|
|
829
|
-
dimensions: buildMethodEntry('dimensions', '||:number', mDimensions),
|
|
830
|
-
model: buildMethodEntry('model', '||:string', mModel),
|
|
831
|
-
similarity: buildMethodEntry('similarity', '|other: any|:number', mSimilarity),
|
|
832
|
-
dot: buildMethodEntry('dot', '|other: any|:number', mDot),
|
|
833
|
-
distance: buildMethodEntry('distance', '|other: any|:number', mDistance),
|
|
834
|
-
norm: buildMethodEntry('norm', '||:number', mNorm),
|
|
835
|
-
normalize: buildMethodEntry('normalize', '||:any', mNormalize),
|
|
846
|
+
dimensions: buildMethodEntry('dimensions', '||:number', mDimensions, true),
|
|
847
|
+
model: buildMethodEntry('model', '||:string', mModel, true),
|
|
848
|
+
similarity: buildMethodEntry('similarity', '|other: any|:number', mSimilarity, true),
|
|
849
|
+
dot: buildMethodEntry('dot', '|other: any|:number', mDot, true),
|
|
850
|
+
distance: buildMethodEntry('distance', '|other: any|:number', mDistance, true),
|
|
851
|
+
norm: buildMethodEntry('norm', '||:number', mNorm, true),
|
|
852
|
+
normalize: buildMethodEntry('normalize', '||:any', mNormalize, true),
|
|
836
853
|
});
|
|
854
|
+
// Populate registration methods from BUILTIN_METHODS at module load time.
|
|
855
|
+
// No circular dependency: type-registrations.ts does not import builtins.ts.
|
|
856
|
+
populateBuiltinMethods(BUILTIN_METHODS);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type { ExtensionEvent, RuntimeCallbacks } from '../core/types.js';
|
|
1
|
+
import type { ApplicationCallable } from '../core/callable.js';
|
|
2
|
+
import type { ExtensionEvent, RuntimeCallbacks } from '../core/types/runtime.js';
|
|
3
|
+
import type { RillValue } from '../core/types/structures.js';
|
|
3
4
|
/**
|
|
4
5
|
* Minimal interface for extension event emission.
|
|
5
6
|
* Allows emitExtensionEvent to accept any context with callbacks.
|
|
@@ -9,27 +10,20 @@ interface RuntimeContextLike {
|
|
|
9
10
|
}
|
|
10
11
|
/**
|
|
11
12
|
* Result object returned by extension factories.
|
|
12
|
-
* Contains
|
|
13
|
+
* Contains the mounted RillValue with optional lifecycle hooks.
|
|
14
|
+
* Lifecycle hooks live on the factory result, not on the value dict (DD-1).
|
|
13
15
|
*/
|
|
14
|
-
export interface
|
|
15
|
-
|
|
16
|
+
export interface ExtensionFactoryResult {
|
|
17
|
+
readonly value: RillValue;
|
|
16
18
|
dispose?: () => void | Promise<void>;
|
|
17
19
|
suspend?: () => unknown;
|
|
18
20
|
restore?: (state: unknown) => void;
|
|
19
21
|
}
|
|
20
|
-
/**
|
|
21
|
-
* Result object returned by hoistExtension.
|
|
22
|
-
* Separates functions from dispose for safe createRuntimeContext usage.
|
|
23
|
-
*/
|
|
24
|
-
export interface HoistedExtension {
|
|
25
|
-
functions: Record<string, RillFunction>;
|
|
26
|
-
dispose?: () => void | Promise<void>;
|
|
27
|
-
}
|
|
28
22
|
/**
|
|
29
23
|
* Factory function contract for creating extensions.
|
|
30
24
|
* Accepts typed configuration and returns isolated instance.
|
|
31
25
|
*/
|
|
32
|
-
export type ExtensionFactory<TConfig> = (config: TConfig) =>
|
|
26
|
+
export type ExtensionFactory<TConfig> = (config: TConfig) => ExtensionFactoryResult | Promise<ExtensionFactoryResult>;
|
|
33
27
|
/**
|
|
34
28
|
* Descriptor for a single configuration field in an extension schema.
|
|
35
29
|
* The secret flag is advisory: harness tooling uses it to mask or omit values.
|
|
@@ -72,18 +66,17 @@ export interface ExtensionManifest {
|
|
|
72
66
|
* - mounts(): List all configured mounts
|
|
73
67
|
*/
|
|
74
68
|
export type KvExtensionContract = {
|
|
75
|
-
readonly get:
|
|
76
|
-
readonly get_or:
|
|
77
|
-
readonly set:
|
|
78
|
-
readonly merge:
|
|
79
|
-
readonly delete:
|
|
80
|
-
readonly keys:
|
|
81
|
-
readonly has:
|
|
82
|
-
readonly clear:
|
|
83
|
-
readonly getAll:
|
|
84
|
-
readonly schema:
|
|
85
|
-
readonly mounts:
|
|
86
|
-
readonly dispose?: (() => void | Promise<void>) | undefined;
|
|
69
|
+
readonly get: ApplicationCallable;
|
|
70
|
+
readonly get_or: ApplicationCallable;
|
|
71
|
+
readonly set: ApplicationCallable;
|
|
72
|
+
readonly merge: ApplicationCallable;
|
|
73
|
+
readonly delete: ApplicationCallable;
|
|
74
|
+
readonly keys: ApplicationCallable;
|
|
75
|
+
readonly has: ApplicationCallable;
|
|
76
|
+
readonly clear: ApplicationCallable;
|
|
77
|
+
readonly getAll: ApplicationCallable;
|
|
78
|
+
readonly schema: ApplicationCallable;
|
|
79
|
+
readonly mounts: ApplicationCallable;
|
|
87
80
|
};
|
|
88
81
|
/**
|
|
89
82
|
* Contract type for fs extension implementations.
|
|
@@ -104,106 +97,19 @@ export type KvExtensionContract = {
|
|
|
104
97
|
* - mounts(): List all configured mounts
|
|
105
98
|
*/
|
|
106
99
|
export type FsExtensionContract = {
|
|
107
|
-
readonly read:
|
|
108
|
-
readonly write:
|
|
109
|
-
readonly append:
|
|
110
|
-
readonly list:
|
|
111
|
-
readonly find:
|
|
112
|
-
readonly exists:
|
|
113
|
-
readonly remove:
|
|
114
|
-
readonly stat:
|
|
115
|
-
readonly mkdir:
|
|
116
|
-
readonly copy:
|
|
117
|
-
readonly move:
|
|
118
|
-
readonly mounts:
|
|
119
|
-
readonly dispose?: (() => void | Promise<void>) | undefined;
|
|
120
|
-
};
|
|
121
|
-
/**
|
|
122
|
-
* Contract type for llm extension implementations.
|
|
123
|
-
* Enforces exact function structure for compile-time verification.
|
|
124
|
-
*
|
|
125
|
-
* Backend implementations must provide all 6 functions:
|
|
126
|
-
* - message(text, options): Send single message
|
|
127
|
-
* - messages(messages, options): Multi-turn conversation
|
|
128
|
-
* - embed(text): Generate embedding vector
|
|
129
|
-
* - embed_batch(texts): Batch embeddings
|
|
130
|
-
* - tool_loop(prompt, options): Tool use orchestration
|
|
131
|
-
* - generate(prompt, options): Structured output extraction
|
|
132
|
-
*/
|
|
133
|
-
export type LlmExtensionContract = {
|
|
134
|
-
readonly message: RillFunction;
|
|
135
|
-
readonly messages: RillFunction;
|
|
136
|
-
readonly embed: RillFunction;
|
|
137
|
-
readonly embed_batch: RillFunction;
|
|
138
|
-
readonly tool_loop: RillFunction;
|
|
139
|
-
readonly generate: RillFunction;
|
|
140
|
-
readonly dispose?: (() => void | Promise<void>) | undefined;
|
|
141
|
-
};
|
|
142
|
-
/**
|
|
143
|
-
* Contract type for vector extension implementations.
|
|
144
|
-
* Enforces exact function structure for compile-time verification.
|
|
145
|
-
*
|
|
146
|
-
* Backend implementations must provide all 11 functions:
|
|
147
|
-
* - upsert(id, vector, metadata): Insert or update vector
|
|
148
|
-
* - upsert_batch(items): Batch insert/update
|
|
149
|
-
* - search(vector, options): Search k nearest neighbors
|
|
150
|
-
* - get(id): Fetch vector by ID
|
|
151
|
-
* - delete(id): Delete vector by ID
|
|
152
|
-
* - delete_batch(ids): Batch delete
|
|
153
|
-
* - count(): Count vectors in collection
|
|
154
|
-
* - create_collection(name, options): Create collection
|
|
155
|
-
* - delete_collection(name): Delete collection
|
|
156
|
-
* - list_collections(): List all collections
|
|
157
|
-
* - describe(): Get collection metadata
|
|
158
|
-
*/
|
|
159
|
-
export type VectorExtensionContract = {
|
|
160
|
-
readonly upsert: RillFunction;
|
|
161
|
-
readonly upsert_batch: RillFunction;
|
|
162
|
-
readonly search: RillFunction;
|
|
163
|
-
readonly get: RillFunction;
|
|
164
|
-
readonly delete: RillFunction;
|
|
165
|
-
readonly delete_batch: RillFunction;
|
|
166
|
-
readonly count: RillFunction;
|
|
167
|
-
readonly create_collection: RillFunction;
|
|
168
|
-
readonly delete_collection: RillFunction;
|
|
169
|
-
readonly list_collections: RillFunction;
|
|
170
|
-
readonly describe: RillFunction;
|
|
171
|
-
readonly dispose?: (() => void | Promise<void>) | undefined;
|
|
100
|
+
readonly read: ApplicationCallable;
|
|
101
|
+
readonly write: ApplicationCallable;
|
|
102
|
+
readonly append: ApplicationCallable;
|
|
103
|
+
readonly list: ApplicationCallable;
|
|
104
|
+
readonly find: ApplicationCallable;
|
|
105
|
+
readonly exists: ApplicationCallable;
|
|
106
|
+
readonly remove: ApplicationCallable;
|
|
107
|
+
readonly stat: ApplicationCallable;
|
|
108
|
+
readonly mkdir: ApplicationCallable;
|
|
109
|
+
readonly copy: ApplicationCallable;
|
|
110
|
+
readonly move: ApplicationCallable;
|
|
111
|
+
readonly mounts: ApplicationCallable;
|
|
172
112
|
};
|
|
173
|
-
/**
|
|
174
|
-
* Prefix all function names in an extension with a namespace.
|
|
175
|
-
*
|
|
176
|
-
* @param namespace - Alphanumeric string with underscores/hyphens (e.g., "fs", "claude_code")
|
|
177
|
-
* @param functions - Extension result with function definitions
|
|
178
|
-
* @returns New ExtensionResult with prefixed function names (namespace::functionName)
|
|
179
|
-
* @throws {RuntimeError} RUNTIME_TYPE_ERROR if namespace is invalid
|
|
180
|
-
*
|
|
181
|
-
* @example
|
|
182
|
-
* ```typescript
|
|
183
|
-
* const fs = createFsExtension();
|
|
184
|
-
* const prefixed = prefixFunctions("fs", fs);
|
|
185
|
-
* // { "fs::read": ..., "fs::write": ..., dispose: ... }
|
|
186
|
-
* ```
|
|
187
|
-
*/
|
|
188
|
-
export declare function prefixFunctions(namespace: string, functions: ExtensionResult): ExtensionResult;
|
|
189
|
-
/**
|
|
190
|
-
* Separate dispose from functions for safe createRuntimeContext usage.
|
|
191
|
-
* Wraps prefixFunctions and returns separated structure.
|
|
192
|
-
*
|
|
193
|
-
* @param namespace - String matching /^[a-zA-Z0-9_-]+$/
|
|
194
|
-
* @param extension - Output from extension factory
|
|
195
|
-
* @returns Separated functions and dispose handler
|
|
196
|
-
* @throws {Error} If namespace is empty
|
|
197
|
-
* @throws {Error} If namespace has invalid format
|
|
198
|
-
* @throws {TypeError} If extension is null or undefined
|
|
199
|
-
*
|
|
200
|
-
* @example
|
|
201
|
-
* ```typescript
|
|
202
|
-
* const { functions, dispose } = hoistExtension('db', dbExtension);
|
|
203
|
-
* const ctx = createRuntimeContext({ functions });
|
|
204
|
-
* ```
|
|
205
|
-
*/
|
|
206
|
-
export declare function hoistExtension(namespace: string, extension: ExtensionResult): HoistedExtension;
|
|
207
113
|
/**
|
|
208
114
|
* Emit an extension event with auto-generated timestamp.
|
|
209
115
|
* Adds ISO timestamp if event.timestamp is undefined, then calls onLogEvent callback.
|
|
@@ -1,96 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
* Prefix all function names in an extension with a namespace.
|
|
3
|
-
*
|
|
4
|
-
* @param namespace - Alphanumeric string with underscores/hyphens (e.g., "fs", "claude_code")
|
|
5
|
-
* @param functions - Extension result with function definitions
|
|
6
|
-
* @returns New ExtensionResult with prefixed function names (namespace::functionName)
|
|
7
|
-
* @throws {RuntimeError} RUNTIME_TYPE_ERROR if namespace is invalid
|
|
8
|
-
*
|
|
9
|
-
* @example
|
|
10
|
-
* ```typescript
|
|
11
|
-
* const fs = createFsExtension();
|
|
12
|
-
* const prefixed = prefixFunctions("fs", fs);
|
|
13
|
-
* // { "fs::read": ..., "fs::write": ..., dispose: ... }
|
|
14
|
-
* ```
|
|
15
|
-
*/
|
|
16
|
-
export function prefixFunctions(namespace, functions) {
|
|
17
|
-
// EC-7: Extension not object
|
|
18
|
-
if (typeof functions !== 'object' ||
|
|
19
|
-
functions === null ||
|
|
20
|
-
Array.isArray(functions)) {
|
|
21
|
-
throw new TypeError('Extension must be an object');
|
|
22
|
-
}
|
|
23
|
-
// EC-6: Invalid namespace format
|
|
24
|
-
const NAMESPACE_PATTERN = /^[a-zA-Z0-9_-]+$/;
|
|
25
|
-
if (!NAMESPACE_PATTERN.test(namespace)) {
|
|
26
|
-
throw new Error('Invalid namespace format: must match /^[a-zA-Z0-9_-]+$/');
|
|
27
|
-
}
|
|
28
|
-
// Create new object with prefixed keys
|
|
29
|
-
const result = {};
|
|
30
|
-
for (const [name, definition] of Object.entries(functions)) {
|
|
31
|
-
// Skip lifecycle hooks during prefixing
|
|
32
|
-
if (name === 'dispose' || name === 'suspend' || name === 'restore')
|
|
33
|
-
continue;
|
|
34
|
-
result[`${namespace}::${name}`] = definition;
|
|
35
|
-
}
|
|
36
|
-
// Preserve lifecycle hooks if present
|
|
37
|
-
const resultWithHooks = result;
|
|
38
|
-
if (functions.dispose !== undefined) {
|
|
39
|
-
resultWithHooks.dispose = functions.dispose;
|
|
40
|
-
}
|
|
41
|
-
if (functions.suspend !== undefined) {
|
|
42
|
-
resultWithHooks.suspend = functions.suspend;
|
|
43
|
-
}
|
|
44
|
-
if (functions.restore !== undefined) {
|
|
45
|
-
resultWithHooks.restore = functions.restore;
|
|
46
|
-
}
|
|
47
|
-
return resultWithHooks;
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* Separate dispose from functions for safe createRuntimeContext usage.
|
|
51
|
-
* Wraps prefixFunctions and returns separated structure.
|
|
52
|
-
*
|
|
53
|
-
* @param namespace - String matching /^[a-zA-Z0-9_-]+$/
|
|
54
|
-
* @param extension - Output from extension factory
|
|
55
|
-
* @returns Separated functions and dispose handler
|
|
56
|
-
* @throws {Error} If namespace is empty
|
|
57
|
-
* @throws {Error} If namespace has invalid format
|
|
58
|
-
* @throws {TypeError} If extension is null or undefined
|
|
59
|
-
*
|
|
60
|
-
* @example
|
|
61
|
-
* ```typescript
|
|
62
|
-
* const { functions, dispose } = hoistExtension('db', dbExtension);
|
|
63
|
-
* const ctx = createRuntimeContext({ functions });
|
|
64
|
-
* ```
|
|
65
|
-
*/
|
|
66
|
-
export function hoistExtension(namespace, extension) {
|
|
67
|
-
// EC-3: Null/undefined extension
|
|
68
|
-
if (extension === null || extension === undefined) {
|
|
69
|
-
throw new TypeError('Extension cannot be null or undefined');
|
|
70
|
-
}
|
|
71
|
-
// EC-2: Empty namespace
|
|
72
|
-
if (namespace === '') {
|
|
73
|
-
throw new Error('Namespace cannot be empty');
|
|
74
|
-
}
|
|
75
|
-
// EC-1: Invalid namespace format
|
|
76
|
-
const NAMESPACE_PATTERN = /^[a-zA-Z0-9_-]+$/;
|
|
77
|
-
if (!NAMESPACE_PATTERN.test(namespace)) {
|
|
78
|
-
throw new Error('Invalid namespace format: must match /^[a-zA-Z0-9_-]+$/');
|
|
79
|
-
}
|
|
80
|
-
// Call prefixFunctions internally
|
|
81
|
-
const prefixed = prefixFunctions(namespace, extension);
|
|
82
|
-
// Extract dispose from result
|
|
83
|
-
const { dispose, ...functions } = prefixed;
|
|
84
|
-
// Return separated structure
|
|
85
|
-
const result = {
|
|
86
|
-
functions: functions,
|
|
87
|
-
};
|
|
88
|
-
// Only add dispose if it exists (exactOptionalPropertyTypes)
|
|
89
|
-
if (dispose !== undefined) {
|
|
90
|
-
result.dispose = dispose;
|
|
91
|
-
}
|
|
92
|
-
return result;
|
|
93
|
-
}
|
|
1
|
+
import { RuntimeError } from '../../types.js';
|
|
94
2
|
/**
|
|
95
3
|
* Emit an extension event with auto-generated timestamp.
|
|
96
4
|
* Adds ISO timestamp if event.timestamp is undefined, then calls onLogEvent callback.
|
|
@@ -119,7 +27,7 @@ export function emitExtensionEvent(ctx, event) {
|
|
|
119
27
|
if (!event['event'] ||
|
|
120
28
|
typeof event['event'] !== 'string' ||
|
|
121
29
|
event['event'].trim() === '') {
|
|
122
|
-
throw new
|
|
30
|
+
throw new RuntimeError('RILL-R075', 'Event must include non-empty event field');
|
|
123
31
|
}
|
|
124
32
|
// IC-2: Guard for callbacks property (graceful degradation)
|
|
125
33
|
if ('callbacks' in ctx && ctx.callbacks) {
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test Context Factory
|
|
3
|
+
*
|
|
4
|
+
* Creates a pre-wired RuntimeContext from extension value maps.
|
|
5
|
+
* Designed for testing and lightweight embedding without rill-config.
|
|
6
|
+
*/
|
|
7
|
+
import type { RuntimeContext } from '../core/types/runtime.js';
|
|
8
|
+
import type { RillValue } from '../core/types/structures.js';
|
|
9
|
+
/**
|
|
10
|
+
* Error thrown when extension binding generation fails.
|
|
11
|
+
* Mirrors the ExtensionBindingError in rill-config for core-only usage.
|
|
12
|
+
*/
|
|
13
|
+
export declare class ExtensionBindingError extends Error {
|
|
14
|
+
readonly code: "EXTENSION_BINDING";
|
|
15
|
+
constructor(message: string);
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Create a RuntimeContext pre-wired with extension values.
|
|
19
|
+
* Builds extension bindings, registers ext and module resolvers,
|
|
20
|
+
* and returns a context ready for execute().
|
|
21
|
+
*
|
|
22
|
+
* @throws {TypeError} when an extension value is undefined (EC-9)
|
|
23
|
+
* @throws {ExtensionBindingError} when binding generation fails (EC-10)
|
|
24
|
+
*/
|
|
25
|
+
export declare function createTestContext(extensions: Record<string, {
|
|
26
|
+
value: RillValue;
|
|
27
|
+
dispose?: () => void | Promise<void>;
|
|
28
|
+
}>): RuntimeContext;
|