@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/dist/score.d.ts
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ReliabilityScore — 可靠性评分引擎
|
|
3
|
+
* Gene source: Gaming achievement systems
|
|
4
|
+
* Viral badge + social sharing built-in.
|
|
5
|
+
*/
|
|
6
|
+
interface ScoreRecord {
|
|
7
|
+
timestamp: number;
|
|
8
|
+
score: number;
|
|
9
|
+
grade: string;
|
|
10
|
+
intercepts: number;
|
|
11
|
+
blocks: number;
|
|
12
|
+
}
|
|
13
|
+
export declare class ReliabilityScore {
|
|
14
|
+
totalRuns: number;
|
|
15
|
+
successfulRuns: number;
|
|
16
|
+
duplicateIntercepts: number;
|
|
17
|
+
outputBlocks: number;
|
|
18
|
+
circuitTrips: number;
|
|
19
|
+
totalToolCalls: number;
|
|
20
|
+
totalToolFailures: number;
|
|
21
|
+
history: ScoreRecord[];
|
|
22
|
+
get score(): number;
|
|
23
|
+
get grade(): string;
|
|
24
|
+
get badgeUrl(): string;
|
|
25
|
+
get markdownBadge(): string;
|
|
26
|
+
get shareText(): string;
|
|
27
|
+
recordRun(opts: {
|
|
28
|
+
success: boolean;
|
|
29
|
+
intercepts?: number;
|
|
30
|
+
blocks?: number;
|
|
31
|
+
toolCalls?: number;
|
|
32
|
+
toolFailures?: number;
|
|
33
|
+
circuitTrips?: number;
|
|
34
|
+
}): void;
|
|
35
|
+
get summary(): {
|
|
36
|
+
score: number;
|
|
37
|
+
grade: string;
|
|
38
|
+
totalRuns: number;
|
|
39
|
+
successRate: string;
|
|
40
|
+
totalIntercepts: number;
|
|
41
|
+
totalBlocks: number;
|
|
42
|
+
toolReliability: string;
|
|
43
|
+
badge: string;
|
|
44
|
+
share: string;
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
export {};
|
package/dist/score.js
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* ReliabilityScore — 可靠性评分引擎
|
|
4
|
+
* Gene source: Gaming achievement systems
|
|
5
|
+
* Viral badge + social sharing built-in.
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.ReliabilityScore = void 0;
|
|
9
|
+
class ReliabilityScore {
|
|
10
|
+
totalRuns = 0;
|
|
11
|
+
successfulRuns = 0;
|
|
12
|
+
duplicateIntercepts = 0;
|
|
13
|
+
outputBlocks = 0;
|
|
14
|
+
circuitTrips = 0;
|
|
15
|
+
totalToolCalls = 0;
|
|
16
|
+
totalToolFailures = 0;
|
|
17
|
+
history = [];
|
|
18
|
+
get score() {
|
|
19
|
+
if (this.totalRuns === 0)
|
|
20
|
+
return 0;
|
|
21
|
+
const base = (this.successfulRuns / this.totalRuns) * 100;
|
|
22
|
+
const penalty = (this.duplicateIntercepts + this.outputBlocks) * 0.3;
|
|
23
|
+
const failPenalty = (this.totalToolFailures / Math.max(this.totalToolCalls, 1)) * 15;
|
|
24
|
+
return Math.max(0, Math.min(100, +(base - penalty - failPenalty).toFixed(1)));
|
|
25
|
+
}
|
|
26
|
+
get grade() {
|
|
27
|
+
const s = this.score;
|
|
28
|
+
if (s >= 97)
|
|
29
|
+
return 'S+ 🏆';
|
|
30
|
+
if (s >= 93)
|
|
31
|
+
return 'S';
|
|
32
|
+
if (s >= 85)
|
|
33
|
+
return 'A+';
|
|
34
|
+
if (s >= 80)
|
|
35
|
+
return 'A';
|
|
36
|
+
if (s >= 70)
|
|
37
|
+
return 'B+';
|
|
38
|
+
if (s >= 60)
|
|
39
|
+
return 'B';
|
|
40
|
+
if (s >= 50)
|
|
41
|
+
return 'C';
|
|
42
|
+
return 'D';
|
|
43
|
+
}
|
|
44
|
+
get badgeUrl() {
|
|
45
|
+
const colors = {
|
|
46
|
+
'S+ 🏆': 'FFD700', S: '00C853', 'A+': '4CAF50',
|
|
47
|
+
A: '8BC34A', 'B+': 'FFC107', B: 'FF9800',
|
|
48
|
+
C: 'FF5722', D: 'F44336',
|
|
49
|
+
};
|
|
50
|
+
const color = colors[this.grade] || '999';
|
|
51
|
+
const label = this.grade.replace(/ /g, '_');
|
|
52
|
+
return `https://img.shields.io/badge/ARK_Score-${this.score}%25_${label}-${color}?style=for-the-badge&logo=shield`;
|
|
53
|
+
}
|
|
54
|
+
get markdownBadge() {
|
|
55
|
+
return `[](https://github.com/wzg0911/ark)`;
|
|
56
|
+
}
|
|
57
|
+
get shareText() {
|
|
58
|
+
const templates = {
|
|
59
|
+
'S+ 🏆': `🔥 ${this.score}% reliability! ARK caught ${this.duplicateIntercepts} dupes. S+ tier agent! ${this.markdownBadge}`,
|
|
60
|
+
S: `⚡ Agent reliability: ${this.score}% (S rank). ARK = trust for AI. ${this.markdownBadge}`,
|
|
61
|
+
'A+': `📈 ${this.score}% (A+). Getting closer to perfect. ${this.markdownBadge}`,
|
|
62
|
+
};
|
|
63
|
+
return templates[this.grade] ||
|
|
64
|
+
`🛡 Agent trust: ${this.score}%. ${this.duplicateIntercepts} safe intercepts. ${this.markdownBadge}`;
|
|
65
|
+
}
|
|
66
|
+
recordRun(opts) {
|
|
67
|
+
this.totalRuns++;
|
|
68
|
+
if (opts.success)
|
|
69
|
+
this.successfulRuns++;
|
|
70
|
+
this.duplicateIntercepts += opts.intercepts ?? 0;
|
|
71
|
+
this.outputBlocks += opts.blocks ?? 0;
|
|
72
|
+
this.totalToolCalls += opts.toolCalls ?? 0;
|
|
73
|
+
this.totalToolFailures += opts.toolFailures ?? 0;
|
|
74
|
+
this.circuitTrips += opts.circuitTrips ?? 0;
|
|
75
|
+
this.history.push({
|
|
76
|
+
timestamp: Date.now(),
|
|
77
|
+
score: this.score,
|
|
78
|
+
grade: this.grade,
|
|
79
|
+
intercepts: opts.intercepts ?? 0,
|
|
80
|
+
blocks: opts.blocks ?? 0,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
get summary() {
|
|
84
|
+
return {
|
|
85
|
+
score: this.score,
|
|
86
|
+
grade: this.grade,
|
|
87
|
+
totalRuns: this.totalRuns,
|
|
88
|
+
successRate: `${((this.successfulRuns / Math.max(this.totalRuns, 1)) * 100).toFixed(1)}%`,
|
|
89
|
+
totalIntercepts: this.duplicateIntercepts,
|
|
90
|
+
totalBlocks: this.outputBlocks,
|
|
91
|
+
toolReliability: `${((1 - this.totalToolFailures / Math.max(this.totalToolCalls, 1)) * 100).toFixed(1)}%`,
|
|
92
|
+
badge: this.markdownBadge,
|
|
93
|
+
share: this.shareText,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
exports.ReliabilityScore = ReliabilityScore;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* StatefulBreaker — 持久化熔断器
|
|
3
|
+
* Gene source: EverOS (⭐7,225) + MemBrain
|
|
4
|
+
* Circuit breaker state persisted to disk — survives process restarts.
|
|
5
|
+
*/
|
|
6
|
+
export declare class CircuitOpenError extends Error {
|
|
7
|
+
constructor(name: string, waitSeconds: number);
|
|
8
|
+
}
|
|
9
|
+
interface StatefulBreakerStats {
|
|
10
|
+
name: string;
|
|
11
|
+
state: string;
|
|
12
|
+
failureCount: number;
|
|
13
|
+
successCount: number;
|
|
14
|
+
totalCalls: number;
|
|
15
|
+
totalFailures: number;
|
|
16
|
+
recoveryTimeout: number;
|
|
17
|
+
persistPath: string;
|
|
18
|
+
reliability: string;
|
|
19
|
+
}
|
|
20
|
+
export declare class StatefulBreaker {
|
|
21
|
+
name: string;
|
|
22
|
+
private failureThreshold;
|
|
23
|
+
private recoveryTimeout;
|
|
24
|
+
private halfOpenMax;
|
|
25
|
+
private autoPersist;
|
|
26
|
+
private state;
|
|
27
|
+
private failureCount;
|
|
28
|
+
private lastFailure;
|
|
29
|
+
private successCount;
|
|
30
|
+
private halfOpenTries;
|
|
31
|
+
private totalCalls;
|
|
32
|
+
private totalFailures;
|
|
33
|
+
private persistPath;
|
|
34
|
+
constructor(name: string, failureThreshold?: number, recoveryTimeout?: number, halfOpenMax?: number, persistPath?: string, autoPersist?: boolean);
|
|
35
|
+
private defaultState;
|
|
36
|
+
private loadState;
|
|
37
|
+
private saveState;
|
|
38
|
+
call<T>(primary: () => Promise<T> | T, fallback?: () => Promise<T> | T): Promise<T>;
|
|
39
|
+
private onSuccess;
|
|
40
|
+
private onFailure;
|
|
41
|
+
reset(): void;
|
|
42
|
+
inspectPersistence(): Record<string, unknown>;
|
|
43
|
+
get stats(): StatefulBreakerStats;
|
|
44
|
+
}
|
|
45
|
+
export {};
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* StatefulBreaker — 持久化熔断器
|
|
4
|
+
* Gene source: EverOS (⭐7,225) + MemBrain
|
|
5
|
+
* Circuit breaker state persisted to disk — survives process restarts.
|
|
6
|
+
*/
|
|
7
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
8
|
+
if (k2 === undefined) k2 = k;
|
|
9
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
10
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
11
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
12
|
+
}
|
|
13
|
+
Object.defineProperty(o, k2, desc);
|
|
14
|
+
}) : (function(o, m, k, k2) {
|
|
15
|
+
if (k2 === undefined) k2 = k;
|
|
16
|
+
o[k2] = m[k];
|
|
17
|
+
}));
|
|
18
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
19
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
20
|
+
}) : function(o, v) {
|
|
21
|
+
o["default"] = v;
|
|
22
|
+
});
|
|
23
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
24
|
+
var ownKeys = function(o) {
|
|
25
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
26
|
+
var ar = [];
|
|
27
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
28
|
+
return ar;
|
|
29
|
+
};
|
|
30
|
+
return ownKeys(o);
|
|
31
|
+
};
|
|
32
|
+
return function (mod) {
|
|
33
|
+
if (mod && mod.__esModule) return mod;
|
|
34
|
+
var result = {};
|
|
35
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
36
|
+
__setModuleDefault(result, mod);
|
|
37
|
+
return result;
|
|
38
|
+
};
|
|
39
|
+
})();
|
|
40
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
41
|
+
exports.StatefulBreaker = exports.CircuitOpenError = void 0;
|
|
42
|
+
const fs = __importStar(require("node:fs"));
|
|
43
|
+
const path = __importStar(require("node:path"));
|
|
44
|
+
const os = __importStar(require("node:os"));
|
|
45
|
+
class CircuitOpenError extends Error {
|
|
46
|
+
constructor(name, waitSeconds) {
|
|
47
|
+
super(`Circuit [${name}] OPEN. Cooldown: ${Math.max(0, waitSeconds).toFixed(0)}s`);
|
|
48
|
+
this.name = 'CircuitOpenError';
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
exports.CircuitOpenError = CircuitOpenError;
|
|
52
|
+
class StatefulBreaker {
|
|
53
|
+
name;
|
|
54
|
+
failureThreshold;
|
|
55
|
+
recoveryTimeout;
|
|
56
|
+
halfOpenMax;
|
|
57
|
+
autoPersist;
|
|
58
|
+
state = 'closed';
|
|
59
|
+
failureCount = 0;
|
|
60
|
+
lastFailure = 0;
|
|
61
|
+
successCount = 0;
|
|
62
|
+
halfOpenTries = 0;
|
|
63
|
+
totalCalls = 0;
|
|
64
|
+
totalFailures = 0;
|
|
65
|
+
persistPath;
|
|
66
|
+
constructor(name, failureThreshold = 3, recoveryTimeout = 30, halfOpenMax = 2, persistPath, autoPersist = true) {
|
|
67
|
+
this.name = name;
|
|
68
|
+
this.failureThreshold = failureThreshold;
|
|
69
|
+
this.recoveryTimeout = recoveryTimeout;
|
|
70
|
+
this.halfOpenMax = halfOpenMax;
|
|
71
|
+
this.autoPersist = autoPersist;
|
|
72
|
+
if (persistPath) {
|
|
73
|
+
this.persistPath = persistPath;
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
const arkDir = path.join(os.homedir(), '.ark', 'state');
|
|
77
|
+
fs.mkdirSync(arkDir, { recursive: true });
|
|
78
|
+
this.persistPath = path.join(arkDir, `breaker_${name}.json`);
|
|
79
|
+
}
|
|
80
|
+
this.loadState();
|
|
81
|
+
this.saveState();
|
|
82
|
+
}
|
|
83
|
+
defaultState() {
|
|
84
|
+
return {
|
|
85
|
+
name: this.name,
|
|
86
|
+
state: 'closed',
|
|
87
|
+
failureCount: 0,
|
|
88
|
+
lastFailure: 0,
|
|
89
|
+
successCount: 0,
|
|
90
|
+
halfOpenTries: 0,
|
|
91
|
+
totalCalls: 0,
|
|
92
|
+
totalFailures: 0,
|
|
93
|
+
updatedAt: Date.now(),
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
loadState() {
|
|
97
|
+
try {
|
|
98
|
+
if (fs.existsSync(this.persistPath)) {
|
|
99
|
+
const data = JSON.parse(fs.readFileSync(this.persistPath, 'utf-8'));
|
|
100
|
+
this.state = data.state ?? 'closed';
|
|
101
|
+
this.failureCount = data.failureCount ?? 0;
|
|
102
|
+
this.lastFailure = data.lastFailure ?? 0;
|
|
103
|
+
this.successCount = data.successCount ?? 0;
|
|
104
|
+
this.halfOpenTries = data.halfOpenTries ?? 0;
|
|
105
|
+
this.totalCalls = data.totalCalls ?? 0;
|
|
106
|
+
this.totalFailures = data.totalFailures ?? 0;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
// Corrupted file → use defaults
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
saveState() {
|
|
114
|
+
if (!this.autoPersist)
|
|
115
|
+
return;
|
|
116
|
+
const snapshot = {
|
|
117
|
+
name: this.name,
|
|
118
|
+
state: this.state,
|
|
119
|
+
failureCount: this.failureCount,
|
|
120
|
+
lastFailure: this.lastFailure,
|
|
121
|
+
successCount: this.successCount,
|
|
122
|
+
halfOpenTries: this.halfOpenTries,
|
|
123
|
+
totalCalls: this.totalCalls,
|
|
124
|
+
totalFailures: this.totalFailures,
|
|
125
|
+
updatedAt: Date.now(),
|
|
126
|
+
};
|
|
127
|
+
try {
|
|
128
|
+
fs.writeFileSync(this.persistPath, JSON.stringify(snapshot, null, 2));
|
|
129
|
+
}
|
|
130
|
+
catch {
|
|
131
|
+
// Silently skip write errors
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
async call(primary, fallback) {
|
|
135
|
+
this.totalCalls++;
|
|
136
|
+
if (this.state === 'open') {
|
|
137
|
+
if (Date.now() / 1000 - this.lastFailure > this.recoveryTimeout) {
|
|
138
|
+
this.state = 'half-open';
|
|
139
|
+
this.halfOpenTries = 0;
|
|
140
|
+
this.saveState();
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
const remaining = this.recoveryTimeout - (Date.now() / 1000 - this.lastFailure);
|
|
144
|
+
if (fallback)
|
|
145
|
+
return fallback();
|
|
146
|
+
throw new CircuitOpenError(this.name, remaining);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
if (this.state === 'half-open') {
|
|
150
|
+
this.halfOpenTries++;
|
|
151
|
+
if (this.halfOpenTries > this.halfOpenMax) {
|
|
152
|
+
this.state = 'open';
|
|
153
|
+
this.saveState();
|
|
154
|
+
if (fallback)
|
|
155
|
+
return fallback();
|
|
156
|
+
throw new CircuitOpenError(this.name, this.recoveryTimeout);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
try {
|
|
160
|
+
const result = await primary();
|
|
161
|
+
this.onSuccess();
|
|
162
|
+
this.saveState();
|
|
163
|
+
return result;
|
|
164
|
+
}
|
|
165
|
+
catch (err) {
|
|
166
|
+
this.onFailure();
|
|
167
|
+
this.totalFailures++;
|
|
168
|
+
this.saveState();
|
|
169
|
+
if (fallback)
|
|
170
|
+
return fallback();
|
|
171
|
+
throw err;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
onSuccess() {
|
|
175
|
+
if (this.state === 'half-open') {
|
|
176
|
+
this.state = 'closed';
|
|
177
|
+
}
|
|
178
|
+
this.failureCount = 0;
|
|
179
|
+
this.successCount++;
|
|
180
|
+
}
|
|
181
|
+
onFailure() {
|
|
182
|
+
this.failureCount++;
|
|
183
|
+
this.lastFailure = Date.now() / 1000;
|
|
184
|
+
if (this.failureCount >= this.failureThreshold) {
|
|
185
|
+
this.state = 'open';
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
reset() {
|
|
189
|
+
const defaults = this.defaultState();
|
|
190
|
+
this.state = defaults.state;
|
|
191
|
+
this.failureCount = defaults.failureCount;
|
|
192
|
+
this.lastFailure = defaults.lastFailure;
|
|
193
|
+
this.successCount = defaults.successCount;
|
|
194
|
+
this.halfOpenTries = defaults.halfOpenTries;
|
|
195
|
+
this.totalCalls = defaults.totalCalls;
|
|
196
|
+
this.totalFailures = defaults.totalFailures;
|
|
197
|
+
this.saveState();
|
|
198
|
+
}
|
|
199
|
+
inspectPersistence() {
|
|
200
|
+
const result = {
|
|
201
|
+
persistPath: this.persistPath,
|
|
202
|
+
fileExists: fs.existsSync(this.persistPath),
|
|
203
|
+
currentState: this.state,
|
|
204
|
+
};
|
|
205
|
+
if (result.fileExists) {
|
|
206
|
+
try {
|
|
207
|
+
result.storedData = JSON.parse(fs.readFileSync(this.persistPath, 'utf-8'));
|
|
208
|
+
}
|
|
209
|
+
catch {
|
|
210
|
+
result.storedData = null;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
return result;
|
|
214
|
+
}
|
|
215
|
+
get stats() {
|
|
216
|
+
return {
|
|
217
|
+
name: this.name,
|
|
218
|
+
state: this.state,
|
|
219
|
+
failureCount: this.failureCount,
|
|
220
|
+
successCount: this.successCount,
|
|
221
|
+
totalCalls: this.totalCalls,
|
|
222
|
+
totalFailures: this.totalFailures,
|
|
223
|
+
recoveryTimeout: this.recoveryTimeout,
|
|
224
|
+
persistPath: this.persistPath,
|
|
225
|
+
reliability: this.totalCalls > 0
|
|
226
|
+
? `${((1 - this.totalFailures / this.totalCalls) * 100).toFixed(1)}%`
|
|
227
|
+
: '100%',
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
exports.StatefulBreaker = StatefulBreaker;
|
package/dist/trace.d.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export interface Span {
|
|
2
|
+
spanId: string;
|
|
3
|
+
parentId?: string;
|
|
4
|
+
name: string;
|
|
5
|
+
start: number;
|
|
6
|
+
end?: number;
|
|
7
|
+
tags: Record<string, string>;
|
|
8
|
+
result?: string;
|
|
9
|
+
error?: string;
|
|
10
|
+
children: Span[];
|
|
11
|
+
}
|
|
12
|
+
interface TraceSummary {
|
|
13
|
+
traceId: string;
|
|
14
|
+
totalSpans: number;
|
|
15
|
+
durationMs: number;
|
|
16
|
+
maxDepth: number;
|
|
17
|
+
status: 'ok' | 'error';
|
|
18
|
+
}
|
|
19
|
+
export declare class Trace {
|
|
20
|
+
traceId: string;
|
|
21
|
+
spans: Span[];
|
|
22
|
+
private stack;
|
|
23
|
+
constructor(name: string);
|
|
24
|
+
startSpan(name: string, tags?: Record<string, string>): Span;
|
|
25
|
+
endSpan(result?: string, error?: string): void;
|
|
26
|
+
/** Count all spans recursively */
|
|
27
|
+
private countSpans;
|
|
28
|
+
/** Max depth of span tree */
|
|
29
|
+
private maxDepth;
|
|
30
|
+
summary(): TraceSummary;
|
|
31
|
+
/** Flatten spans into a list for table rendering */
|
|
32
|
+
flatten(spans?: Span[], depth?: number): Array<Span & {
|
|
33
|
+
depth: number;
|
|
34
|
+
}>;
|
|
35
|
+
}
|
|
36
|
+
export {};
|
package/dist/trace.js
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.Trace = void 0;
|
|
37
|
+
/**
|
|
38
|
+
* Trace — 链路追踪
|
|
39
|
+
* Gene source: OpenTelemetry distributed tracing
|
|
40
|
+
* Full execution trace visibility for agent runs.
|
|
41
|
+
*/
|
|
42
|
+
const crypto = __importStar(require("crypto"));
|
|
43
|
+
class Trace {
|
|
44
|
+
traceId;
|
|
45
|
+
spans = [];
|
|
46
|
+
stack = [];
|
|
47
|
+
constructor(name) {
|
|
48
|
+
this.traceId = crypto.randomUUID().slice(0, 8);
|
|
49
|
+
this.startSpan(name);
|
|
50
|
+
}
|
|
51
|
+
startSpan(name, tags) {
|
|
52
|
+
const span = {
|
|
53
|
+
spanId: crypto.randomUUID().slice(0, 8),
|
|
54
|
+
parentId: this.stack.length > 0 ? this.stack[this.stack.length - 1].spanId : undefined,
|
|
55
|
+
name,
|
|
56
|
+
start: Date.now(),
|
|
57
|
+
tags: tags || {},
|
|
58
|
+
children: [],
|
|
59
|
+
};
|
|
60
|
+
if (this.stack.length > 0) {
|
|
61
|
+
this.stack[this.stack.length - 1].children.push(span);
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
this.spans.push(span);
|
|
65
|
+
}
|
|
66
|
+
this.stack.push(span);
|
|
67
|
+
return span;
|
|
68
|
+
}
|
|
69
|
+
endSpan(result, error) {
|
|
70
|
+
const span = this.stack.pop();
|
|
71
|
+
if (!span)
|
|
72
|
+
return;
|
|
73
|
+
span.end = Date.now();
|
|
74
|
+
if (result)
|
|
75
|
+
span.result = result.slice(0, 200);
|
|
76
|
+
if (error)
|
|
77
|
+
span.error = error.slice(0, 200);
|
|
78
|
+
}
|
|
79
|
+
/** Count all spans recursively */
|
|
80
|
+
countSpans(spans) {
|
|
81
|
+
return spans.reduce((sum, s) => sum + 1 + this.countSpans(s.children), 0);
|
|
82
|
+
}
|
|
83
|
+
/** Max depth of span tree */
|
|
84
|
+
maxDepth(spans, depth = 1) {
|
|
85
|
+
return spans.reduce((max, s) => Math.max(max, ...(s.children.length > 0 ? [this.maxDepth(s.children, depth + 1)] : [depth])), depth);
|
|
86
|
+
}
|
|
87
|
+
summary() {
|
|
88
|
+
const totalSpans = this.countSpans(this.spans);
|
|
89
|
+
const durationMs = this.spans.reduce((max, s) => {
|
|
90
|
+
if (s.end)
|
|
91
|
+
return Math.max(max, s.end - s.start);
|
|
92
|
+
return max;
|
|
93
|
+
}, 0);
|
|
94
|
+
const hasError = this.spans.some((s) => s.error) ||
|
|
95
|
+
this.spans.some((s) => s.children.some((c) => c.error));
|
|
96
|
+
return {
|
|
97
|
+
traceId: this.traceId,
|
|
98
|
+
totalSpans,
|
|
99
|
+
durationMs,
|
|
100
|
+
maxDepth: this.maxDepth(this.spans),
|
|
101
|
+
status: hasError ? 'error' : 'ok',
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
/** Flatten spans into a list for table rendering */
|
|
105
|
+
flatten(spans, depth = 0) {
|
|
106
|
+
const list = spans || this.spans;
|
|
107
|
+
return list.flatMap((s) => [
|
|
108
|
+
{ ...s, depth },
|
|
109
|
+
...this.flatten(s.children, depth + 1),
|
|
110
|
+
]);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
exports.Trace = Trace;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OutputValidator — 输出验证器
|
|
3
|
+
* Gene source: IDE static type checking
|
|
4
|
+
* Validates agent output against Zod schemas.
|
|
5
|
+
*/
|
|
6
|
+
import { ZodSchema } from 'zod';
|
|
7
|
+
export interface ValidationResult {
|
|
8
|
+
valid: boolean;
|
|
9
|
+
data?: unknown;
|
|
10
|
+
errors?: string[];
|
|
11
|
+
}
|
|
12
|
+
export declare class OutputValidator {
|
|
13
|
+
passed: number;
|
|
14
|
+
blocked: number;
|
|
15
|
+
private validations;
|
|
16
|
+
validate<T>(schema: ZodSchema<T>, output: unknown): ValidationResult;
|
|
17
|
+
/** Quick-check an object against a simple shape */
|
|
18
|
+
validateShape(output: unknown, expected: Record<string, string>): ValidationResult;
|
|
19
|
+
get stats(): {
|
|
20
|
+
passed: number;
|
|
21
|
+
blocked: number;
|
|
22
|
+
validations: number;
|
|
23
|
+
blockRate: string;
|
|
24
|
+
};
|
|
25
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.OutputValidator = void 0;
|
|
4
|
+
class OutputValidator {
|
|
5
|
+
passed = 0;
|
|
6
|
+
blocked = 0;
|
|
7
|
+
validations = 0;
|
|
8
|
+
validate(schema, output) {
|
|
9
|
+
this.validations++;
|
|
10
|
+
const result = schema.safeParse(output);
|
|
11
|
+
if (result.success) {
|
|
12
|
+
this.passed++;
|
|
13
|
+
return { valid: true, data: result.data };
|
|
14
|
+
}
|
|
15
|
+
this.blocked++;
|
|
16
|
+
return {
|
|
17
|
+
valid: false,
|
|
18
|
+
errors: result.error.issues.map((i) => `${i.path.join('.')}: ${i.message}`),
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
/** Quick-check an object against a simple shape */
|
|
22
|
+
validateShape(output, expected) {
|
|
23
|
+
if (output === null || output === undefined) {
|
|
24
|
+
return { valid: false, errors: ['Output is null/undefined'] };
|
|
25
|
+
}
|
|
26
|
+
if (typeof output !== 'object') {
|
|
27
|
+
return { valid: false, errors: ['Output is not an object'] };
|
|
28
|
+
}
|
|
29
|
+
const obj = output;
|
|
30
|
+
const errors = [];
|
|
31
|
+
for (const [key, type] of Object.entries(expected)) {
|
|
32
|
+
if (!(key in obj))
|
|
33
|
+
errors.push(`${key} is missing`);
|
|
34
|
+
else if (typeof obj[key] !== type)
|
|
35
|
+
errors.push(`${key} should be ${type}, got ${typeof obj[key]}`);
|
|
36
|
+
}
|
|
37
|
+
this.validations++;
|
|
38
|
+
if (errors.length === 0) {
|
|
39
|
+
this.passed++;
|
|
40
|
+
return { valid: true, data: obj };
|
|
41
|
+
}
|
|
42
|
+
this.blocked++;
|
|
43
|
+
return { valid: false, errors };
|
|
44
|
+
}
|
|
45
|
+
get stats() {
|
|
46
|
+
return {
|
|
47
|
+
passed: this.passed,
|
|
48
|
+
blocked: this.blocked,
|
|
49
|
+
validations: this.validations,
|
|
50
|
+
blockRate: this.validations > 0
|
|
51
|
+
? `${((this.blocked / this.validations) * 100).toFixed(1)}%`
|
|
52
|
+
: '0%',
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
exports.OutputValidator = OutputValidator;
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@feilunxitong/arkit",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "🛡 ARKit — Agent Reliability Kit. Trust infrastructure for AI agents. TypeScript/Node.js SDK. (feilunxitong fork)",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist",
|
|
9
|
+
"README.md"
|
|
10
|
+
],
|
|
11
|
+
"scripts": {
|
|
12
|
+
"build": "tsc",
|
|
13
|
+
"test": "vitest run",
|
|
14
|
+
"prepublishOnly": "npm run build"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"ai",
|
|
18
|
+
"agent",
|
|
19
|
+
"reliability",
|
|
20
|
+
"trust",
|
|
21
|
+
"idempotency",
|
|
22
|
+
"circuit-breaker",
|
|
23
|
+
"langchain"
|
|
24
|
+
],
|
|
25
|
+
"repository": {
|
|
26
|
+
"type": "git",
|
|
27
|
+
"url": "git+https://github.com/wzg0911/ark-ts.git"
|
|
28
|
+
},
|
|
29
|
+
"license": "MIT",
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@types/node": "^25.9.2",
|
|
32
|
+
"typescript": "^6.0.3",
|
|
33
|
+
"vitest": "^4.1.8"
|
|
34
|
+
},
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"zod": "^4.4.3"
|
|
37
|
+
},
|
|
38
|
+
"author": "feilunxitong",
|
|
39
|
+
"bugs": {
|
|
40
|
+
"url": "https://github.com/wzg0911/ark-ts/issues"
|
|
41
|
+
},
|
|
42
|
+
"homepage": "https://github.com/wzg0911/ark-ts#readme"
|
|
43
|
+
}
|