@axlsdk/axl 0.6.0 → 0.7.1

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.d.cts CHANGED
@@ -462,6 +462,63 @@ type Agent = {
462
462
  */
463
463
  declare function agent(config: AgentConfig): Agent;
464
464
 
465
+ /** A pending human decision awaiting resolution. */
466
+ type PendingDecision = {
467
+ executionId: string;
468
+ channel: string;
469
+ prompt: string;
470
+ metadata?: Record<string, unknown>;
471
+ createdAt: string;
472
+ };
473
+ /** Persisted execution state for suspend/resume. */
474
+ type ExecutionState = {
475
+ workflow: string;
476
+ input: unknown;
477
+ step: number;
478
+ status: 'waiting' | 'running';
479
+ metadata?: Record<string, unknown>;
480
+ };
481
+ /**
482
+ * Pluggable state persistence interface.
483
+ *
484
+ * Built-in implementations: MemoryStore (testing), SQLiteStore (file-based),
485
+ * Redis (production).
486
+ */
487
+ interface StateStore {
488
+ saveCheckpoint(executionId: string, step: number, data: unknown): Promise<void>;
489
+ getCheckpoint(executionId: string, step: number): Promise<unknown | null>;
490
+ getLatestCheckpoint(executionId: string): Promise<{
491
+ step: number;
492
+ data: unknown;
493
+ } | null>;
494
+ saveSession(sessionId: string, history: ChatMessage[]): Promise<void>;
495
+ getSession(sessionId: string): Promise<ChatMessage[]>;
496
+ deleteSession(sessionId: string): Promise<void>;
497
+ saveSessionMeta(sessionId: string, key: string, value: unknown): Promise<void>;
498
+ getSessionMeta(sessionId: string, key: string): Promise<unknown | null>;
499
+ savePendingDecision(executionId: string, decision: PendingDecision): Promise<void>;
500
+ getPendingDecisions(): Promise<PendingDecision[]>;
501
+ resolveDecision(executionId: string, result: HumanDecision): Promise<void>;
502
+ saveExecutionState(executionId: string, state: ExecutionState): Promise<void>;
503
+ getExecutionState(executionId: string): Promise<ExecutionState | null>;
504
+ listPendingExecutions(): Promise<string[]>;
505
+ /** Save a memory entry (key-value). */
506
+ saveMemory?(scope: string, key: string, value: unknown): Promise<void>;
507
+ /** Get a memory entry by key. */
508
+ getMemory?(scope: string, key: string): Promise<unknown | null>;
509
+ /** Get all memory entries for a scope. */
510
+ getAllMemory?(scope: string): Promise<Array<{
511
+ key: string;
512
+ value: unknown;
513
+ }>>;
514
+ /** Delete a memory entry by key. */
515
+ deleteMemory?(scope: string, key: string): Promise<void>;
516
+ /** List all session IDs (used by Studio session browser). */
517
+ listSessions?(): Promise<string[]>;
518
+ close?(): Promise<void>;
519
+ deleteCheckpoints?(executionId: string): Promise<void>;
520
+ }
521
+
465
522
  /** Configuration for OpenTelemetry integration. */
466
523
  type TelemetryConfig = {
467
524
  /** Whether telemetry is enabled. Defaults to false. */
@@ -560,15 +617,13 @@ type TraceConfig = {
560
617
  /** When true, redact prompt/response data from agent_call trace events to prevent PII leakage. */
561
618
  redact?: boolean;
562
619
  };
620
+
563
621
  /** State store configuration */
564
622
  type StateConfig = {
565
- store?: 'memory' | 'sqlite' | 'redis';
623
+ store?: StateStore | 'memory' | 'sqlite';
566
624
  sqlite?: {
567
625
  path: string;
568
626
  };
569
- redis?: {
570
- url: string;
571
- };
572
627
  };
573
628
  /** Global defaults */
574
629
  type DefaultsConfig = {
@@ -680,63 +735,6 @@ declare class ProviderRegistry {
680
735
  clearFactories(): void;
681
736
  }
682
737
 
683
- /** A pending human decision awaiting resolution. */
684
- type PendingDecision = {
685
- executionId: string;
686
- channel: string;
687
- prompt: string;
688
- metadata?: Record<string, unknown>;
689
- createdAt: string;
690
- };
691
- /** Persisted execution state for suspend/resume. */
692
- type ExecutionState = {
693
- workflow: string;
694
- input: unknown;
695
- step: number;
696
- status: 'waiting' | 'running';
697
- metadata?: Record<string, unknown>;
698
- };
699
- /**
700
- * Pluggable state persistence interface.
701
- *
702
- * Built-in implementations: MemoryStore (testing), SQLiteStore (file-based),
703
- * Redis (production).
704
- */
705
- interface StateStore {
706
- saveCheckpoint(executionId: string, step: number, data: unknown): Promise<void>;
707
- getCheckpoint(executionId: string, step: number): Promise<unknown | null>;
708
- getLatestCheckpoint(executionId: string): Promise<{
709
- step: number;
710
- data: unknown;
711
- } | null>;
712
- saveSession(sessionId: string, history: ChatMessage[]): Promise<void>;
713
- getSession(sessionId: string): Promise<ChatMessage[]>;
714
- deleteSession(sessionId: string): Promise<void>;
715
- saveSessionMeta(sessionId: string, key: string, value: unknown): Promise<void>;
716
- getSessionMeta(sessionId: string, key: string): Promise<unknown | null>;
717
- savePendingDecision(executionId: string, decision: PendingDecision): Promise<void>;
718
- getPendingDecisions(): Promise<PendingDecision[]>;
719
- resolveDecision(executionId: string, result: HumanDecision): Promise<void>;
720
- saveExecutionState(executionId: string, state: ExecutionState): Promise<void>;
721
- getExecutionState(executionId: string): Promise<ExecutionState | null>;
722
- listPendingExecutions(): Promise<string[]>;
723
- /** Save a memory entry (key-value). */
724
- saveMemory?(scope: string, key: string, value: unknown): Promise<void>;
725
- /** Get a memory entry by key. */
726
- getMemory?(scope: string, key: string): Promise<unknown | null>;
727
- /** Get all memory entries for a scope. */
728
- getAllMemory?(scope: string): Promise<Array<{
729
- key: string;
730
- value: unknown;
731
- }>>;
732
- /** Delete a memory entry by key. */
733
- deleteMemory?(scope: string, key: string): Promise<void>;
734
- /** List all session IDs (used by Studio session browser). */
735
- listSessions?(): Promise<string[]>;
736
- close?(): Promise<void>;
737
- deleteCheckpoints?(executionId: string): Promise<void>;
738
- }
739
-
740
738
  /**
741
739
  * MCP (Model Context Protocol) types for tool discovery and execution.
742
740
  */
@@ -1688,17 +1686,23 @@ declare class SQLiteStore implements StateStore {
1688
1686
  }
1689
1687
 
1690
1688
  /**
1691
- * Redis-backed StateStore using ioredis.
1689
+ * Redis-backed StateStore using the official `redis` (node-redis) client.
1692
1690
  *
1693
1691
  * Designed for multi-process and sidecar deployments where
1694
1692
  * multiple runtime instances need shared state.
1695
1693
  *
1696
- * Requires `ioredis` as a peer dependency. If not installed,
1697
- * the constructor throws a clear error message.
1694
+ * Requires `redis` as a peer dependency. Create instances via the
1695
+ * async `RedisStore.create()` factory, which connects before returning.
1698
1696
  */
1699
1697
  declare class RedisStore implements StateStore {
1700
1698
  private client;
1701
- constructor(url?: string);
1699
+ private constructor();
1700
+ /**
1701
+ * Create a connected RedisStore instance.
1702
+ *
1703
+ * @param url - Redis connection URL (e.g. `redis://localhost:6379`). Defaults to `redis://localhost:6379`.
1704
+ */
1705
+ static create(url?: string): Promise<RedisStore>;
1702
1706
  private checkpointKey;
1703
1707
  private sessionKey;
1704
1708
  private sessionMetaKey;
package/dist/index.d.ts CHANGED
@@ -462,6 +462,63 @@ type Agent = {
462
462
  */
463
463
  declare function agent(config: AgentConfig): Agent;
464
464
 
465
+ /** A pending human decision awaiting resolution. */
466
+ type PendingDecision = {
467
+ executionId: string;
468
+ channel: string;
469
+ prompt: string;
470
+ metadata?: Record<string, unknown>;
471
+ createdAt: string;
472
+ };
473
+ /** Persisted execution state for suspend/resume. */
474
+ type ExecutionState = {
475
+ workflow: string;
476
+ input: unknown;
477
+ step: number;
478
+ status: 'waiting' | 'running';
479
+ metadata?: Record<string, unknown>;
480
+ };
481
+ /**
482
+ * Pluggable state persistence interface.
483
+ *
484
+ * Built-in implementations: MemoryStore (testing), SQLiteStore (file-based),
485
+ * Redis (production).
486
+ */
487
+ interface StateStore {
488
+ saveCheckpoint(executionId: string, step: number, data: unknown): Promise<void>;
489
+ getCheckpoint(executionId: string, step: number): Promise<unknown | null>;
490
+ getLatestCheckpoint(executionId: string): Promise<{
491
+ step: number;
492
+ data: unknown;
493
+ } | null>;
494
+ saveSession(sessionId: string, history: ChatMessage[]): Promise<void>;
495
+ getSession(sessionId: string): Promise<ChatMessage[]>;
496
+ deleteSession(sessionId: string): Promise<void>;
497
+ saveSessionMeta(sessionId: string, key: string, value: unknown): Promise<void>;
498
+ getSessionMeta(sessionId: string, key: string): Promise<unknown | null>;
499
+ savePendingDecision(executionId: string, decision: PendingDecision): Promise<void>;
500
+ getPendingDecisions(): Promise<PendingDecision[]>;
501
+ resolveDecision(executionId: string, result: HumanDecision): Promise<void>;
502
+ saveExecutionState(executionId: string, state: ExecutionState): Promise<void>;
503
+ getExecutionState(executionId: string): Promise<ExecutionState | null>;
504
+ listPendingExecutions(): Promise<string[]>;
505
+ /** Save a memory entry (key-value). */
506
+ saveMemory?(scope: string, key: string, value: unknown): Promise<void>;
507
+ /** Get a memory entry by key. */
508
+ getMemory?(scope: string, key: string): Promise<unknown | null>;
509
+ /** Get all memory entries for a scope. */
510
+ getAllMemory?(scope: string): Promise<Array<{
511
+ key: string;
512
+ value: unknown;
513
+ }>>;
514
+ /** Delete a memory entry by key. */
515
+ deleteMemory?(scope: string, key: string): Promise<void>;
516
+ /** List all session IDs (used by Studio session browser). */
517
+ listSessions?(): Promise<string[]>;
518
+ close?(): Promise<void>;
519
+ deleteCheckpoints?(executionId: string): Promise<void>;
520
+ }
521
+
465
522
  /** Configuration for OpenTelemetry integration. */
466
523
  type TelemetryConfig = {
467
524
  /** Whether telemetry is enabled. Defaults to false. */
@@ -560,15 +617,13 @@ type TraceConfig = {
560
617
  /** When true, redact prompt/response data from agent_call trace events to prevent PII leakage. */
561
618
  redact?: boolean;
562
619
  };
620
+
563
621
  /** State store configuration */
564
622
  type StateConfig = {
565
- store?: 'memory' | 'sqlite' | 'redis';
623
+ store?: StateStore | 'memory' | 'sqlite';
566
624
  sqlite?: {
567
625
  path: string;
568
626
  };
569
- redis?: {
570
- url: string;
571
- };
572
627
  };
573
628
  /** Global defaults */
574
629
  type DefaultsConfig = {
@@ -680,63 +735,6 @@ declare class ProviderRegistry {
680
735
  clearFactories(): void;
681
736
  }
682
737
 
683
- /** A pending human decision awaiting resolution. */
684
- type PendingDecision = {
685
- executionId: string;
686
- channel: string;
687
- prompt: string;
688
- metadata?: Record<string, unknown>;
689
- createdAt: string;
690
- };
691
- /** Persisted execution state for suspend/resume. */
692
- type ExecutionState = {
693
- workflow: string;
694
- input: unknown;
695
- step: number;
696
- status: 'waiting' | 'running';
697
- metadata?: Record<string, unknown>;
698
- };
699
- /**
700
- * Pluggable state persistence interface.
701
- *
702
- * Built-in implementations: MemoryStore (testing), SQLiteStore (file-based),
703
- * Redis (production).
704
- */
705
- interface StateStore {
706
- saveCheckpoint(executionId: string, step: number, data: unknown): Promise<void>;
707
- getCheckpoint(executionId: string, step: number): Promise<unknown | null>;
708
- getLatestCheckpoint(executionId: string): Promise<{
709
- step: number;
710
- data: unknown;
711
- } | null>;
712
- saveSession(sessionId: string, history: ChatMessage[]): Promise<void>;
713
- getSession(sessionId: string): Promise<ChatMessage[]>;
714
- deleteSession(sessionId: string): Promise<void>;
715
- saveSessionMeta(sessionId: string, key: string, value: unknown): Promise<void>;
716
- getSessionMeta(sessionId: string, key: string): Promise<unknown | null>;
717
- savePendingDecision(executionId: string, decision: PendingDecision): Promise<void>;
718
- getPendingDecisions(): Promise<PendingDecision[]>;
719
- resolveDecision(executionId: string, result: HumanDecision): Promise<void>;
720
- saveExecutionState(executionId: string, state: ExecutionState): Promise<void>;
721
- getExecutionState(executionId: string): Promise<ExecutionState | null>;
722
- listPendingExecutions(): Promise<string[]>;
723
- /** Save a memory entry (key-value). */
724
- saveMemory?(scope: string, key: string, value: unknown): Promise<void>;
725
- /** Get a memory entry by key. */
726
- getMemory?(scope: string, key: string): Promise<unknown | null>;
727
- /** Get all memory entries for a scope. */
728
- getAllMemory?(scope: string): Promise<Array<{
729
- key: string;
730
- value: unknown;
731
- }>>;
732
- /** Delete a memory entry by key. */
733
- deleteMemory?(scope: string, key: string): Promise<void>;
734
- /** List all session IDs (used by Studio session browser). */
735
- listSessions?(): Promise<string[]>;
736
- close?(): Promise<void>;
737
- deleteCheckpoints?(executionId: string): Promise<void>;
738
- }
739
-
740
738
  /**
741
739
  * MCP (Model Context Protocol) types for tool discovery and execution.
742
740
  */
@@ -1688,17 +1686,23 @@ declare class SQLiteStore implements StateStore {
1688
1686
  }
1689
1687
 
1690
1688
  /**
1691
- * Redis-backed StateStore using ioredis.
1689
+ * Redis-backed StateStore using the official `redis` (node-redis) client.
1692
1690
  *
1693
1691
  * Designed for multi-process and sidecar deployments where
1694
1692
  * multiple runtime instances need shared state.
1695
1693
  *
1696
- * Requires `ioredis` as a peer dependency. If not installed,
1697
- * the constructor throws a clear error message.
1694
+ * Requires `redis` as a peer dependency. Create instances via the
1695
+ * async `RedisStore.create()` factory, which connects before returning.
1698
1696
  */
1699
1697
  declare class RedisStore implements StateStore {
1700
1698
  private client;
1701
- constructor(url?: string);
1699
+ private constructor();
1700
+ /**
1701
+ * Create a connected RedisStore instance.
1702
+ *
1703
+ * @param url - Redis connection URL (e.g. `redis://localhost:6379`). Defaults to `redis://localhost:6379`.
1704
+ */
1705
+ static create(url?: string): Promise<RedisStore>;
1702
1706
  private checkpointKey;
1703
1707
  private sessionKey;
1704
1708
  private sessionMetaKey;
package/dist/index.js CHANGED
@@ -1983,10 +1983,13 @@ function resolveConfig(config) {
1983
1983
  resolved.defaultProvider = process.env.AXL_DEFAULT_PROVIDER;
1984
1984
  }
1985
1985
  if (process.env.AXL_STATE_STORE) {
1986
- resolved.state = {
1987
- ...resolved.state,
1988
- store: process.env.AXL_STATE_STORE
1989
- };
1986
+ const envStore = process.env.AXL_STATE_STORE;
1987
+ if (envStore === "memory" || envStore === "sqlite") {
1988
+ resolved.state = {
1989
+ ...resolved.state,
1990
+ store: envStore
1991
+ };
1992
+ }
1990
1993
  }
1991
1994
  if (process.env.AXL_TRACE_ENABLED !== void 0) {
1992
1995
  resolved.trace = { ...resolved.trace, enabled: process.env.AXL_TRACE_ENABLED === "true" };
@@ -4113,122 +4116,6 @@ var SQLiteStore = class {
4113
4116
  }
4114
4117
  };
4115
4118
 
4116
- // src/state/redis.ts
4117
- var RedisStore = class {
4118
- client;
4119
- constructor(url) {
4120
- let Redis;
4121
- try {
4122
- const mod = __require("ioredis");
4123
- Redis = mod.default ?? mod;
4124
- } catch {
4125
- throw new Error("ioredis is required for RedisStore. Install it with: npm install ioredis");
4126
- }
4127
- this.client = url ? new Redis(url) : new Redis();
4128
- }
4129
- // ── Key helpers ──────────────────────────────────────────────────────
4130
- checkpointKey(executionId) {
4131
- return `axl:checkpoint:${executionId}`;
4132
- }
4133
- sessionKey(sessionId) {
4134
- return `axl:session:${sessionId}`;
4135
- }
4136
- sessionMetaKey(sessionId) {
4137
- return `axl:session-meta:${sessionId}`;
4138
- }
4139
- decisionsKey() {
4140
- return "axl:decisions";
4141
- }
4142
- executionStateKey(executionId) {
4143
- return `axl:exec-state:${executionId}`;
4144
- }
4145
- pendingExecSetKey() {
4146
- return "axl:pending-executions";
4147
- }
4148
- // ── Checkpoints ──────────────────────────────────────────────────────
4149
- async saveCheckpoint(executionId, step, data) {
4150
- await this.client.hset(this.checkpointKey(executionId), String(step), JSON.stringify(data));
4151
- }
4152
- async getCheckpoint(executionId, step) {
4153
- const raw = await this.client.hget(this.checkpointKey(executionId), String(step));
4154
- return raw !== null ? JSON.parse(raw) : null;
4155
- }
4156
- async getLatestCheckpoint(executionId) {
4157
- const all = await this.client.hgetall(this.checkpointKey(executionId));
4158
- if (!all || Object.keys(all).length === 0) return null;
4159
- let maxStep = -1;
4160
- let maxData = null;
4161
- for (const [stepStr, raw] of Object.entries(all)) {
4162
- const step = Number(stepStr);
4163
- if (step > maxStep) {
4164
- maxStep = step;
4165
- maxData = JSON.parse(raw);
4166
- }
4167
- }
4168
- return { step: maxStep, data: maxData };
4169
- }
4170
- // ── Sessions ─────────────────────────────────────────────────────────
4171
- async saveSession(sessionId, history) {
4172
- await this.client.set(this.sessionKey(sessionId), JSON.stringify(history));
4173
- await this.client.sadd("axl:session-ids", sessionId);
4174
- }
4175
- async getSession(sessionId) {
4176
- const raw = await this.client.get(this.sessionKey(sessionId));
4177
- return raw ? JSON.parse(raw) : [];
4178
- }
4179
- async deleteSession(sessionId) {
4180
- await this.client.del(this.sessionKey(sessionId));
4181
- await this.client.del(this.sessionMetaKey(sessionId));
4182
- await this.client.srem("axl:session-ids", sessionId);
4183
- }
4184
- async saveSessionMeta(sessionId, key, value) {
4185
- await this.client.hset(this.sessionMetaKey(sessionId), key, JSON.stringify(value));
4186
- }
4187
- async getSessionMeta(sessionId, key) {
4188
- const raw = await this.client.hget(this.sessionMetaKey(sessionId), key);
4189
- return raw !== null ? JSON.parse(raw) : null;
4190
- }
4191
- // ── Pending Decisions ────────────────────────────────────────────────
4192
- async savePendingDecision(executionId, decision) {
4193
- await this.client.hset(this.decisionsKey(), executionId, JSON.stringify(decision));
4194
- }
4195
- async getPendingDecisions() {
4196
- const all = await this.client.hgetall(this.decisionsKey());
4197
- if (!all) return [];
4198
- return Object.values(all).map((raw) => JSON.parse(raw));
4199
- }
4200
- async resolveDecision(executionId, _result) {
4201
- await this.client.hdel(this.decisionsKey(), executionId);
4202
- }
4203
- // ── Execution State ──────────────────────────────────────────────────
4204
- async saveExecutionState(executionId, state) {
4205
- await this.client.set(this.executionStateKey(executionId), JSON.stringify(state));
4206
- if (state.status === "waiting") {
4207
- await this.client.sadd(this.pendingExecSetKey(), executionId);
4208
- } else {
4209
- await this.client.srem(this.pendingExecSetKey(), executionId);
4210
- }
4211
- }
4212
- async getExecutionState(executionId) {
4213
- const raw = await this.client.get(this.executionStateKey(executionId));
4214
- return raw ? JSON.parse(raw) : null;
4215
- }
4216
- async listPendingExecutions() {
4217
- return this.client.smembers(this.pendingExecSetKey());
4218
- }
4219
- // ── Sessions (Studio introspection) ────────────────────────────────────
4220
- async listSessions() {
4221
- return this.client.smembers("axl:session-ids");
4222
- }
4223
- /** Close the Redis connection. */
4224
- async close() {
4225
- await this.client.quit();
4226
- }
4227
- async deleteCheckpoints(executionId) {
4228
- await this.client.del(this.checkpointKey(executionId));
4229
- }
4230
- };
4231
-
4232
4119
  // src/session.ts
4233
4120
  var Session = class _Session {
4234
4121
  constructor(sessionId, runtime, store, options) {
@@ -5114,12 +5001,11 @@ var AxlRuntime = class extends EventEmitter2 {
5114
5001
  return this.mcpManager;
5115
5002
  }
5116
5003
  createStateStore() {
5117
- const storeType = this.config.state?.store ?? "memory";
5118
- switch (storeType) {
5004
+ const storeOption = this.config.state?.store ?? "memory";
5005
+ if (typeof storeOption !== "string") return storeOption;
5006
+ switch (storeOption) {
5119
5007
  case "sqlite":
5120
5008
  return new SQLiteStore(this.config.state?.sqlite?.path ?? "./data/axl.db");
5121
- case "redis":
5122
- return new RedisStore(this.config.state?.redis?.url);
5123
5009
  case "memory":
5124
5010
  default:
5125
5011
  return new MemoryStore();
@@ -5750,6 +5636,137 @@ var AxlRuntime = class extends EventEmitter2 {
5750
5636
  }
5751
5637
  };
5752
5638
 
5639
+ // src/state/redis.ts
5640
+ var RedisStore = class _RedisStore {
5641
+ constructor(client) {
5642
+ this.client = client;
5643
+ }
5644
+ /**
5645
+ * Create a connected RedisStore instance.
5646
+ *
5647
+ * @param url - Redis connection URL (e.g. `redis://localhost:6379`). Defaults to `redis://localhost:6379`.
5648
+ */
5649
+ static async create(url) {
5650
+ let createClient;
5651
+ try {
5652
+ const mod = __require("redis");
5653
+ createClient = mod.createClient ?? mod.default?.createClient;
5654
+ if (typeof createClient !== "function") {
5655
+ throw new Error(
5656
+ "redis package does not export createClient. Ensure you have redis ^5.0.0 installed: npm install redis"
5657
+ );
5658
+ }
5659
+ } catch (err) {
5660
+ if (err instanceof Error && err.message.includes("createClient")) throw err;
5661
+ throw new Error("redis is required for RedisStore. Install it with: npm install redis");
5662
+ }
5663
+ const client = url ? createClient({ url }) : createClient();
5664
+ await client.connect();
5665
+ return new _RedisStore(client);
5666
+ }
5667
+ // ── Key helpers ──────────────────────────────────────────────────────
5668
+ checkpointKey(executionId) {
5669
+ return `axl:checkpoint:${executionId}`;
5670
+ }
5671
+ sessionKey(sessionId) {
5672
+ return `axl:session:${sessionId}`;
5673
+ }
5674
+ sessionMetaKey(sessionId) {
5675
+ return `axl:session-meta:${sessionId}`;
5676
+ }
5677
+ decisionsKey() {
5678
+ return "axl:decisions";
5679
+ }
5680
+ executionStateKey(executionId) {
5681
+ return `axl:exec-state:${executionId}`;
5682
+ }
5683
+ pendingExecSetKey() {
5684
+ return "axl:pending-executions";
5685
+ }
5686
+ // ── Checkpoints ──────────────────────────────────────────────────────
5687
+ async saveCheckpoint(executionId, step, data) {
5688
+ await this.client.hSet(this.checkpointKey(executionId), String(step), JSON.stringify(data));
5689
+ }
5690
+ async getCheckpoint(executionId, step) {
5691
+ const raw = await this.client.hGet(this.checkpointKey(executionId), String(step));
5692
+ return raw != null ? JSON.parse(raw) : null;
5693
+ }
5694
+ async getLatestCheckpoint(executionId) {
5695
+ const all = await this.client.hGetAll(this.checkpointKey(executionId));
5696
+ if (!all || Object.keys(all).length === 0) return null;
5697
+ let maxStep = -1;
5698
+ let maxData = null;
5699
+ for (const [stepStr, raw] of Object.entries(all)) {
5700
+ const step = Number(stepStr);
5701
+ if (step > maxStep) {
5702
+ maxStep = step;
5703
+ maxData = JSON.parse(raw);
5704
+ }
5705
+ }
5706
+ return { step: maxStep, data: maxData };
5707
+ }
5708
+ // ── Sessions ─────────────────────────────────────────────────────────
5709
+ async saveSession(sessionId, history) {
5710
+ await this.client.set(this.sessionKey(sessionId), JSON.stringify(history));
5711
+ await this.client.sAdd("axl:session-ids", sessionId);
5712
+ }
5713
+ async getSession(sessionId) {
5714
+ const raw = await this.client.get(this.sessionKey(sessionId));
5715
+ return raw ? JSON.parse(raw) : [];
5716
+ }
5717
+ async deleteSession(sessionId) {
5718
+ await this.client.del(this.sessionKey(sessionId));
5719
+ await this.client.del(this.sessionMetaKey(sessionId));
5720
+ await this.client.sRem("axl:session-ids", sessionId);
5721
+ }
5722
+ async saveSessionMeta(sessionId, key, value) {
5723
+ await this.client.hSet(this.sessionMetaKey(sessionId), key, JSON.stringify(value));
5724
+ }
5725
+ async getSessionMeta(sessionId, key) {
5726
+ const raw = await this.client.hGet(this.sessionMetaKey(sessionId), key);
5727
+ return raw != null ? JSON.parse(raw) : null;
5728
+ }
5729
+ // ── Pending Decisions ────────────────────────────────────────────────
5730
+ async savePendingDecision(executionId, decision) {
5731
+ await this.client.hSet(this.decisionsKey(), executionId, JSON.stringify(decision));
5732
+ }
5733
+ async getPendingDecisions() {
5734
+ const all = await this.client.hGetAll(this.decisionsKey());
5735
+ if (!all) return [];
5736
+ return Object.values(all).map((raw) => JSON.parse(raw));
5737
+ }
5738
+ async resolveDecision(executionId, _result) {
5739
+ await this.client.hDel(this.decisionsKey(), executionId);
5740
+ }
5741
+ // ── Execution State ──────────────────────────────────────────────────
5742
+ async saveExecutionState(executionId, state) {
5743
+ await this.client.set(this.executionStateKey(executionId), JSON.stringify(state));
5744
+ if (state.status === "waiting") {
5745
+ await this.client.sAdd(this.pendingExecSetKey(), executionId);
5746
+ } else {
5747
+ await this.client.sRem(this.pendingExecSetKey(), executionId);
5748
+ }
5749
+ }
5750
+ async getExecutionState(executionId) {
5751
+ const raw = await this.client.get(this.executionStateKey(executionId));
5752
+ return raw ? JSON.parse(raw) : null;
5753
+ }
5754
+ async listPendingExecutions() {
5755
+ return this.client.sMembers(this.pendingExecSetKey());
5756
+ }
5757
+ // ── Sessions (Studio introspection) ────────────────────────────────────
5758
+ async listSessions() {
5759
+ return this.client.sMembers("axl:session-ids");
5760
+ }
5761
+ /** Close the Redis connection. */
5762
+ async close() {
5763
+ await this.client.quit();
5764
+ }
5765
+ async deleteCheckpoints(executionId) {
5766
+ await this.client.del(this.checkpointKey(executionId));
5767
+ }
5768
+ };
5769
+
5753
5770
  // src/memory/embedder-openai.ts
5754
5771
  var OpenAIEmbedder = class {
5755
5772
  apiKey;