@diffdelta/client 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/README.md ADDED
@@ -0,0 +1,152 @@
1
+ # @diffdelta/client
2
+
3
+ TypeScript/JavaScript client for [DiffDelta](https://diffdelta.io) — agent-ready intelligence feeds for security advisories, changelogs, status pages, and more.
4
+
5
+ **One import. 46 sources. Structured signals. Zero scraping.**
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ npm install @diffdelta/client
11
+ ```
12
+
13
+ ## Quick Start
14
+
15
+ ```ts
16
+ import { DiffDelta } from "@diffdelta/client";
17
+
18
+ const dd = new DiffDelta();
19
+
20
+ // Poll for changes — checks head.json first (~200 bytes),
21
+ // only fetches the full feed if something changed.
22
+ const items = await dd.poll();
23
+
24
+ for (const item of items) {
25
+ console.log(`${item.source}: ${item.headline}`);
26
+
27
+ // Structured signals — no parsing needed
28
+ if (item.signals.severity) {
29
+ console.log(` Severity: ${item.signals.severity.level} (CVSS ${item.signals.severity.cvss})`);
30
+ }
31
+
32
+ // Action codes — the bot knows what to do
33
+ if (item.suggestedAction === "PATCH_IMMEDIATELY") {
34
+ triggerEmergencyPatch(item);
35
+ }
36
+ }
37
+ ```
38
+
39
+ ## Stack Discovery
40
+
41
+ Tell DiffDelta what you use, get back exactly which sources to watch:
42
+
43
+ ```ts
44
+ const sources = await dd.discoverSources(["openai", "langchain", "pinecone"]);
45
+ // → ["openai_sdk_releases", "openai_api_changelog", "langchain_releases", "pinecone_status"]
46
+ ```
47
+
48
+ ## Health Check
49
+
50
+ Check if the DiffDelta pipeline is alive before trusting the data:
51
+
52
+ ```ts
53
+ const health = await dd.checkHealth();
54
+ if (!health.ok) {
55
+ console.warn(`Pipeline degraded: ${health.sourcesOk}/${health.sourcesChecked} sources healthy`);
56
+ }
57
+ ```
58
+
59
+ ## Verified Silence
60
+
61
+ When nothing changed, DiffDelta proves it checked:
62
+
63
+ ```ts
64
+ const head = await dd.head();
65
+ if (!head.changed && head.allClear) {
66
+ console.log(`All clear: ${head.sourcesChecked} sources verified, confidence ${head.allClearConfidence}`);
67
+ // A non-DiffDelta bot can never make this claim.
68
+ }
69
+ ```
70
+
71
+ ## Continuous Monitoring
72
+
73
+ ```ts
74
+ const ac = new AbortController();
75
+
76
+ dd.watch(
77
+ (item) => {
78
+ if (item.suggestedAction === "PATCH_IMMEDIATELY") {
79
+ alertOncall(item);
80
+ }
81
+ },
82
+ { tags: ["security"], signal: ac.signal }
83
+ );
84
+
85
+ // Stop after 1 hour
86
+ setTimeout(() => ac.abort(), 3_600_000);
87
+ ```
88
+
89
+ ## Per-Source Polling
90
+
91
+ More efficient if you only care about one source:
92
+
93
+ ```ts
94
+ const items = await dd.pollSource("cisa_kev");
95
+ ```
96
+
97
+ ## Cursor Persistence
98
+
99
+ Cursors are saved to `~/.diffdelta/cursors.json` by default so your bot survives restarts. Disable with:
100
+
101
+ ```ts
102
+ const dd = new DiffDelta({ cursorPath: "memory" }); // in-memory only
103
+ ```
104
+
105
+ ## Signal Types
106
+
107
+ Every item can carry structured signals — pre-extracted, no parsing needed:
108
+
109
+ | Signal | Fields | Example |
110
+ |--------|--------|---------|
111
+ | `severity` | level, cvss, cwes, packages, exploited | `{ level: "critical", cvss: 9.8 }` |
112
+ | `release` | version, prerelease, security_patch | `{ version: "4.2.1", security_patch: true }` |
113
+ | `incident` | status, impact | `{ status: "investigating", impact: "major" }` |
114
+ | `deprecation` | type, affects, confidence | `{ type: "breaking_change", affects: ["gpt-4-turbo"] }` |
115
+ | `suggested_action` | action code | `"PATCH_IMMEDIATELY"` |
116
+
117
+ ## Action Codes
118
+
119
+ | Code | Meaning |
120
+ |------|---------|
121
+ | `PATCH_IMMEDIATELY` | Active exploitation or critical severity. Patch now. |
122
+ | `PATCH_SOON` | High severity. Schedule a patch. |
123
+ | `VERSION_PIN` | Breaking change coming. Pin your current version. |
124
+ | `REVIEW_CHANGELOG` | New release with notable changes. |
125
+ | `MONITOR_STATUS` | Incident in progress. Watch for updates. |
126
+ | `ACKNOWLEDGE` | Low-risk change. Log it. |
127
+ | `NO_ACTION` | Informational only. |
128
+
129
+ ## Options
130
+
131
+ ```ts
132
+ const dd = new DiffDelta({
133
+ baseUrl: "https://diffdelta.io", // default
134
+ apiKey: "dd_live_...", // Pro tier (optional)
135
+ cursorPath: null, // null = in-memory, string = file path
136
+ timeout: 15_000, // HTTP timeout in ms
137
+ });
138
+ ```
139
+
140
+ ## Protocol
141
+
142
+ DiffDelta uses a three-layer polling protocol (ddv1):
143
+
144
+ 1. **head.json** (~200 bytes) — cursor + counts. Poll this first.
145
+ 2. **digest.json** (~500 bytes) — narrative + alert count. Fetch if cursor changed.
146
+ 3. **latest.json** (~5-40KB) — full items with signals. Fetch if alerts > 0.
147
+
148
+ The SDK handles this automatically. You never fetch more than you need.
149
+
150
+ ## License
151
+
152
+ MIT
package/dist/index.d.mts CHANGED
@@ -1,6 +1,55 @@
1
+ /** Severity signal extracted from security advisories. */
2
+ interface SeveritySignal {
3
+ level: "critical" | "high" | "medium" | "low" | string;
4
+ source: string;
5
+ cvss?: number;
6
+ cwes?: string[];
7
+ packages?: string[];
8
+ exploited?: boolean;
9
+ provenance?: SignalProvenance;
10
+ }
11
+ /** Release signal extracted from changelogs/GitHub releases. */
12
+ interface ReleaseSignal {
13
+ version: string;
14
+ prerelease?: boolean;
15
+ security_patch?: boolean;
16
+ provenance?: SignalProvenance;
17
+ }
18
+ /** Incident signal extracted from status pages. */
19
+ interface IncidentSignal {
20
+ status: "investigating" | "identified" | "monitoring" | "resolved" | string;
21
+ impact?: "minor" | "major" | "critical" | string;
22
+ provenance?: SignalProvenance;
23
+ }
24
+ /** Deprecation signal extracted from changelogs/advisories. */
25
+ interface DeprecationSignal {
26
+ type: "breaking_change" | "end_of_life" | "removal" | "deprecated" | string;
27
+ affects?: string[];
28
+ confidence: "high" | "medium" | "low" | string;
29
+ source: string;
30
+ provenance?: SignalProvenance;
31
+ }
32
+ /** Provenance chain for a signal — traces it to an authoritative source. */
33
+ interface SignalProvenance {
34
+ method: string;
35
+ authority: string;
36
+ authority_url: string;
37
+ evidence_url: string;
38
+ }
39
+ /** Action codes telling a bot exactly what to do. */
40
+ type SuggestedAction = "PATCH_IMMEDIATELY" | "PATCH_SOON" | "VERSION_PIN" | "REVIEW_CHANGELOG" | "MONITOR_STATUS" | "ACKNOWLEDGE" | "NO_ACTION";
41
+ /** All structured signals on an item. */
42
+ interface Signals {
43
+ severity?: SeveritySignal;
44
+ release?: ReleaseSignal;
45
+ incident?: IncidentSignal;
46
+ deprecation?: DeprecationSignal;
47
+ suggested_action?: SuggestedAction;
48
+ [key: string]: unknown;
49
+ }
1
50
  /** A single item from a DiffDelta feed. */
2
51
  interface FeedItem {
3
- /** Source identifier (e.g. "cisa_kev", "nist_nvd"). */
52
+ /** Source identifier (e.g. "cisa_kev", "github_advisories"). */
4
53
  source: string;
5
54
  /** Unique item ID within the source. */
6
55
  id: string;
@@ -14,11 +63,15 @@ interface FeedItem {
14
63
  publishedAt: string | null;
15
64
  /** When the item was last updated. */
16
65
  updatedAt: string | null;
17
- /** Which change bucket: "new", "updated", or "removed". */
18
- bucket: "new" | "updated" | "removed";
19
- /** Risk score 0–10, or null if not scored. */
66
+ /** Which change bucket: "new", "updated", "removed", or "flagged". */
67
+ bucket: "new" | "updated" | "removed" | "flagged";
68
+ /** Structured signals: severity, release, incident, deprecation, suggested_action. */
69
+ signals: Signals;
70
+ /** Shortcut: the suggested_action code, if any. */
71
+ suggestedAction: SuggestedAction | null;
72
+ /** Risk score 0.0–1.0, or null if not scored. */
20
73
  riskScore: number | null;
21
- /** Raw provenance data (fetched_at, evidence_urls, content_hash). */
74
+ /** Item-level provenance (fetched_at, evidence_urls, content_hash). */
22
75
  provenance: Record<string, unknown>;
23
76
  /** The full raw item object from the feed. */
24
77
  raw: Record<string, unknown>;
@@ -27,14 +80,40 @@ interface FeedItem {
27
80
  interface Head {
28
81
  /** Opaque cursor string for change detection. */
29
82
  cursor: string;
30
- /** Content hash of the latest feed. */
31
- hash: string;
32
83
  /** Whether content has changed since last generation. */
33
84
  changed: boolean;
34
85
  /** When this head was generated. */
35
86
  generatedAt: string;
36
87
  /** Recommended polling interval in seconds. */
37
88
  ttlSec: number;
89
+ /** URL to the full latest.json feed. */
90
+ latestUrl: string;
91
+ /** URL to the digest (global head only). */
92
+ digestUrl: string | null;
93
+ /** Item counts: new, updated, removed, flagged. */
94
+ counts: {
95
+ new: number;
96
+ updated: number;
97
+ removed: number;
98
+ flagged: number;
99
+ };
100
+ /** Number of sources checked this cycle (Verified Silence). */
101
+ sourcesChecked: number;
102
+ /** Number of sources healthy this cycle. */
103
+ sourcesOk: number;
104
+ /** True if nothing changed AND all sources are healthy. */
105
+ allClear: boolean;
106
+ /** 0.0–1.0 confidence that allClear is trustworthy. */
107
+ allClearConfidence: number | null;
108
+ /** Pipeline freshness: oldest data age, stale count. */
109
+ freshness: {
110
+ oldest_data_age_sec: number;
111
+ mean_data_age_sec: number;
112
+ stale_count: number;
113
+ all_fresh: boolean;
114
+ } | null;
115
+ /** The full raw head.json object. */
116
+ raw: Record<string, unknown>;
38
117
  }
39
118
  /** A full DiffDelta feed response. */
40
119
  interface Feed {
@@ -54,6 +133,8 @@ interface Feed {
54
133
  updated: FeedItem[];
55
134
  /** Items in the "removed" bucket. */
56
135
  removed: FeedItem[];
136
+ /** Items in the "flagged" bucket. */
137
+ flagged: FeedItem[];
57
138
  /** Human-readable summary of what changed. */
58
139
  narrative: string;
59
140
  /** The full raw feed object. */
@@ -80,6 +161,25 @@ interface SourceInfo {
80
161
  /** Path to the source's latest.json. */
81
162
  latestUrl: string;
82
163
  }
164
+ /** Health check response from /healthz.json. */
165
+ interface HealthCheck {
166
+ ok: boolean;
167
+ service: string;
168
+ time: string;
169
+ sourcesChecked: number;
170
+ sourcesOk: number;
171
+ engineVersion: string;
172
+ }
173
+ /** Parse a raw feed item into a typed FeedItem. */
174
+ declare function parseFeedItem(data: Record<string, unknown>, bucket?: "new" | "updated" | "removed" | "flagged"): FeedItem;
175
+ /** Parse a raw head.json response into a typed Head. */
176
+ declare function parseHead(data: Record<string, unknown>): Head;
177
+ /** Parse a raw latest.json response into a typed Feed. */
178
+ declare function parseFeed(data: Record<string, unknown>): Feed;
179
+ /** Parse a raw source object into a typed SourceInfo. */
180
+ declare function parseSourceInfo(data: Record<string, unknown>): SourceInfo;
181
+ /** Parse a raw healthz.json response into a typed HealthCheck. */
182
+ declare function parseHealthCheck(data: Record<string, unknown>): HealthCheck;
83
183
 
84
184
  /**
85
185
  * DiffDelta TypeScript client — agent-ready intelligence feeds.
@@ -90,6 +190,10 @@ interface SourceInfo {
90
190
  *
91
191
  * const dd = new DiffDelta();
92
192
  *
193
+ * // Quick health check — is the pipeline alive?
194
+ * const health = await dd.checkHealth();
195
+ * console.log(`Pipeline: ${health.ok ? "healthy" : "degraded"}, last run: ${health.time}`);
196
+ *
93
197
  * // Poll for new items across all sources
94
198
  * const items = await dd.poll();
95
199
  * items.forEach(i => console.log(`${i.source}: ${i.headline}`));
@@ -97,6 +201,10 @@ interface SourceInfo {
97
201
  * // Poll only security sources
98
202
  * const sec = await dd.poll({ tags: ["security"] });
99
203
  *
204
+ * // Check what's relevant to your stack
205
+ * const sources = await dd.discoverSources(["openai", "langchain", "pinecone"]);
206
+ * console.log("Watch these:", sources);
207
+ *
100
208
  * // Continuous monitoring
101
209
  * dd.watch(item => console.log("🚨", item.headline), { tags: ["security"] });
102
210
  * ```
@@ -119,17 +227,17 @@ interface DiffDeltaOptions {
119
227
  interface PollOptions {
120
228
  /** Filter items to these tags (e.g. ["security"]). */
121
229
  tags?: string[];
122
- /** Filter items to these source IDs (e.g. ["cisa_kev", "nist_nvd"]). */
230
+ /** Filter items to these source IDs (e.g. ["cisa_kev", "github_advisories"]). */
123
231
  sources?: string[];
124
232
  /**
125
233
  * Which buckets to return.
126
- * Defaults to ["new", "updated"].
127
- * Use ["new", "updated", "removed"] to include removals.
234
+ * Defaults to ["new", "updated", "flagged"].
235
+ * Use ["new", "updated", "removed", "flagged"] to include removals.
128
236
  */
129
- buckets?: Array<"new" | "updated" | "removed">;
237
+ buckets?: Array<"new" | "updated" | "removed" | "flagged">;
130
238
  }
131
239
  interface WatchOptions extends PollOptions {
132
- /** Seconds between polls. Defaults to feed TTL (usually 900s). */
240
+ /** Seconds between polls. Defaults to feed TTL (usually 60s). */
133
241
  interval?: number;
134
242
  /** If provided, an AbortSignal to stop watching. */
135
243
  signal?: AbortSignal;
@@ -144,7 +252,7 @@ declare class DiffDelta {
144
252
  /**
145
253
  * Poll the global feed for new items since last poll.
146
254
  *
147
- * Checks head.json first (~400 bytes). Only fetches the full feed
255
+ * Checks head.json first (~200 bytes). Only fetches the full feed
148
256
  * if the cursor has changed. Automatically saves the new cursor.
149
257
  */
150
258
  poll(options?: PollOptions): Promise<FeedItem[]>;
@@ -156,7 +264,7 @@ declare class DiffDelta {
156
264
  */
157
265
  pollSource(sourceId: string, options?: Omit<PollOptions, "sources">): Promise<FeedItem[]>;
158
266
  /**
159
- * Fetch a head.json pointer.
267
+ * Fetch a head.json pointer. Cheapest call (~200 bytes).
160
268
  * @param url Full URL to head.json. Defaults to global head.
161
269
  */
162
270
  head(url?: string): Promise<Head>;
@@ -167,6 +275,23 @@ declare class DiffDelta {
167
275
  fetchFeed(url?: string): Promise<Feed>;
168
276
  /** List all available DiffDelta sources. */
169
277
  sources(): Promise<SourceInfo[]>;
278
+ /**
279
+ * Check pipeline health. Returns when the engine last ran and whether
280
+ * all sources are healthy. A stale timestamp means the pipeline is down.
281
+ */
282
+ checkHealth(): Promise<HealthCheck>;
283
+ /**
284
+ * Given a list of dependency names your bot uses, returns the source IDs
285
+ * you should monitor. Uses the static stacks.json mapping — no API call,
286
+ * pure local lookup after one fetch.
287
+ *
288
+ * @example
289
+ * ```ts
290
+ * const sources = await dd.discoverSources(["openai", "langchain", "pinecone"]);
291
+ * // → ["openai_sdk_releases", "openai_api_changelog", "langchain_releases", "pinecone_status"]
292
+ * ```
293
+ */
294
+ discoverSources(dependencies: string[]): Promise<string[]>;
170
295
  /**
171
296
  * Continuously poll and call a function for each new item.
172
297
  *
@@ -177,6 +302,9 @@ declare class DiffDelta {
177
302
  * ```ts
178
303
  * dd.watch(item => {
179
304
  * console.log(`🚨 ${item.source}: ${item.headline}`);
305
+ * if (item.suggestedAction === "PATCH_IMMEDIATELY") {
306
+ * triggerAlert(item);
307
+ * }
180
308
  * }, { tags: ["security"] });
181
309
  * ```
182
310
  *
@@ -227,4 +355,4 @@ declare class MemoryCursorStore {
227
355
  clear(key?: string): void;
228
356
  }
229
357
 
230
- export { CursorStore, DiffDelta, type DiffDeltaOptions, type Feed, type FeedItem, type Head, MemoryCursorStore, type PollOptions, type SourceInfo, type WatchOptions };
358
+ export { CursorStore, type DeprecationSignal, DiffDelta, type DiffDeltaOptions, type Feed, type FeedItem, type Head, type HealthCheck, type IncidentSignal, MemoryCursorStore, type PollOptions, type ReleaseSignal, type SeveritySignal, type SignalProvenance, type Signals, type SourceInfo, type SuggestedAction, type WatchOptions, parseFeed, parseFeedItem, parseHead, parseHealthCheck, parseSourceInfo };
package/dist/index.d.ts CHANGED
@@ -1,6 +1,55 @@
1
+ /** Severity signal extracted from security advisories. */
2
+ interface SeveritySignal {
3
+ level: "critical" | "high" | "medium" | "low" | string;
4
+ source: string;
5
+ cvss?: number;
6
+ cwes?: string[];
7
+ packages?: string[];
8
+ exploited?: boolean;
9
+ provenance?: SignalProvenance;
10
+ }
11
+ /** Release signal extracted from changelogs/GitHub releases. */
12
+ interface ReleaseSignal {
13
+ version: string;
14
+ prerelease?: boolean;
15
+ security_patch?: boolean;
16
+ provenance?: SignalProvenance;
17
+ }
18
+ /** Incident signal extracted from status pages. */
19
+ interface IncidentSignal {
20
+ status: "investigating" | "identified" | "monitoring" | "resolved" | string;
21
+ impact?: "minor" | "major" | "critical" | string;
22
+ provenance?: SignalProvenance;
23
+ }
24
+ /** Deprecation signal extracted from changelogs/advisories. */
25
+ interface DeprecationSignal {
26
+ type: "breaking_change" | "end_of_life" | "removal" | "deprecated" | string;
27
+ affects?: string[];
28
+ confidence: "high" | "medium" | "low" | string;
29
+ source: string;
30
+ provenance?: SignalProvenance;
31
+ }
32
+ /** Provenance chain for a signal — traces it to an authoritative source. */
33
+ interface SignalProvenance {
34
+ method: string;
35
+ authority: string;
36
+ authority_url: string;
37
+ evidence_url: string;
38
+ }
39
+ /** Action codes telling a bot exactly what to do. */
40
+ type SuggestedAction = "PATCH_IMMEDIATELY" | "PATCH_SOON" | "VERSION_PIN" | "REVIEW_CHANGELOG" | "MONITOR_STATUS" | "ACKNOWLEDGE" | "NO_ACTION";
41
+ /** All structured signals on an item. */
42
+ interface Signals {
43
+ severity?: SeveritySignal;
44
+ release?: ReleaseSignal;
45
+ incident?: IncidentSignal;
46
+ deprecation?: DeprecationSignal;
47
+ suggested_action?: SuggestedAction;
48
+ [key: string]: unknown;
49
+ }
1
50
  /** A single item from a DiffDelta feed. */
2
51
  interface FeedItem {
3
- /** Source identifier (e.g. "cisa_kev", "nist_nvd"). */
52
+ /** Source identifier (e.g. "cisa_kev", "github_advisories"). */
4
53
  source: string;
5
54
  /** Unique item ID within the source. */
6
55
  id: string;
@@ -14,11 +63,15 @@ interface FeedItem {
14
63
  publishedAt: string | null;
15
64
  /** When the item was last updated. */
16
65
  updatedAt: string | null;
17
- /** Which change bucket: "new", "updated", or "removed". */
18
- bucket: "new" | "updated" | "removed";
19
- /** Risk score 0–10, or null if not scored. */
66
+ /** Which change bucket: "new", "updated", "removed", or "flagged". */
67
+ bucket: "new" | "updated" | "removed" | "flagged";
68
+ /** Structured signals: severity, release, incident, deprecation, suggested_action. */
69
+ signals: Signals;
70
+ /** Shortcut: the suggested_action code, if any. */
71
+ suggestedAction: SuggestedAction | null;
72
+ /** Risk score 0.0–1.0, or null if not scored. */
20
73
  riskScore: number | null;
21
- /** Raw provenance data (fetched_at, evidence_urls, content_hash). */
74
+ /** Item-level provenance (fetched_at, evidence_urls, content_hash). */
22
75
  provenance: Record<string, unknown>;
23
76
  /** The full raw item object from the feed. */
24
77
  raw: Record<string, unknown>;
@@ -27,14 +80,40 @@ interface FeedItem {
27
80
  interface Head {
28
81
  /** Opaque cursor string for change detection. */
29
82
  cursor: string;
30
- /** Content hash of the latest feed. */
31
- hash: string;
32
83
  /** Whether content has changed since last generation. */
33
84
  changed: boolean;
34
85
  /** When this head was generated. */
35
86
  generatedAt: string;
36
87
  /** Recommended polling interval in seconds. */
37
88
  ttlSec: number;
89
+ /** URL to the full latest.json feed. */
90
+ latestUrl: string;
91
+ /** URL to the digest (global head only). */
92
+ digestUrl: string | null;
93
+ /** Item counts: new, updated, removed, flagged. */
94
+ counts: {
95
+ new: number;
96
+ updated: number;
97
+ removed: number;
98
+ flagged: number;
99
+ };
100
+ /** Number of sources checked this cycle (Verified Silence). */
101
+ sourcesChecked: number;
102
+ /** Number of sources healthy this cycle. */
103
+ sourcesOk: number;
104
+ /** True if nothing changed AND all sources are healthy. */
105
+ allClear: boolean;
106
+ /** 0.0–1.0 confidence that allClear is trustworthy. */
107
+ allClearConfidence: number | null;
108
+ /** Pipeline freshness: oldest data age, stale count. */
109
+ freshness: {
110
+ oldest_data_age_sec: number;
111
+ mean_data_age_sec: number;
112
+ stale_count: number;
113
+ all_fresh: boolean;
114
+ } | null;
115
+ /** The full raw head.json object. */
116
+ raw: Record<string, unknown>;
38
117
  }
39
118
  /** A full DiffDelta feed response. */
40
119
  interface Feed {
@@ -54,6 +133,8 @@ interface Feed {
54
133
  updated: FeedItem[];
55
134
  /** Items in the "removed" bucket. */
56
135
  removed: FeedItem[];
136
+ /** Items in the "flagged" bucket. */
137
+ flagged: FeedItem[];
57
138
  /** Human-readable summary of what changed. */
58
139
  narrative: string;
59
140
  /** The full raw feed object. */
@@ -80,6 +161,25 @@ interface SourceInfo {
80
161
  /** Path to the source's latest.json. */
81
162
  latestUrl: string;
82
163
  }
164
+ /** Health check response from /healthz.json. */
165
+ interface HealthCheck {
166
+ ok: boolean;
167
+ service: string;
168
+ time: string;
169
+ sourcesChecked: number;
170
+ sourcesOk: number;
171
+ engineVersion: string;
172
+ }
173
+ /** Parse a raw feed item into a typed FeedItem. */
174
+ declare function parseFeedItem(data: Record<string, unknown>, bucket?: "new" | "updated" | "removed" | "flagged"): FeedItem;
175
+ /** Parse a raw head.json response into a typed Head. */
176
+ declare function parseHead(data: Record<string, unknown>): Head;
177
+ /** Parse a raw latest.json response into a typed Feed. */
178
+ declare function parseFeed(data: Record<string, unknown>): Feed;
179
+ /** Parse a raw source object into a typed SourceInfo. */
180
+ declare function parseSourceInfo(data: Record<string, unknown>): SourceInfo;
181
+ /** Parse a raw healthz.json response into a typed HealthCheck. */
182
+ declare function parseHealthCheck(data: Record<string, unknown>): HealthCheck;
83
183
 
84
184
  /**
85
185
  * DiffDelta TypeScript client — agent-ready intelligence feeds.
@@ -90,6 +190,10 @@ interface SourceInfo {
90
190
  *
91
191
  * const dd = new DiffDelta();
92
192
  *
193
+ * // Quick health check — is the pipeline alive?
194
+ * const health = await dd.checkHealth();
195
+ * console.log(`Pipeline: ${health.ok ? "healthy" : "degraded"}, last run: ${health.time}`);
196
+ *
93
197
  * // Poll for new items across all sources
94
198
  * const items = await dd.poll();
95
199
  * items.forEach(i => console.log(`${i.source}: ${i.headline}`));
@@ -97,6 +201,10 @@ interface SourceInfo {
97
201
  * // Poll only security sources
98
202
  * const sec = await dd.poll({ tags: ["security"] });
99
203
  *
204
+ * // Check what's relevant to your stack
205
+ * const sources = await dd.discoverSources(["openai", "langchain", "pinecone"]);
206
+ * console.log("Watch these:", sources);
207
+ *
100
208
  * // Continuous monitoring
101
209
  * dd.watch(item => console.log("🚨", item.headline), { tags: ["security"] });
102
210
  * ```
@@ -119,17 +227,17 @@ interface DiffDeltaOptions {
119
227
  interface PollOptions {
120
228
  /** Filter items to these tags (e.g. ["security"]). */
121
229
  tags?: string[];
122
- /** Filter items to these source IDs (e.g. ["cisa_kev", "nist_nvd"]). */
230
+ /** Filter items to these source IDs (e.g. ["cisa_kev", "github_advisories"]). */
123
231
  sources?: string[];
124
232
  /**
125
233
  * Which buckets to return.
126
- * Defaults to ["new", "updated"].
127
- * Use ["new", "updated", "removed"] to include removals.
234
+ * Defaults to ["new", "updated", "flagged"].
235
+ * Use ["new", "updated", "removed", "flagged"] to include removals.
128
236
  */
129
- buckets?: Array<"new" | "updated" | "removed">;
237
+ buckets?: Array<"new" | "updated" | "removed" | "flagged">;
130
238
  }
131
239
  interface WatchOptions extends PollOptions {
132
- /** Seconds between polls. Defaults to feed TTL (usually 900s). */
240
+ /** Seconds between polls. Defaults to feed TTL (usually 60s). */
133
241
  interval?: number;
134
242
  /** If provided, an AbortSignal to stop watching. */
135
243
  signal?: AbortSignal;
@@ -144,7 +252,7 @@ declare class DiffDelta {
144
252
  /**
145
253
  * Poll the global feed for new items since last poll.
146
254
  *
147
- * Checks head.json first (~400 bytes). Only fetches the full feed
255
+ * Checks head.json first (~200 bytes). Only fetches the full feed
148
256
  * if the cursor has changed. Automatically saves the new cursor.
149
257
  */
150
258
  poll(options?: PollOptions): Promise<FeedItem[]>;
@@ -156,7 +264,7 @@ declare class DiffDelta {
156
264
  */
157
265
  pollSource(sourceId: string, options?: Omit<PollOptions, "sources">): Promise<FeedItem[]>;
158
266
  /**
159
- * Fetch a head.json pointer.
267
+ * Fetch a head.json pointer. Cheapest call (~200 bytes).
160
268
  * @param url Full URL to head.json. Defaults to global head.
161
269
  */
162
270
  head(url?: string): Promise<Head>;
@@ -167,6 +275,23 @@ declare class DiffDelta {
167
275
  fetchFeed(url?: string): Promise<Feed>;
168
276
  /** List all available DiffDelta sources. */
169
277
  sources(): Promise<SourceInfo[]>;
278
+ /**
279
+ * Check pipeline health. Returns when the engine last ran and whether
280
+ * all sources are healthy. A stale timestamp means the pipeline is down.
281
+ */
282
+ checkHealth(): Promise<HealthCheck>;
283
+ /**
284
+ * Given a list of dependency names your bot uses, returns the source IDs
285
+ * you should monitor. Uses the static stacks.json mapping — no API call,
286
+ * pure local lookup after one fetch.
287
+ *
288
+ * @example
289
+ * ```ts
290
+ * const sources = await dd.discoverSources(["openai", "langchain", "pinecone"]);
291
+ * // → ["openai_sdk_releases", "openai_api_changelog", "langchain_releases", "pinecone_status"]
292
+ * ```
293
+ */
294
+ discoverSources(dependencies: string[]): Promise<string[]>;
170
295
  /**
171
296
  * Continuously poll and call a function for each new item.
172
297
  *
@@ -177,6 +302,9 @@ declare class DiffDelta {
177
302
  * ```ts
178
303
  * dd.watch(item => {
179
304
  * console.log(`🚨 ${item.source}: ${item.headline}`);
305
+ * if (item.suggestedAction === "PATCH_IMMEDIATELY") {
306
+ * triggerAlert(item);
307
+ * }
180
308
  * }, { tags: ["security"] });
181
309
  * ```
182
310
  *
@@ -227,4 +355,4 @@ declare class MemoryCursorStore {
227
355
  clear(key?: string): void;
228
356
  }
229
357
 
230
- export { CursorStore, DiffDelta, type DiffDeltaOptions, type Feed, type FeedItem, type Head, MemoryCursorStore, type PollOptions, type SourceInfo, type WatchOptions };
358
+ export { CursorStore, type DeprecationSignal, DiffDelta, type DiffDeltaOptions, type Feed, type FeedItem, type Head, type HealthCheck, type IncidentSignal, MemoryCursorStore, type PollOptions, type ReleaseSignal, type SeveritySignal, type SignalProvenance, type Signals, type SourceInfo, type SuggestedAction, type WatchOptions, parseFeed, parseFeedItem, parseHead, parseHealthCheck, parseSourceInfo };