@superatomai/sdk-node 0.0.2-s → 0.0.3-cp

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.
@@ -5,8 +5,21 @@ import { pathToFileURL } from "url";
5
5
  function encodeMessage(msg) {
6
6
  return JSON.stringify(msg) + "\n";
7
7
  }
8
+ var LineOverflowError = class extends Error {
9
+ constructor(buffered, limit) {
10
+ super(`IPC message exceeded ${limit} bytes without a newline (${buffered} buffered) \u2014 aborting to avoid unbounded memory.`);
11
+ this.buffered = buffered;
12
+ this.limit = limit;
13
+ this.name = "LineOverflowError";
14
+ }
15
+ };
16
+ var DEFAULT_MAX_IPC_BYTES = (() => {
17
+ const envVal = Number(process.env.SCRIPT_MAX_IPC_BYTES);
18
+ return Number.isFinite(envVal) && envVal > 0 ? Math.floor(envVal) : 64 * 1024 * 1024;
19
+ })();
8
20
  var LineSplitter = class {
9
- constructor() {
21
+ constructor(maxBytes = DEFAULT_MAX_IPC_BYTES) {
22
+ this.maxBytes = maxBytes;
10
23
  this.buffer = "";
11
24
  }
12
25
  push(chunk) {
@@ -18,6 +31,11 @@ var LineSplitter = class {
18
31
  this.buffer = this.buffer.slice(idx + 1);
19
32
  if (line.length > 0) lines.push(line);
20
33
  }
34
+ if (this.buffer.length > this.maxBytes) {
35
+ const buffered = this.buffer.length;
36
+ this.buffer = "";
37
+ throw new LineOverflowError(buffered, this.maxBytes);
38
+ }
21
39
  return lines;
22
40
  }
23
41
  /** Flush any remaining partial data (useful on stream close) */
@@ -28,8 +46,126 @@ var LineSplitter = class {
28
46
  return rest;
29
47
  }
30
48
  };
31
- function shortId() {
32
- return Math.random().toString(36).slice(2, 10);
49
+
50
+ // src/userResponse/scripts/fmt.ts
51
+ var DASH = "\u2014";
52
+ var DEFAULT_FMT_CONFIG = { locale: "en-IN", currency: "INR" };
53
+ var MONEY_TIERS = {
54
+ "en-IN": [[1e7, "Cr"], [1e5, "L"]],
55
+ "hi-IN": [[1e7, "Cr"], [1e5, "L"]]
56
+ };
57
+ var DEFAULT_MONEY_TIERS = [[1e9, "B"], [1e6, "M"]];
58
+ function moneyTiers(locale) {
59
+ return MONEY_TIERS[locale] ?? DEFAULT_MONEY_TIERS;
60
+ }
61
+ var COUNT_SCALE_MIN = 1e7;
62
+ function toNum(v) {
63
+ if (v === null || v === void 0 || v === "") return null;
64
+ const n = typeof v === "number" ? v : Number(v);
65
+ return Number.isFinite(n) ? n : null;
66
+ }
67
+ var MONTHS = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
68
+ var ISO_DATE = /^\d{4}-\d{2}-\d{2}([T ]|$)/;
69
+ function toDate(v) {
70
+ if (v === null || v === void 0 || v === "") return null;
71
+ if (v instanceof Date) return Number.isNaN(v.getTime()) ? null : v;
72
+ if (typeof v === "number") {
73
+ const d = new Date(v);
74
+ return Number.isNaN(d.getTime()) ? null : d;
75
+ }
76
+ if (typeof v === "string" && ISO_DATE.test(v.trim())) {
77
+ const d = new Date(v.trim());
78
+ return Number.isNaN(d.getTime()) ? null : d;
79
+ }
80
+ return null;
81
+ }
82
+ function makeFmt(cfg = {}) {
83
+ const locale = cfg.locale || DEFAULT_FMT_CONFIG.locale;
84
+ const currency = cfg.currency || DEFAULT_FMT_CONFIG.currency;
85
+ const group = (n, decimals = 0) => n.toLocaleString(locale, { minimumFractionDigits: decimals, maximumFractionDigits: decimals });
86
+ const symbol = (() => {
87
+ try {
88
+ const parts = new Intl.NumberFormat(locale, { style: "currency", currency }).formatToParts(0);
89
+ return parts.find((p) => p.type === "currency")?.value ?? "";
90
+ } catch {
91
+ return "";
92
+ }
93
+ })();
94
+ const scaled = (abs, tiers, decimals) => {
95
+ for (const [threshold, unit] of tiers) {
96
+ if (abs >= threshold) return `${group(abs / threshold, decimals)} ${unit}`;
97
+ }
98
+ return null;
99
+ };
100
+ function money(v, decimals = 2) {
101
+ const n = toNum(v);
102
+ if (n === null) return DASH;
103
+ const sign = n < 0 ? "-" : "";
104
+ const abs = Math.abs(n);
105
+ const tiers = moneyTiers(locale);
106
+ for (let i = 0; i < tiers.length; i++) {
107
+ const [threshold, unit] = tiers[i];
108
+ if (abs < threshold) continue;
109
+ const value = Number((abs / threshold).toFixed(decimals));
110
+ const higher = tiers[i - 1];
111
+ if (higher && value * threshold >= higher[0]) {
112
+ return `${sign}${symbol}${group(abs / higher[0], decimals)} ${higher[1]}`;
113
+ }
114
+ return `${sign}${symbol}${group(abs / threshold, decimals)} ${unit}`;
115
+ }
116
+ try {
117
+ return new Intl.NumberFormat(locale, {
118
+ style: "currency",
119
+ currency,
120
+ minimumFractionDigits: Number.isInteger(n) ? 0 : decimals,
121
+ maximumFractionDigits: decimals
122
+ }).format(n);
123
+ } catch {
124
+ return `${sign}${symbol}${group(abs, Number.isInteger(abs) ? 0 : decimals)}`;
125
+ }
126
+ }
127
+ function num(v, decimals) {
128
+ const n = toNum(v);
129
+ if (n === null) return DASH;
130
+ return group(n, decimals ?? (Number.isInteger(n) ? 0 : 2));
131
+ }
132
+ function count(v, decimals = 2) {
133
+ const n = toNum(v);
134
+ if (n === null) return DASH;
135
+ const abs = Math.abs(n);
136
+ const s = abs >= COUNT_SCALE_MIN ? scaled(abs, moneyTiers(locale), decimals) : null;
137
+ if (s) return `${n < 0 ? "-" : ""}${s}`;
138
+ return group(n, Number.isInteger(n) ? 0 : decimals);
139
+ }
140
+ function pct(part, whole, decimals = 1) {
141
+ const p = toNum(part), w = toNum(whole);
142
+ if (p === null || w === null || w === 0) return DASH;
143
+ return `${group(p / w * 100, decimals)}%`;
144
+ }
145
+ function delta(current, previous, decimals = 1) {
146
+ const c = toNum(current), p = toNum(previous);
147
+ if (c === null || p === null || p === 0) return DASH;
148
+ const change = (c - p) / Math.abs(p) * 100;
149
+ return `${change >= 0 ? "+" : "-"}${group(Math.abs(change), decimals)}%`;
150
+ }
151
+ function date(v) {
152
+ const d = toDate(v);
153
+ if (!d) return DASH;
154
+ return `${d.getUTCDate()} ${MONTHS[d.getUTCMonth()]} ${d.getUTCFullYear()}`;
155
+ }
156
+ function range(from, to) {
157
+ const a = toDate(from), b = toDate(to);
158
+ if (!a || !b) return DASH;
159
+ const left = a.getUTCFullYear() === b.getUTCFullYear() ? `${a.getUTCDate()} ${MONTHS[a.getUTCMonth()]}` : date(a);
160
+ return `${left} \u2013 ${date(b)}`;
161
+ }
162
+ function list(items, conjunction = "and") {
163
+ const parts = (items || []).map((i) => String(i ?? "").trim()).filter(Boolean);
164
+ if (!parts.length) return DASH;
165
+ if (parts.length === 1) return parts[0];
166
+ return `${parts.slice(0, -1).join(", ")} ${conjunction} ${parts[parts.length - 1]}`;
167
+ }
168
+ return { money, num, count, pct, delta, date, range, list };
33
169
  }
34
170
 
35
171
  // src/userResponse/scripts/script-bootstrap.ts
@@ -38,8 +174,22 @@ if (!SCRIPT_ARG) {
38
174
  sendError("Bootstrap was invoked without a script path.", "compile");
39
175
  process.exit(1);
40
176
  }
41
- var pending = /* @__PURE__ */ new Map();
177
+ var BRIDGE_URL = process.env.SCRIPT_BRIDGE_URL;
42
178
  var executedQueries = [];
179
+ var toolIdCallCounts = {};
180
+ var PREVIEW_MAX_ROWS = 10;
181
+ var PREVIEW_MAX_CHARS = 200;
182
+ var QUERY_ROW_CAP = 250;
183
+ function previewRows(data) {
184
+ return data.slice(0, PREVIEW_MAX_ROWS).map((row) => {
185
+ if (!row || typeof row !== "object") return row;
186
+ const out = {};
187
+ for (const [k, v] of Object.entries(row)) {
188
+ out[k] = typeof v === "string" && v.length > PREVIEW_MAX_CHARS ? v.slice(0, PREVIEW_MAX_CHARS) + "\u2026" : v;
189
+ }
190
+ return out;
191
+ });
192
+ }
43
193
  var initResolve = null;
44
194
  var initPromise = new Promise((resolve) => {
45
195
  initResolve = resolve;
@@ -48,25 +198,104 @@ function buildCtx(init) {
48
198
  return {
49
199
  now: init.now,
50
200
  async query(toolId, sql) {
51
- const id = shortId();
201
+ if (!BRIDGE_URL) throw new Error("SCRIPT_BRIDGE_URL is not set \u2014 script bridge server is not running");
52
202
  const startedAt = Date.now();
53
- const promise = new Promise((resolve, reject) => {
54
- pending.set(id, { resolve, reject, toolId, sql, startedAt });
203
+ send({ type: "stream", chunk: `
204
+ \u{1F4DD} **Querying ${toolId}:**
205
+ \`\`\`sql
206
+ ${sql}
207
+ \`\`\`
208
+
209
+ ` });
210
+ send({ type: "stream", chunk: `__QUERY_TIMER_START_Executing query__` });
211
+ const res = await fetch(`${BRIDGE_URL}/query`, {
212
+ method: "POST",
213
+ headers: { "content-type": "application/json" },
214
+ body: JSON.stringify({ toolId, sql, limit: QUERY_ROW_CAP })
55
215
  });
56
- send({ type: "query", id, toolId, sql });
57
- const result = await promise;
216
+ const json = await res.json();
58
217
  const executionTimeMs = Date.now() - startedAt;
218
+ send({ type: "stream", chunk: `__QUERY_TIMER_DONE_${(executionTimeMs / 1e3).toFixed(1)}__
219
+
220
+ ` });
221
+ if (!res.ok || !json.success) {
222
+ const errMsg = json.error || `Bridge query failed (${res.status})`;
223
+ send({ type: "stream", chunk: `\u274C **Query failed on ${toolId}:** ${errMsg}
224
+
225
+ ` });
226
+ throw new Error(errMsg);
227
+ }
228
+ let truncated = false;
229
+ let totalCount;
230
+ if (json.metadata?.truncated) {
231
+ truncated = true;
232
+ totalCount = typeof json.metadata.totalCount === "number" ? json.metadata.totalCount : void 0;
233
+ const total = json.metadata.totalCount ?? "more";
234
+ const hasGroupBy = /\bGROUP\s+BY\b/i.test(sql);
235
+ const explicitLimitMatch = sql.match(/\bLIMIT\s+(\d+)/i);
236
+ const hasDeliberateLimit = explicitLimitMatch != null && Number(explicitLimitMatch[1]) < QUERY_ROW_CAP;
237
+ if (hasGroupBy) {
238
+ send({ type: "stream", chunk: `\u2139\uFE0F Only the top ${QUERY_ROW_CAP} of ${total} grouped rows are returned (query is already aggregated via GROUP BY) \u2014 expected for a top-N request.
239
+
240
+ ` });
241
+ } else if (hasDeliberateLimit) {
242
+ send({ type: "stream", chunk: `\u2139\uFE0F Only the ${explicitLimitMatch[1]} rows requested (of ${total} matching) are returned \u2014 expected for a top-N request with an explicit LIMIT.
243
+
244
+ ` });
245
+ } else {
246
+ const msg = `ctx.query truncated the result of this query to ${QUERY_ROW_CAP} rows (it matched ${total}). Do NOT compute over raw rows \u2014 AGGREGATE IN SQL (GROUP BY / mode() / mode(...) FILTER (WHERE \u2026) / COUNT(...) FILTER (\u2026) / CASE) so the query returns the final, already-reduced rows, then have getData return those.`;
247
+ send({ type: "stream", chunk: `\u274C **Result truncated on ${toolId}:** ${msg}
248
+
249
+ ` });
250
+ throw new Error(msg);
251
+ }
252
+ }
253
+ const data = json.data ?? [];
254
+ const count = json.count ?? data.length;
255
+ send({ type: "stream", chunk: `\u2705 **${count} rows from ${toolId}**
256
+
257
+ ` });
258
+ if (data.length > 0) {
259
+ send({ type: "stream", chunk: `<DataTable>${JSON.stringify(previewRows(data))}</DataTable>
260
+
261
+ ` });
262
+ }
263
+ const callNumber = toolIdCallCounts[toolId] = (toolIdCallCounts[toolId] ?? 0) + 1;
264
+ const sourceId = callNumber === 1 ? toolId : `${toolId}#${callNumber}`;
59
265
  executedQueries.push({
60
- sourceId: toolId,
266
+ sourceId,
61
267
  sourceName: toolId,
62
- // parent overwrites with the real name
268
+ // enriched by runner after result arrives
63
269
  sql,
64
- data: result.data,
65
- count: result.count,
66
- totalCount: result.metadata?.totalCount,
270
+ data,
271
+ count,
67
272
  executionTimeMs
68
273
  });
69
- return { data: result.data, count: result.count };
274
+ return { data, count, truncated, totalCount };
275
+ },
276
+ /**
277
+ * Call a tool with structured params (typically a direct tool whose
278
+ * fn(params) does not expect a SQL string). Returns whatever the tool
279
+ * returned — shape is up to the tool.
280
+ *
281
+ * Use this when you need a pre-built business-logic tool (e.g.,
282
+ * "Calculate Shelf Life") that takes structured input rather than SQL.
283
+ * For SQL source tools, keep using ctx.query.
284
+ *
285
+ * runTool results do NOT auto-flow into executedQueries. If you want
286
+ * the result visualised, register it via ctx.emit() after extracting
287
+ * the array you want to chart.
288
+ */
289
+ async runTool(toolId, params = {}) {
290
+ if (!BRIDGE_URL) throw new Error("SCRIPT_BRIDGE_URL is not set \u2014 script bridge server is not running");
291
+ const res = await fetch(`${BRIDGE_URL}/run-tool`, {
292
+ method: "POST",
293
+ headers: { "content-type": "application/json" },
294
+ body: JSON.stringify({ toolId, params })
295
+ });
296
+ const json = await res.json();
297
+ if (!res.ok || !json.success) throw new Error(json.error || `Bridge run-tool failed (${res.status})`);
298
+ return json.result;
70
299
  },
71
300
  /**
72
301
  * Register a computed dataset. Flows into executedQueries alongside
@@ -93,8 +322,33 @@ function buildCtx(init) {
93
322
  }
94
323
  };
95
324
  }
325
+ function guardCtx(ctx) {
326
+ const PASSTHROUGH = /* @__PURE__ */ new Set([
327
+ "then",
328
+ "catch",
329
+ "finally",
330
+ "constructor",
331
+ "toJSON",
332
+ "inspect",
333
+ "valueOf",
334
+ "toString",
335
+ "hasOwnProperty",
336
+ "nodeType"
337
+ ]);
338
+ return new Proxy(ctx, {
339
+ get(target, prop, receiver) {
340
+ if (typeof prop === "symbol" || prop in target || PASSTHROUGH.has(prop)) {
341
+ return Reflect.get(target, prop, receiver);
342
+ }
343
+ const available = Reflect.ownKeys(target).filter((k) => typeof k === "string").join(", ");
344
+ throw new TypeError(
345
+ `ctx.${String(prop)} does not exist. ctx has exactly: ${available}. There are no formatting/parsing/date helpers on ctx \u2014 interpolate ISO date strings straight into the SQL and do date arithmetic in SQL.`
346
+ );
347
+ }
348
+ });
349
+ }
96
350
  function send(msg) {
97
- process.stdout.write(encodeMessage(msg));
351
+ return process.stdout.write(encodeMessage(msg));
98
352
  }
99
353
  function sendError(message, phase, stack) {
100
354
  send({ type: "error", message, stack, phase });
@@ -102,7 +356,15 @@ function sendError(message, phase, stack) {
102
356
  var splitter = new LineSplitter();
103
357
  process.stdin.setEncoding("utf-8");
104
358
  process.stdin.on("data", (chunk) => {
105
- for (const line of splitter.push(chunk)) {
359
+ let lines;
360
+ try {
361
+ lines = splitter.push(chunk);
362
+ } catch (err) {
363
+ const msg = err instanceof Error ? err.message : String(err);
364
+ sendError(msg, "runtime");
365
+ process.exit(1);
366
+ }
367
+ for (const line of lines) {
106
368
  let msg;
107
369
  try {
108
370
  msg = JSON.parse(line);
@@ -112,47 +374,71 @@ process.stdin.on("data", (chunk) => {
112
374
  handleMessage(msg);
113
375
  }
114
376
  });
115
- process.stdin.on("end", () => {
116
- });
117
377
  function handleMessage(msg) {
118
378
  switch (msg.type) {
119
379
  case "init": {
120
380
  if (initResolve) {
121
381
  const now = new Date(msg.now || (/* @__PURE__ */ new Date()).toISOString());
122
382
  const params = restoreParamTypes(msg.params || {}, msg.paramSchema);
123
- initResolve({ params, now });
383
+ initResolve({ params, now, mode: msg.mode, data: msg.data, datasets: msg.datasets, fmt: msg.fmt, entities: msg.entities });
124
384
  initResolve = null;
125
385
  }
126
386
  break;
127
387
  }
128
- case "query_result": {
129
- const entry = pending.get(msg.id);
130
- if (entry) {
131
- pending.delete(msg.id);
132
- entry.resolve({ data: msg.data, count: msg.count, metadata: msg.metadata });
133
- }
134
- break;
388
+ }
389
+ }
390
+ function collectDatasets(queries) {
391
+ const out = {};
392
+ for (const q of queries) {
393
+ if (q.virtual && q.sourceId.startsWith("computed:")) {
394
+ out[q.sourceId.slice("computed:".length)] = q.data;
135
395
  }
136
- case "query_error": {
137
- const entry = pending.get(msg.id);
138
- if (entry) {
139
- pending.delete(msg.id);
140
- entry.reject(new Error(msg.error));
141
- }
142
- break;
396
+ }
397
+ return out;
398
+ }
399
+ async function runComponents(mod, data, params, fmtCfg, datasets = {}, entities = []) {
400
+ const getComponents = mod?.getComponents ?? mod?.default?.getComponents;
401
+ if (typeof getComponents !== "function") return {};
402
+ try {
403
+ const out = await getComponents(data, params, makeFmt(fmtCfg), datasets, entities);
404
+ if (!Array.isArray(out)) {
405
+ return { componentsError: "getComponents must return an ARRAY of component specs" };
406
+ }
407
+ if (out.some((c) => !c || typeof c !== "object")) {
408
+ return { componentsError: "every entry getComponents returns must be a component spec object" };
143
409
  }
410
+ return { components: out };
411
+ } catch (err) {
412
+ const e = err;
413
+ return { componentsError: e?.message || String(err) };
414
+ }
415
+ }
416
+ async function runAnalysis(mod, data, params, fmtCfg, datasets = {}, entities = []) {
417
+ const getAnalysis = mod?.getAnalysis ?? mod?.default?.getAnalysis;
418
+ if (typeof getAnalysis !== "function") return {};
419
+ try {
420
+ const out = await getAnalysis(data, params, makeFmt(fmtCfg), datasets, entities);
421
+ if (!out || typeof out !== "object") {
422
+ return { analysisError: "getAnalysis must return an object with { analysis, summary, method }" };
423
+ }
424
+ return {
425
+ analysis: {
426
+ analysis: typeof out.analysis === "string" ? out.analysis : void 0,
427
+ summary: Array.isArray(out.summary) ? out.summary.map((s) => String(s)) : void 0,
428
+ method: typeof out.method === "string" ? out.method : void 0
429
+ }
430
+ };
431
+ } catch (err) {
432
+ const e = err;
433
+ return { analysisError: e?.message || String(err) };
144
434
  }
145
435
  }
146
436
  (async () => {
437
+ let mod;
147
438
  let getData;
148
439
  try {
149
- const mod = await import(pathToFileURL(SCRIPT_ARG).href);
150
- getData = mod.getData ?? mod.default;
151
- if (typeof getData !== "function") {
152
- throw new Error(
153
- `Script at ${SCRIPT_ARG} does not export getData \u2014 expected \`export async function getData(ctx, params)\``
154
- );
155
- }
440
+ mod = await import(pathToFileURL(SCRIPT_ARG).href);
441
+ getData = mod.getData ?? (typeof mod.default === "function" ? mod.default : mod.default?.getData);
156
442
  } catch (err) {
157
443
  const e = err;
158
444
  sendError(e.message || String(err), "compile", e.stack);
@@ -160,7 +446,33 @@ function handleMessage(msg) {
160
446
  return;
161
447
  }
162
448
  const init = await initPromise;
163
- const ctx = buildCtx(init);
449
+ if (init.mode === "analysis" || init.mode === "components") {
450
+ const started = Date.now();
451
+ const rows = Array.isArray(init.data) ? init.data : [];
452
+ const ds = init.datasets ?? {};
453
+ const authored = init.mode === "analysis" ? await runAnalysis(mod, rows, init.params, init.fmt, ds, init.entities) : await runComponents(mod, rows, init.params, init.fmt, ds, init.entities);
454
+ const flushedAuthored = send({
455
+ type: "result",
456
+ data: [],
457
+ count: rows.length,
458
+ executedQueries: [],
459
+ executionTimeMs: Date.now() - started,
460
+ sampleRows: [],
461
+ ...authored
462
+ });
463
+ if (flushedAuthored) process.exit(0);
464
+ else process.stdout.once("drain", () => process.exit(0));
465
+ return;
466
+ }
467
+ if (typeof getData !== "function") {
468
+ sendError(
469
+ `Script at ${SCRIPT_ARG} does not export getData \u2014 expected \`export async function getData(ctx, params)\``,
470
+ "compile"
471
+ );
472
+ process.exit(1);
473
+ return;
474
+ }
475
+ const ctx = guardCtx(buildCtx(init));
164
476
  const startedAt = Date.now();
165
477
  try {
166
478
  const raw = await getData(ctx, init.params);
@@ -168,17 +480,27 @@ function handleMessage(msg) {
168
480
  const data = normalizeResultData(raw);
169
481
  const count = typeof raw?.count === "number" ? raw.count : data.length;
170
482
  const sampleRows = data.slice(0, 5);
483
+ const ds = collectDatasets(executedQueries);
484
+ const { analysis, analysisError } = await runAnalysis(mod, data, init.params, init.fmt, ds, init.entities);
485
+ const { components, componentsError } = await runComponents(mod, data, init.params, init.fmt, ds, init.entities);
171
486
  const result = {
172
487
  type: "result",
173
488
  data,
174
489
  count,
175
490
  executedQueries,
176
491
  executionTimeMs,
177
- sampleRows
492
+ sampleRows,
493
+ analysis,
494
+ analysisError,
495
+ components,
496
+ componentsError
178
497
  };
179
- send(result);
180
- process.stdout.once("drain", () => process.exit(0));
181
- setImmediate(() => process.exit(0));
498
+ const flushed = send(result);
499
+ if (flushed) {
500
+ process.exit(0);
501
+ } else {
502
+ process.stdout.once("drain", () => process.exit(0));
503
+ }
182
504
  } catch (err) {
183
505
  const e = err;
184
506
  sendError(e.message || String(err), "runtime", e.stack);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@superatomai/sdk-node",
3
- "version": "0.0.2-s",
3
+ "version": "0.0.3-cp",
4
4
  "description": "Node.js TypeScript SDK for Superatom",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -13,7 +13,8 @@
13
13
  }
14
14
  },
15
15
  "files": [
16
- "dist"
16
+ "dist",
17
+ "!dist/**/*.map"
17
18
  ],
18
19
  "keywords": [
19
20
  "superatom",
@@ -29,20 +30,26 @@
29
30
  "tsup": "^8.0.1",
30
31
  "tsx": "^4.20.6",
31
32
  "typescript": "^5.3.3",
32
- "ws": "^8.18.3"
33
+ "ws": "^8.21.0"
33
34
  },
34
35
  "dependencies": {
35
36
  "@anthropic-ai/sdk": "^0.66.0",
37
+ "@earendil-works/pi-coding-agent": "^0.80.3",
36
38
  "@google/generative-ai": "^0.21.0",
37
39
  "groq-sdk": "^0.33.0",
38
40
  "jsonrepair": "^3.13.1",
39
41
  "openai": "^4.77.0",
40
- "ws": "^8.18.3",
42
+ "typebox": "^1.1.38",
43
+ "ws": "^8.21.0",
41
44
  "zod": "^3.25.76"
42
45
  },
46
+ "optionalDependencies": {
47
+ "@openai/codex-sdk": "0.149.1"
48
+ },
43
49
  "scripts": {
44
- "build": "tsup",
50
+ "build": "tsc --noEmit && tsup",
45
51
  "dev": "tsup --watch",
46
- "test": "tsx test-sdk.ts"
52
+ "test": "tsx test-sdk.ts",
53
+ "type-check": "tsc --noEmit"
47
54
  }
48
55
  }