@rcrsr/rill 0.17.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/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.js +5 -5
- package/dist/ext/exec/index.js +3 -3
- package/dist/ext/fetch/index.js +4 -4
- package/dist/ext/fetch/request.js +1 -1
- package/dist/ext/fs/index.js +101 -114
- package/dist/ext/fs/sandbox.d.ts +18 -0
- package/dist/ext/fs/sandbox.js +33 -0
- package/dist/ext/kv/index.js +12 -12
- package/dist/ext/kv/store.d.ts +1 -1
- package/dist/ext/kv/store.js +1 -1
- 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 -15
- package/dist/index.js +1 -14
- 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-use.js +19 -2
- package/dist/parser/parser.d.ts +2 -0
- package/dist/parser/parser.js +2 -0
- package/dist/runtime/core/callable.d.ts +5 -6
- package/dist/runtime/core/callable.js +10 -17
- package/dist/runtime/core/context.d.ts +2 -2
- package/dist/runtime/core/context.js +8 -8
- 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 +2 -2
- package/dist/runtime/core/eval/mixins/closures.js +367 -27
- 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 +17 -12
- package/dist/runtime/core/eval/mixins/core.js +15 -2
- package/dist/runtime/core/eval/mixins/expressions.js +3 -2
- 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 +14 -3
- package/dist/runtime/core/eval/mixins/types.js +30 -1
- package/dist/runtime/core/eval/mixins/variables.js +3 -1
- package/dist/runtime/core/execute.d.ts +1 -1
- package/dist/runtime/core/field-descriptor.d.ts +1 -1
- package/dist/runtime/core/introspection.d.ts +2 -2
- package/dist/runtime/core/introspection.js +2 -1
- 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/operations.d.ts +98 -0
- package/dist/runtime/core/types/operations.js +804 -0
- package/dist/runtime/core/{type-registrations.d.ts → types/registrations.d.ts} +12 -22
- package/dist/runtime/core/{type-registrations.js → types/registrations.js} +94 -92
- package/dist/runtime/core/{types.d.ts → types/runtime.d.ts} +8 -8
- package/dist/runtime/core/{type-structures.d.ts → types/structures.d.ts} +21 -3
- package/dist/runtime/core/values.d.ts +13 -102
- package/dist/runtime/core/values.js +26 -722
- package/dist/runtime/ext/builtins.js +9 -8
- package/dist/runtime/ext/extensions.d.ts +2 -2
- package/dist/runtime/ext/extensions.js +2 -1
- package/dist/runtime/ext/test-context.d.ts +2 -2
- package/dist/runtime/ext/test-context.js +3 -2
- package/dist/runtime/index.d.ts +8 -22
- package/dist/runtime/index.js +10 -16
- package/dist/signature-parser.d.ts +1 -1
- package/dist/token-types.d.ts +1 -0
- package/dist/token-types.js +1 -0
- package/package.json +1 -1
- /package/dist/runtime/core/{markers.d.ts → types/markers.d.ts} +0 -0
- /package/dist/runtime/core/{markers.js → types/markers.js} +0 -0
- /package/dist/runtime/core/{types.js → types/runtime.js} +0 -0
- /package/dist/runtime/core/{type-structures.js → types/structures.js} +0 -0
package/dist/ext/fs/index.js
CHANGED
|
@@ -8,8 +8,8 @@ import fs from 'node:fs/promises';
|
|
|
8
8
|
import path from 'node:path';
|
|
9
9
|
import { RuntimeError } from '../../error-classes.js';
|
|
10
10
|
import { toCallable } from '../../runtime/core/callable.js';
|
|
11
|
-
import {
|
|
12
|
-
import { resolvePath, matchesGlob, initializeMount, } from './sandbox.js';
|
|
11
|
+
import { structureToTypeValue } from '../../runtime/core/values.js';
|
|
12
|
+
import { resolvePath, matchesGlob, initializeMount, parseMountPath, } from './sandbox.js';
|
|
13
13
|
export const configSchema = {
|
|
14
14
|
mounts: { type: 'string', required: true },
|
|
15
15
|
};
|
|
@@ -76,8 +76,7 @@ export function createFsExtension(config) {
|
|
|
76
76
|
// ctx and location not used but required by CallableFn signature
|
|
77
77
|
) => {
|
|
78
78
|
await ensureInitialized();
|
|
79
|
-
const mountName = args['
|
|
80
|
-
const filePath = args['path'];
|
|
79
|
+
const { mountName, relativePath: filePath } = parseMountPath(args['path'], mounts);
|
|
81
80
|
// EC-5: Catch file not found from resolvePath
|
|
82
81
|
let resolvedPath;
|
|
83
82
|
try {
|
|
@@ -102,8 +101,7 @@ export function createFsExtension(config) {
|
|
|
102
101
|
*/
|
|
103
102
|
const write = async (args) => {
|
|
104
103
|
await ensureInitialized();
|
|
105
|
-
const mountName = args['
|
|
106
|
-
const filePath = args['path'];
|
|
104
|
+
const { mountName, relativePath: filePath } = parseMountPath(args['path'], mounts);
|
|
107
105
|
const content = args['content'];
|
|
108
106
|
const resolvedPath = await resolvePath(mountName, filePath, mounts, 'write', true // createMode: resolve parent directory
|
|
109
107
|
);
|
|
@@ -121,8 +119,7 @@ export function createFsExtension(config) {
|
|
|
121
119
|
*/
|
|
122
120
|
const append = async (args) => {
|
|
123
121
|
await ensureInitialized();
|
|
124
|
-
const mountName = args['
|
|
125
|
-
const filePath = args['path'];
|
|
122
|
+
const { mountName, relativePath: filePath } = parseMountPath(args['path'], mounts);
|
|
126
123
|
const content = args['content'];
|
|
127
124
|
const resolvedPath = await resolvePath(mountName, filePath, mounts, 'write', true // createMode: allow new files
|
|
128
125
|
);
|
|
@@ -158,8 +155,7 @@ export function createFsExtension(config) {
|
|
|
158
155
|
*/
|
|
159
156
|
const list = async (args) => {
|
|
160
157
|
await ensureInitialized();
|
|
161
|
-
const mountName = args['
|
|
162
|
-
const dirPath = args['path'] ?? '';
|
|
158
|
+
const { mountName, relativePath: dirPath } = parseMountPath(args['path'], mounts);
|
|
163
159
|
const resolvedPath = await resolvePath(mountName, dirPath, mounts, 'read');
|
|
164
160
|
const entries = await fs.readdir(resolvedPath, { withFileTypes: true });
|
|
165
161
|
const result = [];
|
|
@@ -180,13 +176,20 @@ export function createFsExtension(config) {
|
|
|
180
176
|
*/
|
|
181
177
|
const find = async (args) => {
|
|
182
178
|
await ensureInitialized();
|
|
183
|
-
const mountName = args['
|
|
179
|
+
const { mountName, relativePath: searchBase } = parseMountPath(args['path'], mounts);
|
|
184
180
|
const pattern = args['pattern'] ?? '*';
|
|
185
181
|
const mount = mounts[mountName];
|
|
186
182
|
if (!mount || !mount.resolvedPath) {
|
|
187
183
|
throw new RuntimeError('RILL-R004', `mount "${mountName}" not configured`, undefined, { mountName });
|
|
188
184
|
}
|
|
189
|
-
|
|
185
|
+
let basePath;
|
|
186
|
+
if (searchBase) {
|
|
187
|
+
// Validate searchBase through sandbox resolver to prevent path traversal
|
|
188
|
+
basePath = await resolvePath(mountName, searchBase, mounts, 'read');
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
basePath = mount.resolvedPath;
|
|
192
|
+
}
|
|
190
193
|
const results = [];
|
|
191
194
|
// Recursive directory traversal
|
|
192
195
|
const traverse = async (currentPath) => {
|
|
@@ -198,7 +201,7 @@ export function createFsExtension(config) {
|
|
|
198
201
|
}
|
|
199
202
|
else if (matchesGlob(entry.name, pattern)) {
|
|
200
203
|
// Return path relative to mount base
|
|
201
|
-
const relativePath = path.relative(
|
|
204
|
+
const relativePath = path.relative(mount.resolvedPath, fullPath);
|
|
202
205
|
results.push(relativePath);
|
|
203
206
|
}
|
|
204
207
|
}
|
|
@@ -212,8 +215,7 @@ export function createFsExtension(config) {
|
|
|
212
215
|
*/
|
|
213
216
|
const exists = async (args) => {
|
|
214
217
|
await ensureInitialized();
|
|
215
|
-
const mountName = args['
|
|
216
|
-
const filePath = args['path'];
|
|
218
|
+
const { mountName, relativePath: filePath } = parseMountPath(args['path'], mounts);
|
|
217
219
|
try {
|
|
218
220
|
await resolvePath(mountName, filePath, mounts, 'read');
|
|
219
221
|
return true;
|
|
@@ -232,8 +234,7 @@ export function createFsExtension(config) {
|
|
|
232
234
|
*/
|
|
233
235
|
const remove = async (args) => {
|
|
234
236
|
await ensureInitialized();
|
|
235
|
-
const mountName = args['
|
|
236
|
-
const filePath = args['path'];
|
|
237
|
+
const { mountName, relativePath: filePath } = parseMountPath(args['path'], mounts);
|
|
237
238
|
// Catch file not found from resolvePath
|
|
238
239
|
let resolvedPath;
|
|
239
240
|
try {
|
|
@@ -265,8 +266,7 @@ export function createFsExtension(config) {
|
|
|
265
266
|
*/
|
|
266
267
|
const stat = async (args) => {
|
|
267
268
|
await ensureInitialized();
|
|
268
|
-
const mountName = args['
|
|
269
|
-
const filePath = args['path'];
|
|
269
|
+
const { mountName, relativePath: filePath } = parseMountPath(args['path'], mounts);
|
|
270
270
|
// Catch file not found from resolvePath
|
|
271
271
|
let resolvedPath;
|
|
272
272
|
try {
|
|
@@ -295,8 +295,7 @@ export function createFsExtension(config) {
|
|
|
295
295
|
*/
|
|
296
296
|
const mkdir = async (args) => {
|
|
297
297
|
await ensureInitialized();
|
|
298
|
-
const mountName = args['
|
|
299
|
-
const dirPath = args['path'];
|
|
298
|
+
const { mountName, relativePath: dirPath } = parseMountPath(args['path'], mounts);
|
|
300
299
|
const mount = mounts[mountName];
|
|
301
300
|
if (!mount || !mount.resolvedPath) {
|
|
302
301
|
throw new RuntimeError('RILL-R004', `mount "${mountName}" not configured`, undefined, { mountName });
|
|
@@ -345,9 +344,13 @@ export function createFsExtension(config) {
|
|
|
345
344
|
*/
|
|
346
345
|
const copy = async (args) => {
|
|
347
346
|
await ensureInitialized();
|
|
348
|
-
const mountName = args['
|
|
349
|
-
const
|
|
350
|
-
const
|
|
347
|
+
const { mountName: srcMountName, relativePath: srcPath } = parseMountPath(args['src'], mounts);
|
|
348
|
+
const { mountName: destMountName, relativePath: destPath } = parseMountPath(args['dest'], mounts);
|
|
349
|
+
const mountName = srcMountName;
|
|
350
|
+
// Verify same mount
|
|
351
|
+
if (srcMountName !== destMountName) {
|
|
352
|
+
throw new RuntimeError('RILL-R004', `copy requires same mount for src and dest`, undefined, { src: args['src'], dest: args['dest'] });
|
|
353
|
+
}
|
|
351
354
|
const resolvedSrc = await resolvePath(mountName, srcPath, mounts, 'read');
|
|
352
355
|
const resolvedDest = await resolvePath(mountName, destPath, mounts, 'write', true // createMode
|
|
353
356
|
);
|
|
@@ -374,9 +377,13 @@ export function createFsExtension(config) {
|
|
|
374
377
|
*/
|
|
375
378
|
const move = async (args) => {
|
|
376
379
|
await ensureInitialized();
|
|
377
|
-
const mountName = args['
|
|
378
|
-
const
|
|
379
|
-
const
|
|
380
|
+
const { mountName: srcMountName, relativePath: srcPath } = parseMountPath(args['src'], mounts);
|
|
381
|
+
const { mountName: destMountName, relativePath: destPath } = parseMountPath(args['dest'], mounts);
|
|
382
|
+
const mountName = srcMountName;
|
|
383
|
+
// Verify same mount
|
|
384
|
+
if (srcMountName !== destMountName) {
|
|
385
|
+
throw new RuntimeError('RILL-R004', `move requires same mount for src and dest`, undefined, { src: args['src'], dest: args['dest'] });
|
|
386
|
+
}
|
|
380
387
|
const resolvedSrc = await resolvePath(mountName, srcPath, mounts, 'read');
|
|
381
388
|
const resolvedDest = await resolvePath(mountName, destPath, mounts, 'write', true // createMode
|
|
382
389
|
);
|
|
@@ -416,36 +423,28 @@ export function createFsExtension(config) {
|
|
|
416
423
|
value: {
|
|
417
424
|
read: toCallable({
|
|
418
425
|
params: [
|
|
419
|
-
{
|
|
420
|
-
name: 'mount',
|
|
421
|
-
type: { kind: 'string' },
|
|
422
|
-
defaultValue: undefined,
|
|
423
|
-
annotations: { description: 'Mount name' },
|
|
424
|
-
},
|
|
425
426
|
{
|
|
426
427
|
name: 'path',
|
|
427
428
|
type: { kind: 'string' },
|
|
428
429
|
defaultValue: undefined,
|
|
429
|
-
annotations: {
|
|
430
|
+
annotations: {
|
|
431
|
+
description: 'Mount-prefixed file path (e.g. "/mount/file.txt")',
|
|
432
|
+
},
|
|
430
433
|
},
|
|
431
434
|
],
|
|
432
435
|
fn: read,
|
|
433
436
|
annotations: { description: 'Read file contents' },
|
|
434
|
-
returnType:
|
|
437
|
+
returnType: structureToTypeValue({ kind: 'string' }),
|
|
435
438
|
}),
|
|
436
439
|
write: toCallable({
|
|
437
440
|
params: [
|
|
438
|
-
{
|
|
439
|
-
name: 'mount',
|
|
440
|
-
type: { kind: 'string' },
|
|
441
|
-
defaultValue: undefined,
|
|
442
|
-
annotations: { description: 'Mount name' },
|
|
443
|
-
},
|
|
444
441
|
{
|
|
445
442
|
name: 'path',
|
|
446
443
|
type: { kind: 'string' },
|
|
447
444
|
defaultValue: undefined,
|
|
448
|
-
annotations: {
|
|
445
|
+
annotations: {
|
|
446
|
+
description: 'Mount-prefixed file path (e.g. "/mount/file.txt")',
|
|
447
|
+
},
|
|
449
448
|
},
|
|
450
449
|
{
|
|
451
450
|
name: 'content',
|
|
@@ -456,21 +455,17 @@ export function createFsExtension(config) {
|
|
|
456
455
|
],
|
|
457
456
|
fn: write,
|
|
458
457
|
annotations: { description: 'Write file, replacing if exists' },
|
|
459
|
-
returnType:
|
|
458
|
+
returnType: structureToTypeValue({ kind: 'string' }),
|
|
460
459
|
}),
|
|
461
460
|
append: toCallable({
|
|
462
461
|
params: [
|
|
463
|
-
{
|
|
464
|
-
name: 'mount',
|
|
465
|
-
type: { kind: 'string' },
|
|
466
|
-
defaultValue: undefined,
|
|
467
|
-
annotations: { description: 'Mount name' },
|
|
468
|
-
},
|
|
469
462
|
{
|
|
470
463
|
name: 'path',
|
|
471
464
|
type: { kind: 'string' },
|
|
472
465
|
defaultValue: undefined,
|
|
473
|
-
annotations: {
|
|
466
|
+
annotations: {
|
|
467
|
+
description: 'Mount-prefixed file path (e.g. "/mount/file.txt")',
|
|
468
|
+
},
|
|
474
469
|
},
|
|
475
470
|
{
|
|
476
471
|
name: 'content',
|
|
@@ -481,34 +476,42 @@ export function createFsExtension(config) {
|
|
|
481
476
|
],
|
|
482
477
|
fn: append,
|
|
483
478
|
annotations: { description: 'Append content to file' },
|
|
484
|
-
returnType:
|
|
479
|
+
returnType: structureToTypeValue({ kind: 'string' }),
|
|
485
480
|
}),
|
|
486
481
|
list: toCallable({
|
|
487
482
|
params: [
|
|
488
|
-
{
|
|
489
|
-
name: 'mount',
|
|
490
|
-
type: { kind: 'string' },
|
|
491
|
-
defaultValue: undefined,
|
|
492
|
-
annotations: { description: 'Mount name' },
|
|
493
|
-
},
|
|
494
483
|
{
|
|
495
484
|
name: 'path',
|
|
496
485
|
type: { kind: 'string' },
|
|
497
|
-
defaultValue:
|
|
498
|
-
annotations: {
|
|
486
|
+
defaultValue: undefined,
|
|
487
|
+
annotations: {
|
|
488
|
+
description: 'Mount-prefixed directory path (e.g. "/mount/subdir")',
|
|
489
|
+
},
|
|
499
490
|
},
|
|
500
491
|
],
|
|
501
492
|
fn: list,
|
|
502
493
|
annotations: { description: 'List directory contents' },
|
|
503
|
-
returnType:
|
|
494
|
+
returnType: structureToTypeValue({
|
|
495
|
+
kind: 'list',
|
|
496
|
+
element: {
|
|
497
|
+
kind: 'dict',
|
|
498
|
+
fields: {
|
|
499
|
+
name: { type: { kind: 'string' } },
|
|
500
|
+
type: { type: { kind: 'string' } },
|
|
501
|
+
size: { type: { kind: 'number' } },
|
|
502
|
+
},
|
|
503
|
+
},
|
|
504
|
+
}),
|
|
504
505
|
}),
|
|
505
506
|
find: toCallable({
|
|
506
507
|
params: [
|
|
507
508
|
{
|
|
508
|
-
name: '
|
|
509
|
+
name: 'path',
|
|
509
510
|
type: { kind: 'string' },
|
|
510
511
|
defaultValue: undefined,
|
|
511
|
-
annotations: {
|
|
512
|
+
annotations: {
|
|
513
|
+
description: 'Mount-prefixed base path (e.g. "/mount" or "/mount/subdir")',
|
|
514
|
+
},
|
|
512
515
|
},
|
|
513
516
|
{
|
|
514
517
|
name: 'pattern',
|
|
@@ -519,139 +522,123 @@ export function createFsExtension(config) {
|
|
|
519
522
|
],
|
|
520
523
|
fn: find,
|
|
521
524
|
annotations: { description: 'Recursive file search' },
|
|
522
|
-
returnType:
|
|
525
|
+
returnType: structureToTypeValue({
|
|
526
|
+
kind: 'list',
|
|
527
|
+
element: { kind: 'string' },
|
|
528
|
+
}),
|
|
523
529
|
}),
|
|
524
530
|
exists: toCallable({
|
|
525
531
|
params: [
|
|
526
|
-
{
|
|
527
|
-
name: 'mount',
|
|
528
|
-
type: { kind: 'string' },
|
|
529
|
-
defaultValue: undefined,
|
|
530
|
-
annotations: { description: 'Mount name' },
|
|
531
|
-
},
|
|
532
532
|
{
|
|
533
533
|
name: 'path',
|
|
534
534
|
type: { kind: 'string' },
|
|
535
535
|
defaultValue: undefined,
|
|
536
|
-
annotations: {
|
|
536
|
+
annotations: {
|
|
537
|
+
description: 'Mount-prefixed file path (e.g. "/mount/file.txt")',
|
|
538
|
+
},
|
|
537
539
|
},
|
|
538
540
|
],
|
|
539
541
|
fn: exists,
|
|
540
542
|
annotations: { description: 'Check file existence' },
|
|
541
|
-
returnType:
|
|
543
|
+
returnType: structureToTypeValue({ kind: 'bool' }),
|
|
542
544
|
}),
|
|
543
545
|
remove: toCallable({
|
|
544
546
|
params: [
|
|
545
|
-
{
|
|
546
|
-
name: 'mount',
|
|
547
|
-
type: { kind: 'string' },
|
|
548
|
-
defaultValue: undefined,
|
|
549
|
-
annotations: { description: 'Mount name' },
|
|
550
|
-
},
|
|
551
547
|
{
|
|
552
548
|
name: 'path',
|
|
553
549
|
type: { kind: 'string' },
|
|
554
550
|
defaultValue: undefined,
|
|
555
|
-
annotations: {
|
|
551
|
+
annotations: {
|
|
552
|
+
description: 'Mount-prefixed file path (e.g. "/mount/file.txt")',
|
|
553
|
+
},
|
|
556
554
|
},
|
|
557
555
|
],
|
|
558
556
|
fn: remove,
|
|
559
557
|
annotations: { description: 'Delete file' },
|
|
560
|
-
returnType:
|
|
558
|
+
returnType: structureToTypeValue({ kind: 'bool' }),
|
|
561
559
|
}),
|
|
562
560
|
stat: toCallable({
|
|
563
561
|
params: [
|
|
564
|
-
{
|
|
565
|
-
name: 'mount',
|
|
566
|
-
type: { kind: 'string' },
|
|
567
|
-
defaultValue: undefined,
|
|
568
|
-
annotations: { description: 'Mount name' },
|
|
569
|
-
},
|
|
570
562
|
{
|
|
571
563
|
name: 'path',
|
|
572
564
|
type: { kind: 'string' },
|
|
573
565
|
defaultValue: undefined,
|
|
574
|
-
annotations: {
|
|
566
|
+
annotations: {
|
|
567
|
+
description: 'Mount-prefixed file path (e.g. "/mount/file.txt")',
|
|
568
|
+
},
|
|
575
569
|
},
|
|
576
570
|
],
|
|
577
571
|
fn: stat,
|
|
578
572
|
annotations: { description: 'Get file metadata' },
|
|
579
|
-
returnType:
|
|
573
|
+
returnType: structureToTypeValue({
|
|
574
|
+
kind: 'dict',
|
|
575
|
+
fields: {
|
|
576
|
+
name: { type: { kind: 'string' } },
|
|
577
|
+
type: { type: { kind: 'string' } },
|
|
578
|
+
size: { type: { kind: 'number' } },
|
|
579
|
+
created: { type: { kind: 'string' } },
|
|
580
|
+
modified: { type: { kind: 'string' } },
|
|
581
|
+
},
|
|
582
|
+
}),
|
|
580
583
|
}),
|
|
581
584
|
mkdir: toCallable({
|
|
582
585
|
params: [
|
|
583
|
-
{
|
|
584
|
-
name: 'mount',
|
|
585
|
-
type: { kind: 'string' },
|
|
586
|
-
defaultValue: undefined,
|
|
587
|
-
annotations: { description: 'Mount name' },
|
|
588
|
-
},
|
|
589
586
|
{
|
|
590
587
|
name: 'path',
|
|
591
588
|
type: { kind: 'string' },
|
|
592
589
|
defaultValue: undefined,
|
|
593
|
-
annotations: {
|
|
590
|
+
annotations: {
|
|
591
|
+
description: 'Mount-prefixed directory path (e.g. "/mount/subdir")',
|
|
592
|
+
},
|
|
594
593
|
},
|
|
595
594
|
],
|
|
596
595
|
fn: mkdir,
|
|
597
596
|
annotations: { description: 'Create directory' },
|
|
598
|
-
returnType:
|
|
597
|
+
returnType: structureToTypeValue({ kind: 'bool' }),
|
|
599
598
|
}),
|
|
600
599
|
copy: toCallable({
|
|
601
600
|
params: [
|
|
602
|
-
{
|
|
603
|
-
name: 'mount',
|
|
604
|
-
type: { kind: 'string' },
|
|
605
|
-
defaultValue: undefined,
|
|
606
|
-
annotations: { description: 'Mount name' },
|
|
607
|
-
},
|
|
608
601
|
{
|
|
609
602
|
name: 'src',
|
|
610
603
|
type: { kind: 'string' },
|
|
611
604
|
defaultValue: undefined,
|
|
612
|
-
annotations: { description: '
|
|
605
|
+
annotations: { description: 'Mount-prefixed source path' },
|
|
613
606
|
},
|
|
614
607
|
{
|
|
615
608
|
name: 'dest',
|
|
616
609
|
type: { kind: 'string' },
|
|
617
610
|
defaultValue: undefined,
|
|
618
|
-
annotations: { description: '
|
|
611
|
+
annotations: { description: 'Mount-prefixed destination path' },
|
|
619
612
|
},
|
|
620
613
|
],
|
|
621
614
|
fn: copy,
|
|
622
615
|
annotations: { description: 'Copy file within mount' },
|
|
623
|
-
returnType:
|
|
616
|
+
returnType: structureToTypeValue({ kind: 'bool' }),
|
|
624
617
|
}),
|
|
625
618
|
move: toCallable({
|
|
626
619
|
params: [
|
|
627
|
-
{
|
|
628
|
-
name: 'mount',
|
|
629
|
-
type: { kind: 'string' },
|
|
630
|
-
defaultValue: undefined,
|
|
631
|
-
annotations: { description: 'Mount name' },
|
|
632
|
-
},
|
|
633
620
|
{
|
|
634
621
|
name: 'src',
|
|
635
622
|
type: { kind: 'string' },
|
|
636
623
|
defaultValue: undefined,
|
|
637
|
-
annotations: { description: '
|
|
624
|
+
annotations: { description: 'Mount-prefixed source path' },
|
|
638
625
|
},
|
|
639
626
|
{
|
|
640
627
|
name: 'dest',
|
|
641
628
|
type: { kind: 'string' },
|
|
642
629
|
defaultValue: undefined,
|
|
643
|
-
annotations: { description: '
|
|
630
|
+
annotations: { description: 'Mount-prefixed destination path' },
|
|
644
631
|
},
|
|
645
632
|
],
|
|
646
633
|
fn: move,
|
|
647
634
|
annotations: { description: 'Move file within mount' },
|
|
648
|
-
returnType:
|
|
635
|
+
returnType: structureToTypeValue({ kind: 'bool' }),
|
|
649
636
|
}),
|
|
650
637
|
mounts: toCallable({
|
|
651
638
|
params: [],
|
|
652
639
|
fn: mountsList,
|
|
653
640
|
annotations: { description: 'List configured mounts' },
|
|
654
|
-
returnType:
|
|
641
|
+
returnType: structureToTypeValue({ kind: 'list' }),
|
|
655
642
|
}),
|
|
656
643
|
},
|
|
657
644
|
};
|
package/dist/ext/fs/sandbox.d.ts
CHANGED
|
@@ -75,3 +75,21 @@ export declare function checkMode(mode: 'read' | 'write' | 'read-write', operati
|
|
|
75
75
|
* @throws RuntimeError - If mount path invalid or inaccessible
|
|
76
76
|
*/
|
|
77
77
|
export declare function initializeMount(mount: MountConfig): Promise<void>;
|
|
78
|
+
/**
|
|
79
|
+
* Parses a mount-prefixed path into mount name and relative path.
|
|
80
|
+
*
|
|
81
|
+
* Uses longest-first prefix matching to support mount names containing slashes.
|
|
82
|
+
* Strips a leading `/` before matching.
|
|
83
|
+
* Example: "/workspace/my/file.txt" → { mountName: "workspace", relativePath: "my/file.txt" }
|
|
84
|
+
* Example: "/the/mount/file.txt" → { mountName: "the/mount", relativePath: "file.txt" }
|
|
85
|
+
* Example: "/workspace" → { mountName: "workspace", relativePath: "" }
|
|
86
|
+
*
|
|
87
|
+
* @param fullPath - Path with leading `/` and mount prefix
|
|
88
|
+
* @param mounts - Mount configuration map
|
|
89
|
+
* @returns Parsed mount name and relative path
|
|
90
|
+
* @throws RuntimeError - If no mount matches the path prefix
|
|
91
|
+
*/
|
|
92
|
+
export declare function parseMountPath(fullPath: string, mounts: Record<string, MountConfig>): {
|
|
93
|
+
mountName: string;
|
|
94
|
+
relativePath: string;
|
|
95
|
+
};
|
package/dist/ext/fs/sandbox.js
CHANGED
|
@@ -205,3 +205,36 @@ export async function initializeMount(mount) {
|
|
|
205
205
|
throw error;
|
|
206
206
|
}
|
|
207
207
|
}
|
|
208
|
+
// ============================================================
|
|
209
|
+
// MOUNT PATH PARSING
|
|
210
|
+
// ============================================================
|
|
211
|
+
/**
|
|
212
|
+
* Parses a mount-prefixed path into mount name and relative path.
|
|
213
|
+
*
|
|
214
|
+
* Uses longest-first prefix matching to support mount names containing slashes.
|
|
215
|
+
* Strips a leading `/` before matching.
|
|
216
|
+
* Example: "/workspace/my/file.txt" → { mountName: "workspace", relativePath: "my/file.txt" }
|
|
217
|
+
* Example: "/the/mount/file.txt" → { mountName: "the/mount", relativePath: "file.txt" }
|
|
218
|
+
* Example: "/workspace" → { mountName: "workspace", relativePath: "" }
|
|
219
|
+
*
|
|
220
|
+
* @param fullPath - Path with leading `/` and mount prefix
|
|
221
|
+
* @param mounts - Mount configuration map
|
|
222
|
+
* @returns Parsed mount name and relative path
|
|
223
|
+
* @throws RuntimeError - If no mount matches the path prefix
|
|
224
|
+
*/
|
|
225
|
+
export function parseMountPath(fullPath, mounts) {
|
|
226
|
+
const normalized = fullPath.startsWith('/') ? fullPath.slice(1) : fullPath;
|
|
227
|
+
const sortedNames = Object.keys(mounts).sort((a, b) => b.length - a.length);
|
|
228
|
+
for (const mountName of sortedNames) {
|
|
229
|
+
if (normalized === mountName) {
|
|
230
|
+
return { mountName, relativePath: '' };
|
|
231
|
+
}
|
|
232
|
+
if (normalized.startsWith(mountName + '/')) {
|
|
233
|
+
return {
|
|
234
|
+
mountName,
|
|
235
|
+
relativePath: normalized.slice(mountName.length + 1),
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
throw new RuntimeError('RILL-R017', `no mount matches path "${fullPath}"`, undefined, { path: fullPath });
|
|
240
|
+
}
|
package/dist/ext/kv/index.js
CHANGED
|
@@ -8,7 +8,7 @@ import { RuntimeError } from '../../error-classes.js';
|
|
|
8
8
|
import { toCallable } from '../../runtime/core/callable.js';
|
|
9
9
|
import { isDict } from '../../runtime/core/callable.js';
|
|
10
10
|
import { createStore } from './store.js';
|
|
11
|
-
import {
|
|
11
|
+
import { structureToTypeValue } from '../../runtime/core/values.js';
|
|
12
12
|
export const configSchema = {
|
|
13
13
|
store: { type: 'string' },
|
|
14
14
|
mounts: { type: 'string' },
|
|
@@ -299,7 +299,7 @@ export function createKvExtension(config) {
|
|
|
299
299
|
],
|
|
300
300
|
fn: get,
|
|
301
301
|
annotations: { description: 'Get value or schema default' },
|
|
302
|
-
returnType:
|
|
302
|
+
returnType: structureToTypeValue({ kind: 'any' }),
|
|
303
303
|
}),
|
|
304
304
|
get_or: toCallable({
|
|
305
305
|
params: [
|
|
@@ -326,7 +326,7 @@ export function createKvExtension(config) {
|
|
|
326
326
|
annotations: {
|
|
327
327
|
description: 'Get value or return fallback if key missing',
|
|
328
328
|
},
|
|
329
|
-
returnType:
|
|
329
|
+
returnType: structureToTypeValue({ kind: 'any' }),
|
|
330
330
|
}),
|
|
331
331
|
set: toCallable({
|
|
332
332
|
params: [
|
|
@@ -351,7 +351,7 @@ export function createKvExtension(config) {
|
|
|
351
351
|
],
|
|
352
352
|
fn: set,
|
|
353
353
|
annotations: { description: 'Set value with validation' },
|
|
354
|
-
returnType:
|
|
354
|
+
returnType: structureToTypeValue({ kind: 'bool' }),
|
|
355
355
|
}),
|
|
356
356
|
merge: toCallable({
|
|
357
357
|
params: [
|
|
@@ -378,7 +378,7 @@ export function createKvExtension(config) {
|
|
|
378
378
|
annotations: {
|
|
379
379
|
description: 'Merge partial dict into existing dict value',
|
|
380
380
|
},
|
|
381
|
-
returnType:
|
|
381
|
+
returnType: structureToTypeValue({ kind: 'bool' }),
|
|
382
382
|
}),
|
|
383
383
|
delete: toCallable({
|
|
384
384
|
params: [
|
|
@@ -397,7 +397,7 @@ export function createKvExtension(config) {
|
|
|
397
397
|
],
|
|
398
398
|
fn: deleteKey,
|
|
399
399
|
annotations: { description: 'Delete key' },
|
|
400
|
-
returnType:
|
|
400
|
+
returnType: structureToTypeValue({ kind: 'bool' }),
|
|
401
401
|
}),
|
|
402
402
|
keys: toCallable({
|
|
403
403
|
params: [
|
|
@@ -410,7 +410,7 @@ export function createKvExtension(config) {
|
|
|
410
410
|
],
|
|
411
411
|
fn: keys,
|
|
412
412
|
annotations: { description: 'Get all keys in mount' },
|
|
413
|
-
returnType:
|
|
413
|
+
returnType: structureToTypeValue({ kind: 'list' }),
|
|
414
414
|
}),
|
|
415
415
|
has: toCallable({
|
|
416
416
|
params: [
|
|
@@ -429,7 +429,7 @@ export function createKvExtension(config) {
|
|
|
429
429
|
],
|
|
430
430
|
fn: has,
|
|
431
431
|
annotations: { description: 'Check key existence' },
|
|
432
|
-
returnType:
|
|
432
|
+
returnType: structureToTypeValue({ kind: 'bool' }),
|
|
433
433
|
}),
|
|
434
434
|
clear: toCallable({
|
|
435
435
|
params: [
|
|
@@ -442,7 +442,7 @@ export function createKvExtension(config) {
|
|
|
442
442
|
],
|
|
443
443
|
fn: clear,
|
|
444
444
|
annotations: { description: 'Clear all keys in mount' },
|
|
445
|
-
returnType:
|
|
445
|
+
returnType: structureToTypeValue({ kind: 'bool' }),
|
|
446
446
|
}),
|
|
447
447
|
getAll: toCallable({
|
|
448
448
|
params: [
|
|
@@ -455,7 +455,7 @@ export function createKvExtension(config) {
|
|
|
455
455
|
],
|
|
456
456
|
fn: getAll,
|
|
457
457
|
annotations: { description: 'Get all entries as dict' },
|
|
458
|
-
returnType:
|
|
458
|
+
returnType: structureToTypeValue({ kind: 'dict' }),
|
|
459
459
|
}),
|
|
460
460
|
schema: toCallable({
|
|
461
461
|
params: [
|
|
@@ -468,13 +468,13 @@ export function createKvExtension(config) {
|
|
|
468
468
|
],
|
|
469
469
|
fn: schema,
|
|
470
470
|
annotations: { description: 'Get schema information' },
|
|
471
|
-
returnType:
|
|
471
|
+
returnType: structureToTypeValue({ kind: 'list' }),
|
|
472
472
|
}),
|
|
473
473
|
mounts: toCallable({
|
|
474
474
|
params: [],
|
|
475
475
|
fn: mountsList,
|
|
476
476
|
annotations: { description: 'Get list of mount metadata' },
|
|
477
|
-
returnType:
|
|
477
|
+
returnType: structureToTypeValue({ kind: 'list' }),
|
|
478
478
|
}),
|
|
479
479
|
},
|
|
480
480
|
dispose,
|
package/dist/ext/kv/store.d.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Provides JSON-based key-value persistence with schema validation.
|
|
5
5
|
* Lifecycle: Load (read store file) -> Execute (in-memory operations) -> Flush (atomic write on dispose)
|
|
6
6
|
*/
|
|
7
|
-
import type { RillValue } from '../../runtime/core/
|
|
7
|
+
import type { RillValue } from '../../runtime/core/types/structures.js';
|
|
8
8
|
/** Schema entry defining type and default for a key */
|
|
9
9
|
export interface SchemaEntry {
|
|
10
10
|
type: 'string' | 'number' | 'bool' | 'list' | 'dict';
|
package/dist/ext/kv/store.js
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
import fs from 'node:fs/promises';
|
|
8
8
|
import path from 'node:path';
|
|
9
9
|
import { RuntimeError } from '../../error-classes.js';
|
|
10
|
-
import { deserializeValue } from '../../runtime/core/
|
|
10
|
+
import { deserializeValue } from '../../runtime/core/types/registrations.js';
|
|
11
11
|
// ============================================================
|
|
12
12
|
// STORE IMPLEMENTATION
|
|
13
13
|
// ============================================================
|
|
@@ -3,13 +3,13 @@
|
|
|
3
3
|
/**
|
|
4
4
|
* Version string from package.json
|
|
5
5
|
*/
|
|
6
|
-
export const VERSION = '0.
|
|
6
|
+
export const VERSION = '0.18.0';
|
|
7
7
|
/**
|
|
8
8
|
* Parsed version components
|
|
9
9
|
*/
|
|
10
10
|
export const VERSION_INFO = {
|
|
11
11
|
major: 0,
|
|
12
|
-
minor:
|
|
12
|
+
minor: 18,
|
|
13
13
|
patch: 0,
|
|
14
14
|
prerelease: undefined,
|
|
15
15
|
};
|