@superatomai/sdk-node 0.0.8-s → 0.0.9-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.
@@ -46,8 +46,126 @@ var LineSplitter = class {
46
46
  return rest;
47
47
  }
48
48
  };
49
- function shortId() {
50
- 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 };
51
169
  }
52
170
 
53
171
  // src/userResponse/scripts/script-bootstrap.ts
@@ -56,8 +174,28 @@ if (!SCRIPT_ARG) {
56
174
  sendError("Bootstrap was invoked without a script path.", "compile");
57
175
  process.exit(1);
58
176
  }
59
- var pending = /* @__PURE__ */ new Map();
177
+ var BRIDGE_URL = process.env.SCRIPT_BRIDGE_URL;
178
+ var CONTEXT_TOKEN = process.env.SA_CONTEXT_TOKEN;
179
+ var observedPolicies = /* @__PURE__ */ new Set();
180
+ var bridgeHeaders = () => ({
181
+ "content-type": "application/json",
182
+ ...CONTEXT_TOKEN ? { "x-sa-context": CONTEXT_TOKEN } : {}
183
+ });
60
184
  var executedQueries = [];
185
+ var toolIdCallCounts = {};
186
+ var PREVIEW_MAX_ROWS = 10;
187
+ var PREVIEW_MAX_CHARS = 200;
188
+ var QUERY_ROW_CAP = 250;
189
+ function previewRows(data) {
190
+ return data.slice(0, PREVIEW_MAX_ROWS).map((row) => {
191
+ if (!row || typeof row !== "object") return row;
192
+ const out = {};
193
+ for (const [k, v] of Object.entries(row)) {
194
+ out[k] = typeof v === "string" && v.length > PREVIEW_MAX_CHARS ? v.slice(0, PREVIEW_MAX_CHARS) + "\u2026" : v;
195
+ }
196
+ return out;
197
+ });
198
+ }
61
199
  var initResolve = null;
62
200
  var initPromise = new Promise((resolve) => {
63
201
  initResolve = resolve;
@@ -66,31 +204,87 @@ function buildCtx(init) {
66
204
  return {
67
205
  now: init.now,
68
206
  async query(toolId, sql) {
69
- const id = shortId();
207
+ if (!BRIDGE_URL) throw new Error("SCRIPT_BRIDGE_URL is not set \u2014 script bridge server is not running");
70
208
  const startedAt = Date.now();
71
- const promise = new Promise((resolve, reject) => {
72
- pending.set(id, { resolve, reject, toolId, sql, startedAt });
209
+ send({ type: "stream", chunk: `
210
+ \u{1F4DD} **Querying ${toolId}:**
211
+ \`\`\`sql
212
+ ${sql}
213
+ \`\`\`
214
+
215
+ ` });
216
+ send({ type: "stream", chunk: `__QUERY_TIMER_START_Executing query__` });
217
+ const res = await fetch(`${BRIDGE_URL}/query`, {
218
+ method: "POST",
219
+ headers: bridgeHeaders(),
220
+ body: JSON.stringify({ toolId, sql, limit: QUERY_ROW_CAP })
73
221
  });
74
- send({ type: "query", id, toolId, sql });
75
- const result = await promise;
222
+ const json = await res.json();
76
223
  const executionTimeMs = Date.now() - startedAt;
224
+ for (const p of json?.metadata?.appliedPolicies ?? []) observedPolicies.add(p);
225
+ send({ type: "stream", chunk: `__QUERY_TIMER_DONE_${(executionTimeMs / 1e3).toFixed(1)}__
226
+
227
+ ` });
228
+ if (!res.ok || !json.success) {
229
+ const errMsg = json.error || `Bridge query failed (${res.status})`;
230
+ send({ type: "stream", chunk: `\u274C **Query failed on ${toolId}:** ${errMsg}
231
+
232
+ ` });
233
+ throw new Error(errMsg);
234
+ }
235
+ let truncated = false;
236
+ let totalCount;
237
+ if (json.metadata?.truncated) {
238
+ truncated = true;
239
+ totalCount = typeof json.metadata.totalCount === "number" ? json.metadata.totalCount : void 0;
240
+ const total = json.metadata.totalCount ?? "more";
241
+ const hasGroupBy = /\bGROUP\s+BY\b/i.test(sql);
242
+ const explicitLimitMatch = sql.match(/\bLIMIT\s+(\d+)/i);
243
+ const hasDeliberateLimit = explicitLimitMatch != null && Number(explicitLimitMatch[1]) < QUERY_ROW_CAP;
244
+ if (hasGroupBy) {
245
+ 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.
246
+
247
+ ` });
248
+ } else if (hasDeliberateLimit) {
249
+ 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.
250
+
251
+ ` });
252
+ } else {
253
+ 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.`;
254
+ send({ type: "stream", chunk: `\u274C **Result truncated on ${toolId}:** ${msg}
255
+
256
+ ` });
257
+ throw new Error(msg);
258
+ }
259
+ }
260
+ const data = json.data ?? [];
261
+ const count = json.count ?? data.length;
262
+ send({ type: "stream", chunk: `\u2705 **${count} rows from ${toolId}**
263
+
264
+ ` });
265
+ if (data.length > 0) {
266
+ send({ type: "stream", chunk: `<DataTable>${JSON.stringify(previewRows(data))}</DataTable>
267
+
268
+ ` });
269
+ }
270
+ const callNumber = toolIdCallCounts[toolId] = (toolIdCallCounts[toolId] ?? 0) + 1;
271
+ const sourceId = callNumber === 1 ? toolId : `${toolId}#${callNumber}`;
77
272
  executedQueries.push({
78
- sourceId: toolId,
273
+ sourceId,
79
274
  sourceName: toolId,
80
- // parent overwrites with the real name
275
+ // enriched by runner after result arrives
81
276
  sql,
82
- data: result.data,
83
- count: result.count,
84
- totalCount: result.metadata?.totalCount,
85
- executionTimeMs
277
+ data,
278
+ count,
279
+ executionTimeMs,
280
+ ...json?.metadata?.appliedPolicies?.length ? { appliedPolicies: json.metadata.appliedPolicies } : {}
86
281
  });
87
- return { data: result.data, count: result.count };
282
+ return { data, count, truncated, totalCount };
88
283
  },
89
284
  /**
90
285
  * Call a tool with structured params (typically a direct tool whose
91
286
  * fn(params) does not expect a SQL string). Returns whatever the tool
92
- * returned — shape is up to the tool. The parent verifies toolId
93
- * against the authorized externalTools list before executing.
287
+ * returned — shape is up to the tool.
94
288
  *
95
289
  * Use this when you need a pre-built business-logic tool (e.g.,
96
290
  * "Calculate Shelf Life") that takes structured input rather than SQL.
@@ -101,18 +295,15 @@ function buildCtx(init) {
101
295
  * the array you want to chart.
102
296
  */
103
297
  async runTool(toolId, params = {}) {
104
- const id = shortId();
105
- const promise = new Promise((resolveResult, rejectResult) => {
106
- pending.set(id, {
107
- resolve: (payload) => resolveResult(payload?.result ?? payload),
108
- reject: rejectResult,
109
- toolId,
110
- sql: `-- runTool: ${toolId}`,
111
- startedAt: Date.now()
112
- });
298
+ if (!BRIDGE_URL) throw new Error("SCRIPT_BRIDGE_URL is not set \u2014 script bridge server is not running");
299
+ const res = await fetch(`${BRIDGE_URL}/run-tool`, {
300
+ method: "POST",
301
+ headers: bridgeHeaders(),
302
+ body: JSON.stringify({ toolId, params })
113
303
  });
114
- send({ type: "run_tool", id, toolId, params });
115
- return promise;
304
+ const json = await res.json();
305
+ if (!res.ok || !json.success) throw new Error(json.error || `Bridge run-tool failed (${res.status})`);
306
+ return json.result;
116
307
  },
117
308
  /**
118
309
  * Register a computed dataset. Flows into executedQueries alongside
@@ -139,18 +330,37 @@ function buildCtx(init) {
139
330
  }
140
331
  };
141
332
  }
333
+ function guardCtx(ctx) {
334
+ const PASSTHROUGH = /* @__PURE__ */ new Set([
335
+ "then",
336
+ "catch",
337
+ "finally",
338
+ "constructor",
339
+ "toJSON",
340
+ "inspect",
341
+ "valueOf",
342
+ "toString",
343
+ "hasOwnProperty",
344
+ "nodeType"
345
+ ]);
346
+ return new Proxy(ctx, {
347
+ get(target, prop, receiver) {
348
+ if (typeof prop === "symbol" || prop in target || PASSTHROUGH.has(prop)) {
349
+ return Reflect.get(target, prop, receiver);
350
+ }
351
+ const available = Reflect.ownKeys(target).filter((k) => typeof k === "string").join(", ");
352
+ throw new TypeError(
353
+ `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.`
354
+ );
355
+ }
356
+ });
357
+ }
142
358
  function send(msg) {
143
- process.stdout.write(encodeMessage(msg));
359
+ return process.stdout.write(encodeMessage(msg));
144
360
  }
145
361
  function sendError(message, phase, stack) {
146
362
  send({ type: "error", message, stack, phase });
147
363
  }
148
- function rejectAllPending(reason) {
149
- for (const [id, entry] of Array.from(pending.entries())) {
150
- pending.delete(id);
151
- entry.reject(new Error(reason));
152
- }
153
- }
154
364
  var splitter = new LineSplitter();
155
365
  process.stdin.setEncoding("utf-8");
156
366
  process.stdin.on("data", (chunk) => {
@@ -159,7 +369,6 @@ process.stdin.on("data", (chunk) => {
159
369
  lines = splitter.push(chunk);
160
370
  } catch (err) {
161
371
  const msg = err instanceof Error ? err.message : String(err);
162
- rejectAllPending(msg);
163
372
  sendError(msg, "runtime");
164
373
  process.exit(1);
165
374
  }
@@ -173,59 +382,71 @@ process.stdin.on("data", (chunk) => {
173
382
  handleMessage(msg);
174
383
  }
175
384
  });
176
- process.stdin.on("end", () => {
177
- rejectAllPending("Parent closed the IPC channel (stdin end) before a query completed.");
178
- });
179
- process.stdin.on("error", (err) => {
180
- rejectAllPending(`IPC channel error before a query completed: ${err.message}`);
181
- });
182
385
  function handleMessage(msg) {
183
386
  switch (msg.type) {
184
387
  case "init": {
185
388
  if (initResolve) {
186
389
  const now = new Date(msg.now || (/* @__PURE__ */ new Date()).toISOString());
187
390
  const params = restoreParamTypes(msg.params || {}, msg.paramSchema);
188
- initResolve({ params, now });
391
+ initResolve({ params, now, mode: msg.mode, data: msg.data, datasets: msg.datasets, fmt: msg.fmt, entities: msg.entities, appliedPolicies: msg.appliedPolicies });
189
392
  initResolve = null;
190
393
  }
191
394
  break;
192
395
  }
193
- case "query_result": {
194
- const entry = pending.get(msg.id);
195
- if (entry) {
196
- pending.delete(msg.id);
197
- entry.resolve({ data: msg.data, count: msg.count, metadata: msg.metadata });
198
- }
199
- break;
396
+ }
397
+ }
398
+ function collectDatasets(queries) {
399
+ const out = {};
400
+ for (const q of queries) {
401
+ if (q.virtual && q.sourceId.startsWith("computed:")) {
402
+ out[q.sourceId.slice("computed:".length)] = q.data;
200
403
  }
201
- case "run_tool_result": {
202
- const entry = pending.get(msg.id);
203
- if (entry) {
204
- pending.delete(msg.id);
205
- entry.resolve({ result: msg.result });
206
- }
207
- break;
404
+ }
405
+ return out;
406
+ }
407
+ async function runComponents(mod, data, params, fmtCfg, datasets = {}, entities = [], scope = []) {
408
+ const getComponents = mod?.getComponents ?? mod?.default?.getComponents;
409
+ if (typeof getComponents !== "function") return {};
410
+ try {
411
+ const out = await getComponents(data, params, makeFmt(fmtCfg), datasets, entities, scope);
412
+ if (!Array.isArray(out)) {
413
+ return { componentsError: "getComponents must return an ARRAY of component specs" };
208
414
  }
209
- case "query_error": {
210
- const entry = pending.get(msg.id);
211
- if (entry) {
212
- pending.delete(msg.id);
213
- entry.reject(new Error(msg.error));
214
- }
215
- break;
415
+ if (out.some((c) => !c || typeof c !== "object")) {
416
+ return { componentsError: "every entry getComponents returns must be a component spec object" };
216
417
  }
418
+ return { components: out };
419
+ } catch (err) {
420
+ const e = err;
421
+ return { componentsError: e?.message || String(err) };
422
+ }
423
+ }
424
+ async function runAnalysis(mod, data, params, fmtCfg, datasets = {}, entities = [], scope = []) {
425
+ const getAnalysis = mod?.getAnalysis ?? mod?.default?.getAnalysis;
426
+ if (typeof getAnalysis !== "function") return {};
427
+ try {
428
+ const out = await getAnalysis(data, params, makeFmt(fmtCfg), datasets, entities, scope);
429
+ if (!out || typeof out !== "object") {
430
+ return { analysisError: "getAnalysis must return an object with { analysis, summary, method }" };
431
+ }
432
+ return {
433
+ analysis: {
434
+ analysis: typeof out.analysis === "string" ? out.analysis : void 0,
435
+ summary: Array.isArray(out.summary) ? out.summary.map((s) => String(s)) : void 0,
436
+ method: typeof out.method === "string" ? out.method : void 0
437
+ }
438
+ };
439
+ } catch (err) {
440
+ const e = err;
441
+ return { analysisError: e?.message || String(err) };
217
442
  }
218
443
  }
219
444
  (async () => {
445
+ let mod;
220
446
  let getData;
221
447
  try {
222
- const mod = await import(pathToFileURL(SCRIPT_ARG).href);
223
- getData = mod.getData ?? mod.default;
224
- if (typeof getData !== "function") {
225
- throw new Error(
226
- `Script at ${SCRIPT_ARG} does not export getData \u2014 expected \`export async function getData(ctx, params)\``
227
- );
228
- }
448
+ mod = await import(pathToFileURL(SCRIPT_ARG).href);
449
+ getData = mod.getData ?? (typeof mod.default === "function" ? mod.default : mod.default?.getData);
229
450
  } catch (err) {
230
451
  const e = err;
231
452
  sendError(e.message || String(err), "compile", e.stack);
@@ -233,7 +454,33 @@ function handleMessage(msg) {
233
454
  return;
234
455
  }
235
456
  const init = await initPromise;
236
- const ctx = buildCtx(init);
457
+ if (init.mode === "analysis" || init.mode === "components") {
458
+ const started = Date.now();
459
+ const rows = Array.isArray(init.data) ? init.data : [];
460
+ const ds = init.datasets ?? {};
461
+ const authored = init.mode === "analysis" ? await runAnalysis(mod, rows, init.params, init.fmt, ds, init.entities, init.appliedPolicies ?? []) : await runComponents(mod, rows, init.params, init.fmt, ds, init.entities, init.appliedPolicies ?? []);
462
+ const flushedAuthored = send({
463
+ type: "result",
464
+ data: [],
465
+ count: rows.length,
466
+ executedQueries: [],
467
+ executionTimeMs: Date.now() - started,
468
+ sampleRows: [],
469
+ ...authored
470
+ });
471
+ if (flushedAuthored) process.exit(0);
472
+ else process.stdout.once("drain", () => process.exit(0));
473
+ return;
474
+ }
475
+ if (typeof getData !== "function") {
476
+ sendError(
477
+ `Script at ${SCRIPT_ARG} does not export getData \u2014 expected \`export async function getData(ctx, params)\``,
478
+ "compile"
479
+ );
480
+ process.exit(1);
481
+ return;
482
+ }
483
+ const ctx = guardCtx(buildCtx(init));
237
484
  const startedAt = Date.now();
238
485
  try {
239
486
  const raw = await getData(ctx, init.params);
@@ -241,17 +488,28 @@ function handleMessage(msg) {
241
488
  const data = normalizeResultData(raw);
242
489
  const count = typeof raw?.count === "number" ? raw.count : data.length;
243
490
  const sampleRows = data.slice(0, 5);
491
+ const ds = collectDatasets(executedQueries);
492
+ const observed = [...observedPolicies];
493
+ const { analysis, analysisError } = await runAnalysis(mod, data, init.params, init.fmt, ds, init.entities, observed);
494
+ const { components, componentsError } = await runComponents(mod, data, init.params, init.fmt, ds, init.entities, observed);
244
495
  const result = {
245
496
  type: "result",
246
497
  data,
247
498
  count,
248
499
  executedQueries,
249
500
  executionTimeMs,
250
- sampleRows
501
+ sampleRows,
502
+ analysis,
503
+ analysisError,
504
+ components,
505
+ componentsError
251
506
  };
252
- send(result);
253
- process.stdout.once("drain", () => process.exit(0));
254
- setImmediate(() => process.exit(0));
507
+ const flushed = send(result);
508
+ if (flushed) {
509
+ process.exit(0);
510
+ } else {
511
+ process.stdout.once("drain", () => process.exit(0));
512
+ }
255
513
  } catch (err) {
256
514
  const e = err;
257
515
  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.8-s",
3
+ "version": "0.0.9-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
  }