@almadar/std 1.0.15 → 2.1.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/LICENSE +21 -72
- package/README.md +25 -0
- package/dist/behaviors/index.d.ts +1 -0
- package/dist/behaviors/index.js +940 -2
- package/dist/behaviors/index.js.map +1 -1
- package/dist/behaviors/infrastructure.d.ts +21 -0
- package/dist/behaviors/infrastructure.js +940 -0
- package/dist/behaviors/infrastructure.js.map +1 -0
- package/dist/behaviors/registry.js +939 -1
- package/dist/behaviors/registry.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1273 -85
- package/dist/index.js.map +1 -1
- package/dist/modules/array.d.ts +1 -1
- package/dist/modules/async.d.ts +1 -1
- package/dist/modules/async.js +22 -5
- package/dist/modules/async.js.map +1 -1
- package/dist/modules/format.d.ts +1 -1
- package/dist/modules/index.d.ts +2 -1
- package/dist/modules/index.js +249 -6
- package/dist/modules/index.js.map +1 -1
- package/dist/modules/math.d.ts +1 -1
- package/dist/modules/nn.d.ts +1 -1
- package/dist/modules/object.d.ts +1 -1
- package/dist/modules/prob.d.ts +21 -0
- package/dist/modules/prob.js +229 -0
- package/dist/modules/prob.js.map +1 -0
- package/dist/modules/str.d.ts +1 -1
- package/dist/modules/tensor.d.ts +1 -1
- package/dist/modules/time.d.ts +1 -1
- package/dist/modules/train.d.ts +1 -1
- package/dist/modules/validate.d.ts +1 -1
- package/dist/registry.d.ts +1 -1
- package/dist/registry.js +251 -8
- package/dist/registry.js.map +1 -1
- package/dist/{types-I95R8_FN.d.ts → types-CmNM_IbV.d.ts} +3 -3
- package/package.json +5 -4
package/dist/index.js
CHANGED
|
@@ -10,7 +10,8 @@ var STD_MODULES = [
|
|
|
10
10
|
"async",
|
|
11
11
|
"nn",
|
|
12
12
|
"tensor",
|
|
13
|
-
"train"
|
|
13
|
+
"train",
|
|
14
|
+
"prob"
|
|
14
15
|
];
|
|
15
16
|
var STD_OPERATOR_CATEGORIES = [
|
|
16
17
|
"std-math",
|
|
@@ -23,7 +24,8 @@ var STD_OPERATOR_CATEGORIES = [
|
|
|
23
24
|
"std-async",
|
|
24
25
|
"std-nn",
|
|
25
26
|
"std-tensor",
|
|
26
|
-
"std-train"
|
|
27
|
+
"std-train",
|
|
28
|
+
"std-prob"
|
|
27
29
|
];
|
|
28
30
|
function isStdCategory(category) {
|
|
29
31
|
return STD_OPERATOR_CATEGORIES.includes(category);
|
|
@@ -2142,12 +2144,29 @@ var ASYNC_OPERATORS = {
|
|
|
2142
2144
|
module: "async",
|
|
2143
2145
|
category: "std-async",
|
|
2144
2146
|
minArity: 1,
|
|
2145
|
-
maxArity:
|
|
2146
|
-
description: "Wait for specified milliseconds",
|
|
2147
|
+
maxArity: 2,
|
|
2148
|
+
description: "Wait for specified milliseconds, optionally execute an effect after",
|
|
2147
2149
|
hasSideEffects: true,
|
|
2148
|
-
returnType: "
|
|
2149
|
-
params: [
|
|
2150
|
-
|
|
2150
|
+
returnType: "any",
|
|
2151
|
+
params: [
|
|
2152
|
+
{ name: "ms", type: "number", description: "Milliseconds to wait" },
|
|
2153
|
+
{ name: "effect", type: "expression", description: "Optional effect to execute after delay" }
|
|
2154
|
+
],
|
|
2155
|
+
example: '["async/delay", 2000, ["emit", "RETRY"]] // Wait 2s then emit'
|
|
2156
|
+
},
|
|
2157
|
+
"async/interval": {
|
|
2158
|
+
module: "async",
|
|
2159
|
+
category: "std-async",
|
|
2160
|
+
minArity: 2,
|
|
2161
|
+
maxArity: 2,
|
|
2162
|
+
description: "Execute an effect periodically at a fixed interval",
|
|
2163
|
+
hasSideEffects: true,
|
|
2164
|
+
returnType: "string",
|
|
2165
|
+
params: [
|
|
2166
|
+
{ name: "ms", type: "number", description: "Interval in milliseconds" },
|
|
2167
|
+
{ name: "effect", type: "expression", description: "Effect to execute each interval" }
|
|
2168
|
+
],
|
|
2169
|
+
example: '["async/interval", 5000, ["emit", "POLL_TICK"]] // Emit every 5s'
|
|
2151
2170
|
},
|
|
2152
2171
|
"async/timeout": {
|
|
2153
2172
|
module: "async",
|
|
@@ -3148,6 +3167,229 @@ var TRAIN_OPERATORS = {
|
|
|
3148
3167
|
}
|
|
3149
3168
|
};
|
|
3150
3169
|
|
|
3170
|
+
// modules/prob.ts
|
|
3171
|
+
var PROB_OPERATORS = {
|
|
3172
|
+
// ========================================
|
|
3173
|
+
// Distribution Sampling
|
|
3174
|
+
// ========================================
|
|
3175
|
+
"prob/seed": {
|
|
3176
|
+
module: "prob",
|
|
3177
|
+
category: "std-prob",
|
|
3178
|
+
minArity: 1,
|
|
3179
|
+
maxArity: 1,
|
|
3180
|
+
description: "Set seeded PRNG for deterministic probabilistic sampling",
|
|
3181
|
+
hasSideEffects: true,
|
|
3182
|
+
returnType: "void",
|
|
3183
|
+
params: [{ name: "n", type: "number", description: "Seed value (integer)" }],
|
|
3184
|
+
example: '["prob/seed", 42]'
|
|
3185
|
+
},
|
|
3186
|
+
"prob/flip": {
|
|
3187
|
+
module: "prob",
|
|
3188
|
+
category: "std-prob",
|
|
3189
|
+
minArity: 1,
|
|
3190
|
+
maxArity: 1,
|
|
3191
|
+
description: "Bernoulli trial: returns true with probability p",
|
|
3192
|
+
hasSideEffects: false,
|
|
3193
|
+
returnType: "boolean",
|
|
3194
|
+
params: [{ name: "p", type: "number", description: "Probability of true (0 to 1)" }],
|
|
3195
|
+
example: '["prob/flip", 0.5] // => true or false with equal probability'
|
|
3196
|
+
},
|
|
3197
|
+
"prob/gaussian": {
|
|
3198
|
+
module: "prob",
|
|
3199
|
+
category: "std-prob",
|
|
3200
|
+
minArity: 2,
|
|
3201
|
+
maxArity: 2,
|
|
3202
|
+
description: "Sample from a Gaussian (normal) distribution",
|
|
3203
|
+
hasSideEffects: false,
|
|
3204
|
+
returnType: "number",
|
|
3205
|
+
params: [
|
|
3206
|
+
{ name: "mu", type: "number", description: "Mean" },
|
|
3207
|
+
{ name: "sigma", type: "number", description: "Standard deviation" }
|
|
3208
|
+
],
|
|
3209
|
+
example: '["prob/gaussian", 0, 1] // => standard normal sample'
|
|
3210
|
+
},
|
|
3211
|
+
"prob/uniform": {
|
|
3212
|
+
module: "prob",
|
|
3213
|
+
category: "std-prob",
|
|
3214
|
+
minArity: 2,
|
|
3215
|
+
maxArity: 2,
|
|
3216
|
+
description: "Sample from a uniform distribution [lo, hi)",
|
|
3217
|
+
hasSideEffects: false,
|
|
3218
|
+
returnType: "number",
|
|
3219
|
+
params: [
|
|
3220
|
+
{ name: "lo", type: "number", description: "Lower bound (inclusive)" },
|
|
3221
|
+
{ name: "hi", type: "number", description: "Upper bound (exclusive)" }
|
|
3222
|
+
],
|
|
3223
|
+
example: '["prob/uniform", 0, 10] // => number in [0, 10)'
|
|
3224
|
+
},
|
|
3225
|
+
"prob/beta": {
|
|
3226
|
+
module: "prob",
|
|
3227
|
+
category: "std-prob",
|
|
3228
|
+
minArity: 2,
|
|
3229
|
+
maxArity: 2,
|
|
3230
|
+
description: "Sample from a Beta(alpha, beta) distribution",
|
|
3231
|
+
hasSideEffects: false,
|
|
3232
|
+
returnType: "number",
|
|
3233
|
+
params: [
|
|
3234
|
+
{ name: "alpha", type: "number", description: "Alpha shape parameter (> 0)" },
|
|
3235
|
+
{ name: "beta", type: "number", description: "Beta shape parameter (> 0)" }
|
|
3236
|
+
],
|
|
3237
|
+
example: '["prob/beta", 2, 5] // => number in [0, 1], mean ~ 0.286'
|
|
3238
|
+
},
|
|
3239
|
+
"prob/categorical": {
|
|
3240
|
+
module: "prob",
|
|
3241
|
+
category: "std-prob",
|
|
3242
|
+
minArity: 2,
|
|
3243
|
+
maxArity: 2,
|
|
3244
|
+
description: "Weighted random selection from items",
|
|
3245
|
+
hasSideEffects: false,
|
|
3246
|
+
returnType: "any",
|
|
3247
|
+
params: [
|
|
3248
|
+
{ name: "items", type: "array", description: "Array of items to choose from" },
|
|
3249
|
+
{ name: "weights", type: "number[]", description: "Array of weights (same length as items)" }
|
|
3250
|
+
],
|
|
3251
|
+
example: '["prob/categorical", ["a", "b", "c"], [1, 2, 1]] // => "b" most likely'
|
|
3252
|
+
},
|
|
3253
|
+
"prob/poisson": {
|
|
3254
|
+
module: "prob",
|
|
3255
|
+
category: "std-prob",
|
|
3256
|
+
minArity: 1,
|
|
3257
|
+
maxArity: 1,
|
|
3258
|
+
description: "Sample from a Poisson distribution",
|
|
3259
|
+
hasSideEffects: false,
|
|
3260
|
+
returnType: "number",
|
|
3261
|
+
params: [{ name: "lambda", type: "number", description: "Rate parameter (> 0)" }],
|
|
3262
|
+
example: '["prob/poisson", 4] // => non-negative integer, mean ~ 4'
|
|
3263
|
+
},
|
|
3264
|
+
// ========================================
|
|
3265
|
+
// Inference
|
|
3266
|
+
// ========================================
|
|
3267
|
+
"prob/condition": {
|
|
3268
|
+
module: "prob",
|
|
3269
|
+
category: "std-prob",
|
|
3270
|
+
minArity: 1,
|
|
3271
|
+
maxArity: 1,
|
|
3272
|
+
description: "Mark current sample as rejected if predicate is false",
|
|
3273
|
+
hasSideEffects: true,
|
|
3274
|
+
returnType: "void",
|
|
3275
|
+
params: [{ name: "predicate", type: "boolean", description: "Condition that must hold" }],
|
|
3276
|
+
example: '["prob/condition", [">", "@entity.x", 0]]'
|
|
3277
|
+
},
|
|
3278
|
+
"prob/sample": {
|
|
3279
|
+
module: "prob",
|
|
3280
|
+
category: "std-prob",
|
|
3281
|
+
minArity: 2,
|
|
3282
|
+
maxArity: 2,
|
|
3283
|
+
description: "Evaluate an expression n times and collect results",
|
|
3284
|
+
hasSideEffects: false,
|
|
3285
|
+
returnType: "array",
|
|
3286
|
+
params: [
|
|
3287
|
+
{ name: "n", type: "number", description: "Number of samples" },
|
|
3288
|
+
{ name: "expr", type: "SExpr", description: "Expression to evaluate (lazy)" }
|
|
3289
|
+
],
|
|
3290
|
+
example: '["prob/sample", 1000, ["prob/flip", 0.5]] // => array of booleans'
|
|
3291
|
+
},
|
|
3292
|
+
"prob/posterior": {
|
|
3293
|
+
module: "prob",
|
|
3294
|
+
category: "std-prob",
|
|
3295
|
+
minArity: 4,
|
|
3296
|
+
maxArity: 4,
|
|
3297
|
+
description: "Rejection sampling: returns accepted query values",
|
|
3298
|
+
hasSideEffects: false,
|
|
3299
|
+
returnType: "array",
|
|
3300
|
+
params: [
|
|
3301
|
+
{ name: "model", type: "SExpr", description: "Model expression (lazy, may call set/condition)" },
|
|
3302
|
+
{ name: "evidence", type: "SExpr", description: "Evidence expression (lazy, boolean)" },
|
|
3303
|
+
{ name: "query", type: "SExpr", description: "Query expression (lazy, value to collect)" },
|
|
3304
|
+
{ name: "n", type: "number", description: "Number of samples to attempt" }
|
|
3305
|
+
],
|
|
3306
|
+
example: '["prob/posterior", model, evidence, query, 5000]'
|
|
3307
|
+
},
|
|
3308
|
+
"prob/infer": {
|
|
3309
|
+
module: "prob",
|
|
3310
|
+
category: "std-prob",
|
|
3311
|
+
minArity: 4,
|
|
3312
|
+
maxArity: 4,
|
|
3313
|
+
description: "Like posterior but returns {mean, variance, samples, acceptRate}",
|
|
3314
|
+
hasSideEffects: false,
|
|
3315
|
+
returnType: "object",
|
|
3316
|
+
params: [
|
|
3317
|
+
{ name: "model", type: "SExpr", description: "Model expression (lazy)" },
|
|
3318
|
+
{ name: "evidence", type: "SExpr", description: "Evidence expression (lazy, boolean)" },
|
|
3319
|
+
{ name: "query", type: "SExpr", description: "Query expression (lazy)" },
|
|
3320
|
+
{ name: "n", type: "number", description: "Number of samples to attempt" }
|
|
3321
|
+
],
|
|
3322
|
+
example: '["prob/infer", model, evidence, query, 5000]'
|
|
3323
|
+
},
|
|
3324
|
+
// ========================================
|
|
3325
|
+
// Statistics
|
|
3326
|
+
// ========================================
|
|
3327
|
+
"prob/expected-value": {
|
|
3328
|
+
module: "prob",
|
|
3329
|
+
category: "std-prob",
|
|
3330
|
+
minArity: 1,
|
|
3331
|
+
maxArity: 1,
|
|
3332
|
+
description: "Mean of numeric samples",
|
|
3333
|
+
hasSideEffects: false,
|
|
3334
|
+
returnType: "number",
|
|
3335
|
+
params: [{ name: "samples", type: "number[]", description: "Array of numeric samples" }],
|
|
3336
|
+
example: '["prob/expected-value", [2, 4, 6, 8]] // => 5'
|
|
3337
|
+
},
|
|
3338
|
+
"prob/variance": {
|
|
3339
|
+
module: "prob",
|
|
3340
|
+
category: "std-prob",
|
|
3341
|
+
minArity: 1,
|
|
3342
|
+
maxArity: 1,
|
|
3343
|
+
description: "Population variance of numeric samples",
|
|
3344
|
+
hasSideEffects: false,
|
|
3345
|
+
returnType: "number",
|
|
3346
|
+
params: [{ name: "samples", type: "number[]", description: "Array of numeric samples" }],
|
|
3347
|
+
example: '["prob/variance", [2, 4, 4, 4, 5, 5, 7, 9]] // => 4'
|
|
3348
|
+
},
|
|
3349
|
+
"prob/histogram": {
|
|
3350
|
+
module: "prob",
|
|
3351
|
+
category: "std-prob",
|
|
3352
|
+
minArity: 2,
|
|
3353
|
+
maxArity: 2,
|
|
3354
|
+
description: "Bin numeric samples into a histogram",
|
|
3355
|
+
hasSideEffects: false,
|
|
3356
|
+
returnType: "object",
|
|
3357
|
+
params: [
|
|
3358
|
+
{ name: "samples", type: "number[]", description: "Array of numeric samples" },
|
|
3359
|
+
{ name: "bins", type: "number", description: "Number of bins" }
|
|
3360
|
+
],
|
|
3361
|
+
example: '["prob/histogram", [1, 2, 3, 4, 5], 2] // => {binEdges, counts}'
|
|
3362
|
+
},
|
|
3363
|
+
"prob/percentile": {
|
|
3364
|
+
module: "prob",
|
|
3365
|
+
category: "std-prob",
|
|
3366
|
+
minArity: 2,
|
|
3367
|
+
maxArity: 2,
|
|
3368
|
+
description: "Get the p-th percentile (0-100) from samples",
|
|
3369
|
+
hasSideEffects: false,
|
|
3370
|
+
returnType: "number",
|
|
3371
|
+
params: [
|
|
3372
|
+
{ name: "samples", type: "number[]", description: "Array of numeric samples" },
|
|
3373
|
+
{ name: "p", type: "number", description: "Percentile (0 to 100)" }
|
|
3374
|
+
],
|
|
3375
|
+
example: '["prob/percentile", [1, 2, 3, 4, 5], 50] // => 3'
|
|
3376
|
+
},
|
|
3377
|
+
"prob/credible-interval": {
|
|
3378
|
+
module: "prob",
|
|
3379
|
+
category: "std-prob",
|
|
3380
|
+
minArity: 2,
|
|
3381
|
+
maxArity: 2,
|
|
3382
|
+
description: "Compute symmetric credible interval from samples",
|
|
3383
|
+
hasSideEffects: false,
|
|
3384
|
+
returnType: "array",
|
|
3385
|
+
params: [
|
|
3386
|
+
{ name: "samples", type: "number[]", description: "Array of numeric samples" },
|
|
3387
|
+
{ name: "alpha", type: "number", description: "Significance level (e.g., 0.05 for 95% interval)" }
|
|
3388
|
+
],
|
|
3389
|
+
example: '["prob/credible-interval", samples, 0.05] // => [lo, hi]'
|
|
3390
|
+
}
|
|
3391
|
+
};
|
|
3392
|
+
|
|
3151
3393
|
// registry.ts
|
|
3152
3394
|
var STD_OPERATORS = {
|
|
3153
3395
|
...MATH_OPERATORS,
|
|
@@ -3160,7 +3402,8 @@ var STD_OPERATORS = {
|
|
|
3160
3402
|
...ASYNC_OPERATORS,
|
|
3161
3403
|
...NN_OPERATORS,
|
|
3162
3404
|
...TENSOR_OPERATORS,
|
|
3163
|
-
...TRAIN_OPERATORS
|
|
3405
|
+
...TRAIN_OPERATORS,
|
|
3406
|
+
...PROB_OPERATORS
|
|
3164
3407
|
};
|
|
3165
3408
|
var STD_OPERATORS_BY_MODULE = {
|
|
3166
3409
|
math: MATH_OPERATORS,
|
|
@@ -3173,7 +3416,8 @@ var STD_OPERATORS_BY_MODULE = {
|
|
|
3173
3416
|
async: ASYNC_OPERATORS,
|
|
3174
3417
|
nn: NN_OPERATORS,
|
|
3175
3418
|
tensor: TENSOR_OPERATORS,
|
|
3176
|
-
train: TRAIN_OPERATORS
|
|
3419
|
+
train: TRAIN_OPERATORS,
|
|
3420
|
+
prob: PROB_OPERATORS
|
|
3177
3421
|
};
|
|
3178
3422
|
function getStdOperatorMeta(operator) {
|
|
3179
3423
|
return STD_OPERATORS[operator];
|
|
@@ -7696,84 +7940,1022 @@ var GAME_UI_BEHAVIORS = [
|
|
|
7696
7940
|
LEVEL_PROGRESS_BEHAVIOR
|
|
7697
7941
|
];
|
|
7698
7942
|
|
|
7699
|
-
// behaviors/
|
|
7700
|
-
var
|
|
7701
|
-
|
|
7702
|
-
|
|
7703
|
-
|
|
7704
|
-
|
|
7705
|
-
|
|
7706
|
-
|
|
7707
|
-
|
|
7708
|
-
|
|
7709
|
-
|
|
7710
|
-
|
|
7711
|
-
|
|
7712
|
-
|
|
7713
|
-
|
|
7714
|
-
|
|
7715
|
-
|
|
7716
|
-
|
|
7717
|
-
|
|
7718
|
-
}
|
|
7719
|
-
|
|
7720
|
-
|
|
7721
|
-
}
|
|
7722
|
-
|
|
7723
|
-
|
|
7724
|
-
|
|
7725
|
-
|
|
7726
|
-
|
|
7727
|
-
|
|
7728
|
-
|
|
7729
|
-
|
|
7730
|
-
|
|
7731
|
-
|
|
7732
|
-
|
|
7733
|
-
|
|
7734
|
-
|
|
7735
|
-
|
|
7736
|
-
|
|
7737
|
-
|
|
7738
|
-
|
|
7739
|
-
|
|
7740
|
-
|
|
7741
|
-
|
|
7742
|
-
|
|
7743
|
-
|
|
7744
|
-
|
|
7745
|
-
|
|
7746
|
-
|
|
7747
|
-
|
|
7748
|
-
|
|
7749
|
-
|
|
7750
|
-
|
|
7751
|
-
|
|
7752
|
-
|
|
7753
|
-
|
|
7754
|
-
|
|
7755
|
-
|
|
7756
|
-
|
|
7757
|
-
|
|
7758
|
-
|
|
7759
|
-
|
|
7760
|
-
|
|
7943
|
+
// behaviors/infrastructure.ts
|
|
7944
|
+
var CIRCUIT_BREAKER_BEHAVIOR = {
|
|
7945
|
+
name: "std-circuit-breaker",
|
|
7946
|
+
version: "1.0.0",
|
|
7947
|
+
description: "Circuit breaker pattern with automatic recovery",
|
|
7948
|
+
orbitals: [
|
|
7949
|
+
{
|
|
7950
|
+
name: "CircuitBreakerOrbital",
|
|
7951
|
+
entity: {
|
|
7952
|
+
name: "CircuitBreakerState",
|
|
7953
|
+
persistence: "runtime",
|
|
7954
|
+
fields: [
|
|
7955
|
+
{ name: "id", type: "string", required: true },
|
|
7956
|
+
{ name: "circuitState", type: "string", default: "closed" },
|
|
7957
|
+
{ name: "errorCount", type: "number", default: 0 },
|
|
7958
|
+
{ name: "errorRate", type: "number", default: 0 },
|
|
7959
|
+
{ name: "successCount", type: "number", default: 0 },
|
|
7960
|
+
{ name: "totalCount", type: "number", default: 0 },
|
|
7961
|
+
{ name: "lastFailure", type: "number", default: null },
|
|
7962
|
+
{ name: "lastSuccess", type: "number", default: null },
|
|
7963
|
+
{ name: "errorThreshold", type: "number", default: 5 },
|
|
7964
|
+
{ name: "errorRateThreshold", type: "number", default: 0.5 },
|
|
7965
|
+
{ name: "resetAfterMs", type: "number", default: 6e4 },
|
|
7966
|
+
{ name: "halfOpenMaxAttempts", type: "number", default: 3 },
|
|
7967
|
+
{ name: "halfOpenAttempts", type: "number", default: 0 }
|
|
7968
|
+
]
|
|
7969
|
+
},
|
|
7970
|
+
traits: [
|
|
7971
|
+
{
|
|
7972
|
+
name: "CircuitBreaker",
|
|
7973
|
+
linkedEntity: "CircuitBreakerState",
|
|
7974
|
+
category: "lifecycle",
|
|
7975
|
+
emits: [
|
|
7976
|
+
{ event: "CIRCUIT_OPENED", scope: "external" },
|
|
7977
|
+
{ event: "CIRCUIT_CLOSED", scope: "external" },
|
|
7978
|
+
{ event: "CIRCUIT_HALF_OPEN", scope: "external" }
|
|
7979
|
+
],
|
|
7980
|
+
stateMachine: {
|
|
7981
|
+
states: [
|
|
7982
|
+
{ name: "Closed", isInitial: true },
|
|
7983
|
+
{ name: "Open" },
|
|
7984
|
+
{ name: "HalfOpen" }
|
|
7985
|
+
],
|
|
7986
|
+
events: [
|
|
7987
|
+
{ key: "RECORD_SUCCESS", name: "Record Success" },
|
|
7988
|
+
{ key: "RECORD_FAILURE", name: "Record Failure" },
|
|
7989
|
+
{ key: "PROBE", name: "Probe" },
|
|
7990
|
+
{ key: "RESET", name: "Reset" }
|
|
7991
|
+
],
|
|
7992
|
+
transitions: [
|
|
7993
|
+
// Closed: record success
|
|
7994
|
+
{
|
|
7995
|
+
from: "Closed",
|
|
7996
|
+
to: "Closed",
|
|
7997
|
+
event: "RECORD_SUCCESS",
|
|
7998
|
+
effects: [
|
|
7999
|
+
["set", "@entity.successCount", ["+", "@entity.successCount", 1]],
|
|
8000
|
+
["set", "@entity.totalCount", ["+", "@entity.totalCount", 1]],
|
|
8001
|
+
["set", "@entity.lastSuccess", ["time/now"]],
|
|
8002
|
+
["set", "@entity.errorRate", ["/", "@entity.errorCount", ["math/max", "@entity.totalCount", 1]]]
|
|
8003
|
+
]
|
|
8004
|
+
},
|
|
8005
|
+
// Closed: record failure, stay closed if under threshold
|
|
8006
|
+
{
|
|
8007
|
+
from: "Closed",
|
|
8008
|
+
to: "Closed",
|
|
8009
|
+
event: "RECORD_FAILURE",
|
|
8010
|
+
guard: ["<", ["+", "@entity.errorCount", 1], "@entity.errorThreshold"],
|
|
8011
|
+
effects: [
|
|
8012
|
+
["set", "@entity.errorCount", ["+", "@entity.errorCount", 1]],
|
|
8013
|
+
["set", "@entity.totalCount", ["+", "@entity.totalCount", 1]],
|
|
8014
|
+
["set", "@entity.lastFailure", ["time/now"]],
|
|
8015
|
+
["set", "@entity.errorRate", ["/", ["+", "@entity.errorCount", 1], ["math/max", "@entity.totalCount", 1]]]
|
|
8016
|
+
]
|
|
8017
|
+
},
|
|
8018
|
+
// Closed -> Open: threshold exceeded
|
|
8019
|
+
{
|
|
8020
|
+
from: "Closed",
|
|
8021
|
+
to: "Open",
|
|
8022
|
+
event: "RECORD_FAILURE",
|
|
8023
|
+
guard: [">=", ["+", "@entity.errorCount", 1], "@entity.errorThreshold"],
|
|
8024
|
+
effects: [
|
|
8025
|
+
["set", "@entity.errorCount", ["+", "@entity.errorCount", 1]],
|
|
8026
|
+
["set", "@entity.totalCount", ["+", "@entity.totalCount", 1]],
|
|
8027
|
+
["set", "@entity.lastFailure", ["time/now"]],
|
|
8028
|
+
["set", "@entity.errorRate", ["/", ["+", "@entity.errorCount", 1], ["math/max", "@entity.totalCount", 1]]],
|
|
8029
|
+
["emit", "CIRCUIT_OPENED", { errorCount: "@entity.errorCount", errorRate: "@entity.errorRate" }]
|
|
8030
|
+
]
|
|
8031
|
+
},
|
|
8032
|
+
// Open -> HalfOpen: probe after reset timeout
|
|
8033
|
+
{
|
|
8034
|
+
from: "Open",
|
|
8035
|
+
to: "HalfOpen",
|
|
8036
|
+
event: "PROBE",
|
|
8037
|
+
guard: [">", ["-", ["time/now"], "@entity.lastFailure"], "@entity.resetAfterMs"],
|
|
8038
|
+
effects: [
|
|
8039
|
+
["set", "@entity.halfOpenAttempts", 0],
|
|
8040
|
+
["emit", "CIRCUIT_HALF_OPEN", {}]
|
|
8041
|
+
]
|
|
8042
|
+
},
|
|
8043
|
+
// HalfOpen: success -> close
|
|
8044
|
+
{
|
|
8045
|
+
from: "HalfOpen",
|
|
8046
|
+
to: "Closed",
|
|
8047
|
+
event: "RECORD_SUCCESS",
|
|
8048
|
+
effects: [
|
|
8049
|
+
["set", "@entity.errorCount", 0],
|
|
8050
|
+
["set", "@entity.errorRate", 0],
|
|
8051
|
+
["set", "@entity.halfOpenAttempts", 0],
|
|
8052
|
+
["set", "@entity.successCount", ["+", "@entity.successCount", 1]],
|
|
8053
|
+
["set", "@entity.lastSuccess", ["time/now"]],
|
|
8054
|
+
["emit", "CIRCUIT_CLOSED", {}]
|
|
8055
|
+
]
|
|
8056
|
+
},
|
|
8057
|
+
// HalfOpen: failure -> back to open
|
|
8058
|
+
{
|
|
8059
|
+
from: "HalfOpen",
|
|
8060
|
+
to: "Open",
|
|
8061
|
+
event: "RECORD_FAILURE",
|
|
8062
|
+
effects: [
|
|
8063
|
+
["set", "@entity.errorCount", ["+", "@entity.errorCount", 1]],
|
|
8064
|
+
["set", "@entity.lastFailure", ["time/now"]],
|
|
8065
|
+
["emit", "CIRCUIT_OPENED", { errorCount: "@entity.errorCount" }]
|
|
8066
|
+
]
|
|
8067
|
+
},
|
|
8068
|
+
// Reset from any state
|
|
8069
|
+
{
|
|
8070
|
+
from: ["Closed", "Open", "HalfOpen"],
|
|
8071
|
+
to: "Closed",
|
|
8072
|
+
event: "RESET",
|
|
8073
|
+
effects: [
|
|
8074
|
+
["set", "@entity.errorCount", 0],
|
|
8075
|
+
["set", "@entity.successCount", 0],
|
|
8076
|
+
["set", "@entity.totalCount", 0],
|
|
8077
|
+
["set", "@entity.errorRate", 0],
|
|
8078
|
+
["set", "@entity.halfOpenAttempts", 0],
|
|
8079
|
+
["set", "@entity.circuitState", "closed"]
|
|
8080
|
+
]
|
|
8081
|
+
}
|
|
8082
|
+
]
|
|
8083
|
+
},
|
|
8084
|
+
ticks: [
|
|
8085
|
+
{
|
|
8086
|
+
name: "probe_half_open",
|
|
8087
|
+
interval: "30000",
|
|
8088
|
+
guard: ["=", "@entity.circuitState", "open"],
|
|
8089
|
+
effects: [["emit", "PROBE"]],
|
|
8090
|
+
description: "Periodically probe to transition from Open to HalfOpen"
|
|
8091
|
+
}
|
|
8092
|
+
]
|
|
7761
8093
|
}
|
|
7762
|
-
|
|
7763
|
-
|
|
7764
|
-
return false;
|
|
7765
|
-
});
|
|
7766
|
-
}
|
|
7767
|
-
function validateBehaviorReference(name) {
|
|
7768
|
-
if (!name.startsWith("std-")) {
|
|
7769
|
-
return `Behavior name must start with 'std-': ${name}`;
|
|
7770
|
-
}
|
|
7771
|
-
if (!isKnownBehavior(name)) {
|
|
7772
|
-
const suggestions = findSimilarBehaviors(name);
|
|
7773
|
-
if (suggestions.length > 0) {
|
|
7774
|
-
return `Unknown behavior '${name}'. Did you mean: ${suggestions.join(", ")}?`;
|
|
8094
|
+
],
|
|
8095
|
+
pages: []
|
|
7775
8096
|
}
|
|
7776
|
-
|
|
8097
|
+
]
|
|
8098
|
+
};
|
|
8099
|
+
var HEALTH_CHECK_BEHAVIOR = {
|
|
8100
|
+
name: "std-health-check",
|
|
8101
|
+
version: "1.0.0",
|
|
8102
|
+
description: "Tick-based health monitoring with degradation detection",
|
|
8103
|
+
orbitals: [
|
|
8104
|
+
{
|
|
8105
|
+
name: "HealthCheckOrbital",
|
|
8106
|
+
entity: {
|
|
8107
|
+
name: "HealthCheckState",
|
|
8108
|
+
persistence: "runtime",
|
|
8109
|
+
fields: [
|
|
8110
|
+
{ name: "id", type: "string", required: true },
|
|
8111
|
+
{ name: "healthStatus", type: "string", default: "unknown" },
|
|
8112
|
+
{ name: "lastCheck", type: "number", default: null },
|
|
8113
|
+
{ name: "lastHealthy", type: "number", default: null },
|
|
8114
|
+
{ name: "consecutiveFailures", type: "number", default: 0 },
|
|
8115
|
+
{ name: "consecutiveSuccesses", type: "number", default: 0 },
|
|
8116
|
+
{ name: "checkIntervalMs", type: "number", default: 3e4 },
|
|
8117
|
+
{ name: "degradedThreshold", type: "number", default: 2 },
|
|
8118
|
+
{ name: "unhealthyThreshold", type: "number", default: 5 },
|
|
8119
|
+
{ name: "recoveryThreshold", type: "number", default: 3 },
|
|
8120
|
+
{ name: "totalChecks", type: "number", default: 0 },
|
|
8121
|
+
{ name: "totalFailures", type: "number", default: 0 }
|
|
8122
|
+
]
|
|
8123
|
+
},
|
|
8124
|
+
traits: [
|
|
8125
|
+
{
|
|
8126
|
+
name: "HealthCheck",
|
|
8127
|
+
linkedEntity: "HealthCheckState",
|
|
8128
|
+
category: "lifecycle",
|
|
8129
|
+
emits: [
|
|
8130
|
+
{ event: "SERVICE_HEALTHY", scope: "external" },
|
|
8131
|
+
{ event: "SERVICE_DEGRADED", scope: "external" },
|
|
8132
|
+
{ event: "SERVICE_UNHEALTHY", scope: "external" }
|
|
8133
|
+
],
|
|
8134
|
+
stateMachine: {
|
|
8135
|
+
states: [
|
|
8136
|
+
{ name: "Unknown", isInitial: true },
|
|
8137
|
+
{ name: "Healthy" },
|
|
8138
|
+
{ name: "Degraded" },
|
|
8139
|
+
{ name: "Unhealthy" }
|
|
8140
|
+
],
|
|
8141
|
+
events: [
|
|
8142
|
+
{ key: "CHECK_SUCCESS", name: "Check Success" },
|
|
8143
|
+
{ key: "CHECK_FAILURE", name: "Check Failure" },
|
|
8144
|
+
{ key: "HEALTH_TICK", name: "Health Tick" },
|
|
8145
|
+
{ key: "RESET", name: "Reset" }
|
|
8146
|
+
],
|
|
8147
|
+
transitions: [
|
|
8148
|
+
// Unknown -> Healthy on first success
|
|
8149
|
+
{
|
|
8150
|
+
from: "Unknown",
|
|
8151
|
+
to: "Healthy",
|
|
8152
|
+
event: "CHECK_SUCCESS",
|
|
8153
|
+
effects: [
|
|
8154
|
+
["set", "@entity.healthStatus", "healthy"],
|
|
8155
|
+
["set", "@entity.consecutiveSuccesses", 1],
|
|
8156
|
+
["set", "@entity.consecutiveFailures", 0],
|
|
8157
|
+
["set", "@entity.lastCheck", ["time/now"]],
|
|
8158
|
+
["set", "@entity.lastHealthy", ["time/now"]],
|
|
8159
|
+
["set", "@entity.totalChecks", ["+", "@entity.totalChecks", 1]],
|
|
8160
|
+
["emit", "SERVICE_HEALTHY", {}]
|
|
8161
|
+
]
|
|
8162
|
+
},
|
|
8163
|
+
// Unknown -> Degraded on first failure
|
|
8164
|
+
{
|
|
8165
|
+
from: "Unknown",
|
|
8166
|
+
to: "Degraded",
|
|
8167
|
+
event: "CHECK_FAILURE",
|
|
8168
|
+
effects: [
|
|
8169
|
+
["set", "@entity.healthStatus", "degraded"],
|
|
8170
|
+
["set", "@entity.consecutiveFailures", 1],
|
|
8171
|
+
["set", "@entity.consecutiveSuccesses", 0],
|
|
8172
|
+
["set", "@entity.lastCheck", ["time/now"]],
|
|
8173
|
+
["set", "@entity.totalChecks", ["+", "@entity.totalChecks", 1]],
|
|
8174
|
+
["set", "@entity.totalFailures", ["+", "@entity.totalFailures", 1]],
|
|
8175
|
+
["emit", "SERVICE_DEGRADED", { consecutiveFailures: 1 }]
|
|
8176
|
+
]
|
|
8177
|
+
},
|
|
8178
|
+
// Healthy: stay healthy on success
|
|
8179
|
+
{
|
|
8180
|
+
from: "Healthy",
|
|
8181
|
+
to: "Healthy",
|
|
8182
|
+
event: "CHECK_SUCCESS",
|
|
8183
|
+
effects: [
|
|
8184
|
+
["set", "@entity.consecutiveSuccesses", ["+", "@entity.consecutiveSuccesses", 1]],
|
|
8185
|
+
["set", "@entity.consecutiveFailures", 0],
|
|
8186
|
+
["set", "@entity.lastCheck", ["time/now"]],
|
|
8187
|
+
["set", "@entity.lastHealthy", ["time/now"]],
|
|
8188
|
+
["set", "@entity.totalChecks", ["+", "@entity.totalChecks", 1]]
|
|
8189
|
+
]
|
|
8190
|
+
},
|
|
8191
|
+
// Healthy -> Degraded on failure
|
|
8192
|
+
{
|
|
8193
|
+
from: "Healthy",
|
|
8194
|
+
to: "Degraded",
|
|
8195
|
+
event: "CHECK_FAILURE",
|
|
8196
|
+
effects: [
|
|
8197
|
+
["set", "@entity.healthStatus", "degraded"],
|
|
8198
|
+
["set", "@entity.consecutiveFailures", 1],
|
|
8199
|
+
["set", "@entity.consecutiveSuccesses", 0],
|
|
8200
|
+
["set", "@entity.lastCheck", ["time/now"]],
|
|
8201
|
+
["set", "@entity.totalChecks", ["+", "@entity.totalChecks", 1]],
|
|
8202
|
+
["set", "@entity.totalFailures", ["+", "@entity.totalFailures", 1]],
|
|
8203
|
+
["emit", "SERVICE_DEGRADED", { consecutiveFailures: 1 }]
|
|
8204
|
+
]
|
|
8205
|
+
},
|
|
8206
|
+
// Degraded: stay degraded on failure (below unhealthy threshold)
|
|
8207
|
+
{
|
|
8208
|
+
from: "Degraded",
|
|
8209
|
+
to: "Degraded",
|
|
8210
|
+
event: "CHECK_FAILURE",
|
|
8211
|
+
guard: ["<", ["+", "@entity.consecutiveFailures", 1], "@entity.unhealthyThreshold"],
|
|
8212
|
+
effects: [
|
|
8213
|
+
["set", "@entity.consecutiveFailures", ["+", "@entity.consecutiveFailures", 1]],
|
|
8214
|
+
["set", "@entity.consecutiveSuccesses", 0],
|
|
8215
|
+
["set", "@entity.lastCheck", ["time/now"]],
|
|
8216
|
+
["set", "@entity.totalChecks", ["+", "@entity.totalChecks", 1]],
|
|
8217
|
+
["set", "@entity.totalFailures", ["+", "@entity.totalFailures", 1]]
|
|
8218
|
+
]
|
|
8219
|
+
},
|
|
8220
|
+
// Degraded -> Unhealthy when threshold exceeded
|
|
8221
|
+
{
|
|
8222
|
+
from: "Degraded",
|
|
8223
|
+
to: "Unhealthy",
|
|
8224
|
+
event: "CHECK_FAILURE",
|
|
8225
|
+
guard: [">=", ["+", "@entity.consecutiveFailures", 1], "@entity.unhealthyThreshold"],
|
|
8226
|
+
effects: [
|
|
8227
|
+
["set", "@entity.healthStatus", "unhealthy"],
|
|
8228
|
+
["set", "@entity.consecutiveFailures", ["+", "@entity.consecutiveFailures", 1]],
|
|
8229
|
+
["set", "@entity.lastCheck", ["time/now"]],
|
|
8230
|
+
["set", "@entity.totalChecks", ["+", "@entity.totalChecks", 1]],
|
|
8231
|
+
["set", "@entity.totalFailures", ["+", "@entity.totalFailures", 1]],
|
|
8232
|
+
["emit", "SERVICE_UNHEALTHY", { consecutiveFailures: ["+", "@entity.consecutiveFailures", 1] }]
|
|
8233
|
+
]
|
|
8234
|
+
},
|
|
8235
|
+
// Degraded -> Healthy on enough successes
|
|
8236
|
+
{
|
|
8237
|
+
from: "Degraded",
|
|
8238
|
+
to: "Healthy",
|
|
8239
|
+
event: "CHECK_SUCCESS",
|
|
8240
|
+
guard: [">=", ["+", "@entity.consecutiveSuccesses", 1], "@entity.recoveryThreshold"],
|
|
8241
|
+
effects: [
|
|
8242
|
+
["set", "@entity.healthStatus", "healthy"],
|
|
8243
|
+
["set", "@entity.consecutiveSuccesses", ["+", "@entity.consecutiveSuccesses", 1]],
|
|
8244
|
+
["set", "@entity.consecutiveFailures", 0],
|
|
8245
|
+
["set", "@entity.lastCheck", ["time/now"]],
|
|
8246
|
+
["set", "@entity.lastHealthy", ["time/now"]],
|
|
8247
|
+
["set", "@entity.totalChecks", ["+", "@entity.totalChecks", 1]],
|
|
8248
|
+
["emit", "SERVICE_HEALTHY", {}]
|
|
8249
|
+
]
|
|
8250
|
+
},
|
|
8251
|
+
// Degraded: stay degraded on success (not enough to recover)
|
|
8252
|
+
{
|
|
8253
|
+
from: "Degraded",
|
|
8254
|
+
to: "Degraded",
|
|
8255
|
+
event: "CHECK_SUCCESS",
|
|
8256
|
+
guard: ["<", ["+", "@entity.consecutiveSuccesses", 1], "@entity.recoveryThreshold"],
|
|
8257
|
+
effects: [
|
|
8258
|
+
["set", "@entity.consecutiveSuccesses", ["+", "@entity.consecutiveSuccesses", 1]],
|
|
8259
|
+
["set", "@entity.consecutiveFailures", 0],
|
|
8260
|
+
["set", "@entity.lastCheck", ["time/now"]],
|
|
8261
|
+
["set", "@entity.totalChecks", ["+", "@entity.totalChecks", 1]]
|
|
8262
|
+
]
|
|
8263
|
+
},
|
|
8264
|
+
// Unhealthy: stay unhealthy on failure
|
|
8265
|
+
{
|
|
8266
|
+
from: "Unhealthy",
|
|
8267
|
+
to: "Unhealthy",
|
|
8268
|
+
event: "CHECK_FAILURE",
|
|
8269
|
+
effects: [
|
|
8270
|
+
["set", "@entity.consecutiveFailures", ["+", "@entity.consecutiveFailures", 1]],
|
|
8271
|
+
["set", "@entity.lastCheck", ["time/now"]],
|
|
8272
|
+
["set", "@entity.totalChecks", ["+", "@entity.totalChecks", 1]],
|
|
8273
|
+
["set", "@entity.totalFailures", ["+", "@entity.totalFailures", 1]]
|
|
8274
|
+
]
|
|
8275
|
+
},
|
|
8276
|
+
// Unhealthy -> Degraded on first success (recovery begins)
|
|
8277
|
+
{
|
|
8278
|
+
from: "Unhealthy",
|
|
8279
|
+
to: "Degraded",
|
|
8280
|
+
event: "CHECK_SUCCESS",
|
|
8281
|
+
effects: [
|
|
8282
|
+
["set", "@entity.healthStatus", "degraded"],
|
|
8283
|
+
["set", "@entity.consecutiveSuccesses", 1],
|
|
8284
|
+
["set", "@entity.consecutiveFailures", 0],
|
|
8285
|
+
["set", "@entity.lastCheck", ["time/now"]],
|
|
8286
|
+
["set", "@entity.totalChecks", ["+", "@entity.totalChecks", 1]],
|
|
8287
|
+
["emit", "SERVICE_DEGRADED", { recovering: true }]
|
|
8288
|
+
]
|
|
8289
|
+
},
|
|
8290
|
+
// Reset from any state
|
|
8291
|
+
{
|
|
8292
|
+
from: ["Unknown", "Healthy", "Degraded", "Unhealthy"],
|
|
8293
|
+
to: "Unknown",
|
|
8294
|
+
event: "RESET",
|
|
8295
|
+
effects: [
|
|
8296
|
+
["set", "@entity.healthStatus", "unknown"],
|
|
8297
|
+
["set", "@entity.consecutiveFailures", 0],
|
|
8298
|
+
["set", "@entity.consecutiveSuccesses", 0],
|
|
8299
|
+
["set", "@entity.totalChecks", 0],
|
|
8300
|
+
["set", "@entity.totalFailures", 0]
|
|
8301
|
+
]
|
|
8302
|
+
}
|
|
8303
|
+
]
|
|
8304
|
+
},
|
|
8305
|
+
ticks: [
|
|
8306
|
+
{
|
|
8307
|
+
name: "periodic_health_check",
|
|
8308
|
+
interval: "@entity.checkIntervalMs",
|
|
8309
|
+
effects: [["emit", "HEALTH_TICK"]],
|
|
8310
|
+
description: "Periodically trigger health check"
|
|
8311
|
+
}
|
|
8312
|
+
]
|
|
8313
|
+
}
|
|
8314
|
+
],
|
|
8315
|
+
pages: []
|
|
8316
|
+
}
|
|
8317
|
+
]
|
|
8318
|
+
};
|
|
8319
|
+
var RATE_LIMITER_BEHAVIOR = {
|
|
8320
|
+
name: "std-rate-limiter",
|
|
8321
|
+
version: "1.0.0",
|
|
8322
|
+
description: "Guard-based rate limiting with sliding window reset",
|
|
8323
|
+
orbitals: [
|
|
8324
|
+
{
|
|
8325
|
+
name: "RateLimiterOrbital",
|
|
8326
|
+
entity: {
|
|
8327
|
+
name: "RateLimiterState",
|
|
8328
|
+
persistence: "runtime",
|
|
8329
|
+
fields: [
|
|
8330
|
+
{ name: "id", type: "string", required: true },
|
|
8331
|
+
{ name: "requestCount", type: "number", default: 0 },
|
|
8332
|
+
{ name: "windowStart", type: "number", default: 0 },
|
|
8333
|
+
{ name: "rateLimit", type: "number", default: 60 },
|
|
8334
|
+
{ name: "windowMs", type: "number", default: 6e4 },
|
|
8335
|
+
{ name: "totalRequests", type: "number", default: 0 },
|
|
8336
|
+
{ name: "rejectedRequests", type: "number", default: 0 }
|
|
8337
|
+
]
|
|
8338
|
+
},
|
|
8339
|
+
traits: [
|
|
8340
|
+
{
|
|
8341
|
+
name: "RateLimiter",
|
|
8342
|
+
linkedEntity: "RateLimiterState",
|
|
8343
|
+
category: "lifecycle",
|
|
8344
|
+
emits: [
|
|
8345
|
+
{ event: "RATE_LIMIT_EXCEEDED", scope: "external" }
|
|
8346
|
+
],
|
|
8347
|
+
stateMachine: {
|
|
8348
|
+
states: [
|
|
8349
|
+
{ name: "Active", isInitial: true }
|
|
8350
|
+
],
|
|
8351
|
+
events: [
|
|
8352
|
+
{ key: "REQUEST", name: "Record Request" },
|
|
8353
|
+
{ key: "REQUEST_REJECTED", name: "Request Rejected" },
|
|
8354
|
+
{ key: "WINDOW_RESET", name: "Window Reset" },
|
|
8355
|
+
{ key: "RESET", name: "Full Reset" }
|
|
8356
|
+
],
|
|
8357
|
+
transitions: [
|
|
8358
|
+
// Request allowed
|
|
8359
|
+
{
|
|
8360
|
+
from: "Active",
|
|
8361
|
+
to: "Active",
|
|
8362
|
+
event: "REQUEST",
|
|
8363
|
+
guard: ["<", "@entity.requestCount", "@entity.rateLimit"],
|
|
8364
|
+
effects: [
|
|
8365
|
+
["set", "@entity.requestCount", ["+", "@entity.requestCount", 1]],
|
|
8366
|
+
["set", "@entity.totalRequests", ["+", "@entity.totalRequests", 1]]
|
|
8367
|
+
]
|
|
8368
|
+
},
|
|
8369
|
+
// Request rejected — over limit
|
|
8370
|
+
{
|
|
8371
|
+
from: "Active",
|
|
8372
|
+
to: "Active",
|
|
8373
|
+
event: "REQUEST",
|
|
8374
|
+
guard: [">=", "@entity.requestCount", "@entity.rateLimit"],
|
|
8375
|
+
effects: [
|
|
8376
|
+
["set", "@entity.rejectedRequests", ["+", "@entity.rejectedRequests", 1]],
|
|
8377
|
+
["emit", "RATE_LIMIT_EXCEEDED", {
|
|
8378
|
+
requestCount: "@entity.requestCount",
|
|
8379
|
+
rateLimit: "@entity.rateLimit"
|
|
8380
|
+
}]
|
|
8381
|
+
]
|
|
8382
|
+
},
|
|
8383
|
+
// Sliding window reset
|
|
8384
|
+
{
|
|
8385
|
+
from: "Active",
|
|
8386
|
+
to: "Active",
|
|
8387
|
+
event: "WINDOW_RESET",
|
|
8388
|
+
effects: [
|
|
8389
|
+
["set", "@entity.requestCount", 0],
|
|
8390
|
+
["set", "@entity.windowStart", ["time/now"]]
|
|
8391
|
+
]
|
|
8392
|
+
},
|
|
8393
|
+
// Full counter reset
|
|
8394
|
+
{
|
|
8395
|
+
from: "Active",
|
|
8396
|
+
to: "Active",
|
|
8397
|
+
event: "RESET",
|
|
8398
|
+
effects: [
|
|
8399
|
+
["set", "@entity.requestCount", 0],
|
|
8400
|
+
["set", "@entity.totalRequests", 0],
|
|
8401
|
+
["set", "@entity.rejectedRequests", 0],
|
|
8402
|
+
["set", "@entity.windowStart", ["time/now"]]
|
|
8403
|
+
]
|
|
8404
|
+
}
|
|
8405
|
+
]
|
|
8406
|
+
},
|
|
8407
|
+
ticks: [
|
|
8408
|
+
{
|
|
8409
|
+
name: "window_reset",
|
|
8410
|
+
interval: "@entity.windowMs",
|
|
8411
|
+
effects: [["emit", "WINDOW_RESET"]],
|
|
8412
|
+
description: "Reset request counter on sliding window expiry"
|
|
8413
|
+
}
|
|
8414
|
+
]
|
|
8415
|
+
}
|
|
8416
|
+
],
|
|
8417
|
+
pages: []
|
|
8418
|
+
}
|
|
8419
|
+
]
|
|
8420
|
+
};
|
|
8421
|
+
var CACHE_ASIDE_BEHAVIOR = {
|
|
8422
|
+
name: "std-cache-aside",
|
|
8423
|
+
version: "1.0.0",
|
|
8424
|
+
description: "Cache-aside pattern with TTL-based freshness and eviction",
|
|
8425
|
+
orbitals: [
|
|
8426
|
+
{
|
|
8427
|
+
name: "CacheAsideOrbital",
|
|
8428
|
+
entity: {
|
|
8429
|
+
name: "CacheEntry",
|
|
8430
|
+
persistence: "runtime",
|
|
8431
|
+
fields: [
|
|
8432
|
+
{ name: "id", type: "string", required: true },
|
|
8433
|
+
{ name: "cacheKey", type: "string", default: "" },
|
|
8434
|
+
{ name: "cachedValue", type: "object", default: null },
|
|
8435
|
+
{ name: "cachedAt", type: "number", default: 0 },
|
|
8436
|
+
{ name: "ttlMs", type: "number", default: 3e5 },
|
|
8437
|
+
{ name: "cacheHits", type: "number", default: 0 },
|
|
8438
|
+
{ name: "cacheMisses", type: "number", default: 0 },
|
|
8439
|
+
{ name: "isFresh", type: "boolean", default: false },
|
|
8440
|
+
{ name: "lastAccessed", type: "number", default: 0 }
|
|
8441
|
+
]
|
|
8442
|
+
},
|
|
8443
|
+
traits: [
|
|
8444
|
+
{
|
|
8445
|
+
name: "CacheAside",
|
|
8446
|
+
linkedEntity: "CacheEntry",
|
|
8447
|
+
category: "lifecycle",
|
|
8448
|
+
emits: [
|
|
8449
|
+
{ event: "CACHE_HIT", scope: "internal" },
|
|
8450
|
+
{ event: "CACHE_MISS", scope: "internal" },
|
|
8451
|
+
{ event: "CACHE_EVICTED", scope: "internal" }
|
|
8452
|
+
],
|
|
8453
|
+
stateMachine: {
|
|
8454
|
+
states: [
|
|
8455
|
+
{ name: "Empty", isInitial: true },
|
|
8456
|
+
{ name: "Fresh" },
|
|
8457
|
+
{ name: "Stale" }
|
|
8458
|
+
],
|
|
8459
|
+
events: [
|
|
8460
|
+
{ key: "LOOKUP", name: "Cache Lookup" },
|
|
8461
|
+
{ key: "POPULATE", name: "Populate Cache" },
|
|
8462
|
+
{ key: "INVALIDATE", name: "Invalidate" },
|
|
8463
|
+
{ key: "EVICT", name: "Evict" },
|
|
8464
|
+
{ key: "EVICTION_TICK", name: "Eviction Tick" }
|
|
8465
|
+
],
|
|
8466
|
+
transitions: [
|
|
8467
|
+
// Empty: lookup is a miss
|
|
8468
|
+
{
|
|
8469
|
+
from: "Empty",
|
|
8470
|
+
to: "Empty",
|
|
8471
|
+
event: "LOOKUP",
|
|
8472
|
+
effects: [
|
|
8473
|
+
["set", "@entity.cacheMisses", ["+", "@entity.cacheMisses", 1]],
|
|
8474
|
+
["set", "@entity.lastAccessed", ["time/now"]],
|
|
8475
|
+
["emit", "CACHE_MISS", { key: "@entity.cacheKey" }]
|
|
8476
|
+
]
|
|
8477
|
+
},
|
|
8478
|
+
// Empty → Fresh: populate after fetch
|
|
8479
|
+
{
|
|
8480
|
+
from: "Empty",
|
|
8481
|
+
to: "Fresh",
|
|
8482
|
+
event: "POPULATE",
|
|
8483
|
+
effects: [
|
|
8484
|
+
["set", "@entity.cachedValue", "@payload.value"],
|
|
8485
|
+
["set", "@entity.cacheKey", "@payload.key"],
|
|
8486
|
+
["set", "@entity.cachedAt", ["time/now"]],
|
|
8487
|
+
["set", "@entity.isFresh", true]
|
|
8488
|
+
]
|
|
8489
|
+
},
|
|
8490
|
+
// Fresh: lookup is a hit
|
|
8491
|
+
{
|
|
8492
|
+
from: "Fresh",
|
|
8493
|
+
to: "Fresh",
|
|
8494
|
+
event: "LOOKUP",
|
|
8495
|
+
guard: ["<", ["-", ["time/now"], "@entity.cachedAt"], "@entity.ttlMs"],
|
|
8496
|
+
effects: [
|
|
8497
|
+
["set", "@entity.cacheHits", ["+", "@entity.cacheHits", 1]],
|
|
8498
|
+
["set", "@entity.lastAccessed", ["time/now"]],
|
|
8499
|
+
["emit", "CACHE_HIT", { key: "@entity.cacheKey" }]
|
|
8500
|
+
]
|
|
8501
|
+
},
|
|
8502
|
+
// Fresh → Stale: TTL expired on lookup
|
|
8503
|
+
{
|
|
8504
|
+
from: "Fresh",
|
|
8505
|
+
to: "Stale",
|
|
8506
|
+
event: "LOOKUP",
|
|
8507
|
+
guard: [">=", ["-", ["time/now"], "@entity.cachedAt"], "@entity.ttlMs"],
|
|
8508
|
+
effects: [
|
|
8509
|
+
["set", "@entity.isFresh", false],
|
|
8510
|
+
["set", "@entity.cacheMisses", ["+", "@entity.cacheMisses", 1]],
|
|
8511
|
+
["set", "@entity.lastAccessed", ["time/now"]],
|
|
8512
|
+
["emit", "CACHE_MISS", { key: "@entity.cacheKey", reason: "ttl_expired" }]
|
|
8513
|
+
]
|
|
8514
|
+
},
|
|
8515
|
+
// Stale: lookup is a miss
|
|
8516
|
+
{
|
|
8517
|
+
from: "Stale",
|
|
8518
|
+
to: "Stale",
|
|
8519
|
+
event: "LOOKUP",
|
|
8520
|
+
effects: [
|
|
8521
|
+
["set", "@entity.cacheMisses", ["+", "@entity.cacheMisses", 1]],
|
|
8522
|
+
["set", "@entity.lastAccessed", ["time/now"]],
|
|
8523
|
+
["emit", "CACHE_MISS", { key: "@entity.cacheKey", reason: "stale" }]
|
|
8524
|
+
]
|
|
8525
|
+
},
|
|
8526
|
+
// Stale → Fresh: re-populate
|
|
8527
|
+
{
|
|
8528
|
+
from: "Stale",
|
|
8529
|
+
to: "Fresh",
|
|
8530
|
+
event: "POPULATE",
|
|
8531
|
+
effects: [
|
|
8532
|
+
["set", "@entity.cachedValue", "@payload.value"],
|
|
8533
|
+
["set", "@entity.cachedAt", ["time/now"]],
|
|
8534
|
+
["set", "@entity.isFresh", true]
|
|
8535
|
+
]
|
|
8536
|
+
},
|
|
8537
|
+
// Fresh → Fresh: update cache
|
|
8538
|
+
{
|
|
8539
|
+
from: "Fresh",
|
|
8540
|
+
to: "Fresh",
|
|
8541
|
+
event: "POPULATE",
|
|
8542
|
+
effects: [
|
|
8543
|
+
["set", "@entity.cachedValue", "@payload.value"],
|
|
8544
|
+
["set", "@entity.cachedAt", ["time/now"]]
|
|
8545
|
+
]
|
|
8546
|
+
},
|
|
8547
|
+
// Invalidate from any cached state
|
|
8548
|
+
{
|
|
8549
|
+
from: ["Fresh", "Stale"],
|
|
8550
|
+
to: "Empty",
|
|
8551
|
+
event: "INVALIDATE",
|
|
8552
|
+
effects: [
|
|
8553
|
+
["set", "@entity.cachedValue", null],
|
|
8554
|
+
["set", "@entity.isFresh", false],
|
|
8555
|
+
["set", "@entity.cachedAt", 0]
|
|
8556
|
+
]
|
|
8557
|
+
},
|
|
8558
|
+
// Evict (with event)
|
|
8559
|
+
{
|
|
8560
|
+
from: ["Fresh", "Stale"],
|
|
8561
|
+
to: "Empty",
|
|
8562
|
+
event: "EVICT",
|
|
8563
|
+
effects: [
|
|
8564
|
+
["set", "@entity.cachedValue", null],
|
|
8565
|
+
["set", "@entity.isFresh", false],
|
|
8566
|
+
["set", "@entity.cachedAt", 0],
|
|
8567
|
+
["emit", "CACHE_EVICTED", { key: "@entity.cacheKey" }]
|
|
8568
|
+
]
|
|
8569
|
+
},
|
|
8570
|
+
// Eviction tick: evict if stale
|
|
8571
|
+
{
|
|
8572
|
+
from: "Stale",
|
|
8573
|
+
to: "Empty",
|
|
8574
|
+
event: "EVICTION_TICK",
|
|
8575
|
+
effects: [
|
|
8576
|
+
["set", "@entity.cachedValue", null],
|
|
8577
|
+
["set", "@entity.isFresh", false],
|
|
8578
|
+
["set", "@entity.cachedAt", 0],
|
|
8579
|
+
["emit", "CACHE_EVICTED", { key: "@entity.cacheKey", reason: "ttl_eviction" }]
|
|
8580
|
+
]
|
|
8581
|
+
}
|
|
8582
|
+
]
|
|
8583
|
+
},
|
|
8584
|
+
ticks: [
|
|
8585
|
+
{
|
|
8586
|
+
name: "eviction_sweep",
|
|
8587
|
+
interval: "60000",
|
|
8588
|
+
guard: ["and", ["!=", "@entity.cachedAt", 0], [">=", ["-", ["time/now"], "@entity.cachedAt"], "@entity.ttlMs"]],
|
|
8589
|
+
effects: [["emit", "EVICTION_TICK"]],
|
|
8590
|
+
description: "Periodically evict stale cache entries"
|
|
8591
|
+
}
|
|
8592
|
+
]
|
|
8593
|
+
}
|
|
8594
|
+
],
|
|
8595
|
+
pages: []
|
|
8596
|
+
}
|
|
8597
|
+
]
|
|
8598
|
+
};
|
|
8599
|
+
var SAGA_BEHAVIOR = {
|
|
8600
|
+
name: "std-saga",
|
|
8601
|
+
version: "1.0.0",
|
|
8602
|
+
description: "Saga pattern with step-by-step execution and reverse compensation on failure",
|
|
8603
|
+
orbitals: [
|
|
8604
|
+
{
|
|
8605
|
+
name: "SagaOrbital",
|
|
8606
|
+
entity: {
|
|
8607
|
+
name: "SagaState",
|
|
8608
|
+
persistence: "runtime",
|
|
8609
|
+
fields: [
|
|
8610
|
+
{ name: "id", type: "string", required: true },
|
|
8611
|
+
{ name: "sagaName", type: "string", default: "" },
|
|
8612
|
+
{ name: "currentStep", type: "number", default: 0 },
|
|
8613
|
+
{ name: "totalSteps", type: "number", default: 0 },
|
|
8614
|
+
{ name: "sagaStatus", type: "string", default: "idle" },
|
|
8615
|
+
{ name: "completedSteps", type: "array", default: [] },
|
|
8616
|
+
{ name: "compensatedSteps", type: "array", default: [] },
|
|
8617
|
+
{ name: "failedStep", type: "number", default: -1 },
|
|
8618
|
+
{ name: "failureReason", type: "string", default: "" },
|
|
8619
|
+
{ name: "startedAt", type: "number", default: 0 },
|
|
8620
|
+
{ name: "completedAt", type: "number", default: 0 }
|
|
8621
|
+
]
|
|
8622
|
+
},
|
|
8623
|
+
traits: [
|
|
8624
|
+
{
|
|
8625
|
+
name: "Saga",
|
|
8626
|
+
linkedEntity: "SagaState",
|
|
8627
|
+
category: "lifecycle",
|
|
8628
|
+
emits: [
|
|
8629
|
+
{ event: "SAGA_STARTED", scope: "external" },
|
|
8630
|
+
{ event: "SAGA_STEP_COMPLETED", scope: "external" },
|
|
8631
|
+
{ event: "SAGA_COMPLETED", scope: "external" },
|
|
8632
|
+
{ event: "SAGA_COMPENSATING", scope: "external" },
|
|
8633
|
+
{ event: "SAGA_COMPENSATION_DONE", scope: "external" },
|
|
8634
|
+
{ event: "SAGA_FAILED", scope: "external" }
|
|
8635
|
+
],
|
|
8636
|
+
stateMachine: {
|
|
8637
|
+
states: [
|
|
8638
|
+
{ name: "Idle", isInitial: true },
|
|
8639
|
+
{ name: "Running" },
|
|
8640
|
+
{ name: "Compensating" },
|
|
8641
|
+
{ name: "Completed" },
|
|
8642
|
+
{ name: "Failed" }
|
|
8643
|
+
],
|
|
8644
|
+
events: [
|
|
8645
|
+
{ key: "START_SAGA", name: "Start Saga" },
|
|
8646
|
+
{ key: "STEP_SUCCESS", name: "Step Success" },
|
|
8647
|
+
{ key: "STEP_FAILURE", name: "Step Failure" },
|
|
8648
|
+
{ key: "COMPENSATE_SUCCESS", name: "Compensate Success" },
|
|
8649
|
+
{ key: "COMPENSATE_FAILURE", name: "Compensate Failure" },
|
|
8650
|
+
{ key: "RESET", name: "Reset" }
|
|
8651
|
+
],
|
|
8652
|
+
transitions: [
|
|
8653
|
+
// Idle → Running: start the saga
|
|
8654
|
+
{
|
|
8655
|
+
from: "Idle",
|
|
8656
|
+
to: "Running",
|
|
8657
|
+
event: "START_SAGA",
|
|
8658
|
+
effects: [
|
|
8659
|
+
["set", "@entity.sagaStatus", "running"],
|
|
8660
|
+
["set", "@entity.currentStep", 0],
|
|
8661
|
+
["set", "@entity.completedSteps", []],
|
|
8662
|
+
["set", "@entity.compensatedSteps", []],
|
|
8663
|
+
["set", "@entity.failedStep", -1],
|
|
8664
|
+
["set", "@entity.failureReason", ""],
|
|
8665
|
+
["set", "@entity.startedAt", ["time/now"]],
|
|
8666
|
+
["emit", "SAGA_STARTED", { sagaName: "@entity.sagaName" }]
|
|
8667
|
+
]
|
|
8668
|
+
},
|
|
8669
|
+
// Running: step success, more steps remaining
|
|
8670
|
+
{
|
|
8671
|
+
from: "Running",
|
|
8672
|
+
to: "Running",
|
|
8673
|
+
event: "STEP_SUCCESS",
|
|
8674
|
+
guard: ["<", ["+", "@entity.currentStep", 1], "@entity.totalSteps"],
|
|
8675
|
+
effects: [
|
|
8676
|
+
["set", "@entity.currentStep", ["+", "@entity.currentStep", 1]],
|
|
8677
|
+
["emit", "SAGA_STEP_COMPLETED", {
|
|
8678
|
+
step: "@entity.currentStep",
|
|
8679
|
+
totalSteps: "@entity.totalSteps"
|
|
8680
|
+
}]
|
|
8681
|
+
]
|
|
8682
|
+
},
|
|
8683
|
+
// Running → Completed: last step succeeded
|
|
8684
|
+
{
|
|
8685
|
+
from: "Running",
|
|
8686
|
+
to: "Completed",
|
|
8687
|
+
event: "STEP_SUCCESS",
|
|
8688
|
+
guard: [">=", ["+", "@entity.currentStep", 1], "@entity.totalSteps"],
|
|
8689
|
+
effects: [
|
|
8690
|
+
["set", "@entity.sagaStatus", "completed"],
|
|
8691
|
+
["set", "@entity.completedAt", ["time/now"]],
|
|
8692
|
+
["emit", "SAGA_COMPLETED", { sagaName: "@entity.sagaName" }]
|
|
8693
|
+
]
|
|
8694
|
+
},
|
|
8695
|
+
// Running → Compensating: a step failed
|
|
8696
|
+
{
|
|
8697
|
+
from: "Running",
|
|
8698
|
+
to: "Compensating",
|
|
8699
|
+
event: "STEP_FAILURE",
|
|
8700
|
+
effects: [
|
|
8701
|
+
["set", "@entity.sagaStatus", "compensating"],
|
|
8702
|
+
["set", "@entity.failedStep", "@entity.currentStep"],
|
|
8703
|
+
["emit", "SAGA_COMPENSATING", {
|
|
8704
|
+
failedStep: "@entity.currentStep",
|
|
8705
|
+
sagaName: "@entity.sagaName"
|
|
8706
|
+
}]
|
|
8707
|
+
]
|
|
8708
|
+
},
|
|
8709
|
+
// Compensating: compensation step succeeded, more to undo
|
|
8710
|
+
{
|
|
8711
|
+
from: "Compensating",
|
|
8712
|
+
to: "Compensating",
|
|
8713
|
+
event: "COMPENSATE_SUCCESS",
|
|
8714
|
+
guard: [">", "@entity.currentStep", 0],
|
|
8715
|
+
effects: [
|
|
8716
|
+
["set", "@entity.currentStep", ["-", "@entity.currentStep", 1]]
|
|
8717
|
+
]
|
|
8718
|
+
},
|
|
8719
|
+
// Compensating → Failed: all compensations done (reached step 0)
|
|
8720
|
+
{
|
|
8721
|
+
from: "Compensating",
|
|
8722
|
+
to: "Failed",
|
|
8723
|
+
event: "COMPENSATE_SUCCESS",
|
|
8724
|
+
guard: ["<=", "@entity.currentStep", 0],
|
|
8725
|
+
effects: [
|
|
8726
|
+
["set", "@entity.sagaStatus", "failed"],
|
|
8727
|
+
["set", "@entity.completedAt", ["time/now"]],
|
|
8728
|
+
["emit", "SAGA_COMPENSATION_DONE", { sagaName: "@entity.sagaName" }]
|
|
8729
|
+
]
|
|
8730
|
+
},
|
|
8731
|
+
// Compensating → Failed: compensation itself failed
|
|
8732
|
+
{
|
|
8733
|
+
from: "Compensating",
|
|
8734
|
+
to: "Failed",
|
|
8735
|
+
event: "COMPENSATE_FAILURE",
|
|
8736
|
+
effects: [
|
|
8737
|
+
["set", "@entity.sagaStatus", "failed"],
|
|
8738
|
+
["set", "@entity.completedAt", ["time/now"]],
|
|
8739
|
+
["emit", "SAGA_FAILED", {
|
|
8740
|
+
sagaName: "@entity.sagaName",
|
|
8741
|
+
reason: "Compensation failed"
|
|
8742
|
+
}]
|
|
8743
|
+
]
|
|
8744
|
+
},
|
|
8745
|
+
// Reset from terminal states
|
|
8746
|
+
{
|
|
8747
|
+
from: ["Completed", "Failed"],
|
|
8748
|
+
to: "Idle",
|
|
8749
|
+
event: "RESET",
|
|
8750
|
+
effects: [
|
|
8751
|
+
["set", "@entity.sagaStatus", "idle"],
|
|
8752
|
+
["set", "@entity.currentStep", 0],
|
|
8753
|
+
["set", "@entity.completedSteps", []],
|
|
8754
|
+
["set", "@entity.compensatedSteps", []],
|
|
8755
|
+
["set", "@entity.failedStep", -1],
|
|
8756
|
+
["set", "@entity.failureReason", ""]
|
|
8757
|
+
]
|
|
8758
|
+
}
|
|
8759
|
+
]
|
|
8760
|
+
},
|
|
8761
|
+
ticks: []
|
|
8762
|
+
}
|
|
8763
|
+
],
|
|
8764
|
+
pages: []
|
|
8765
|
+
}
|
|
8766
|
+
]
|
|
8767
|
+
};
|
|
8768
|
+
var METRICS_COLLECTOR_BEHAVIOR = {
|
|
8769
|
+
name: "std-metrics-collector",
|
|
8770
|
+
version: "1.0.0",
|
|
8771
|
+
description: "Tick-based metrics aggregation with periodic flush and reporting",
|
|
8772
|
+
orbitals: [
|
|
8773
|
+
{
|
|
8774
|
+
name: "MetricsCollectorOrbital",
|
|
8775
|
+
entity: {
|
|
8776
|
+
name: "MetricsState",
|
|
8777
|
+
persistence: "runtime",
|
|
8778
|
+
fields: [
|
|
8779
|
+
{ name: "id", type: "string", required: true },
|
|
8780
|
+
{ name: "counters", type: "object", default: {} },
|
|
8781
|
+
{ name: "gauges", type: "object", default: {} },
|
|
8782
|
+
{ name: "lastFlush", type: "number", default: 0 },
|
|
8783
|
+
{ name: "flushIntervalMs", type: "number", default: 6e4 },
|
|
8784
|
+
{ name: "totalFlushes", type: "number", default: 0 },
|
|
8785
|
+
{ name: "totalRecorded", type: "number", default: 0 }
|
|
8786
|
+
]
|
|
8787
|
+
},
|
|
8788
|
+
traits: [
|
|
8789
|
+
{
|
|
8790
|
+
name: "MetricsCollector",
|
|
8791
|
+
linkedEntity: "MetricsState",
|
|
8792
|
+
category: "lifecycle",
|
|
8793
|
+
emits: [
|
|
8794
|
+
{ event: "METRICS_REPORT", scope: "external" }
|
|
8795
|
+
],
|
|
8796
|
+
stateMachine: {
|
|
8797
|
+
states: [
|
|
8798
|
+
{ name: "Collecting", isInitial: true }
|
|
8799
|
+
],
|
|
8800
|
+
events: [
|
|
8801
|
+
{ key: "RECORD_COUNTER", name: "Record Counter" },
|
|
8802
|
+
{ key: "RECORD_GAUGE", name: "Record Gauge" },
|
|
8803
|
+
{ key: "FLUSH", name: "Flush Metrics" },
|
|
8804
|
+
{ key: "RESET", name: "Reset All" }
|
|
8805
|
+
],
|
|
8806
|
+
transitions: [
|
|
8807
|
+
// Record a counter increment
|
|
8808
|
+
{
|
|
8809
|
+
from: "Collecting",
|
|
8810
|
+
to: "Collecting",
|
|
8811
|
+
event: "RECORD_COUNTER",
|
|
8812
|
+
effects: [
|
|
8813
|
+
["set", "@entity.totalRecorded", ["+", "@entity.totalRecorded", 1]]
|
|
8814
|
+
]
|
|
8815
|
+
},
|
|
8816
|
+
// Record a gauge value
|
|
8817
|
+
{
|
|
8818
|
+
from: "Collecting",
|
|
8819
|
+
to: "Collecting",
|
|
8820
|
+
event: "RECORD_GAUGE",
|
|
8821
|
+
effects: [
|
|
8822
|
+
["set", "@entity.totalRecorded", ["+", "@entity.totalRecorded", 1]]
|
|
8823
|
+
]
|
|
8824
|
+
},
|
|
8825
|
+
// Flush: emit report and reset counters
|
|
8826
|
+
{
|
|
8827
|
+
from: "Collecting",
|
|
8828
|
+
to: "Collecting",
|
|
8829
|
+
event: "FLUSH",
|
|
8830
|
+
effects: [
|
|
8831
|
+
["emit", "METRICS_REPORT", {
|
|
8832
|
+
counters: "@entity.counters",
|
|
8833
|
+
gauges: "@entity.gauges",
|
|
8834
|
+
totalRecorded: "@entity.totalRecorded"
|
|
8835
|
+
}],
|
|
8836
|
+
["set", "@entity.counters", {}],
|
|
8837
|
+
["set", "@entity.lastFlush", ["time/now"]],
|
|
8838
|
+
["set", "@entity.totalFlushes", ["+", "@entity.totalFlushes", 1]]
|
|
8839
|
+
]
|
|
8840
|
+
},
|
|
8841
|
+
// Full reset
|
|
8842
|
+
{
|
|
8843
|
+
from: "Collecting",
|
|
8844
|
+
to: "Collecting",
|
|
8845
|
+
event: "RESET",
|
|
8846
|
+
effects: [
|
|
8847
|
+
["set", "@entity.counters", {}],
|
|
8848
|
+
["set", "@entity.gauges", {}],
|
|
8849
|
+
["set", "@entity.totalRecorded", 0],
|
|
8850
|
+
["set", "@entity.totalFlushes", 0],
|
|
8851
|
+
["set", "@entity.lastFlush", 0]
|
|
8852
|
+
]
|
|
8853
|
+
}
|
|
8854
|
+
]
|
|
8855
|
+
},
|
|
8856
|
+
ticks: [
|
|
8857
|
+
{
|
|
8858
|
+
name: "periodic_flush",
|
|
8859
|
+
interval: "@entity.flushIntervalMs",
|
|
8860
|
+
guard: [">", "@entity.totalRecorded", 0],
|
|
8861
|
+
effects: [["emit", "FLUSH"]],
|
|
8862
|
+
description: "Periodically flush accumulated metrics"
|
|
8863
|
+
}
|
|
8864
|
+
]
|
|
8865
|
+
}
|
|
8866
|
+
],
|
|
8867
|
+
pages: []
|
|
8868
|
+
}
|
|
8869
|
+
]
|
|
8870
|
+
};
|
|
8871
|
+
var INFRASTRUCTURE_BEHAVIORS = [
|
|
8872
|
+
CIRCUIT_BREAKER_BEHAVIOR,
|
|
8873
|
+
HEALTH_CHECK_BEHAVIOR,
|
|
8874
|
+
RATE_LIMITER_BEHAVIOR,
|
|
8875
|
+
CACHE_ASIDE_BEHAVIOR,
|
|
8876
|
+
SAGA_BEHAVIOR,
|
|
8877
|
+
METRICS_COLLECTOR_BEHAVIOR
|
|
8878
|
+
];
|
|
8879
|
+
|
|
8880
|
+
// behaviors/registry.ts
|
|
8881
|
+
var STANDARD_BEHAVIORS = [
|
|
8882
|
+
...UI_INTERACTION_BEHAVIORS,
|
|
8883
|
+
...DATA_MANAGEMENT_BEHAVIORS,
|
|
8884
|
+
...ASYNC_BEHAVIORS,
|
|
8885
|
+
...FEEDBACK_BEHAVIORS,
|
|
8886
|
+
...GAME_CORE_BEHAVIORS,
|
|
8887
|
+
...GAME_ENTITY_BEHAVIORS,
|
|
8888
|
+
...GAME_UI_BEHAVIORS,
|
|
8889
|
+
...INFRASTRUCTURE_BEHAVIORS
|
|
8890
|
+
];
|
|
8891
|
+
var BEHAVIOR_REGISTRY = STANDARD_BEHAVIORS.reduce(
|
|
8892
|
+
(acc, behavior) => {
|
|
8893
|
+
acc[behavior.name] = behavior;
|
|
8894
|
+
return acc;
|
|
8895
|
+
},
|
|
8896
|
+
{}
|
|
8897
|
+
);
|
|
8898
|
+
function getBehavior(name) {
|
|
8899
|
+
return BEHAVIOR_REGISTRY[name];
|
|
8900
|
+
}
|
|
8901
|
+
function isKnownBehavior(name) {
|
|
8902
|
+
return name in BEHAVIOR_REGISTRY;
|
|
8903
|
+
}
|
|
8904
|
+
function getAllBehaviorNames() {
|
|
8905
|
+
return Object.keys(BEHAVIOR_REGISTRY);
|
|
8906
|
+
}
|
|
8907
|
+
function getAllBehaviors() {
|
|
8908
|
+
return STANDARD_BEHAVIORS;
|
|
8909
|
+
}
|
|
8910
|
+
function getAllBehaviorMetadata() {
|
|
8911
|
+
return STANDARD_BEHAVIORS.map(getBehaviorMetadata);
|
|
8912
|
+
}
|
|
8913
|
+
function findBehaviorsForUseCase(useCase) {
|
|
8914
|
+
const lowerUseCase = useCase.toLowerCase();
|
|
8915
|
+
return STANDARD_BEHAVIORS.filter(
|
|
8916
|
+
(behavior) => behavior.description?.toLowerCase().includes(lowerUseCase) ?? false
|
|
8917
|
+
);
|
|
8918
|
+
}
|
|
8919
|
+
function getBehaviorsForEvent(event) {
|
|
8920
|
+
return STANDARD_BEHAVIORS.filter((behavior) => {
|
|
8921
|
+
for (const orbital of behavior.orbitals || []) {
|
|
8922
|
+
for (const trait of orbital.traits || []) {
|
|
8923
|
+
if (typeof trait === "object" && "stateMachine" in trait) {
|
|
8924
|
+
const events = trait.stateMachine?.events || [];
|
|
8925
|
+
if (events.some((e) => e.key === event)) {
|
|
8926
|
+
return true;
|
|
8927
|
+
}
|
|
8928
|
+
}
|
|
8929
|
+
}
|
|
8930
|
+
}
|
|
8931
|
+
return false;
|
|
8932
|
+
});
|
|
8933
|
+
}
|
|
8934
|
+
function getBehaviorsWithState(state) {
|
|
8935
|
+
return STANDARD_BEHAVIORS.filter((behavior) => {
|
|
8936
|
+
for (const orbital of behavior.orbitals || []) {
|
|
8937
|
+
for (const trait of orbital.traits || []) {
|
|
8938
|
+
if (typeof trait === "object" && "stateMachine" in trait) {
|
|
8939
|
+
const states = trait.stateMachine?.states || [];
|
|
8940
|
+
if (states.some((s) => s.name === state)) {
|
|
8941
|
+
return true;
|
|
8942
|
+
}
|
|
8943
|
+
}
|
|
8944
|
+
}
|
|
8945
|
+
}
|
|
8946
|
+
return false;
|
|
8947
|
+
});
|
|
8948
|
+
}
|
|
8949
|
+
function validateBehaviorReference(name) {
|
|
8950
|
+
if (!name.startsWith("std-")) {
|
|
8951
|
+
return `Behavior name must start with 'std-': ${name}`;
|
|
8952
|
+
}
|
|
8953
|
+
if (!isKnownBehavior(name)) {
|
|
8954
|
+
const suggestions = findSimilarBehaviors(name);
|
|
8955
|
+
if (suggestions.length > 0) {
|
|
8956
|
+
return `Unknown behavior '${name}'. Did you mean: ${suggestions.join(", ")}?`;
|
|
8957
|
+
}
|
|
8958
|
+
return `Unknown behavior: ${name}`;
|
|
7777
8959
|
}
|
|
7778
8960
|
return null;
|
|
7779
8961
|
}
|
|
@@ -7905,6 +9087,12 @@ var MODULE_DESCRIPTIONS = {
|
|
|
7905
9087
|
displayName: "Training Operations",
|
|
7906
9088
|
description: "Training loops, loss functions, and optimization for neural networks.",
|
|
7907
9089
|
icon: "\u{1F3AF}"
|
|
9090
|
+
},
|
|
9091
|
+
prob: {
|
|
9092
|
+
name: "Probabilistic",
|
|
9093
|
+
displayName: "Probabilistic Programming",
|
|
9094
|
+
description: "Distribution sampling, Bayesian inference via rejection sampling, and statistical summaries.",
|
|
9095
|
+
icon: "\u{1F3B2}"
|
|
7908
9096
|
}
|
|
7909
9097
|
};
|
|
7910
9098
|
var BEHAVIOR_GROUPINGS = {
|