@feilunxitong/arkit 0.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/README.md +74 -0
- package/dist/achievements.d.ts +79 -0
- package/dist/achievements.js +76 -0
- package/dist/auto.d.ts +19 -0
- package/dist/auto.js +42 -0
- package/dist/benchmarks.d.ts +29 -0
- package/dist/benchmarks.js +145 -0
- package/dist/breaker.d.ts +36 -0
- package/dist/breaker.js +115 -0
- package/dist/dashboard.d.ts +32 -0
- package/dist/dashboard.js +66 -0
- package/dist/guard.d.ts +24 -0
- package/dist/guard.js +106 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.js +57 -0
- package/dist/langchain.d.ts +72 -0
- package/dist/langchain.js +138 -0
- package/dist/module-kit.d.ts +64 -0
- package/dist/module-kit.js +157 -0
- package/dist/multi-agent.d.ts +59 -0
- package/dist/multi-agent.js +192 -0
- package/dist/proactive.d.ts +45 -0
- package/dist/proactive.js +183 -0
- package/dist/schema-hub.d.ts +64 -0
- package/dist/schema-hub.js +508 -0
- package/dist/schema-registry.d.ts +17 -0
- package/dist/schema-registry.js +142 -0
- package/dist/score.d.ts +47 -0
- package/dist/score.js +97 -0
- package/dist/stateful-breaker.d.ts +45 -0
- package/dist/stateful-breaker.js +231 -0
- package/dist/trace.d.ts +36 -0
- package/dist/trace.js +113 -0
- package/dist/validator.d.ts +25 -0
- package/dist/validator.js +56 -0
- package/package.json +43 -0
package/README.md
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# 🛡 ARK — Agent Reliability Kit (TypeScript)
|
|
2
|
+
|
|
3
|
+
> **Trust infrastructure for AI agents.** Now in TypeScript.
|
|
4
|
+
> Stripe-level idempotency × Sentinel circuit breakers × OpenTelemetry tracing × IDE-style validation.
|
|
5
|
+
|
|
6
|
+
[](https://github.com/wzg0911/ark-ts)
|
|
7
|
+
[](https://www.npmjs.com/package/ark-trust)
|
|
8
|
+
[](https://www.typescriptlang.org/)
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
npm install ark-trust
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
```typescript
|
|
15
|
+
import { IdempotencyGuard, CircuitBreaker, autoInit } from 'ark-trust';
|
|
16
|
+
|
|
17
|
+
// 🛡 Never run duplicate tool calls
|
|
18
|
+
const guard = new IdempotencyGuard();
|
|
19
|
+
const safeCharge = guard.wrap('stripe.charge', (amount: number) =>
|
|
20
|
+
stripe.charges.create({ amount })
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
// ⚡ Auto-fallback when APIs fail
|
|
24
|
+
const breaker = new CircuitBreaker('gpt4', 3);
|
|
25
|
+
const result = await breaker.call(
|
|
26
|
+
() => gpt4.generate(prompt),
|
|
27
|
+
() => claude.generate(prompt) // falls back automatically
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
// 🔧 Validate agent output
|
|
31
|
+
const { guard: g, breaker: b, validator: v, score: s } = autoInit();
|
|
32
|
+
// Zero config — auto-detects your agent framework
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## What's Included
|
|
36
|
+
|
|
37
|
+
| Component | Size | Description |
|
|
38
|
+
|-----------|------|-------------|
|
|
39
|
+
| 🛡 IdempotencyGuard | 2.3KB | Prevents duplicate tool calls |
|
|
40
|
+
| ⚡ CircuitBreaker | 2.8KB | Auto-fallback on failure |
|
|
41
|
+
| 🔧 OutputValidator | 1.9KB | Validates agent output |
|
|
42
|
+
| 👁 Trace | 2.7KB | Full execution tracing |
|
|
43
|
+
| 🎮 ReliabilityScore | 3.4KB | Viral reliability badge |
|
|
44
|
+
| 🏆 Achievements | 2.9KB | Gamification system |
|
|
45
|
+
| 📦 SchemaRegistry | 4.2KB | 8 built-in tool schemas |
|
|
46
|
+
| 🖥 Dashboard | 3.3KB | Trust monitor dashboard |
|
|
47
|
+
| 🔍 Auto-detect | 1.4KB | Zero-config framework detection |
|
|
48
|
+
|
|
49
|
+
**25KB total** · 16/16 tests · Node.js 18+ / TypeScript 5.x
|
|
50
|
+
|
|
51
|
+
## Quick Demo
|
|
52
|
+
|
|
53
|
+
```typescript
|
|
54
|
+
import { autoInit, Dashboard, Achievements } from 'ark-trust';
|
|
55
|
+
|
|
56
|
+
const ark = autoInit();
|
|
57
|
+
const dash = new Dashboard(ark.guard, ark.breaker, ark.validator, ark.score, ark.achievements);
|
|
58
|
+
|
|
59
|
+
// Simulate agent runs
|
|
60
|
+
ark.score.recordRun({ success: true, intercepts: 2, toolCalls: 10 });
|
|
61
|
+
ark.score.recordRun({ success: true, toolCalls: 15 });
|
|
62
|
+
|
|
63
|
+
// Get your reliability badge to share
|
|
64
|
+
console.log(ark.score.badgeUrl); // shields.io badge URL
|
|
65
|
+
console.log(dash.render()); // Trust dashboard
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Python SDK
|
|
69
|
+
|
|
70
|
+
Also available: [`pip install ark-trust`](https://github.com/wzg0911/ark) (Python 3.9+)
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
**Built with 🧬 gene recombination · MIT License**
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Achievements — 成就系统
|
|
3
|
+
* Gene source: Gaming achievement systems
|
|
4
|
+
* Makes reliability fun and shareable.
|
|
5
|
+
*/
|
|
6
|
+
export interface Achievement {
|
|
7
|
+
id: string;
|
|
8
|
+
name: string;
|
|
9
|
+
icon: string;
|
|
10
|
+
description: string;
|
|
11
|
+
unlocked: boolean;
|
|
12
|
+
progress: number;
|
|
13
|
+
target: number;
|
|
14
|
+
}
|
|
15
|
+
export declare const definitions: {
|
|
16
|
+
guardian_bronze: {
|
|
17
|
+
name: string;
|
|
18
|
+
icon: string;
|
|
19
|
+
description: string;
|
|
20
|
+
target: number;
|
|
21
|
+
};
|
|
22
|
+
guardian_silver: {
|
|
23
|
+
name: string;
|
|
24
|
+
icon: string;
|
|
25
|
+
description: string;
|
|
26
|
+
target: number;
|
|
27
|
+
};
|
|
28
|
+
guardian_gold: {
|
|
29
|
+
name: string;
|
|
30
|
+
icon: string;
|
|
31
|
+
description: string;
|
|
32
|
+
target: number;
|
|
33
|
+
};
|
|
34
|
+
survivor_bronze: {
|
|
35
|
+
name: string;
|
|
36
|
+
icon: string;
|
|
37
|
+
description: string;
|
|
38
|
+
target: number;
|
|
39
|
+
};
|
|
40
|
+
survivor_silver: {
|
|
41
|
+
name: string;
|
|
42
|
+
icon: string;
|
|
43
|
+
description: string;
|
|
44
|
+
target: number;
|
|
45
|
+
};
|
|
46
|
+
inspector_bronze: {
|
|
47
|
+
name: string;
|
|
48
|
+
icon: string;
|
|
49
|
+
description: string;
|
|
50
|
+
target: number;
|
|
51
|
+
};
|
|
52
|
+
watcher_bronze: {
|
|
53
|
+
name: string;
|
|
54
|
+
icon: string;
|
|
55
|
+
description: string;
|
|
56
|
+
target: number;
|
|
57
|
+
};
|
|
58
|
+
ark_master: {
|
|
59
|
+
name: string;
|
|
60
|
+
icon: string;
|
|
61
|
+
description: string;
|
|
62
|
+
target: number;
|
|
63
|
+
};
|
|
64
|
+
};
|
|
65
|
+
export declare class Achievements {
|
|
66
|
+
private achievements;
|
|
67
|
+
constructor();
|
|
68
|
+
/** Update progress for an achievement */
|
|
69
|
+
update(id: string, progress: number): boolean;
|
|
70
|
+
private checkArkMaster;
|
|
71
|
+
get list(): Achievement[];
|
|
72
|
+
get unlocked(): Achievement[];
|
|
73
|
+
get summary(): Record<string, {
|
|
74
|
+
name: string;
|
|
75
|
+
icon: string;
|
|
76
|
+
unlocked: boolean;
|
|
77
|
+
progress: string;
|
|
78
|
+
}>;
|
|
79
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Achievements — 成就系统
|
|
4
|
+
* Gene source: Gaming achievement systems
|
|
5
|
+
* Makes reliability fun and shareable.
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.Achievements = exports.definitions = void 0;
|
|
9
|
+
exports.definitions = {
|
|
10
|
+
guardian_bronze: { name: 'Guardian Bronze', icon: '🛡', description: 'Intercept 10 duplicate calls', target: 10 },
|
|
11
|
+
guardian_silver: { name: 'Guardian Silver', icon: '🛡', description: 'Intercept 100 duplicate calls', target: 100 },
|
|
12
|
+
guardian_gold: { name: 'Guardian Gold', icon: '🛡', description: 'Intercept 1000 duplicate calls', target: 1000 },
|
|
13
|
+
survivor_bronze: { name: 'Survivor Bronze', icon: '⚡', description: 'Recover from 3 circuit breaks', target: 3 },
|
|
14
|
+
survivor_silver: { name: 'Survivor Silver', icon: '⚡', description: 'Recover from 10 circuit breaks', target: 10 },
|
|
15
|
+
inspector_bronze: { name: 'Inspector Bronze', icon: '🔧', description: '99%+ validation pass rate over 100 checks', target: 100 },
|
|
16
|
+
watcher_bronze: { name: 'Watcher Bronze', icon: '👁', description: 'Trace 1000 spans', target: 1000 },
|
|
17
|
+
ark_master: { name: 'ARK Master', icon: '🎖', description: 'Unlock all other achievements', target: 7 },
|
|
18
|
+
};
|
|
19
|
+
class Achievements {
|
|
20
|
+
achievements = new Map();
|
|
21
|
+
constructor() {
|
|
22
|
+
for (const [id, def] of Object.entries(exports.definitions)) {
|
|
23
|
+
this.achievements.set(id, {
|
|
24
|
+
id,
|
|
25
|
+
name: def.name,
|
|
26
|
+
icon: def.icon,
|
|
27
|
+
description: def.description,
|
|
28
|
+
unlocked: false,
|
|
29
|
+
progress: 0,
|
|
30
|
+
target: def.target,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/** Update progress for an achievement */
|
|
35
|
+
update(id, progress) {
|
|
36
|
+
const a = this.achievements.get(id);
|
|
37
|
+
if (!a)
|
|
38
|
+
return false;
|
|
39
|
+
a.progress = Math.max(a.progress, progress);
|
|
40
|
+
if (a.progress >= a.target && !a.unlocked) {
|
|
41
|
+
a.unlocked = true;
|
|
42
|
+
this.checkArkMaster();
|
|
43
|
+
return true; // newly unlocked
|
|
44
|
+
}
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
checkArkMaster() {
|
|
48
|
+
const master = this.achievements.get('ark_master');
|
|
49
|
+
if (!master || master.unlocked)
|
|
50
|
+
return;
|
|
51
|
+
const others = [...this.achievements.values()].filter((a) => a.id !== 'ark_master');
|
|
52
|
+
if (others.every((a) => a.unlocked)) {
|
|
53
|
+
master.unlocked = true;
|
|
54
|
+
master.progress = master.target;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
get list() {
|
|
58
|
+
return [...this.achievements.values()];
|
|
59
|
+
}
|
|
60
|
+
get unlocked() {
|
|
61
|
+
return this.list.filter((a) => a.unlocked);
|
|
62
|
+
}
|
|
63
|
+
get summary() {
|
|
64
|
+
const result = {};
|
|
65
|
+
for (const a of this.list) {
|
|
66
|
+
result[a.id] = {
|
|
67
|
+
name: a.name,
|
|
68
|
+
icon: a.icon,
|
|
69
|
+
unlocked: a.unlocked,
|
|
70
|
+
progress: `${a.progress}/${a.target}`,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
return result;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
exports.Achievements = Achievements;
|
package/dist/auto.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-detection + zero-config bootstrap
|
|
3
|
+
*/
|
|
4
|
+
import { IdempotencyGuard } from './guard.js';
|
|
5
|
+
import { CircuitBreaker } from './breaker.js';
|
|
6
|
+
import { OutputValidator } from './validator.js';
|
|
7
|
+
import { ReliabilityScore } from './score.js';
|
|
8
|
+
import { SchemaRegistry } from './schema-registry.js';
|
|
9
|
+
export declare function detectFrameworks(): string[];
|
|
10
|
+
export interface ARKConfig {
|
|
11
|
+
frameworks: string[];
|
|
12
|
+
mode: 'standalone' | 'integrated';
|
|
13
|
+
guard: IdempotencyGuard;
|
|
14
|
+
breaker: CircuitBreaker;
|
|
15
|
+
validator: OutputValidator;
|
|
16
|
+
score: ReliabilityScore;
|
|
17
|
+
registry: SchemaRegistry;
|
|
18
|
+
}
|
|
19
|
+
export declare function autoInit(): ARKConfig;
|
package/dist/auto.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.detectFrameworks = detectFrameworks;
|
|
4
|
+
exports.autoInit = autoInit;
|
|
5
|
+
/**
|
|
6
|
+
* Auto-detection + zero-config bootstrap
|
|
7
|
+
*/
|
|
8
|
+
const guard_js_1 = require("./guard.js");
|
|
9
|
+
const breaker_js_1 = require("./breaker.js");
|
|
10
|
+
const validator_js_1 = require("./validator.js");
|
|
11
|
+
const score_js_1 = require("./score.js");
|
|
12
|
+
const schema_registry_js_1 = require("./schema-registry.js");
|
|
13
|
+
function detectFrameworks() {
|
|
14
|
+
const frameworks = [];
|
|
15
|
+
const checks = [
|
|
16
|
+
['langchain', 'LangChain'],
|
|
17
|
+
['openai', 'OpenAI SDK'],
|
|
18
|
+
['anthropic', 'Anthropic SDK'],
|
|
19
|
+
['@google/generative-ai', 'Gemini SDK'],
|
|
20
|
+
['llamaindex', 'LlamaIndex'],
|
|
21
|
+
];
|
|
22
|
+
for (const [mod, name] of checks) {
|
|
23
|
+
try {
|
|
24
|
+
require.resolve(mod);
|
|
25
|
+
frameworks.push(name);
|
|
26
|
+
}
|
|
27
|
+
catch { /* not installed */ }
|
|
28
|
+
}
|
|
29
|
+
return frameworks;
|
|
30
|
+
}
|
|
31
|
+
function autoInit() {
|
|
32
|
+
const frameworks = detectFrameworks();
|
|
33
|
+
return {
|
|
34
|
+
frameworks,
|
|
35
|
+
mode: frameworks.length > 0 ? 'integrated' : 'standalone',
|
|
36
|
+
guard: new guard_js_1.IdempotencyGuard(),
|
|
37
|
+
breaker: new breaker_js_1.CircuitBreaker('auto-detect'),
|
|
38
|
+
validator: new validator_js_1.OutputValidator(),
|
|
39
|
+
score: new score_js_1.ReliabilityScore(),
|
|
40
|
+
registry: new schema_registry_js_1.SchemaRegistry(),
|
|
41
|
+
};
|
|
42
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Benchmarks — 性能基准测试套件
|
|
3
|
+
* Performance benchmarking for core ARK components.
|
|
4
|
+
*/
|
|
5
|
+
export interface BenchmarkMetrics {
|
|
6
|
+
name: string;
|
|
7
|
+
iterations: number;
|
|
8
|
+
totalMs: number;
|
|
9
|
+
avgMs: number;
|
|
10
|
+
p50Ms: number;
|
|
11
|
+
p99Ms: number;
|
|
12
|
+
stdMs: number;
|
|
13
|
+
throughputOps: number;
|
|
14
|
+
}
|
|
15
|
+
export declare class Benchmarks {
|
|
16
|
+
iterations: number;
|
|
17
|
+
results: BenchmarkMetrics[];
|
|
18
|
+
constructor(iterations?: number);
|
|
19
|
+
private measure;
|
|
20
|
+
benchIdempotencyKeyGen(): BenchmarkMetrics;
|
|
21
|
+
benchIdempotencyCheckHit(): BenchmarkMetrics;
|
|
22
|
+
benchIdempotencyCheckMiss(): BenchmarkMetrics;
|
|
23
|
+
benchCircuitBreakerClosed(): BenchmarkMetrics;
|
|
24
|
+
benchValidatorValid(): BenchmarkMetrics;
|
|
25
|
+
benchValidatorNone(): BenchmarkMetrics;
|
|
26
|
+
runAll(): BenchmarkMetrics[];
|
|
27
|
+
toJSON(): string;
|
|
28
|
+
summary(): Record<string, unknown>;
|
|
29
|
+
}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Benchmarks — 性能基准测试套件
|
|
4
|
+
* Performance benchmarking for core ARK components.
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.Benchmarks = void 0;
|
|
8
|
+
const guard_js_1 = require("./guard.js");
|
|
9
|
+
const breaker_js_1 = require("./breaker.js");
|
|
10
|
+
const validator_js_1 = require("./validator.js");
|
|
11
|
+
function sortedPercentile(sorted, p) {
|
|
12
|
+
const idx = Math.floor(sorted.length * p);
|
|
13
|
+
return sorted[Math.min(idx, sorted.length - 1)];
|
|
14
|
+
}
|
|
15
|
+
function stdDev(values, mean) {
|
|
16
|
+
if (values.length <= 1)
|
|
17
|
+
return 0;
|
|
18
|
+
const sqDiffs = values.map((v) => (v - mean) ** 2);
|
|
19
|
+
return Math.sqrt(sqDiffs.reduce((a, b) => a + b, 0) / (values.length - 1));
|
|
20
|
+
}
|
|
21
|
+
class Benchmarks {
|
|
22
|
+
iterations;
|
|
23
|
+
results = [];
|
|
24
|
+
constructor(iterations = 10_000) {
|
|
25
|
+
this.iterations = iterations;
|
|
26
|
+
}
|
|
27
|
+
measure(name, fn) {
|
|
28
|
+
const timings = [];
|
|
29
|
+
for (let i = 0; i < this.iterations; i++) {
|
|
30
|
+
const start = performance.now();
|
|
31
|
+
fn();
|
|
32
|
+
const elapsed = performance.now() - start;
|
|
33
|
+
timings.push(elapsed);
|
|
34
|
+
}
|
|
35
|
+
const sorted = [...timings].sort((a, b) => a - b);
|
|
36
|
+
const total = timings.reduce((a, b) => a + b, 0);
|
|
37
|
+
const avg = total / timings.length;
|
|
38
|
+
return {
|
|
39
|
+
name,
|
|
40
|
+
iterations: this.iterations,
|
|
41
|
+
totalMs: total,
|
|
42
|
+
avgMs: avg,
|
|
43
|
+
p50Ms: sortedPercentile(sorted, 0.5),
|
|
44
|
+
p99Ms: sortedPercentile(sorted, 0.99),
|
|
45
|
+
stdMs: stdDev(timings, avg),
|
|
46
|
+
throughputOps: 1000 / avg,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
benchIdempotencyKeyGen() {
|
|
50
|
+
const guard = new guard_js_1.IdempotencyGuard();
|
|
51
|
+
const args = { tool: 'send_email', to: 'test@ark.dev', body: 'hello'.repeat(10) };
|
|
52
|
+
return this.measure('IdempotencyGuard.key()', () => {
|
|
53
|
+
guard.key('send_email', args);
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
benchIdempotencyCheckHit() {
|
|
57
|
+
const guard = new guard_js_1.IdempotencyGuard();
|
|
58
|
+
const key = guard.key('send_payment', {
|
|
59
|
+
amount: 100,
|
|
60
|
+
currency: 'USD',
|
|
61
|
+
});
|
|
62
|
+
// Manually record so check returns hit
|
|
63
|
+
const record = {
|
|
64
|
+
idempotencyKey: key,
|
|
65
|
+
toolName: 'send_payment',
|
|
66
|
+
argsHash: 'abc123',
|
|
67
|
+
result: { status: 'ok' },
|
|
68
|
+
};
|
|
69
|
+
// Access internal cache via guard's record method
|
|
70
|
+
guard.record(key, record);
|
|
71
|
+
return this.measure('IdempotencyGuard.check() [hit]', () => {
|
|
72
|
+
guard.check(key);
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
benchIdempotencyCheckMiss() {
|
|
76
|
+
const guard = new guard_js_1.IdempotencyGuard();
|
|
77
|
+
const key = guard.key('new_tool', { foo: 'bar' });
|
|
78
|
+
return this.measure('IdempotencyGuard.check() [miss]', () => {
|
|
79
|
+
guard.check(key);
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
benchCircuitBreakerClosed() {
|
|
83
|
+
const cb = new breaker_js_1.CircuitBreaker('bench');
|
|
84
|
+
return this.measure('CircuitBreaker.call() [closed]', () => {
|
|
85
|
+
cb.callSync(() => 'ok');
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
benchValidatorValid() {
|
|
89
|
+
const v = new validator_js_1.OutputValidator();
|
|
90
|
+
return this.measure('OutputValidator.validateShape() [valid]', () => {
|
|
91
|
+
v.validateShape({ status: 'ok', data: 'test' }, { status: 'string', data: 'string' });
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
benchValidatorNone() {
|
|
95
|
+
const v = new validator_js_1.OutputValidator();
|
|
96
|
+
return this.measure('OutputValidator.validateShape() [none]', () => {
|
|
97
|
+
v.validateShape(null, {});
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
runAll() {
|
|
101
|
+
const benches = [
|
|
102
|
+
['Idempotency Key Gen', () => this.benchIdempotencyKeyGen()],
|
|
103
|
+
['Idempotency Check [hit]', () => this.benchIdempotencyCheckHit()],
|
|
104
|
+
['Idempotency Check [miss]', () => this.benchIdempotencyCheckMiss()],
|
|
105
|
+
['CircuitBreaker [closed]', () => this.benchCircuitBreakerClosed()],
|
|
106
|
+
['Validator [valid]', () => this.benchValidatorValid()],
|
|
107
|
+
['Validator [none]', () => this.benchValidatorNone()],
|
|
108
|
+
];
|
|
109
|
+
console.log('\n' + '='.repeat(60));
|
|
110
|
+
console.log(` ARK Benchmarks (${this.iterations.toLocaleString()} iterations each)`);
|
|
111
|
+
console.log('='.repeat(60));
|
|
112
|
+
console.log(`${'Benchmark'.padEnd(35)} ${'avg(μs)'.padStart(10)} ${'p50(μs)'.padStart(10)} ${'p99(μs)'.padStart(10)} ${'ops/s'.padStart(12)}`);
|
|
113
|
+
console.log(`${'-'.repeat(35)} ${'-'.repeat(10)} ${'-'.repeat(10)} ${'-'.repeat(10)} ${'-'.repeat(12)}`);
|
|
114
|
+
for (const [, benchFn] of benches) {
|
|
115
|
+
const result = benchFn();
|
|
116
|
+
this.results.push(result);
|
|
117
|
+
const μs = 1000; // convert ms → μs for display
|
|
118
|
+
console.log(`${result.name.padEnd(35)} ` +
|
|
119
|
+
`${(result.avgMs * μs).toFixed(1).padStart(10)} ` +
|
|
120
|
+
`${(result.p50Ms * μs).toFixed(1).padStart(10)} ` +
|
|
121
|
+
`${(result.p99Ms * μs).toFixed(1).padStart(10)} ` +
|
|
122
|
+
`${Math.round(result.throughputOps).toLocaleString().padStart(12)}`);
|
|
123
|
+
}
|
|
124
|
+
console.log('='.repeat(60) + '\n');
|
|
125
|
+
return this.results;
|
|
126
|
+
}
|
|
127
|
+
toJSON() {
|
|
128
|
+
return JSON.stringify(this.results, null, 2);
|
|
129
|
+
}
|
|
130
|
+
summary() {
|
|
131
|
+
if (this.results.length === 0)
|
|
132
|
+
this.runAll();
|
|
133
|
+
const fastest = this.results.reduce((a, b) => (a.avgMs < b.avgMs ? a : b));
|
|
134
|
+
const slowest = this.results.reduce((a, b) => (a.avgMs > b.avgMs ? a : b));
|
|
135
|
+
return {
|
|
136
|
+
version: '0.4.1-dev',
|
|
137
|
+
iterations: this.iterations,
|
|
138
|
+
results: this.results,
|
|
139
|
+
slowest: slowest.name,
|
|
140
|
+
fastest: fastest.name,
|
|
141
|
+
totalTimeMs: this.results.reduce((a, b) => a + b.totalMs, 0),
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
exports.Benchmarks = Benchmarks;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CircuitBreaker — 熔断控制器
|
|
3
|
+
* Gene source: Sentinel microservice resilience
|
|
4
|
+
* Auto-meltdown → safe fallback
|
|
5
|
+
*/
|
|
6
|
+
export declare class CircuitOpenError extends Error {
|
|
7
|
+
constructor(name: string);
|
|
8
|
+
}
|
|
9
|
+
type CircuitState = 'closed' | 'open' | 'half-open';
|
|
10
|
+
interface BreakerStats {
|
|
11
|
+
state: CircuitState;
|
|
12
|
+
failures: number;
|
|
13
|
+
totalCalls: number;
|
|
14
|
+
totalFailures: number;
|
|
15
|
+
reliability: string;
|
|
16
|
+
}
|
|
17
|
+
export declare class CircuitBreaker {
|
|
18
|
+
private name;
|
|
19
|
+
private failureThreshold;
|
|
20
|
+
private recoveryMs;
|
|
21
|
+
private halfOpenMaxCalls;
|
|
22
|
+
state: CircuitState;
|
|
23
|
+
private failures;
|
|
24
|
+
private totalCalls;
|
|
25
|
+
private totalFailures;
|
|
26
|
+
private lastFailure;
|
|
27
|
+
private openedAt;
|
|
28
|
+
constructor(name: string, failureThreshold?: number, recoveryMs?: number, halfOpenMaxCalls?: number);
|
|
29
|
+
call<T>(primary: () => Promise<T> | T, fallback?: () => Promise<T> | T): Promise<T>;
|
|
30
|
+
callSync<T>(primary: () => T, fallback?: () => T): T;
|
|
31
|
+
private onSuccess;
|
|
32
|
+
private onFailure;
|
|
33
|
+
reset(): void;
|
|
34
|
+
get stats(): BreakerStats;
|
|
35
|
+
}
|
|
36
|
+
export {};
|
package/dist/breaker.js
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* CircuitBreaker — 熔断控制器
|
|
4
|
+
* Gene source: Sentinel microservice resilience
|
|
5
|
+
* Auto-meltdown → safe fallback
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.CircuitBreaker = exports.CircuitOpenError = void 0;
|
|
9
|
+
class CircuitOpenError extends Error {
|
|
10
|
+
constructor(name) {
|
|
11
|
+
super(`Circuit ${name} is OPEN — refusing call`);
|
|
12
|
+
this.name = 'CircuitOpenError';
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
exports.CircuitOpenError = CircuitOpenError;
|
|
16
|
+
class CircuitBreaker {
|
|
17
|
+
name;
|
|
18
|
+
failureThreshold;
|
|
19
|
+
recoveryMs;
|
|
20
|
+
halfOpenMaxCalls;
|
|
21
|
+
state = 'closed';
|
|
22
|
+
failures = 0;
|
|
23
|
+
totalCalls = 0;
|
|
24
|
+
totalFailures = 0;
|
|
25
|
+
lastFailure = 0;
|
|
26
|
+
openedAt = 0;
|
|
27
|
+
constructor(name, failureThreshold = 3, recoveryMs = 30_000, halfOpenMaxCalls = 1) {
|
|
28
|
+
this.name = name;
|
|
29
|
+
this.failureThreshold = failureThreshold;
|
|
30
|
+
this.recoveryMs = recoveryMs;
|
|
31
|
+
this.halfOpenMaxCalls = halfOpenMaxCalls;
|
|
32
|
+
}
|
|
33
|
+
async call(primary, fallback) {
|
|
34
|
+
this.totalCalls++;
|
|
35
|
+
if (this.state === 'open') {
|
|
36
|
+
if (Date.now() - this.openedAt > this.recoveryMs) {
|
|
37
|
+
this.state = 'half-open';
|
|
38
|
+
}
|
|
39
|
+
else if (fallback) {
|
|
40
|
+
return fallback();
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
throw new CircuitOpenError(this.name);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
const result = await primary();
|
|
48
|
+
this.onSuccess();
|
|
49
|
+
return result;
|
|
50
|
+
}
|
|
51
|
+
catch (err) {
|
|
52
|
+
this.onFailure();
|
|
53
|
+
if (fallback)
|
|
54
|
+
return fallback();
|
|
55
|
+
throw err;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
callSync(primary, fallback) {
|
|
59
|
+
this.totalCalls++;
|
|
60
|
+
if (this.state === 'open') {
|
|
61
|
+
if (Date.now() - this.openedAt > this.recoveryMs) {
|
|
62
|
+
this.state = 'half-open';
|
|
63
|
+
}
|
|
64
|
+
else if (fallback) {
|
|
65
|
+
return fallback();
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
throw new CircuitOpenError(this.name);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
try {
|
|
72
|
+
const result = primary();
|
|
73
|
+
this.onSuccess();
|
|
74
|
+
return result;
|
|
75
|
+
}
|
|
76
|
+
catch (err) {
|
|
77
|
+
this.onFailure();
|
|
78
|
+
if (fallback)
|
|
79
|
+
return fallback();
|
|
80
|
+
throw err;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
onSuccess() {
|
|
84
|
+
if (this.state === 'half-open')
|
|
85
|
+
this.state = 'closed';
|
|
86
|
+
this.failures = 0;
|
|
87
|
+
}
|
|
88
|
+
onFailure() {
|
|
89
|
+
this.failures++;
|
|
90
|
+
this.totalFailures++;
|
|
91
|
+
this.lastFailure = Date.now();
|
|
92
|
+
if (this.failures >= this.failureThreshold) {
|
|
93
|
+
this.state = 'open';
|
|
94
|
+
this.openedAt = Date.now();
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
reset() {
|
|
98
|
+
this.state = 'closed';
|
|
99
|
+
this.failures = 0;
|
|
100
|
+
this.totalCalls = 0;
|
|
101
|
+
this.totalFailures = 0;
|
|
102
|
+
}
|
|
103
|
+
get stats() {
|
|
104
|
+
return {
|
|
105
|
+
state: this.state,
|
|
106
|
+
failures: this.failures,
|
|
107
|
+
totalCalls: this.totalCalls,
|
|
108
|
+
totalFailures: this.totalFailures,
|
|
109
|
+
reliability: this.totalCalls > 0
|
|
110
|
+
? `${((1 - this.totalFailures / this.totalCalls) * 100).toFixed(1)}%`
|
|
111
|
+
: '100%',
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
exports.CircuitBreaker = CircuitBreaker;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dashboard — 信任仪表盘
|
|
3
|
+
* Real-time trust monitoring for AI agents.
|
|
4
|
+
*/
|
|
5
|
+
import { IdempotencyGuard } from './guard.js';
|
|
6
|
+
import { CircuitBreaker } from './breaker.js';
|
|
7
|
+
import { OutputValidator } from './validator.js';
|
|
8
|
+
import { ReliabilityScore } from './score.js';
|
|
9
|
+
import { Achievements } from './achievements.js';
|
|
10
|
+
export interface TrustMonitor {
|
|
11
|
+
guardPasses: number;
|
|
12
|
+
guardIntercepts: number;
|
|
13
|
+
guardSaveRate: string;
|
|
14
|
+
breakerState: string;
|
|
15
|
+
breakerReliability: string;
|
|
16
|
+
validatorPassed: number;
|
|
17
|
+
validatorBlocked: number;
|
|
18
|
+
validatorBlockRate: string;
|
|
19
|
+
score: number;
|
|
20
|
+
grade: string;
|
|
21
|
+
}
|
|
22
|
+
export declare class Dashboard {
|
|
23
|
+
private guard;
|
|
24
|
+
private breaker;
|
|
25
|
+
private validator;
|
|
26
|
+
private score;
|
|
27
|
+
private achievements;
|
|
28
|
+
constructor(guard: IdempotencyGuard, breaker: CircuitBreaker, validator: OutputValidator, score: ReliabilityScore, achievements: Achievements);
|
|
29
|
+
get trustMonitor(): TrustMonitor;
|
|
30
|
+
/** Render a text dashboard */
|
|
31
|
+
render(): string;
|
|
32
|
+
}
|