@basedchef/contextkit 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 ADDED
@@ -0,0 +1,41 @@
1
+ # contextkit TypeScript SDK
2
+
3
+ Typed SDK for ContextKit, the x402-powered context infrastructure API for AI agents.
4
+
5
+ ```ts
6
+ import { ContextKit } from "contextkit";
7
+
8
+ const client = new ContextKit({
9
+ apiKey: process.env.CONTEXTKIT_API_KEY!,
10
+ x402: async (challenge) => wallet.pay(challenge)
11
+ });
12
+
13
+ const response = await client.summarize({ messages });
14
+ ```
15
+
16
+ ## Methods
17
+
18
+ - `summarize(request)`
19
+ - `compressContext(request)`
20
+ - `handoff(request)`
21
+ - `extractProfile(request)`
22
+ - `estimateTokens(request)`
23
+
24
+ ## Webhook Verification
25
+
26
+ ```ts
27
+ import { verifyContextKitWebhook } from "contextkit";
28
+
29
+ const valid = await verifyContextKitWebhook({
30
+ payload: rawBody,
31
+ signature: request.headers.get("ContextKit-Signature")!,
32
+ secret: process.env.CONTEXTKIT_WEBHOOK_SECRET!
33
+ });
34
+ ```
35
+
36
+ ## Build
37
+
38
+ ```bash
39
+ npm install
40
+ npm run build
41
+ ```
package/dist/index.cjs ADDED
@@ -0,0 +1,146 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ ContextKit: () => ContextKit,
24
+ ContextKitError: () => ContextKitError,
25
+ encodeX402Payment: () => encodeX402Payment,
26
+ getFirstX402Requirement: () => getFirstX402Requirement,
27
+ verifyContextKitWebhook: () => verifyContextKitWebhook
28
+ });
29
+ module.exports = __toCommonJS(index_exports);
30
+
31
+ // src/client.ts
32
+ var ContextKit = class {
33
+ constructor(options) {
34
+ this.options = options;
35
+ this.baseUrl = options.baseUrl ?? "https://contextkit.dev";
36
+ this.fetcher = options.fetch ?? fetch;
37
+ this.retries = options.retries ?? 2;
38
+ this.x402 = options.x402;
39
+ }
40
+ options;
41
+ baseUrl;
42
+ fetcher;
43
+ retries;
44
+ x402;
45
+ summarize(request) {
46
+ return this.post("/api/summarize", request);
47
+ }
48
+ compressContext(request) {
49
+ return this.post("/api/compress-context", request);
50
+ }
51
+ handoff(request) {
52
+ return this.post("/api/handoff", request);
53
+ }
54
+ extractProfile(request) {
55
+ return this.post("/api/extract-profile", request);
56
+ }
57
+ memoryEnrichment(request) {
58
+ return this.post("/api/memory-enrichment", request);
59
+ }
60
+ async estimateTokens(input) {
61
+ return this.post("/api/tokens/estimate", input);
62
+ }
63
+ async post(path, body) {
64
+ const url = `${this.baseUrl.replace(/\/$/, "")}${path}`;
65
+ const init = {
66
+ method: "POST",
67
+ headers: {
68
+ Authorization: `Bearer ${this.options.apiKey}`,
69
+ "Content-Type": "application/json"
70
+ },
71
+ body: JSON.stringify(body)
72
+ };
73
+ for (let attempt = 0; attempt <= this.retries; attempt += 1) {
74
+ const response = await this.fetcher(url, init);
75
+ if (response.status === 402 && this.x402) {
76
+ const challenge = await response.json();
77
+ const payment = await this.x402(challenge, { ...init, url });
78
+ init.headers = { ...init.headers, "X-Payment": payment };
79
+ continue;
80
+ }
81
+ if (response.ok) {
82
+ return await response.json();
83
+ }
84
+ if (response.status >= 500 && attempt < this.retries) {
85
+ await delay(2 ** attempt * 250);
86
+ continue;
87
+ }
88
+ throw new ContextKitError(response.status, await response.text());
89
+ }
90
+ throw new Error("ContextKit request failed after retries.");
91
+ }
92
+ };
93
+ var ContextKitError = class extends Error {
94
+ constructor(status, body) {
95
+ super(`ContextKit API request failed with ${status}: ${body}`);
96
+ this.status = status;
97
+ this.body = body;
98
+ }
99
+ status;
100
+ body;
101
+ };
102
+ function delay(ms) {
103
+ return new Promise((resolve) => setTimeout(resolve, ms));
104
+ }
105
+
106
+ // src/webhooks.ts
107
+ async function verifyContextKitWebhook(input) {
108
+ const key = await crypto.subtle.importKey(
109
+ "raw",
110
+ new TextEncoder().encode(input.secret),
111
+ { name: "HMAC", hash: "SHA-256" },
112
+ false,
113
+ ["sign"]
114
+ );
115
+ const digest = await crypto.subtle.sign("HMAC", key, new TextEncoder().encode(input.payload));
116
+ const expected = Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, "0")).join("");
117
+ return timingSafeEqual(expected, input.signature);
118
+ }
119
+ function timingSafeEqual(a, b) {
120
+ if (a.length !== b.length) return false;
121
+ let result = 0;
122
+ for (let index = 0; index < a.length; index += 1) {
123
+ result |= a.charCodeAt(index) ^ b.charCodeAt(index);
124
+ }
125
+ return result === 0;
126
+ }
127
+
128
+ // src/x402.ts
129
+ function getFirstX402Requirement(challenge) {
130
+ const requirement = challenge.accepts?.[0];
131
+ if (!requirement) {
132
+ throw new Error("ContextKit response did not include an x402 payment requirement.");
133
+ }
134
+ return requirement;
135
+ }
136
+ function encodeX402Payment(payment) {
137
+ return typeof payment === "string" ? payment : JSON.stringify(payment);
138
+ }
139
+ // Annotate the CommonJS export names for ESM import in node:
140
+ 0 && (module.exports = {
141
+ ContextKit,
142
+ ContextKitError,
143
+ encodeX402Payment,
144
+ getFirstX402Requirement,
145
+ verifyContextKitWebhook
146
+ });
@@ -0,0 +1,256 @@
1
+ type Role = "system" | "user" | "assistant" | "tool";
2
+ type ConversationMessage = {
3
+ role: Role;
4
+ content: string;
5
+ };
6
+ type ContextRequest = {
7
+ messages: ConversationMessage[];
8
+ mode?: "micro" | "compact" | "extended" | "debug";
9
+ metadata?: Record<string, unknown>;
10
+ webhookUrl?: string;
11
+ };
12
+ type SummarizeResponse = {
13
+ mode: "micro" | "compact" | "extended" | "debug";
14
+ summary?: string;
15
+ micro?: string;
16
+ compact?: string;
17
+ extended?: string;
18
+ state: {
19
+ goal: string;
20
+ status: string;
21
+ blockers: string[];
22
+ next: string[];
23
+ };
24
+ keyDecisions?: string[];
25
+ actionItems?: string[];
26
+ openQuestions?: string[];
27
+ risks?: string[];
28
+ metrics: {
29
+ inputTokens: number;
30
+ compactTokens: number;
31
+ stateTokens: number;
32
+ totalOutputTokens: number;
33
+ reductionPercent: number;
34
+ latencyMs: number;
35
+ };
36
+ confidence?: number;
37
+ };
38
+ type CompressContextResponse = {
39
+ compressedContext: string;
40
+ state: {
41
+ goals: string[];
42
+ status: string[];
43
+ activeProblems: string[];
44
+ constraints: string[];
45
+ decisions: string[];
46
+ nextSteps: string[];
47
+ };
48
+ entities: {
49
+ people: string[];
50
+ projects: string[];
51
+ technologies: string[];
52
+ organizations: string[];
53
+ deadlines: string[];
54
+ };
55
+ conflicts?: Array<{
56
+ old: string;
57
+ new: string;
58
+ }>;
59
+ metrics: {
60
+ inputTokens: number;
61
+ compressedTokens: number;
62
+ reductionPercent: number;
63
+ };
64
+ };
65
+ type HandoffResponse = {
66
+ project: {
67
+ name: string;
68
+ goal: string;
69
+ currentState: string;
70
+ };
71
+ completed: string[];
72
+ inProgress: string[];
73
+ pending: string[];
74
+ blockers: string[];
75
+ failedApproaches: Array<{
76
+ attempt: string;
77
+ result: string;
78
+ lesson: string;
79
+ }>;
80
+ decisions: Array<{
81
+ decision: string;
82
+ reason: string;
83
+ }>;
84
+ priorities: string[];
85
+ criticalContext: {
86
+ mustKnow: string[];
87
+ mustNotDo: string[];
88
+ biggestRisk: string;
89
+ successMetric: string;
90
+ };
91
+ startHere: string;
92
+ agentNotes: string[];
93
+ };
94
+ type ProfileResponse = {
95
+ mode: "micro" | "compact" | "full";
96
+ micro: {
97
+ identity: {
98
+ profession?: string;
99
+ location?: string;
100
+ age?: number | null;
101
+ };
102
+ preferences: string[];
103
+ goals: string[];
104
+ };
105
+ compact: {
106
+ identity: {
107
+ profession?: string;
108
+ location?: string;
109
+ age?: number | null;
110
+ };
111
+ skills: string[];
112
+ interests: string[];
113
+ preferences: string[];
114
+ goals: string[];
115
+ traits: string[];
116
+ };
117
+ full: {
118
+ identity: {
119
+ profession?: string;
120
+ location?: string;
121
+ age?: number | null;
122
+ };
123
+ skills: string[];
124
+ interests: string[];
125
+ stablePreferences: string[];
126
+ currentGoals: string[];
127
+ futurePlans: string[];
128
+ inferredTraits: string[];
129
+ stableMemories: string[];
130
+ evolvingMemories: string[];
131
+ };
132
+ memoryFacts: Array<{
133
+ fact: string;
134
+ category: string;
135
+ stability: "stable" | "evolving";
136
+ confidence: number;
137
+ }>;
138
+ interests: string[];
139
+ riskTolerance: string;
140
+ communicationStyle: string;
141
+ preferences: string[];
142
+ importantContext: string[];
143
+ identity: {
144
+ profession?: string;
145
+ location?: string;
146
+ age?: number | null;
147
+ };
148
+ skills: string[];
149
+ goals: string[];
150
+ futurePlans: string[];
151
+ behaviorPatterns: string[];
152
+ dislikes: string[];
153
+ careerStage: string;
154
+ managementIntent: boolean;
155
+ entrepreneurial: boolean;
156
+ inferredTraits: string[];
157
+ memoryImportance: number;
158
+ stableMemories: string[];
159
+ evolvingMemories: string[];
160
+ deprecatedMemories: string[];
161
+ confidence: number;
162
+ };
163
+ type MemoryEnrichmentResponse = {
164
+ activeMemories: Array<{
165
+ fact: string;
166
+ category: string;
167
+ stability: "stable";
168
+ confidence: number;
169
+ }>;
170
+ evolvingMemories: Array<{
171
+ fact: string;
172
+ category: string;
173
+ stability: "evolving";
174
+ confidence: number;
175
+ }>;
176
+ conflicts: Array<{
177
+ old: string;
178
+ new: string;
179
+ reason: string;
180
+ }>;
181
+ stablePreferences: string[];
182
+ evolvingPreferences: string[];
183
+ longTermGoals: string[];
184
+ supersededMemories: string[];
185
+ memoryConflicts: Array<{
186
+ current: string;
187
+ superseded: string[];
188
+ }>;
189
+ stableMemories: string[];
190
+ legacyEvolvingMemories?: string[];
191
+ deprecatedMemories: string[];
192
+ confidence: number;
193
+ };
194
+ type X402PaymentHandler = (challenge: unknown, request: RequestInit & {
195
+ url: string;
196
+ }) => Promise<string>;
197
+
198
+ type ContextKitOptions = {
199
+ apiKey: string;
200
+ baseUrl?: string;
201
+ fetch?: typeof fetch;
202
+ retries?: number;
203
+ x402?: X402PaymentHandler;
204
+ };
205
+ declare class ContextKit {
206
+ private readonly options;
207
+ private readonly baseUrl;
208
+ private readonly fetcher;
209
+ private readonly retries;
210
+ private readonly x402?;
211
+ constructor(options: ContextKitOptions);
212
+ summarize(request: ContextRequest): Promise<SummarizeResponse>;
213
+ compressContext(request: ContextRequest): Promise<CompressContextResponse>;
214
+ handoff(request: ContextRequest): Promise<HandoffResponse>;
215
+ extractProfile(request: ContextRequest): Promise<ProfileResponse>;
216
+ memoryEnrichment(request: ContextRequest): Promise<MemoryEnrichmentResponse>;
217
+ estimateTokens(input: unknown): Promise<{
218
+ inputTokens: number;
219
+ compressedTokens: number;
220
+ reductionPercent: number;
221
+ }>;
222
+ private post;
223
+ }
224
+ declare class ContextKitError extends Error {
225
+ readonly status: number;
226
+ readonly body: string;
227
+ constructor(status: number, body: string);
228
+ }
229
+
230
+ declare function verifyContextKitWebhook(input: {
231
+ payload: string;
232
+ signature: string;
233
+ secret: string;
234
+ }): Promise<boolean>;
235
+
236
+ type X402Challenge = {
237
+ accepts?: Array<{
238
+ scheme: string;
239
+ network: string;
240
+ maxAmountRequired: string;
241
+ resource: string;
242
+ payTo: string;
243
+ asset: string;
244
+ }>;
245
+ };
246
+ declare function getFirstX402Requirement(challenge: X402Challenge): {
247
+ scheme: string;
248
+ network: string;
249
+ maxAmountRequired: string;
250
+ resource: string;
251
+ payTo: string;
252
+ asset: string;
253
+ };
254
+ declare function encodeX402Payment(payment: unknown): string;
255
+
256
+ export { type CompressContextResponse, ContextKit, ContextKitError, type ContextRequest, type ConversationMessage, type HandoffResponse, type MemoryEnrichmentResponse, type ProfileResponse, type SummarizeResponse, type X402PaymentHandler, encodeX402Payment, getFirstX402Requirement, verifyContextKitWebhook };
@@ -0,0 +1,256 @@
1
+ type Role = "system" | "user" | "assistant" | "tool";
2
+ type ConversationMessage = {
3
+ role: Role;
4
+ content: string;
5
+ };
6
+ type ContextRequest = {
7
+ messages: ConversationMessage[];
8
+ mode?: "micro" | "compact" | "extended" | "debug";
9
+ metadata?: Record<string, unknown>;
10
+ webhookUrl?: string;
11
+ };
12
+ type SummarizeResponse = {
13
+ mode: "micro" | "compact" | "extended" | "debug";
14
+ summary?: string;
15
+ micro?: string;
16
+ compact?: string;
17
+ extended?: string;
18
+ state: {
19
+ goal: string;
20
+ status: string;
21
+ blockers: string[];
22
+ next: string[];
23
+ };
24
+ keyDecisions?: string[];
25
+ actionItems?: string[];
26
+ openQuestions?: string[];
27
+ risks?: string[];
28
+ metrics: {
29
+ inputTokens: number;
30
+ compactTokens: number;
31
+ stateTokens: number;
32
+ totalOutputTokens: number;
33
+ reductionPercent: number;
34
+ latencyMs: number;
35
+ };
36
+ confidence?: number;
37
+ };
38
+ type CompressContextResponse = {
39
+ compressedContext: string;
40
+ state: {
41
+ goals: string[];
42
+ status: string[];
43
+ activeProblems: string[];
44
+ constraints: string[];
45
+ decisions: string[];
46
+ nextSteps: string[];
47
+ };
48
+ entities: {
49
+ people: string[];
50
+ projects: string[];
51
+ technologies: string[];
52
+ organizations: string[];
53
+ deadlines: string[];
54
+ };
55
+ conflicts?: Array<{
56
+ old: string;
57
+ new: string;
58
+ }>;
59
+ metrics: {
60
+ inputTokens: number;
61
+ compressedTokens: number;
62
+ reductionPercent: number;
63
+ };
64
+ };
65
+ type HandoffResponse = {
66
+ project: {
67
+ name: string;
68
+ goal: string;
69
+ currentState: string;
70
+ };
71
+ completed: string[];
72
+ inProgress: string[];
73
+ pending: string[];
74
+ blockers: string[];
75
+ failedApproaches: Array<{
76
+ attempt: string;
77
+ result: string;
78
+ lesson: string;
79
+ }>;
80
+ decisions: Array<{
81
+ decision: string;
82
+ reason: string;
83
+ }>;
84
+ priorities: string[];
85
+ criticalContext: {
86
+ mustKnow: string[];
87
+ mustNotDo: string[];
88
+ biggestRisk: string;
89
+ successMetric: string;
90
+ };
91
+ startHere: string;
92
+ agentNotes: string[];
93
+ };
94
+ type ProfileResponse = {
95
+ mode: "micro" | "compact" | "full";
96
+ micro: {
97
+ identity: {
98
+ profession?: string;
99
+ location?: string;
100
+ age?: number | null;
101
+ };
102
+ preferences: string[];
103
+ goals: string[];
104
+ };
105
+ compact: {
106
+ identity: {
107
+ profession?: string;
108
+ location?: string;
109
+ age?: number | null;
110
+ };
111
+ skills: string[];
112
+ interests: string[];
113
+ preferences: string[];
114
+ goals: string[];
115
+ traits: string[];
116
+ };
117
+ full: {
118
+ identity: {
119
+ profession?: string;
120
+ location?: string;
121
+ age?: number | null;
122
+ };
123
+ skills: string[];
124
+ interests: string[];
125
+ stablePreferences: string[];
126
+ currentGoals: string[];
127
+ futurePlans: string[];
128
+ inferredTraits: string[];
129
+ stableMemories: string[];
130
+ evolvingMemories: string[];
131
+ };
132
+ memoryFacts: Array<{
133
+ fact: string;
134
+ category: string;
135
+ stability: "stable" | "evolving";
136
+ confidence: number;
137
+ }>;
138
+ interests: string[];
139
+ riskTolerance: string;
140
+ communicationStyle: string;
141
+ preferences: string[];
142
+ importantContext: string[];
143
+ identity: {
144
+ profession?: string;
145
+ location?: string;
146
+ age?: number | null;
147
+ };
148
+ skills: string[];
149
+ goals: string[];
150
+ futurePlans: string[];
151
+ behaviorPatterns: string[];
152
+ dislikes: string[];
153
+ careerStage: string;
154
+ managementIntent: boolean;
155
+ entrepreneurial: boolean;
156
+ inferredTraits: string[];
157
+ memoryImportance: number;
158
+ stableMemories: string[];
159
+ evolvingMemories: string[];
160
+ deprecatedMemories: string[];
161
+ confidence: number;
162
+ };
163
+ type MemoryEnrichmentResponse = {
164
+ activeMemories: Array<{
165
+ fact: string;
166
+ category: string;
167
+ stability: "stable";
168
+ confidence: number;
169
+ }>;
170
+ evolvingMemories: Array<{
171
+ fact: string;
172
+ category: string;
173
+ stability: "evolving";
174
+ confidence: number;
175
+ }>;
176
+ conflicts: Array<{
177
+ old: string;
178
+ new: string;
179
+ reason: string;
180
+ }>;
181
+ stablePreferences: string[];
182
+ evolvingPreferences: string[];
183
+ longTermGoals: string[];
184
+ supersededMemories: string[];
185
+ memoryConflicts: Array<{
186
+ current: string;
187
+ superseded: string[];
188
+ }>;
189
+ stableMemories: string[];
190
+ legacyEvolvingMemories?: string[];
191
+ deprecatedMemories: string[];
192
+ confidence: number;
193
+ };
194
+ type X402PaymentHandler = (challenge: unknown, request: RequestInit & {
195
+ url: string;
196
+ }) => Promise<string>;
197
+
198
+ type ContextKitOptions = {
199
+ apiKey: string;
200
+ baseUrl?: string;
201
+ fetch?: typeof fetch;
202
+ retries?: number;
203
+ x402?: X402PaymentHandler;
204
+ };
205
+ declare class ContextKit {
206
+ private readonly options;
207
+ private readonly baseUrl;
208
+ private readonly fetcher;
209
+ private readonly retries;
210
+ private readonly x402?;
211
+ constructor(options: ContextKitOptions);
212
+ summarize(request: ContextRequest): Promise<SummarizeResponse>;
213
+ compressContext(request: ContextRequest): Promise<CompressContextResponse>;
214
+ handoff(request: ContextRequest): Promise<HandoffResponse>;
215
+ extractProfile(request: ContextRequest): Promise<ProfileResponse>;
216
+ memoryEnrichment(request: ContextRequest): Promise<MemoryEnrichmentResponse>;
217
+ estimateTokens(input: unknown): Promise<{
218
+ inputTokens: number;
219
+ compressedTokens: number;
220
+ reductionPercent: number;
221
+ }>;
222
+ private post;
223
+ }
224
+ declare class ContextKitError extends Error {
225
+ readonly status: number;
226
+ readonly body: string;
227
+ constructor(status: number, body: string);
228
+ }
229
+
230
+ declare function verifyContextKitWebhook(input: {
231
+ payload: string;
232
+ signature: string;
233
+ secret: string;
234
+ }): Promise<boolean>;
235
+
236
+ type X402Challenge = {
237
+ accepts?: Array<{
238
+ scheme: string;
239
+ network: string;
240
+ maxAmountRequired: string;
241
+ resource: string;
242
+ payTo: string;
243
+ asset: string;
244
+ }>;
245
+ };
246
+ declare function getFirstX402Requirement(challenge: X402Challenge): {
247
+ scheme: string;
248
+ network: string;
249
+ maxAmountRequired: string;
250
+ resource: string;
251
+ payTo: string;
252
+ asset: string;
253
+ };
254
+ declare function encodeX402Payment(payment: unknown): string;
255
+
256
+ export { type CompressContextResponse, ContextKit, ContextKitError, type ContextRequest, type ConversationMessage, type HandoffResponse, type MemoryEnrichmentResponse, type ProfileResponse, type SummarizeResponse, type X402PaymentHandler, encodeX402Payment, getFirstX402Requirement, verifyContextKitWebhook };
package/dist/index.js ADDED
@@ -0,0 +1,115 @@
1
+ // src/client.ts
2
+ var ContextKit = class {
3
+ constructor(options) {
4
+ this.options = options;
5
+ this.baseUrl = options.baseUrl ?? "https://contextkit.dev";
6
+ this.fetcher = options.fetch ?? fetch;
7
+ this.retries = options.retries ?? 2;
8
+ this.x402 = options.x402;
9
+ }
10
+ options;
11
+ baseUrl;
12
+ fetcher;
13
+ retries;
14
+ x402;
15
+ summarize(request) {
16
+ return this.post("/api/summarize", request);
17
+ }
18
+ compressContext(request) {
19
+ return this.post("/api/compress-context", request);
20
+ }
21
+ handoff(request) {
22
+ return this.post("/api/handoff", request);
23
+ }
24
+ extractProfile(request) {
25
+ return this.post("/api/extract-profile", request);
26
+ }
27
+ memoryEnrichment(request) {
28
+ return this.post("/api/memory-enrichment", request);
29
+ }
30
+ async estimateTokens(input) {
31
+ return this.post("/api/tokens/estimate", input);
32
+ }
33
+ async post(path, body) {
34
+ const url = `${this.baseUrl.replace(/\/$/, "")}${path}`;
35
+ const init = {
36
+ method: "POST",
37
+ headers: {
38
+ Authorization: `Bearer ${this.options.apiKey}`,
39
+ "Content-Type": "application/json"
40
+ },
41
+ body: JSON.stringify(body)
42
+ };
43
+ for (let attempt = 0; attempt <= this.retries; attempt += 1) {
44
+ const response = await this.fetcher(url, init);
45
+ if (response.status === 402 && this.x402) {
46
+ const challenge = await response.json();
47
+ const payment = await this.x402(challenge, { ...init, url });
48
+ init.headers = { ...init.headers, "X-Payment": payment };
49
+ continue;
50
+ }
51
+ if (response.ok) {
52
+ return await response.json();
53
+ }
54
+ if (response.status >= 500 && attempt < this.retries) {
55
+ await delay(2 ** attempt * 250);
56
+ continue;
57
+ }
58
+ throw new ContextKitError(response.status, await response.text());
59
+ }
60
+ throw new Error("ContextKit request failed after retries.");
61
+ }
62
+ };
63
+ var ContextKitError = class extends Error {
64
+ constructor(status, body) {
65
+ super(`ContextKit API request failed with ${status}: ${body}`);
66
+ this.status = status;
67
+ this.body = body;
68
+ }
69
+ status;
70
+ body;
71
+ };
72
+ function delay(ms) {
73
+ return new Promise((resolve) => setTimeout(resolve, ms));
74
+ }
75
+
76
+ // src/webhooks.ts
77
+ async function verifyContextKitWebhook(input) {
78
+ const key = await crypto.subtle.importKey(
79
+ "raw",
80
+ new TextEncoder().encode(input.secret),
81
+ { name: "HMAC", hash: "SHA-256" },
82
+ false,
83
+ ["sign"]
84
+ );
85
+ const digest = await crypto.subtle.sign("HMAC", key, new TextEncoder().encode(input.payload));
86
+ const expected = Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, "0")).join("");
87
+ return timingSafeEqual(expected, input.signature);
88
+ }
89
+ function timingSafeEqual(a, b) {
90
+ if (a.length !== b.length) return false;
91
+ let result = 0;
92
+ for (let index = 0; index < a.length; index += 1) {
93
+ result |= a.charCodeAt(index) ^ b.charCodeAt(index);
94
+ }
95
+ return result === 0;
96
+ }
97
+
98
+ // src/x402.ts
99
+ function getFirstX402Requirement(challenge) {
100
+ const requirement = challenge.accepts?.[0];
101
+ if (!requirement) {
102
+ throw new Error("ContextKit response did not include an x402 payment requirement.");
103
+ }
104
+ return requirement;
105
+ }
106
+ function encodeX402Payment(payment) {
107
+ return typeof payment === "string" ? payment : JSON.stringify(payment);
108
+ }
109
+ export {
110
+ ContextKit,
111
+ ContextKitError,
112
+ encodeX402Payment,
113
+ getFirstX402Requirement,
114
+ verifyContextKitWebhook
115
+ };
package/package.json ADDED
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "@basedchef/contextkit",
3
+ "version": "0.1.0",
4
+ "description": "TypeScript SDK for ContextKit context infrastructure APIs.",
5
+ "type": "module",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "files": ["dist", "README.md"],
10
+ "sideEffects": false,
11
+ "publishConfig": {
12
+ "access": "public"
13
+ },
14
+ "scripts": {
15
+ "build": "tsup src/index.ts --format esm,cjs --dts --clean",
16
+ "typecheck": "tsc --noEmit",
17
+ "prepublishOnly": "npm run build"
18
+ },
19
+ "dependencies": {
20
+ "zod": "^3.24.1"
21
+ },
22
+ "devDependencies": {
23
+ "tsup": "^8.3.5",
24
+ "typescript": "^5.7.2"
25
+ }
26
+ }