@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/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
+ }