@clawpify/skills 1.0.4 → 1.0.5

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/dist/index.js CHANGED
@@ -6,7 +6,7 @@ class ShopifyClient {
6
6
  constructor(config) {
7
7
  this.storeUrl = config.storeUrl.replace(/^https?:\/\//, "").replace(/\/$/, "");
8
8
  this.accessToken = config.accessToken;
9
- this.apiVersion = config.apiVersion ?? "2026-01";
9
+ this.apiVersion = config.apiVersion ?? "2026-04";
10
10
  }
11
11
  async graphql(query, variables) {
12
12
  const url = `https://${this.storeUrl}/admin/api/${this.apiVersion}/graphql.json`;
@@ -89,6 +89,7 @@ async function createAuthenticatedConfig() {
89
89
 
90
90
  // src/agent.ts
91
91
  import Anthropic from "@anthropic-ai/sdk";
92
+ var DEFAULT_SYSTEM_INSTRUCTION = "You're Clawpify. You help run a Shopify store. The merchant texts you to get stuff done";
92
93
  var SHOPIFY_GRAPHQL_TOOL = {
93
94
  name: "shopify_graphql",
94
95
  description: "Execute a GraphQL query against the Shopify Admin API. Use this to interact with products, orders, customers, inventory, and other Shopify resources.",
@@ -107,79 +108,384 @@ var SHOPIFY_GRAPHQL_TOOL = {
107
108
  required: ["query"]
108
109
  }
109
110
  };
111
+ var DEFAULT_PRICING = {
112
+ inputPerMillion: 3,
113
+ outputPerMillion: 15,
114
+ cacheWritePerMillion: 3.75,
115
+ cacheReadPerMillion: 0.3
116
+ };
117
+ var DEFAULT_MAX_ITERATIONS = 20;
118
+ async function safeHook(hook, ...args) {
119
+ if (!hook)
120
+ return;
121
+ try {
122
+ await hook(...args);
123
+ } catch {}
124
+ }
125
+ function computeCost(usage, pricing) {
126
+ return usage.inputTokens * pricing.inputPerMillion / 1e6 + usage.outputTokens * pricing.outputPerMillion / 1e6 + usage.cacheCreationInputTokens * pricing.cacheWritePerMillion / 1e6 + usage.cacheReadInputTokens * pricing.cacheReadPerMillion / 1e6;
127
+ }
128
+ function emptyUsage() {
129
+ return {
130
+ inputTokens: 0,
131
+ outputTokens: 0,
132
+ cacheCreationInputTokens: 0,
133
+ cacheReadInputTokens: 0,
134
+ totalCost: 0
135
+ };
136
+ }
137
+ function accumulateUsage(total, raw, pricing) {
138
+ total.inputTokens += raw.input_tokens;
139
+ total.outputTokens += raw.output_tokens;
140
+ total.cacheCreationInputTokens += raw.cache_creation_input_tokens ?? 0;
141
+ total.cacheReadInputTokens += raw.cache_read_input_tokens ?? 0;
142
+ total.totalCost = computeCost(total, pricing);
143
+ }
144
+ function extractContent(response) {
145
+ let text = "";
146
+ let thinking = "";
147
+ for (const block of response.content) {
148
+ if (block.type === "text") {
149
+ text += (text ? `
150
+ ` : "") + block.text;
151
+ } else if (block.type === "thinking") {
152
+ thinking += (thinking ? `
153
+ ` : "") + block.thinking;
154
+ }
155
+ }
156
+ return { text, thinking };
157
+ }
110
158
 
111
159
  class ShopifyAgent {
112
160
  anthropic;
113
161
  shopify;
114
162
  skillContent;
163
+ systemInstruction;
115
164
  model;
165
+ pricing;
166
+ plugins = new Map;
167
+ hooks;
168
+ thinkingConfig;
169
+ maxIterations;
170
+ memory;
116
171
  constructor(config) {
117
172
  this.anthropic = new Anthropic;
118
173
  this.shopify = config.shopify;
119
174
  this.skillContent = config.skillContent;
175
+ this.systemInstruction = config.systemInstruction ?? DEFAULT_SYSTEM_INSTRUCTION;
120
176
  this.model = config.model ?? "claude-sonnet-4-5";
177
+ this.pricing = config.pricing ?? DEFAULT_PRICING;
178
+ this.hooks = config.hooks ?? {};
179
+ this.thinkingConfig = config.thinking;
180
+ this.maxIterations = config.maxIterations ?? DEFAULT_MAX_ITERATIONS;
181
+ this.memory = config.memory;
182
+ if (config.plugins) {
183
+ for (const plugin of config.plugins) {
184
+ this.registerPlugin(plugin);
185
+ }
186
+ }
187
+ }
188
+ registerPlugin(plugin) {
189
+ const name = plugin.tool.name;
190
+ if (name === "shopify_graphql") {
191
+ throw new Error(`Cannot register plugin with reserved tool name "shopify_graphql"`);
192
+ }
193
+ if (this.plugins.has(name)) {
194
+ throw new Error(`Plugin with tool name "${name}" is already registered`);
195
+ }
196
+ this.plugins.set(name, plugin);
197
+ }
198
+ buildSystemPrompt() {
199
+ return [
200
+ { type: "text", text: this.systemInstruction },
201
+ {
202
+ type: "text",
203
+ text: this.skillContent,
204
+ cache_control: { type: "ephemeral" }
205
+ }
206
+ ];
207
+ }
208
+ buildTools() {
209
+ const allTools = [
210
+ SHOPIFY_GRAPHQL_TOOL,
211
+ ...[...this.plugins.values()].map((p) => p.tool)
212
+ ];
213
+ if (allTools.length > 0) {
214
+ const last = allTools[allTools.length - 1];
215
+ allTools[allTools.length - 1] = Object.assign({}, last, {
216
+ cache_control: { type: "ephemeral" }
217
+ });
218
+ }
219
+ return allTools;
220
+ }
221
+ getMaxTokens() {
222
+ return this.thinkingConfig ? this.thinkingConfig.budgetTokens + 4096 : 4096;
223
+ }
224
+ getThinkingParam() {
225
+ if (!this.thinkingConfig)
226
+ return {};
227
+ return {
228
+ thinking: {
229
+ type: "enabled",
230
+ budget_tokens: this.thinkingConfig.budgetTokens
231
+ }
232
+ };
233
+ }
234
+ async executeTool(name, input) {
235
+ await safeHook(this.hooks.onToolCall, name, input);
236
+ if (name === "shopify_graphql") {
237
+ try {
238
+ const result = await this.shopify.graphql(input.query, input.variables);
239
+ const content2 = JSON.stringify(result, null, 2);
240
+ await safeHook(this.hooks.onToolResult, name, content2, false);
241
+ return { content: content2, isError: false };
242
+ } catch (error) {
243
+ const content2 = `Error: ${error instanceof Error ? error.message : String(error)}`;
244
+ await safeHook(this.hooks.onToolResult, name, content2, true);
245
+ return { content: content2, isError: true };
246
+ }
247
+ }
248
+ if (this.plugins.has(name)) {
249
+ const plugin = this.plugins.get(name);
250
+ try {
251
+ const content2 = await plugin.handler(input);
252
+ await safeHook(this.hooks.onToolResult, name, content2, false);
253
+ return { content: content2, isError: false };
254
+ } catch (error) {
255
+ const content2 = `Error: ${error instanceof Error ? error.message : String(error)}`;
256
+ await safeHook(this.hooks.onToolResult, name, content2, true);
257
+ return { content: content2, isError: true };
258
+ }
259
+ }
260
+ const content = `Error: Unknown tool "${name}"`;
261
+ await safeHook(this.hooks.onToolResult, name, content, true);
262
+ return { content, isError: true };
263
+ }
264
+ async processToolCalls(response) {
265
+ const toolUseBlocks = response.content.filter((block) => block.type === "tool_use");
266
+ const toolResults = [];
267
+ for (const toolUse of toolUseBlocks) {
268
+ const input = toolUse.input;
269
+ const { content, isError } = await this.executeTool(toolUse.name, input);
270
+ toolResults.push({
271
+ type: "tool_result",
272
+ tool_use_id: toolUse.id,
273
+ content,
274
+ ...isError ? { is_error: true } : {}
275
+ });
276
+ }
277
+ return toolResults;
121
278
  }
122
279
  async chat(userMessage, conversationHistory = []) {
123
- const systemPrompt = `You are a helpful Shopify assistant that can query and manage a Shopify store using the GraphQL Admin API.
124
-
125
- ${this.skillContent}
126
-
127
- When the user asks about products, orders, customers, or any Shopify data, use the shopify_graphql tool to fetch or modify the data. Always explain what you're doing and present results clearly.`;
280
+ const usage = emptyUsage();
281
+ let iterationsUsed = 0;
282
+ let allThinking = "";
283
+ const systemPrompt = this.buildSystemPrompt();
284
+ const allTools = this.buildTools();
285
+ const maxTokens = this.getMaxTokens();
286
+ const thinkingParam = this.getThinkingParam();
128
287
  const messages = [
129
288
  ...conversationHistory,
130
289
  { role: "user", content: userMessage }
131
290
  ];
132
- let response = await this.anthropic.messages.create({
133
- model: this.model,
134
- max_tokens: 4096,
135
- system: systemPrompt,
136
- tools: [SHOPIFY_GRAPHQL_TOOL],
137
- messages
138
- });
139
- const assistantMessages = [];
140
- while (response.stop_reason === "tool_use") {
141
- const toolUseBlocks = response.content.filter((block) => block.type === "tool_use");
142
- assistantMessages.push(...response.content);
143
- const toolResults = [];
144
- for (const toolUse of toolUseBlocks) {
145
- if (toolUse.name === "shopify_graphql") {
146
- const input = toolUse.input;
147
- try {
148
- const result = await this.shopify.graphql(input.query, input.variables);
149
- toolResults.push({
291
+ await safeHook(this.hooks.onRequest, userMessage, conversationHistory);
292
+ try {
293
+ await safeHook(this.hooks.onApiCall, {
294
+ model: this.model,
295
+ messages,
296
+ tools: allTools
297
+ });
298
+ let response = await this.anthropic.messages.create({
299
+ model: this.model,
300
+ max_tokens: maxTokens,
301
+ system: systemPrompt,
302
+ tools: allTools,
303
+ messages,
304
+ ...thinkingParam
305
+ });
306
+ accumulateUsage(usage, response.usage, this.pricing);
307
+ const firstContent = extractContent(response);
308
+ if (firstContent.thinking)
309
+ allThinking += firstContent.thinking;
310
+ while (response.stop_reason === "tool_use") {
311
+ iterationsUsed++;
312
+ if (iterationsUsed > this.maxIterations) {
313
+ const err = new Error(`Agent exceeded maximum iterations (${this.maxIterations})`);
314
+ await safeHook(this.hooks.onError, err);
315
+ break;
316
+ }
317
+ messages.push({
318
+ role: "assistant",
319
+ content: response.content
320
+ });
321
+ const toolResults = await this.processToolCalls(response);
322
+ messages.push({ role: "user", content: toolResults });
323
+ await safeHook(this.hooks.onApiCall, {
324
+ model: this.model,
325
+ messages,
326
+ tools: allTools
327
+ });
328
+ response = await this.anthropic.messages.create({
329
+ model: this.model,
330
+ max_tokens: maxTokens,
331
+ system: systemPrompt,
332
+ tools: allTools,
333
+ messages,
334
+ ...thinkingParam
335
+ });
336
+ accumulateUsage(usage, response.usage, this.pricing);
337
+ const loopContent = extractContent(response);
338
+ if (loopContent.thinking) {
339
+ allThinking += (allThinking ? `
340
+ ` : "") + loopContent.thinking;
341
+ }
342
+ }
343
+ const { text: finalResponse } = extractContent(response);
344
+ const updatedHistory = [
345
+ ...messages,
346
+ { role: "assistant", content: response.content }
347
+ ];
348
+ await safeHook(this.hooks.onResponse, finalResponse, usage);
349
+ return {
350
+ response: finalResponse,
351
+ history: updatedHistory,
352
+ usage,
353
+ thinking: allThinking || undefined,
354
+ iterationsUsed
355
+ };
356
+ } catch (error) {
357
+ const err = error instanceof Error ? error : new Error(String(error));
358
+ await safeHook(this.hooks.onError, err);
359
+ throw err;
360
+ }
361
+ }
362
+ async* chatStream(userMessage, conversationHistory = []) {
363
+ const usage = emptyUsage();
364
+ let iterationsUsed = 0;
365
+ let allThinking = "";
366
+ let finalResponse = "";
367
+ const systemPrompt = this.buildSystemPrompt();
368
+ const allTools = this.buildTools();
369
+ const maxTokens = this.getMaxTokens();
370
+ const thinkingParam = this.getThinkingParam();
371
+ const messages = [
372
+ ...conversationHistory,
373
+ { role: "user", content: userMessage }
374
+ ];
375
+ await safeHook(this.hooks.onRequest, userMessage, conversationHistory);
376
+ try {
377
+ let stopReason = null;
378
+ do {
379
+ await safeHook(this.hooks.onApiCall, {
380
+ model: this.model,
381
+ messages,
382
+ tools: allTools
383
+ });
384
+ const stream = this.anthropic.messages.stream({
385
+ model: this.model,
386
+ max_tokens: maxTokens,
387
+ system: systemPrompt,
388
+ tools: allTools,
389
+ messages,
390
+ ...thinkingParam
391
+ });
392
+ for await (const event of stream) {
393
+ if (event.type === "content_block_delta") {
394
+ const delta = event.delta;
395
+ if (delta.type === "text_delta") {
396
+ yield { type: "text", text: delta.text };
397
+ } else if (delta.type === "thinking_delta") {
398
+ yield { type: "thinking", text: delta.thinking };
399
+ }
400
+ }
401
+ }
402
+ const response = await stream.finalMessage();
403
+ accumulateUsage(usage, response.usage, this.pricing);
404
+ stopReason = response.stop_reason;
405
+ const content = extractContent(response);
406
+ if (content.thinking) {
407
+ allThinking += (allThinking ? `
408
+ ` : "") + content.thinking;
409
+ }
410
+ if (content.text) {
411
+ finalResponse = content.text;
412
+ }
413
+ if (stopReason === "tool_use") {
414
+ iterationsUsed++;
415
+ if (iterationsUsed > this.maxIterations) {
416
+ const err = new Error(`Agent exceeded maximum iterations (${this.maxIterations})`);
417
+ await safeHook(this.hooks.onError, err);
418
+ break;
419
+ }
420
+ messages.push({
421
+ role: "assistant",
422
+ content: response.content
423
+ });
424
+ const toolUseBlocks = response.content.filter((block) => block.type === "tool_use");
425
+ const toolResults = [];
426
+ for (const toolUse of toolUseBlocks) {
427
+ const input = toolUse.input;
428
+ yield { type: "tool_call", name: toolUse.name, input };
429
+ const result = await this.executeTool(toolUse.name, input);
430
+ yield {
150
431
  type: "tool_result",
151
- tool_use_id: toolUse.id,
152
- content: JSON.stringify(result, null, 2)
153
- });
154
- } catch (error) {
432
+ name: toolUse.name,
433
+ result: result.content,
434
+ isError: result.isError
435
+ };
155
436
  toolResults.push({
156
437
  type: "tool_result",
157
438
  tool_use_id: toolUse.id,
158
- content: `Error: ${error instanceof Error ? error.message : String(error)}`,
159
- is_error: true
439
+ content: result.content,
440
+ ...result.isError ? { is_error: true } : {}
160
441
  });
161
442
  }
443
+ messages.push({ role: "user", content: toolResults });
444
+ } else {
445
+ messages.push({
446
+ role: "assistant",
447
+ content: response.content
448
+ });
162
449
  }
163
- }
164
- messages.push({ role: "assistant", content: assistantMessages.slice() });
165
- messages.push({ role: "user", content: toolResults });
166
- assistantMessages.length = 0;
167
- response = await this.anthropic.messages.create({
168
- model: this.model,
169
- max_tokens: 4096,
170
- system: systemPrompt,
171
- tools: [SHOPIFY_GRAPHQL_TOOL],
172
- messages
173
- });
450
+ } while (stopReason === "tool_use");
451
+ await safeHook(this.hooks.onResponse, finalResponse, usage);
452
+ yield {
453
+ type: "done",
454
+ response: finalResponse,
455
+ thinking: allThinking || undefined,
456
+ usage,
457
+ iterationsUsed,
458
+ history: messages
459
+ };
460
+ } catch (error) {
461
+ const err = error instanceof Error ? error : new Error(String(error));
462
+ await safeHook(this.hooks.onError, err);
463
+ throw err;
174
464
  }
175
- const textBlocks = response.content.filter((block) => block.type === "text");
176
- const finalResponse = textBlocks.map((b) => b.text).join(`
177
- `);
178
- const updatedHistory = [
179
- ...messages,
180
- { role: "assistant", content: response.content }
181
- ];
182
- return { response: finalResponse, history: updatedHistory };
465
+ }
466
+ async chatWithMemory(sessionId, userMessage) {
467
+ if (!this.memory) {
468
+ throw new Error("chatWithMemory requires a MemoryStore. Pass `memory` in AgentConfig.");
469
+ }
470
+ const history = await this.memory.load(sessionId);
471
+ const result = await this.chat(userMessage, history);
472
+ await this.memory.save(sessionId, result.history);
473
+ return result;
474
+ }
475
+ }
476
+
477
+ // src/memory.ts
478
+ class InMemoryStore {
479
+ store = new Map;
480
+ async save(sessionId, history) {
481
+ this.store.set(sessionId, structuredClone(history));
482
+ }
483
+ async load(sessionId) {
484
+ const data = this.store.get(sessionId);
485
+ return data ? structuredClone(data) : [];
486
+ }
487
+ async clear(sessionId) {
488
+ this.store.delete(sessionId);
183
489
  }
184
490
  }
185
491
 
@@ -220,5 +526,7 @@ export {
220
526
  createShopifyClient,
221
527
  createAuthenticatedConfig,
222
528
  ShopifyClient,
223
- ShopifyAgent
529
+ ShopifyAgent,
530
+ InMemoryStore,
531
+ DEFAULT_SYSTEM_INSTRUCTION
224
532
  };
@@ -8,7 +8,7 @@ class ShopifyClient {
8
8
  constructor(config) {
9
9
  this.storeUrl = config.storeUrl.replace(/^https?:\/\//, "").replace(/\/$/, "");
10
10
  this.accessToken = config.accessToken;
11
- this.apiVersion = config.apiVersion ?? "2026-01";
11
+ this.apiVersion = config.apiVersion ?? "2026-04";
12
12
  }
13
13
  async graphql(query, variables) {
14
14
  const url = `https://${this.storeUrl}/admin/api/${this.apiVersion}/graphql.json`;
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Interface for persisting conversation history across sessions.
3
+ * Implement this interface to plug in any storage backend (Redis, SQLite, etc.).
4
+ *
5
+ * History is stored as raw MessageParam arrays — the same type the agent
6
+ * accepts and returns — so round-tripping is lossless.
7
+ */
8
+ export interface MemoryStore {
9
+ /** Save conversation history for a session. */
10
+ save(sessionId: string, history: any[]): Promise<void>;
11
+ /** Load conversation history for a session. Returns empty array if not found. */
12
+ load(sessionId: string): Promise<any[]>;
13
+ /** Clear conversation history for a session. */
14
+ clear(sessionId: string): Promise<void>;
15
+ }
16
+ /**
17
+ * Simple in-memory implementation of MemoryStore.
18
+ * Data is lost when the process restarts — use for dev/testing only.
19
+ */
20
+ export declare class InMemoryStore implements MemoryStore {
21
+ private store;
22
+ save(sessionId: string, history: any[]): Promise<void>;
23
+ load(sessionId: string): Promise<any[]>;
24
+ clear(sessionId: string): Promise<void>;
25
+ }
26
+ //# sourceMappingURL=memory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../src/memory.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,WAAW,WAAW;IAC1B,+CAA+C;IAC/C,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEvD,iFAAiF;IACjF,IAAI,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IAExC,gDAAgD;IAChD,KAAK,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACzC;AAED;;;GAGG;AACH,qBAAa,aAAc,YAAW,WAAW;IAC/C,OAAO,CAAC,KAAK,CAA4B;IAEnC,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAItD,IAAI,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAKvC,KAAK,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAG9C"}
package/dist/memory.js ADDED
@@ -0,0 +1,17 @@
1
+ // src/memory.ts
2
+ class InMemoryStore {
3
+ store = new Map;
4
+ async save(sessionId, history) {
5
+ this.store.set(sessionId, structuredClone(history));
6
+ }
7
+ async load(sessionId) {
8
+ const data = this.store.get(sessionId);
9
+ return data ? structuredClone(data) : [];
10
+ }
11
+ async clear(sessionId) {
12
+ this.store.delete(sessionId);
13
+ }
14
+ }
15
+ export {
16
+ InMemoryStore
17
+ };
package/dist/shopify.d.ts CHANGED
@@ -3,7 +3,7 @@ export interface ShopifyClientConfig {
3
3
  storeUrl: string;
4
4
  /** Admin API access token */
5
5
  accessToken: string;
6
- /** API version (defaults to "2026-01") */
6
+ /** API version (defaults to "2026-04") */
7
7
  apiVersion?: string;
8
8
  }
9
9
  export interface GraphQLResponse<T = any> {
package/dist/shopify.js CHANGED
@@ -6,7 +6,7 @@ class ShopifyClient {
6
6
  constructor(config) {
7
7
  this.storeUrl = config.storeUrl.replace(/^https?:\/\//, "").replace(/\/$/, "");
8
8
  this.accessToken = config.accessToken;
9
- this.apiVersion = config.apiVersion ?? "2026-01";
9
+ this.apiVersion = config.apiVersion ?? "2026-04";
10
10
  }
11
11
  async graphql(query, variables) {
12
12
  const url = `https://${this.storeUrl}/admin/api/${this.apiVersion}/graphql.json`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clawpify/skills",
3
- "version": "1.0.4",
3
+ "version": "1.0.5",
4
4
  "description": "Shopify Agent SDK — query and manage Shopify stores via GraphQL Admin API with AI agents and MCP",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -35,6 +35,12 @@
35
35
  "bun": "./src/skills.ts",
36
36
  "import": "./dist/skills.js",
37
37
  "default": "./dist/skills.js"
38
+ },
39
+ "./memory": {
40
+ "types": "./dist/memory.d.ts",
41
+ "bun": "./src/memory.ts",
42
+ "import": "./dist/memory.js",
43
+ "default": "./dist/memory.js"
38
44
  }
39
45
  },
40
46
  "bin": {
@@ -46,7 +52,7 @@
46
52
  "clawpify"
47
53
  ],
48
54
  "scripts": {
49
- "build": "rm -rf dist && bun build ./src/index.ts ./src/agent.ts ./src/shopify.ts ./src/auth.ts ./src/skills.ts ./src/mcp-server.ts --outdir ./dist --target node --format esm --external @anthropic-ai/sdk --external @modelcontextprotocol/sdk && tsc -p tsconfig.build.json",
55
+ "build": "rm -rf dist && bun build ./src/index.ts ./src/agent.ts ./src/shopify.ts ./src/auth.ts ./src/skills.ts ./src/memory.ts ./src/mcp-server.ts --outdir ./dist --target node --format esm --external @anthropic-ai/sdk --external @modelcontextprotocol/sdk && tsc -p tsconfig.build.json",
50
56
  "prepublishOnly": "bun run build",
51
57
  "start": "bun run examples/server.ts"
52
58
  },