@axlsdk/axl 0.1.1 → 0.3.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/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  __require
3
- } from "./chunk-EE2BCC37.js";
3
+ } from "./chunk-JBLQKU6X.js";
4
4
 
5
5
  // src/tool.ts
6
6
  var DEFAULT_MAX_STRING_LENGTH = 1e4;
@@ -102,6 +102,48 @@ function tool(config) {
102
102
  };
103
103
  }
104
104
 
105
+ // src/providers/retry.ts
106
+ var RETRYABLE_STATUS_CODES = /* @__PURE__ */ new Set([429, 503, 529]);
107
+ var MAX_RETRIES = 2;
108
+ var BASE_DELAY_MS = 1e3;
109
+ function sleep2(ms, signal) {
110
+ return new Promise((resolve) => {
111
+ if (signal?.aborted) {
112
+ resolve();
113
+ return;
114
+ }
115
+ const timer = setTimeout(resolve, ms);
116
+ signal?.addEventListener(
117
+ "abort",
118
+ () => {
119
+ clearTimeout(timer);
120
+ resolve();
121
+ },
122
+ { once: true }
123
+ );
124
+ });
125
+ }
126
+ async function fetchWithRetry(input, init, maxRetries = MAX_RETRIES) {
127
+ for (let attempt = 0; ; attempt++) {
128
+ const res = await fetch(input, init);
129
+ if (res.ok || !RETRYABLE_STATUS_CODES.has(res.status) || attempt >= maxRetries) {
130
+ return res;
131
+ }
132
+ if (init?.signal?.aborted) {
133
+ return res;
134
+ }
135
+ const retryAfter = res.headers.get("retry-after");
136
+ let delay;
137
+ if (retryAfter && !isNaN(Number(retryAfter))) {
138
+ delay = Number(retryAfter) * 1e3;
139
+ } else {
140
+ delay = BASE_DELAY_MS * 2 ** attempt;
141
+ }
142
+ delay *= 0.75 + Math.random() * 0.5;
143
+ await sleep2(delay, init?.signal ?? void 0);
144
+ }
145
+ }
146
+
105
147
  // src/providers/openai.ts
106
148
  var OPENAI_PRICING = {
107
149
  "gpt-4o": [25e-7, 1e-5],
@@ -161,7 +203,7 @@ var OpenAIProvider = class {
161
203
  // ---------------------------------------------------------------------------
162
204
  async chat(messages, options) {
163
205
  const body = this.buildRequestBody(messages, options, false);
164
- const res = await fetch(`${this.baseUrl}/chat/completions`, {
206
+ const res = await fetchWithRetry(`${this.baseUrl}/chat/completions`, {
165
207
  method: "POST",
166
208
  headers: {
167
209
  "Content-Type": "application/json",
@@ -209,7 +251,7 @@ var OpenAIProvider = class {
209
251
  // ---------------------------------------------------------------------------
210
252
  async *stream(messages, options) {
211
253
  const body = this.buildRequestBody(messages, options, true);
212
- const res = await fetch(`${this.baseUrl}/chat/completions`, {
254
+ const res = await fetchWithRetry(`${this.baseUrl}/chat/completions`, {
213
255
  method: "POST",
214
256
  headers: {
215
257
  "Content-Type": "application/json",
@@ -368,7 +410,7 @@ var OpenAIResponsesProvider = class {
368
410
  // ---------------------------------------------------------------------------
369
411
  async chat(messages, options) {
370
412
  const body = this.buildRequestBody(messages, options, false);
371
- const res = await fetch(`${this.baseUrl}/responses`, {
413
+ const res = await fetchWithRetry(`${this.baseUrl}/responses`, {
372
414
  method: "POST",
373
415
  headers: {
374
416
  "Content-Type": "application/json",
@@ -390,7 +432,7 @@ var OpenAIResponsesProvider = class {
390
432
  // ---------------------------------------------------------------------------
391
433
  async *stream(messages, options) {
392
434
  const body = this.buildRequestBody(messages, options, true);
393
- const res = await fetch(`${this.baseUrl}/responses`, {
435
+ const res = await fetchWithRetry(`${this.baseUrl}/responses`, {
394
436
  method: "POST",
395
437
  headers: {
396
438
  "Content-Type": "application/json",
@@ -702,7 +744,7 @@ var AnthropicProvider = class {
702
744
  async chat(messages, options) {
703
745
  this.currentModel = options.model;
704
746
  const body = this.buildRequestBody(messages, options, false);
705
- const res = await fetch(`${this.baseUrl}/messages`, {
747
+ const res = await fetchWithRetry(`${this.baseUrl}/messages`, {
706
748
  method: "POST",
707
749
  headers: this.buildHeaders(),
708
750
  body: JSON.stringify(body),
@@ -721,7 +763,7 @@ var AnthropicProvider = class {
721
763
  // ---------------------------------------------------------------------------
722
764
  async *stream(messages, options) {
723
765
  const body = this.buildRequestBody(messages, options, true);
724
- const res = await fetch(`${this.baseUrl}/messages`, {
766
+ const res = await fetchWithRetry(`${this.baseUrl}/messages`, {
725
767
  method: "POST",
726
768
  headers: this.buildHeaders(),
727
769
  body: JSON.stringify(body),
@@ -1072,7 +1114,7 @@ var GeminiProvider = class {
1072
1114
  // ---------------------------------------------------------------------------
1073
1115
  async chat(messages, options) {
1074
1116
  const body = this.buildRequestBody(messages, options);
1075
- const res = await fetch(`${this.baseUrl}/models/${options.model}:generateContent`, {
1117
+ const res = await fetchWithRetry(`${this.baseUrl}/models/${options.model}:generateContent`, {
1076
1118
  method: "POST",
1077
1119
  headers: this.buildHeaders(),
1078
1120
  body: JSON.stringify(body),
@@ -1091,7 +1133,7 @@ var GeminiProvider = class {
1091
1133
  // ---------------------------------------------------------------------------
1092
1134
  async *stream(messages, options) {
1093
1135
  const body = this.buildRequestBody(messages, options);
1094
- const res = await fetch(
1136
+ const res = await fetchWithRetry(
1095
1137
  `${this.baseUrl}/models/${options.model}:streamGenerateContent?alt=sse`,
1096
1138
  {
1097
1139
  method: "POST",
@@ -2173,7 +2215,8 @@ Please fix and try again.`;
2173
2215
  span.setAttribute("axl.tool.duration", Date.now() - toolStart2);
2174
2216
  const isError = r && typeof r === "object" && "error" in r;
2175
2217
  span.setAttribute("axl.tool.success", !isError);
2176
- if (isError) span.setStatus("error", r.error);
2218
+ if (isError)
2219
+ span.setStatus("error", r.error);
2177
2220
  return r;
2178
2221
  }
2179
2222
  ) : await executeOverride();
@@ -2285,7 +2328,9 @@ Please fix and try again.`;
2285
2328
  try {
2286
2329
  const mcpResult = await this.mcpManager.callTool(toolName, toolArgs);
2287
2330
  toolResult2 = mcpResult;
2288
- resultContent2 = mcpResult.content.map((c) => c.type === "text" ? c.text : `[${c.type}]`).join("\n");
2331
+ resultContent2 = mcpResult.content.map(
2332
+ (c) => c.type === "text" ? c.text : `[${c.type}]`
2333
+ ).join("\n");
2289
2334
  if (mcpResult.isError) {
2290
2335
  resultContent2 = `Error: ${resultContent2}`;
2291
2336
  }
@@ -2327,7 +2372,11 @@ Please fix and try again.`;
2327
2372
  span.setAttribute("axl.tool.duration", Date.now() - toolStart);
2328
2373
  const isError = r.toolResult && typeof r.toolResult === "object" && "error" in r.toolResult;
2329
2374
  span.setAttribute("axl.tool.success", !isError);
2330
- if (isError) span.setStatus("error", r.toolResult.error);
2375
+ if (isError)
2376
+ span.setStatus(
2377
+ "error",
2378
+ r.toolResult.error
2379
+ );
2331
2380
  return r;
2332
2381
  }
2333
2382
  ) : await executeTool();
@@ -3306,6 +3355,10 @@ var MemoryStore = class {
3306
3355
  async deleteMemory(scope, key) {
3307
3356
  this.memories.get(scope)?.delete(key);
3308
3357
  }
3358
+ // ── Sessions (Studio introspection) ─────────────────────────────────
3359
+ async listSessions() {
3360
+ return [...this.sessions.keys()];
3361
+ }
3309
3362
  // ── Lifecycle ──────────────────────────────────────────────────────
3310
3363
  async close() {
3311
3364
  }
@@ -3534,6 +3587,11 @@ var SQLiteStore = class {
3534
3587
  const rows = stmt.all();
3535
3588
  return rows.map((r) => r.execution_id);
3536
3589
  }
3590
+ // ── Sessions (Studio introspection) ────────────────────────────────────
3591
+ async listSessions() {
3592
+ const rows = this.db.prepare("SELECT session_id FROM sessions").all();
3593
+ return rows.map((r) => r.session_id);
3594
+ }
3537
3595
  // ── Memory ────────────────────────────────────────────────────────────
3538
3596
  async saveMemory(scope, key, value) {
3539
3597
  this.db.prepare(
@@ -3567,7 +3625,8 @@ var RedisStore = class {
3567
3625
  constructor(url) {
3568
3626
  let Redis;
3569
3627
  try {
3570
- Redis = __require("ioredis").default ?? __require("ioredis");
3628
+ const mod = __require("ioredis");
3629
+ Redis = mod.default ?? mod;
3571
3630
  } catch {
3572
3631
  throw new Error("ioredis is required for RedisStore. Install it with: npm install ioredis");
3573
3632
  }
@@ -3617,6 +3676,7 @@ var RedisStore = class {
3617
3676
  // ── Sessions ─────────────────────────────────────────────────────────
3618
3677
  async saveSession(sessionId, history) {
3619
3678
  await this.client.set(this.sessionKey(sessionId), JSON.stringify(history));
3679
+ await this.client.sadd("axl:session-ids", sessionId);
3620
3680
  }
3621
3681
  async getSession(sessionId) {
3622
3682
  const raw = await this.client.get(this.sessionKey(sessionId));
@@ -3625,6 +3685,7 @@ var RedisStore = class {
3625
3685
  async deleteSession(sessionId) {
3626
3686
  await this.client.del(this.sessionKey(sessionId));
3627
3687
  await this.client.del(this.sessionMetaKey(sessionId));
3688
+ await this.client.srem("axl:session-ids", sessionId);
3628
3689
  }
3629
3690
  async saveSessionMeta(sessionId, key, value) {
3630
3691
  await this.client.hset(this.sessionMetaKey(sessionId), key, JSON.stringify(value));
@@ -3661,6 +3722,10 @@ var RedisStore = class {
3661
3722
  async listPendingExecutions() {
3662
3723
  return this.client.smembers(this.pendingExecSetKey());
3663
3724
  }
3725
+ // ── Sessions (Studio introspection) ────────────────────────────────────
3726
+ async listSessions() {
3727
+ return this.client.smembers("axl:session-ids");
3728
+ }
3664
3729
  /** Close the Redis connection. */
3665
3730
  async close() {
3666
3731
  await this.client.quit();
@@ -4489,7 +4554,7 @@ async function createSpanManager(config) {
4489
4554
  if (!config?.enabled) {
4490
4555
  return new NoopSpanManager();
4491
4556
  }
4492
- const { OTelSpanManager: OTelSpanManager2 } = await import("./span-manager-LGX7QHZ7.js");
4557
+ const { OTelSpanManager: OTelSpanManager2 } = await import("./span-manager-3IKXXUTZ.js");
4493
4558
  return OTelSpanManager2.create(config);
4494
4559
  }
4495
4560
 
@@ -4505,11 +4570,14 @@ function hashInput(input) {
4505
4570
  var AxlRuntime = class extends EventEmitter2 {
4506
4571
  config;
4507
4572
  workflows = /* @__PURE__ */ new Map();
4573
+ tools = /* @__PURE__ */ new Map();
4574
+ agents = /* @__PURE__ */ new Map();
4508
4575
  providerRegistry;
4509
4576
  stateStore;
4510
4577
  executions = /* @__PURE__ */ new Map();
4511
4578
  pendingDecisionResolvers = /* @__PURE__ */ new Map();
4512
4579
  abortControllers = /* @__PURE__ */ new Map();
4580
+ registeredEvals = /* @__PURE__ */ new Map();
4513
4581
  mcpManager;
4514
4582
  memoryManager;
4515
4583
  spanManager = new NoopSpanManager();
@@ -4559,9 +4627,102 @@ var AxlRuntime = class extends EventEmitter2 {
4559
4627
  }
4560
4628
  }
4561
4629
  /** Register a workflow with the runtime. */
4630
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
4562
4631
  register(workflow2) {
4563
4632
  this.workflows.set(workflow2.name, workflow2);
4564
4633
  }
4634
+ /** Register standalone tools for Studio introspection and direct testing. */
4635
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
4636
+ registerTool(...tools) {
4637
+ for (const t of tools) {
4638
+ this.tools.set(t.name, t);
4639
+ }
4640
+ }
4641
+ /** Register standalone agents for Studio playground and introspection. */
4642
+ registerAgent(...agents) {
4643
+ for (const a of agents) {
4644
+ this.agents.set(a._name, a);
4645
+ }
4646
+ }
4647
+ // ── Introspection (used by Studio) ────────────────────────────────
4648
+ /** Get all registered workflow names. */
4649
+ getWorkflowNames() {
4650
+ return [...this.workflows.keys()];
4651
+ }
4652
+ /** Get a registered workflow by name. */
4653
+ getWorkflow(name) {
4654
+ return this.workflows.get(name);
4655
+ }
4656
+ /** Get all registered workflows. */
4657
+ getWorkflows() {
4658
+ return [...this.workflows.values()];
4659
+ }
4660
+ /** Get all registered standalone tools. */
4661
+ getTools() {
4662
+ return [...this.tools.values()];
4663
+ }
4664
+ /** Get a registered standalone tool by name. */
4665
+ getTool(name) {
4666
+ return this.tools.get(name);
4667
+ }
4668
+ /** Get all registered standalone agents. */
4669
+ getAgents() {
4670
+ return [...this.agents.values()];
4671
+ }
4672
+ /** Get a registered standalone agent by name. */
4673
+ getAgent(name) {
4674
+ return this.agents.get(name);
4675
+ }
4676
+ /**
4677
+ * Register an eval config for Studio introspection and execution.
4678
+ * The config should be the result of `defineEval()` from `@axlsdk/eval`.
4679
+ * An optional `executeWorkflow` function can override the default behavior
4680
+ * of calling `runtime.execute()`.
4681
+ */
4682
+ registerEval(name, config, executeWorkflow) {
4683
+ this.registeredEvals.set(name, { config, executeWorkflow });
4684
+ }
4685
+ /** Get metadata about all registered evals. */
4686
+ getRegisteredEvals() {
4687
+ const result = [];
4688
+ for (const [name, { config }] of this.registeredEvals) {
4689
+ const cfg = config;
4690
+ result.push({
4691
+ name,
4692
+ workflow: cfg.workflow ?? "unknown",
4693
+ dataset: cfg.dataset?.name ?? "unknown",
4694
+ scorers: (cfg.scorers ?? []).map((s) => s.name ?? "unknown")
4695
+ });
4696
+ }
4697
+ return result;
4698
+ }
4699
+ /** Get a registered eval config by name. */
4700
+ getRegisteredEval(name) {
4701
+ return this.registeredEvals.get(name);
4702
+ }
4703
+ /** Run a registered eval by name. */
4704
+ async runRegisteredEval(name) {
4705
+ const entry = this.registeredEvals.get(name);
4706
+ if (!entry) throw new Error(`Eval "${name}" is not registered`);
4707
+ if (entry.executeWorkflow) {
4708
+ let runEvalFn;
4709
+ try {
4710
+ ({ runEval: runEvalFn } = await import("@axlsdk/eval"));
4711
+ } catch {
4712
+ throw new Error(
4713
+ "axl-eval is required for AxlRuntime.runRegisteredEval(). Install it with: npm install @axlsdk/eval"
4714
+ );
4715
+ }
4716
+ return runEvalFn(entry.config, entry.executeWorkflow);
4717
+ }
4718
+ return this.eval(
4719
+ entry.config
4720
+ );
4721
+ }
4722
+ /** Get all execution info (running + completed). */
4723
+ getExecutions() {
4724
+ return [...this.executions.values()];
4725
+ }
4565
4726
  /** Register a custom provider instance. */
4566
4727
  registerProvider(name, provider) {
4567
4728
  this.providerRegistry.registerInstance(name, provider);
@@ -4941,10 +5102,10 @@ var AxlRuntime = class extends EventEmitter2 {
4941
5102
  async eval(config) {
4942
5103
  let runEval;
4943
5104
  try {
4944
- ({ runEval } = await import("axl-eval"));
5105
+ ({ runEval } = await import("@axlsdk/eval"));
4945
5106
  } catch {
4946
5107
  throw new Error(
4947
- "axl-eval is required for AxlRuntime.eval(). Install it with: npm install axl-eval"
5108
+ "axl-eval is required for AxlRuntime.eval(). Install it with: npm install @axlsdk/eval"
4948
5109
  );
4949
5110
  }
4950
5111
  const executeWorkflow = async (input) => {
@@ -4971,10 +5132,10 @@ var AxlRuntime = class extends EventEmitter2 {
4971
5132
  async evalCompare(baseline, candidate) {
4972
5133
  let evalCompareFn;
4973
5134
  try {
4974
- ({ evalCompare: evalCompareFn } = await import("axl-eval"));
5135
+ ({ evalCompare: evalCompareFn } = await import("@axlsdk/eval"));
4975
5136
  } catch {
4976
5137
  throw new Error(
4977
- "axl-eval is required for AxlRuntime.evalCompare(). Install it with: npm install axl-eval"
5138
+ "axl-eval is required for AxlRuntime.evalCompare(). Install it with: npm install @axlsdk/eval"
4978
5139
  );
4979
5140
  }
4980
5141
  return evalCompareFn(baseline, candidate);
@@ -5260,6 +5421,7 @@ export {
5260
5421
  createSpanManager,
5261
5422
  defineConfig,
5262
5423
  tool,
5263
- workflow
5424
+ workflow,
5425
+ zodToJsonSchema
5264
5426
  };
5265
5427
  //# sourceMappingURL=index.js.map