@punktechnologies/sdk 0.1.0 → 0.1.1
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 +75 -81
- package/README.md +216 -94
- package/SECURITY.md +11 -0
- package/dist/index.js +14 -4
- package/package.json +35 -19
- package/src/index.ts +1559 -0
- package/src/types.ts +512 -0
package/src/types.ts
ADDED
|
@@ -0,0 +1,512 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @punktechnologies/sdk — local type contracts.
|
|
3
|
+
*
|
|
4
|
+
* These mirror the canonical definitions in `@punk/trace-schema` (the
|
|
5
|
+
* dependency-free contract package every Punk service imports). They are
|
|
6
|
+
* copied here — not imported — so the published SDK has zero dependencies.
|
|
7
|
+
*
|
|
8
|
+
* If a shape changes in `@punk/trace-schema`, update the mirror here.
|
|
9
|
+
* The gateway is the source of truth at runtime; these types describe what
|
|
10
|
+
* its API returns.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
// Identity & trust (mirrors @punk/trace-schema)
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
|
|
17
|
+
/** MeshGuard-compatible trust tiers. */
|
|
18
|
+
export type TrustTier = "unverified" | "verified" | "trusted" | "privileged";
|
|
19
|
+
|
|
20
|
+
/** Trust lane of a memory/context source (memory quarantine). */
|
|
21
|
+
export type TrustLane = "untrusted" | "observed" | "verified" | "human_approved";
|
|
22
|
+
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
// Side effects (PRD §17)
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* 0 pure computation, 1 read-only external, 2 reversible/idempotent writes,
|
|
29
|
+
* 3 user-visible writes (slack/email/tickets), 4 high-impact (payments,
|
|
30
|
+
* deletion, permissions). Undeclared tools default to level 3 (conservative).
|
|
31
|
+
*/
|
|
32
|
+
export type SideEffectLevel = 0 | 1 | 2 | 3 | 4;
|
|
33
|
+
|
|
34
|
+
export type SideEffectStatus =
|
|
35
|
+
| "planned"
|
|
36
|
+
| "executed"
|
|
37
|
+
| "suppressed"
|
|
38
|
+
| "dry_run"
|
|
39
|
+
| "blocked";
|
|
40
|
+
|
|
41
|
+
export interface SideEffectRecord {
|
|
42
|
+
id: string;
|
|
43
|
+
runId: string;
|
|
44
|
+
tenantId: string;
|
|
45
|
+
toolName: string;
|
|
46
|
+
level: SideEffectLevel;
|
|
47
|
+
status: SideEffectStatus;
|
|
48
|
+
idempotencyKey?: string;
|
|
49
|
+
payload?: unknown;
|
|
50
|
+
createdAt: number;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// ---------------------------------------------------------------------------
|
|
54
|
+
// Routes & explanations
|
|
55
|
+
// ---------------------------------------------------------------------------
|
|
56
|
+
|
|
57
|
+
export type RouteType =
|
|
58
|
+
| "live" // pass-through to live provider
|
|
59
|
+
| "exact_cache"
|
|
60
|
+
| "semantic_cache"
|
|
61
|
+
| "tool_cache"
|
|
62
|
+
| "som_cache"
|
|
63
|
+
| "plan_cache"
|
|
64
|
+
| "artifact" // promoted deterministic artifact
|
|
65
|
+
| "hybrid_artifact" // artifact with model fallback for low-confidence rows
|
|
66
|
+
| "model_substitution" // learned cheaper-model substitution
|
|
67
|
+
| "chorus" // claim-graph intelligence composition through Punk Chorus
|
|
68
|
+
| "blocked"; // policy denied
|
|
69
|
+
|
|
70
|
+
export interface RouteAlternative {
|
|
71
|
+
route: RouteType;
|
|
72
|
+
rejected: string; // why this route was not taken
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export interface PolicyVerdict {
|
|
76
|
+
decision: "allow" | "deny" | "approval_required";
|
|
77
|
+
policyName?: string;
|
|
78
|
+
ruleIndex?: number;
|
|
79
|
+
reason: string;
|
|
80
|
+
trustTier?: TrustTier;
|
|
81
|
+
sideEffectLevel?: SideEffectLevel;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/** Every optimized response must be explainable. */
|
|
85
|
+
export interface RouteExplanation {
|
|
86
|
+
route: RouteType;
|
|
87
|
+
reason: string;
|
|
88
|
+
alternatives: RouteAlternative[];
|
|
89
|
+
policy?: PolicyVerdict;
|
|
90
|
+
cache?: {
|
|
91
|
+
type: string;
|
|
92
|
+
hit: boolean;
|
|
93
|
+
key?: string;
|
|
94
|
+
freshness?: "valid" | "stale" | "expired";
|
|
95
|
+
ageMs?: number;
|
|
96
|
+
};
|
|
97
|
+
artifact?: {
|
|
98
|
+
id: string;
|
|
99
|
+
version: number;
|
|
100
|
+
confidence: number;
|
|
101
|
+
shadowed?: boolean;
|
|
102
|
+
};
|
|
103
|
+
pattern?: { id: string; name: string; confidence: number };
|
|
104
|
+
estimatedSavedUsd?: number;
|
|
105
|
+
estimatedSavedMs?: number;
|
|
106
|
+
/**
|
|
107
|
+
* Observe-mode ghost accounting: what the optimizer WOULD have done.
|
|
108
|
+
* Present only when the API key runs in "observe" mode and a
|
|
109
|
+
* cheaper/blocked route existed.
|
|
110
|
+
*/
|
|
111
|
+
ghost?: {
|
|
112
|
+
route: RouteType | "blocked";
|
|
113
|
+
estimatedSavedUsd: number;
|
|
114
|
+
estimatedSavedMs: number;
|
|
115
|
+
reason: string;
|
|
116
|
+
};
|
|
117
|
+
fallback: string;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// ---------------------------------------------------------------------------
|
|
121
|
+
// Runs
|
|
122
|
+
// ---------------------------------------------------------------------------
|
|
123
|
+
|
|
124
|
+
export type RunStatus = "running" | "completed" | "failed" | "blocked";
|
|
125
|
+
|
|
126
|
+
export interface Run {
|
|
127
|
+
id: string;
|
|
128
|
+
tenantId: string;
|
|
129
|
+
appId: string;
|
|
130
|
+
agentId?: string;
|
|
131
|
+
/** Pseudonymous subject (end user) identifier. */
|
|
132
|
+
subject?: string;
|
|
133
|
+
status: RunStatus;
|
|
134
|
+
route?: RouteType;
|
|
135
|
+
shadowed?: boolean; // a candidate artifact shadow-ran beside this run
|
|
136
|
+
requestHash: string;
|
|
137
|
+
/** Normalized prompt-shape fingerprint; groups runs into patterns. */
|
|
138
|
+
fingerprint?: string;
|
|
139
|
+
patternId?: string;
|
|
140
|
+
provider?: string;
|
|
141
|
+
model?: string;
|
|
142
|
+
inputTokens: number;
|
|
143
|
+
outputTokens: number;
|
|
144
|
+
costUsd: number;
|
|
145
|
+
/** Estimated USD avoided versus the live path (0 for live runs). */
|
|
146
|
+
savedUsd: number;
|
|
147
|
+
/** Observe mode: estimated USD Punk WOULD have saved (ghost accounting). */
|
|
148
|
+
ghostSavedUsd?: number;
|
|
149
|
+
latencyMs: number;
|
|
150
|
+
startedAt: number;
|
|
151
|
+
completedAt?: number;
|
|
152
|
+
routeExplanation?: RouteExplanation;
|
|
153
|
+
error?: string;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// ---------------------------------------------------------------------------
|
|
157
|
+
// Trace events
|
|
158
|
+
// ---------------------------------------------------------------------------
|
|
159
|
+
|
|
160
|
+
export type TraceEventType =
|
|
161
|
+
| "request.received"
|
|
162
|
+
| "policy.checked"
|
|
163
|
+
| "route.selected"
|
|
164
|
+
| "model.requested"
|
|
165
|
+
| "model.failover"
|
|
166
|
+
| "model.completed"
|
|
167
|
+
| "chorus.contract"
|
|
168
|
+
| "chorus.claim_graph"
|
|
169
|
+
| "chorus.route_selected"
|
|
170
|
+
| "chorus.verifier"
|
|
171
|
+
| "chorus.auction"
|
|
172
|
+
| "chorus.ledger"
|
|
173
|
+
| "chorus.research_pack"
|
|
174
|
+
| "chorus.live_synthesis"
|
|
175
|
+
| "chorus.live_synthesis_empty"
|
|
176
|
+
| "chorus.live_synthesis_failed"
|
|
177
|
+
| "chorus.receipt"
|
|
178
|
+
| "tool.called"
|
|
179
|
+
| "tool.completed"
|
|
180
|
+
| "web.fetched"
|
|
181
|
+
| "som.compiled"
|
|
182
|
+
| "som.cache_hit"
|
|
183
|
+
| "som.diffed"
|
|
184
|
+
| "web.acted"
|
|
185
|
+
| "side_effect.planned"
|
|
186
|
+
| "side_effect.executed"
|
|
187
|
+
| "side_effect.suppressed"
|
|
188
|
+
| "side_effect.blocked"
|
|
189
|
+
| "cache.checked"
|
|
190
|
+
| "cache.hit"
|
|
191
|
+
| "cache.miss"
|
|
192
|
+
| "cache.stored"
|
|
193
|
+
| "artifact.selected"
|
|
194
|
+
| "artifact.executed"
|
|
195
|
+
| "artifact.failed"
|
|
196
|
+
| "artifact.shadowed"
|
|
197
|
+
| "evaluator.scored"
|
|
198
|
+
| "pattern.updated"
|
|
199
|
+
| "artifact.synthesized"
|
|
200
|
+
| "artifact.state_changed"
|
|
201
|
+
| "drift.detected"
|
|
202
|
+
| "tripwire.fired"
|
|
203
|
+
| "user.feedback"
|
|
204
|
+
| "run.completed";
|
|
205
|
+
|
|
206
|
+
export interface TraceEvent {
|
|
207
|
+
id: string;
|
|
208
|
+
runId: string;
|
|
209
|
+
tenantId: string;
|
|
210
|
+
type: TraceEventType;
|
|
211
|
+
ts: number;
|
|
212
|
+
parentId?: string;
|
|
213
|
+
payload: Record<string, unknown>;
|
|
214
|
+
schemaVersion: 1;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// ---------------------------------------------------------------------------
|
|
218
|
+
// Patterns
|
|
219
|
+
// ---------------------------------------------------------------------------
|
|
220
|
+
|
|
221
|
+
export type PatternState =
|
|
222
|
+
| "observed"
|
|
223
|
+
| "candidate"
|
|
224
|
+
| "watchlisted"
|
|
225
|
+
| "synthesizing"
|
|
226
|
+
| "replay_tested"
|
|
227
|
+
| "shadowing"
|
|
228
|
+
| "promoted"
|
|
229
|
+
| "negative" // negative cache: do not attempt optimization
|
|
230
|
+
| "retired";
|
|
231
|
+
|
|
232
|
+
export type TaskClass =
|
|
233
|
+
| "deterministic"
|
|
234
|
+
| "schema_deterministic"
|
|
235
|
+
| "semantic"
|
|
236
|
+
| "preference"
|
|
237
|
+
| "open_ended"
|
|
238
|
+
| "high_risk";
|
|
239
|
+
|
|
240
|
+
export interface Pattern {
|
|
241
|
+
id: string;
|
|
242
|
+
tenantId: string;
|
|
243
|
+
appId: string;
|
|
244
|
+
name: string;
|
|
245
|
+
state: PatternState;
|
|
246
|
+
/** Normalized prompt-shape fingerprint (primary cluster key). */
|
|
247
|
+
fingerprint: string;
|
|
248
|
+
toolSequenceFp?: string;
|
|
249
|
+
outputSchemaFp?: string;
|
|
250
|
+
taskClass: TaskClass;
|
|
251
|
+
riskLevel: SideEffectLevel;
|
|
252
|
+
runCount: number;
|
|
253
|
+
totalCostUsd: number;
|
|
254
|
+
avgCostUsd: number;
|
|
255
|
+
avgLatencyMs: number;
|
|
256
|
+
/** How stable inputs→outputs are across observed runs, [0,1]. */
|
|
257
|
+
stabilityScore: number;
|
|
258
|
+
/** expected_value-style prioritization score. */
|
|
259
|
+
optimizableScore: number;
|
|
260
|
+
exampleRunIds: string[];
|
|
261
|
+
negativeReason?: string;
|
|
262
|
+
createdAt: number;
|
|
263
|
+
updatedAt: number;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// ---------------------------------------------------------------------------
|
|
267
|
+
// Artifacts
|
|
268
|
+
// ---------------------------------------------------------------------------
|
|
269
|
+
|
|
270
|
+
export type ArtifactState =
|
|
271
|
+
| "candidate"
|
|
272
|
+
| "replay_failed"
|
|
273
|
+
| "replay_passed"
|
|
274
|
+
| "shadowing"
|
|
275
|
+
| "shadow_failed"
|
|
276
|
+
| "approved"
|
|
277
|
+
| "promoted"
|
|
278
|
+
| "canary"
|
|
279
|
+
| "stable"
|
|
280
|
+
| "degraded"
|
|
281
|
+
| "quarantined"
|
|
282
|
+
| "retired";
|
|
283
|
+
|
|
284
|
+
export type ArtifactType =
|
|
285
|
+
| "static_response"
|
|
286
|
+
| "template"
|
|
287
|
+
| "deterministic_transform"
|
|
288
|
+
| "ruleset_classifier"
|
|
289
|
+
| "tool_plan"
|
|
290
|
+
| "web_extraction"
|
|
291
|
+
| "hybrid";
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* Loose representation slot; the gateway's artifact runtime defines and
|
|
295
|
+
* validates the concrete declarative DSL.
|
|
296
|
+
*/
|
|
297
|
+
export type ArtifactRepresentation = {
|
|
298
|
+
dslVersion: 1;
|
|
299
|
+
kind: ArtifactType;
|
|
300
|
+
} & Record<string, unknown>;
|
|
301
|
+
|
|
302
|
+
export interface ArtifactProvenance {
|
|
303
|
+
synthesizer: string; // e.g. "punk-inductive-compiler/v1"
|
|
304
|
+
sourceRunIds: string[];
|
|
305
|
+
holdoutRunIds: string[];
|
|
306
|
+
parentArtifactId?: string;
|
|
307
|
+
notes?: string;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
export interface Artifact {
|
|
311
|
+
id: string;
|
|
312
|
+
tenantId: string;
|
|
313
|
+
patternId: string;
|
|
314
|
+
version: number;
|
|
315
|
+
type: ArtifactType;
|
|
316
|
+
state: ArtifactState;
|
|
317
|
+
representation: ArtifactRepresentation;
|
|
318
|
+
provenance: ArtifactProvenance;
|
|
319
|
+
inputSchema?: Record<string, unknown>;
|
|
320
|
+
outputSchema?: Record<string, unknown>;
|
|
321
|
+
sideEffectLevel: SideEffectLevel;
|
|
322
|
+
// --- self-improving confidence state (Beta posterior over correctness) ---
|
|
323
|
+
/** Successes + prior. Updated on every replay/shadow/live evaluation. */
|
|
324
|
+
alpha: number;
|
|
325
|
+
/** Failures + prior. */
|
|
326
|
+
beta: number;
|
|
327
|
+
/** Lower-bound confidence derived from the posterior; the router gates on this. */
|
|
328
|
+
confidence: number;
|
|
329
|
+
replayPasses: number;
|
|
330
|
+
replayFails: number;
|
|
331
|
+
shadowPasses: number;
|
|
332
|
+
shadowFails: number;
|
|
333
|
+
livePasses: number;
|
|
334
|
+
liveFails: number;
|
|
335
|
+
estCostUsd: number; // cost of running this artifact (≈0 for deterministic)
|
|
336
|
+
estLatencyMs: number;
|
|
337
|
+
createdAt: number;
|
|
338
|
+
promotedAt?: number;
|
|
339
|
+
lastEvaluatedAt?: number;
|
|
340
|
+
stateReason?: string;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
export interface PromotionGateStatus {
|
|
344
|
+
eligible: boolean;
|
|
345
|
+
autoPromotable: boolean;
|
|
346
|
+
reasons: string[];
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
export type EvaluationKind = "replay" | "shadow" | "live";
|
|
350
|
+
|
|
351
|
+
export interface ArtifactEvaluation {
|
|
352
|
+
id: string;
|
|
353
|
+
artifactId: string;
|
|
354
|
+
tenantId: string;
|
|
355
|
+
kind: EvaluationKind;
|
|
356
|
+
runId?: string; // trace this evaluation compared against
|
|
357
|
+
pass: boolean;
|
|
358
|
+
structuralPass: boolean;
|
|
359
|
+
semanticScore: number; // [0,1]
|
|
360
|
+
sideEffectPass: boolean;
|
|
361
|
+
expected?: string;
|
|
362
|
+
actual?: string;
|
|
363
|
+
details?: string;
|
|
364
|
+
createdAt: number;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
// ---------------------------------------------------------------------------
|
|
368
|
+
// Web runtime (Plasmate SOM v0.1 contracts)
|
|
369
|
+
// ---------------------------------------------------------------------------
|
|
370
|
+
|
|
371
|
+
/** Mirrors Plasmate's Som struct (som_version "0.1"). */
|
|
372
|
+
export interface SomSnapshot {
|
|
373
|
+
som_version: string;
|
|
374
|
+
url: string;
|
|
375
|
+
title: string;
|
|
376
|
+
lang: string;
|
|
377
|
+
regions: SomRegion[];
|
|
378
|
+
meta: {
|
|
379
|
+
html_bytes: number;
|
|
380
|
+
som_bytes: number;
|
|
381
|
+
element_count: number;
|
|
382
|
+
interactive_count: number;
|
|
383
|
+
};
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
export interface SomRegion {
|
|
387
|
+
id: string; // r_navigation, r_main_0 ...
|
|
388
|
+
role: string; // navigation | main | aside | header | footer | form | dialog | content
|
|
389
|
+
label?: string;
|
|
390
|
+
action?: string;
|
|
391
|
+
method?: string;
|
|
392
|
+
elements: SomElement[];
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
export interface SomElement {
|
|
396
|
+
id: string; // e_<12 hex> deterministic
|
|
397
|
+
role: string; // link | button | heading | paragraph | text_input | ...
|
|
398
|
+
text?: string;
|
|
399
|
+
label?: string;
|
|
400
|
+
actions?: string[];
|
|
401
|
+
attrs?: Record<string, unknown>;
|
|
402
|
+
children?: SomElement[];
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
export interface SomDiffEntry {
|
|
406
|
+
kind: "added" | "removed" | "changed";
|
|
407
|
+
regionId: string;
|
|
408
|
+
elementId?: string;
|
|
409
|
+
field?: string;
|
|
410
|
+
before?: string;
|
|
411
|
+
after?: string;
|
|
412
|
+
/** Semantic weight: pricing/CTA/form changes matter more than footer noise. */
|
|
413
|
+
significance: "high" | "medium" | "low";
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
export interface SomDiff {
|
|
417
|
+
url: string;
|
|
418
|
+
beforeFingerprint: string;
|
|
419
|
+
afterFingerprint: string;
|
|
420
|
+
entries: SomDiffEntry[];
|
|
421
|
+
/** Aggregate drift signal in [0,1]. */
|
|
422
|
+
driftScore: number;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
// ---------------------------------------------------------------------------
|
|
426
|
+
// Web actions (perception→action loop over SOM sessions)
|
|
427
|
+
// ---------------------------------------------------------------------------
|
|
428
|
+
|
|
429
|
+
/** Protocol-level actions an agent can take on a SOM page (no JS engine). */
|
|
430
|
+
export type WebActionKind = "click" | "type" | "select" | "submit";
|
|
431
|
+
|
|
432
|
+
export interface WebActionIntent {
|
|
433
|
+
action: WebActionKind;
|
|
434
|
+
/** SOM element id (e_…) — or a region id (r_form…) for submit. */
|
|
435
|
+
target: string;
|
|
436
|
+
value?: string;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
export interface WebActionResult {
|
|
440
|
+
ok: boolean;
|
|
441
|
+
action: WebActionKind;
|
|
442
|
+
target: string;
|
|
443
|
+
/** Element/region id the engine resolved the target to. */
|
|
444
|
+
resolved?: string;
|
|
445
|
+
/** True when the action caused a page navigation (link follow / form submit). */
|
|
446
|
+
navigated?: boolean;
|
|
447
|
+
/** Page URL after the action. */
|
|
448
|
+
url: string;
|
|
449
|
+
/** URL the action attempted before redirects, when it caused navigation. */
|
|
450
|
+
requestedUrl?: string;
|
|
451
|
+
error?: string;
|
|
452
|
+
/**
|
|
453
|
+
* For successful form submissions, including submit-button clicks: the
|
|
454
|
+
* serialized field set that was posted (name -> value), so the operator can
|
|
455
|
+
* see exactly what was sent.
|
|
456
|
+
*/
|
|
457
|
+
posted?: Record<string, string>;
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
// ---------------------------------------------------------------------------
|
|
461
|
+
// Savings rollup (dashboard)
|
|
462
|
+
// ---------------------------------------------------------------------------
|
|
463
|
+
|
|
464
|
+
export interface SavingsSummary {
|
|
465
|
+
tenantId: string;
|
|
466
|
+
totalRuns: number;
|
|
467
|
+
liveRuns: number;
|
|
468
|
+
optimizedRuns: number;
|
|
469
|
+
blockedRuns: number;
|
|
470
|
+
totalCostUsd: number;
|
|
471
|
+
totalSavedUsd: number;
|
|
472
|
+
/** Observe-mode ghost accounting: sum of per-run ghostSavedUsd. */
|
|
473
|
+
ghostSavedUsd: number;
|
|
474
|
+
totalSavedMs: number;
|
|
475
|
+
cacheHits: number;
|
|
476
|
+
artifactHits: number;
|
|
477
|
+
cacheHitRate: number;
|
|
478
|
+
artifactHitRate: number;
|
|
479
|
+
somTokensSaved: number;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
// ---------------------------------------------------------------------------
|
|
483
|
+
// External MCP servers (registry consumed by the gateway's tool_call nodes)
|
|
484
|
+
// ---------------------------------------------------------------------------
|
|
485
|
+
|
|
486
|
+
export interface McpServerRecord {
|
|
487
|
+
id: string;
|
|
488
|
+
tenantId: string;
|
|
489
|
+
name: string;
|
|
490
|
+
transport: "stdio" | "http";
|
|
491
|
+
command?: string;
|
|
492
|
+
args?: string[];
|
|
493
|
+
url?: string;
|
|
494
|
+
/** Values may be cred:<credentialId> references resolved at connect time. */
|
|
495
|
+
env?: Record<string, string>;
|
|
496
|
+
headers?: Record<string, string>;
|
|
497
|
+
enabled: boolean;
|
|
498
|
+
status: "unknown" | "ok" | "error";
|
|
499
|
+
lastTestedAt?: number;
|
|
500
|
+
lastError?: string;
|
|
501
|
+
toolCount: number;
|
|
502
|
+
createdAt: number;
|
|
503
|
+
updatedAt: number;
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
export interface McpTestResult {
|
|
507
|
+
ok: boolean;
|
|
508
|
+
toolCount?: number;
|
|
509
|
+
tools?: Array<{ name: string; description?: string; inputSchema?: unknown }>;
|
|
510
|
+
error?: string;
|
|
511
|
+
latencyMs: number;
|
|
512
|
+
}
|