@adecore/intelligent-ui 0.33.2 → 0.34.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/budget.js +10 -8
- package/dist/compiler.d.ts +1 -1
- package/dist/compiler.js +3 -3
- package/package.json +1 -1
- package/src/budget.ts +12 -8
- package/src/compiler.ts +3 -3
package/dist/budget.js
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
|
+
const BLOCK_CHARACTERS = 65536;
|
|
1
2
|
export const UI_LIMITS = {
|
|
2
|
-
characters:
|
|
3
|
+
characters: BLOCK_CHARACTERS,
|
|
3
4
|
depth: 32,
|
|
4
5
|
nodes: 512,
|
|
5
6
|
diagnostics: 20,
|
|
6
|
-
|
|
7
|
+
// Parsing and validating a string literal can account for each character four times.
|
|
8
|
+
steps: 4 * BLOCK_CHARACTERS,
|
|
7
9
|
iterations: 2000,
|
|
8
10
|
stringLength: 16384,
|
|
9
|
-
milliseconds:
|
|
11
|
+
milliseconds: 0
|
|
10
12
|
};
|
|
11
13
|
export class UiFailure extends Error {
|
|
12
14
|
code;
|
|
@@ -26,16 +28,16 @@ export class UiBudget {
|
|
|
26
28
|
constructor(limits = {}, now = Date.now) {
|
|
27
29
|
this.now = now;
|
|
28
30
|
this.limits = { ...UI_LIMITS, ...limits };
|
|
29
|
-
for (const value of Object.
|
|
30
|
-
if (!Number.isSafeInteger(value) || value
|
|
31
|
-
throw new UiFailure('invalid_limits', 'Budgets must be positive safe integers.');
|
|
31
|
+
for (const [name, value] of Object.entries(this.limits)) {
|
|
32
|
+
if (!Number.isSafeInteger(value) || value < 0 || (value === 0 && name !== 'milliseconds')) {
|
|
33
|
+
throw new UiFailure('invalid_limits', 'Budgets must be positive safe integers, except milliseconds may be zero.');
|
|
32
34
|
}
|
|
33
35
|
}
|
|
34
|
-
this.started = now();
|
|
36
|
+
this.started = this.limits.milliseconds > 0 ? now() : 0;
|
|
35
37
|
}
|
|
36
38
|
step(count = 1) {
|
|
37
39
|
this.steps += count;
|
|
38
|
-
if (this.steps > this.limits.steps || this.now() - this.started > this.limits.milliseconds) {
|
|
40
|
+
if (this.steps > this.limits.steps || (this.limits.milliseconds > 0 && this.now() - this.started > this.limits.milliseconds)) {
|
|
39
41
|
throw new UiFailure('budget_exceeded', 'The operation exceeded its work budget.');
|
|
40
42
|
}
|
|
41
43
|
}
|
package/dist/compiler.d.ts
CHANGED
package/dist/compiler.js
CHANGED
|
@@ -9,7 +9,7 @@ import { parseUiSyntax, uiDiagnostic } from './syntax.js';
|
|
|
9
9
|
import {} from 'zod';
|
|
10
10
|
// The info string a fence carries when the host names none of its own.
|
|
11
11
|
export const UI_FENCE_LANGUAGE = 'ui';
|
|
12
|
-
export const UI_REPLY_LIMITS = { blocks: 16, characters: 262144, nodes: 2048, milliseconds:
|
|
12
|
+
export const UI_REPLY_LIMITS = { blocks: 16, characters: 262144, nodes: 2048, milliseconds: 0 };
|
|
13
13
|
// What a host reads for one block: its queries, its link targets, the places it looks up and how often a visible block reads again.
|
|
14
14
|
export const UI_HOST_LIMITS = { queries: 8, links: 64, places: 50, refreshMilliseconds: 10_000 };
|
|
15
15
|
/* A Place that names an address, whose tag may hold quoted text with a `>` before it. */
|
|
@@ -361,7 +361,7 @@ export class UiCompiler {
|
|
|
361
361
|
const now = this.options.now ?? Date.now;
|
|
362
362
|
const language = this.options.fenceLanguage ?? UI_FENCE_LANGUAGE;
|
|
363
363
|
const diagnostics = this.options.limits?.diagnostics ?? UI_LIMITS.diagnostics;
|
|
364
|
-
const started = now();
|
|
364
|
+
const started = UI_REPLY_LIMITS.milliseconds > 0 ? now() : 0;
|
|
365
365
|
const nodeCount = (items) => items.reduce((count, node) => count + 1 + nodeCount(node.children), 0);
|
|
366
366
|
const rejected = (start, codeStart, codeEnd, end, complete) => ({
|
|
367
367
|
id: `${this.options.id}:ui:${start}`,
|
|
@@ -393,7 +393,7 @@ export class UiCompiler {
|
|
|
393
393
|
}
|
|
394
394
|
const complete = closed || update.final === true;
|
|
395
395
|
characters += codeEnd - codeStart;
|
|
396
|
-
if (characters > UI_REPLY_LIMITS.characters || now() - started > UI_REPLY_LIMITS.milliseconds) {
|
|
396
|
+
if (characters > UI_REPLY_LIMITS.characters || (UI_REPLY_LIMITS.milliseconds > 0 && now() - started > UI_REPLY_LIMITS.milliseconds)) {
|
|
397
397
|
blocks.push(rejected(start, codeStart, codeEnd, end, complete));
|
|
398
398
|
exhausted = true;
|
|
399
399
|
return;
|
package/package.json
CHANGED
package/src/budget.ts
CHANGED
|
@@ -6,18 +6,22 @@ export interface UiLimits {
|
|
|
6
6
|
steps: number;
|
|
7
7
|
iterations: number;
|
|
8
8
|
stringLength: number;
|
|
9
|
+
/* Zero leaves admission to deterministic work limits; a positive value also bounds elapsed time. */
|
|
9
10
|
milliseconds: number;
|
|
10
11
|
}
|
|
11
12
|
|
|
13
|
+
const BLOCK_CHARACTERS = 65536;
|
|
14
|
+
|
|
12
15
|
export const UI_LIMITS: Readonly<UiLimits> = {
|
|
13
|
-
characters:
|
|
16
|
+
characters: BLOCK_CHARACTERS,
|
|
14
17
|
depth: 32,
|
|
15
18
|
nodes: 512,
|
|
16
19
|
diagnostics: 20,
|
|
17
|
-
|
|
20
|
+
// Parsing and validating a string literal can account for each character four times.
|
|
21
|
+
steps: 4 * BLOCK_CHARACTERS,
|
|
18
22
|
iterations: 2000,
|
|
19
23
|
stringLength: 16384,
|
|
20
|
-
milliseconds:
|
|
24
|
+
milliseconds: 0
|
|
21
25
|
};
|
|
22
26
|
|
|
23
27
|
export class UiFailure extends Error {
|
|
@@ -41,17 +45,17 @@ export class UiBudget {
|
|
|
41
45
|
constructor(limits: Partial<UiLimits> = {}, now: () => number = Date.now) {
|
|
42
46
|
this.now = now;
|
|
43
47
|
this.limits = { ...UI_LIMITS, ...limits };
|
|
44
|
-
for (const value of Object.
|
|
45
|
-
if (!Number.isSafeInteger(value) || value
|
|
46
|
-
throw new UiFailure('invalid_limits', 'Budgets must be positive safe integers.');
|
|
48
|
+
for (const [name, value] of Object.entries(this.limits)) {
|
|
49
|
+
if (!Number.isSafeInteger(value) || value < 0 || (value === 0 && name !== 'milliseconds')) {
|
|
50
|
+
throw new UiFailure('invalid_limits', 'Budgets must be positive safe integers, except milliseconds may be zero.');
|
|
47
51
|
}
|
|
48
52
|
}
|
|
49
|
-
this.started = now();
|
|
53
|
+
this.started = this.limits.milliseconds > 0 ? now() : 0;
|
|
50
54
|
}
|
|
51
55
|
|
|
52
56
|
step(count = 1): void {
|
|
53
57
|
this.steps += count;
|
|
54
|
-
if (this.steps > this.limits.steps || this.now() - this.started > this.limits.milliseconds) {
|
|
58
|
+
if (this.steps > this.limits.steps || (this.limits.milliseconds > 0 && this.now() - this.started > this.limits.milliseconds)) {
|
|
55
59
|
throw new UiFailure('budget_exceeded', 'The operation exceeded its work budget.');
|
|
56
60
|
}
|
|
57
61
|
}
|
package/src/compiler.ts
CHANGED
|
@@ -11,7 +11,7 @@ import { type z } from 'zod';
|
|
|
11
11
|
// The info string a fence carries when the host names none of its own.
|
|
12
12
|
export const UI_FENCE_LANGUAGE = 'ui';
|
|
13
13
|
|
|
14
|
-
export const UI_REPLY_LIMITS = { blocks: 16, characters: 262144, nodes: 2048, milliseconds:
|
|
14
|
+
export const UI_REPLY_LIMITS = { blocks: 16, characters: 262144, nodes: 2048, milliseconds: 0 } as const;
|
|
15
15
|
|
|
16
16
|
// What a host reads for one block: its queries, its link targets, the places it looks up and how often a visible block reads again.
|
|
17
17
|
export const UI_HOST_LIMITS = { queries: 8, links: 64, places: 50, refreshMilliseconds: 10_000 } as const;
|
|
@@ -456,7 +456,7 @@ export class UiCompiler {
|
|
|
456
456
|
const now = this.options.now ?? Date.now;
|
|
457
457
|
const language = this.options.fenceLanguage ?? UI_FENCE_LANGUAGE;
|
|
458
458
|
const diagnostics = this.options.limits?.diagnostics ?? UI_LIMITS.diagnostics;
|
|
459
|
-
const started = now();
|
|
459
|
+
const started = UI_REPLY_LIMITS.milliseconds > 0 ? now() : 0;
|
|
460
460
|
const nodeCount = (items: readonly UiNode[]): number => items.reduce((count, node) => count + 1 + nodeCount(node.children), 0);
|
|
461
461
|
const rejected = (start: number, codeStart: number, codeEnd: number, end: number, complete: boolean): UiBlock => ({
|
|
462
462
|
id: `${this.options.id}:ui:${start}`,
|
|
@@ -488,7 +488,7 @@ export class UiCompiler {
|
|
|
488
488
|
}
|
|
489
489
|
const complete = closed || update.final === true;
|
|
490
490
|
characters += codeEnd - codeStart;
|
|
491
|
-
if (characters > UI_REPLY_LIMITS.characters || now() - started > UI_REPLY_LIMITS.milliseconds) {
|
|
491
|
+
if (characters > UI_REPLY_LIMITS.characters || (UI_REPLY_LIMITS.milliseconds > 0 && now() - started > UI_REPLY_LIMITS.milliseconds)) {
|
|
492
492
|
blocks.push(rejected(start, codeStart, codeEnd, end, complete));
|
|
493
493
|
exhausted = true;
|
|
494
494
|
return;
|