@almadar/agent 2.0.4 → 3.1.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.
@@ -11,4 +11,5 @@ export { AgenticSearchEngine, createAgenticSearchEngine, type SearchStrategy, ty
11
11
  export { ObservabilityCollector, getObservabilityCollector, resetObservabilityCollector, recordEvent, startObservabilitySession, endObservabilitySession, getPerformanceSnapshot, type ObservableEventType, type ObservableEvent, type SessionTelemetry, type PerformanceSnapshot, type HealthCheckResult, } from '../observability.js';
12
12
  export { MultiUserManager, getMultiUserManager, resetMultiUserManager, createUserContext, isAdmin, requireOwnership, type UserContext, type ScopedSessionMetadata, type AccessCheckResult, type UserSessionStats, } from '../multi-user.js';
13
13
  export { StateSyncManager, getStateSyncManager, resetStateSyncManager, withSync, debounceSync, type StateChangeType, type StateChangeEvent, type VersionVector, type StateSyncSnapshot, type ConflictResolution, type StateSyncConfig, } from '../state-sync.js';
14
+ export { LocalMemoryBackend, type LocalMemoryBackendOptions, type ErrorResolution, } from './local-memory-backend.js';
14
15
  export type { UserFeedback, PatternAffinity, InterruptRecord, ToolApprovalPreference, CheckpointRecord, } from './types.js';
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Local File-System Memory Backend
3
+ *
4
+ * Implements MemoryManager's storage interface backed by `.orb` files
5
+ * instead of Firestore collections.
6
+ *
7
+ * Per the minimal memory strategy, only error resolution files are active
8
+ * at launch. Other memory types are stubbed (accept writes, return empty
9
+ * on reads) until evaluation proves their value.
10
+ *
11
+ * Storage layout:
12
+ * ~/.almadar/memory/
13
+ * ├── memory.orb (schema definition)
14
+ * ├── errors.orb (error resolution instances - ACTIVE)
15
+ * ├── preferences.orb (stubbed until eval)
16
+ * ├── sessions.orb (stubbed until eval)
17
+ * ├── projects.orb (stubbed until eval)
18
+ * ├── patterns.orb (stubbed until eval)
19
+ * └── index.orb (stubbed until eval)
20
+ */
21
+ import type { UserPreference, GenerationSession, ProjectContext } from './memory-orbital.js';
22
+ import type { PatternAffinity, InterruptRecord, ToolApprovalPreference, CheckpointRecord, UserFeedback } from './types.js';
23
+ export interface LocalMemoryBackendOptions {
24
+ memoryDir?: string;
25
+ }
26
+ /**
27
+ * Error resolution record stored in errors.orb.
28
+ */
29
+ export interface ErrorResolution {
30
+ id: string;
31
+ errorSignature: string;
32
+ errorMessage: string;
33
+ resolution: string;
34
+ context: string;
35
+ createdAt: number;
36
+ usageCount: number;
37
+ }
38
+ export declare class LocalMemoryBackend {
39
+ private readonly memoryDir;
40
+ constructor(options?: LocalMemoryBackendOptions);
41
+ private filePath;
42
+ private readInstances;
43
+ private writeInstances;
44
+ recordErrorResolution(resolution: Omit<ErrorResolution, 'id' | 'createdAt' | 'usageCount'>): Promise<string>;
45
+ findErrorResolution(errorSignature: string): Promise<ErrorResolution | null>;
46
+ searchErrorResolutions(query: string): Promise<ErrorResolution[]>;
47
+ getAllErrorResolutions(): Promise<ErrorResolution[]>;
48
+ getUserPreferences(_userId: string): Promise<UserPreference | null>;
49
+ updateUserPreferences(_userId: string, _preferences: Partial<Omit<UserPreference, 'id' | 'userId' | 'learnedAt'>>): Promise<void>;
50
+ recordGeneration(_userId: string, session: Omit<GenerationSession, 'id' | 'userId' | 'createdAt'>): Promise<string>;
51
+ getGenerationSession(sessionId: string): Promise<GenerationSession | null>;
52
+ getUserGenerationHistory(_userId: string, limit?: number): Promise<GenerationSession[]>;
53
+ getProjectContext(_appId: string): Promise<ProjectContext | null>;
54
+ updateProjectContext(_appId: string, _update: Partial<Omit<ProjectContext, 'id' | 'appId'>>): Promise<void>;
55
+ updatePatternAffinity(_userId: string, _patternId: string, _outcome: 'success' | 'failure' | 'partial', _context?: {
56
+ entityType?: string;
57
+ useCase?: string;
58
+ }): Promise<void>;
59
+ getPatternAffinity(_userId: string, _patternId: string): Promise<PatternAffinity | null>;
60
+ getUserPatterns(_userId: string): Promise<PatternAffinity[]>;
61
+ recordFeedback(_sessionId: string, _feedback: Omit<UserFeedback, 'feedbackId' | 'sessionId' | 'timestamp'>): Promise<void>;
62
+ recordInterruptDecision(_sessionId: string, _userId: string, _interruptData: {
63
+ toolName: string;
64
+ toolArgs: Record<string, unknown>;
65
+ decision: 'approved' | 'rejected' | 'modified';
66
+ modifiedArgs?: Record<string, unknown>;
67
+ reason?: string;
68
+ }): Promise<void>;
69
+ getSessionInterrupts(_sessionId: string): Promise<InterruptRecord[]>;
70
+ getToolApprovalPreference(_userId: string, _toolName: string): Promise<ToolApprovalPreference | null>;
71
+ shouldAutoApproveTool(_userId: string, _toolName: string): Promise<boolean>;
72
+ recordCheckpoint(_userId: string, _checkpointData: {
73
+ checkpointId: string;
74
+ threadId: string;
75
+ parentCheckpointId?: string;
76
+ metadata?: Record<string, unknown>;
77
+ }): Promise<void>;
78
+ getUserCheckpoints(_userId: string, _limit?: number): Promise<CheckpointRecord[]>;
79
+ getThreadCheckpoints(_threadId: string): Promise<CheckpointRecord[]>;
80
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Neural Pipeline Module
3
+ *
4
+ * Schema generation via the Masar server. The neural pipeline (GFlowNet +
5
+ * LLM fix loop) now runs server-side in the Masar container. This module
6
+ * provides the HTTP client and shared types.
7
+ *
8
+ * @packageDocumentation
9
+ */
10
+ export type { GoalSpec, NeuralGenerateResult, NeuralPipelineResult, NeuralPipelineOptions, CommandExecutor, PythonExecutor, InferOptions, InferResult, ValidationError, ValidationResult, CompileResult, } from './types.js';
11
+ export { MasarClient } from './masar-client.js';
12
+ export type { MasarClientOptions } from './masar-client.js';
@@ -0,0 +1,86 @@
1
+ // src/neural/masar-client.ts
2
+ var MasarClient = class {
3
+ constructor(options) {
4
+ this.baseUrl = (options?.baseUrl ?? process.env["MASAR_URL"] ?? "https://masar-345008351456.europe-west4.run.app").replace(/\/$/, "");
5
+ this.timeoutMs = options?.timeoutMs ?? 12e4;
6
+ this.onProgress = options?.onProgress ?? null;
7
+ }
8
+ /**
9
+ * Generate an .orb schema from a natural language prompt.
10
+ *
11
+ * Sends the prompt to the Masar server which runs the full neural pipeline
12
+ * (goal parsing, GFlowNet generation, validation, LLM fix loop) and returns
13
+ * the result.
14
+ */
15
+ async generate(prompt) {
16
+ this.onProgress?.("request", `Sending prompt to Masar at ${this.baseUrl}`);
17
+ const url = `${this.baseUrl}/generate`;
18
+ const controller = new AbortController();
19
+ const timeout = setTimeout(() => controller.abort(), this.timeoutMs);
20
+ try {
21
+ const response = await fetch(url, {
22
+ method: "POST",
23
+ headers: { "Content-Type": "application/json" },
24
+ body: JSON.stringify({ prompt }),
25
+ signal: controller.signal
26
+ });
27
+ if (!response.ok) {
28
+ const body = await response.text().catch(() => "");
29
+ return makeErrorResult(
30
+ `Masar server returned ${response.status} ${response.statusText}${body ? `: ${body}` : ""}`
31
+ );
32
+ }
33
+ const data = await response.json();
34
+ this.onProgress?.("response", data.success ? "Generation succeeded" : `Generation failed: ${data.error ?? "unknown"}`);
35
+ return toNeuralPipelineResult(data);
36
+ } catch (err) {
37
+ if (err instanceof DOMException && err.name === "AbortError") {
38
+ return makeErrorResult(`Masar request timed out after ${this.timeoutMs}ms`);
39
+ }
40
+ const message = err instanceof Error ? err.message : String(err);
41
+ return makeErrorResult(`Masar request failed: ${message}`);
42
+ } finally {
43
+ clearTimeout(timeout);
44
+ }
45
+ }
46
+ };
47
+ function toNeuralPipelineResult(data) {
48
+ return {
49
+ success: data.success,
50
+ validationPass: data.validation_pass,
51
+ compilationPass: false,
52
+ goalMatch: data.goal_match ?? 0,
53
+ totalSteps: data.total_steps ?? 0,
54
+ fixRounds: data.fix_rounds ?? 0,
55
+ llmCalls: data.llm_calls ?? 0,
56
+ durationMs: data.duration_ms ?? 0,
57
+ schema: data.schema ?? null,
58
+ schemaPath: null,
59
+ actions: data.actions ?? [],
60
+ validationErrors: data.validation_errors ?? [],
61
+ compilationErrors: [],
62
+ error: data.error ?? null
63
+ };
64
+ }
65
+ function makeErrorResult(error) {
66
+ return {
67
+ success: false,
68
+ validationPass: false,
69
+ compilationPass: false,
70
+ goalMatch: 0,
71
+ totalSteps: 0,
72
+ fixRounds: 0,
73
+ llmCalls: 0,
74
+ durationMs: 0,
75
+ schema: null,
76
+ schemaPath: null,
77
+ actions: [],
78
+ validationErrors: [],
79
+ compilationErrors: [],
80
+ error
81
+ };
82
+ }
83
+
84
+ export { MasarClient };
85
+ //# sourceMappingURL=index.js.map
86
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/neural/masar-client.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Masar HTTP Client\n *\n * Calls the Masar server's /generate endpoint via HTTP instead of\n * orchestrating the neural pipeline (GFlowNet + LLM fix loop) directly.\n *\n * The Masar server runs the full pipeline server-side and returns\n * a NeuralPipelineResult-compatible response.\n */\n\nimport type { NeuralPipelineResult } from './types.js';\n\n/** Response shape returned by the Masar /generate endpoint (snake_case from Python). */\ninterface MasarGenerateResponse {\n success: boolean;\n schema: string | null;\n validation_pass: boolean;\n goal_match: number;\n total_steps: number;\n fix_rounds: number;\n llm_calls: number;\n duration_ms: number;\n actions: string[];\n validation_errors: string[];\n error: string | null;\n}\n\n/** Options for constructing a MasarClient. */\nexport interface MasarClientOptions {\n /** Base URL of the Masar server. Defaults to MASAR_URL env var or http://localhost:8080 */\n baseUrl?: string;\n /** Request timeout in milliseconds. Defaults to 120000 (2 minutes). */\n timeoutMs?: number;\n /** Optional callback for progress updates. */\n onProgress?: (phase: string, detail: string) => void;\n}\n\n/**\n * HTTP client for the Masar schema generation server.\n *\n * Usage:\n * ```ts\n * const client = new MasarClient();\n * const result = await client.generate('Build a todo app with projects and tasks');\n * ```\n */\nexport class MasarClient {\n private readonly baseUrl: string;\n private readonly timeoutMs: number;\n private readonly onProgress: ((phase: string, detail: string) => void) | null;\n\n constructor(options?: MasarClientOptions) {\n this.baseUrl = (options?.baseUrl ?? process.env['MASAR_URL'] ?? 'https://masar-345008351456.europe-west4.run.app').replace(/\\/$/, '');\n this.timeoutMs = options?.timeoutMs ?? 120_000;\n this.onProgress = options?.onProgress ?? null;\n }\n\n /**\n * Generate an .orb schema from a natural language prompt.\n *\n * Sends the prompt to the Masar server which runs the full neural pipeline\n * (goal parsing, GFlowNet generation, validation, LLM fix loop) and returns\n * the result.\n */\n async generate(prompt: string): Promise<NeuralPipelineResult> {\n this.onProgress?.('request', `Sending prompt to Masar at ${this.baseUrl}`);\n\n const url = `${this.baseUrl}/generate`;\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), this.timeoutMs);\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ prompt }),\n signal: controller.signal,\n });\n\n if (!response.ok) {\n const body = await response.text().catch(() => '');\n return makeErrorResult(\n `Masar server returned ${response.status} ${response.statusText}${body ? `: ${body}` : ''}`,\n );\n }\n\n const data: MasarGenerateResponse = await response.json() as MasarGenerateResponse;\n this.onProgress?.('response', data.success ? 'Generation succeeded' : `Generation failed: ${data.error ?? 'unknown'}`);\n\n return toNeuralPipelineResult(data);\n } catch (err: unknown) {\n if (err instanceof DOMException && err.name === 'AbortError') {\n return makeErrorResult(`Masar request timed out after ${this.timeoutMs}ms`);\n }\n const message = err instanceof Error ? err.message : String(err);\n return makeErrorResult(`Masar request failed: ${message}`);\n } finally {\n clearTimeout(timeout);\n }\n }\n}\n\n/**\n * Map the Masar server response to a NeuralPipelineResult.\n * Provides defaults for any missing fields so the result always satisfies the full interface.\n */\nfunction toNeuralPipelineResult(data: MasarGenerateResponse): NeuralPipelineResult {\n return {\n success: data.success,\n validationPass: data.validation_pass,\n compilationPass: false,\n goalMatch: data.goal_match ?? 0,\n totalSteps: data.total_steps ?? 0,\n fixRounds: data.fix_rounds ?? 0,\n llmCalls: data.llm_calls ?? 0,\n durationMs: data.duration_ms ?? 0,\n schema: data.schema ?? null,\n schemaPath: null,\n actions: data.actions ?? [],\n validationErrors: data.validation_errors ?? [],\n compilationErrors: [],\n error: data.error ?? null,\n };\n}\n\nfunction makeErrorResult(error: string): NeuralPipelineResult {\n return {\n success: false,\n validationPass: false,\n compilationPass: false,\n goalMatch: 0,\n totalSteps: 0,\n fixRounds: 0,\n llmCalls: 0,\n durationMs: 0,\n schema: null,\n schemaPath: null,\n actions: [],\n validationErrors: [],\n compilationErrors: [],\n error,\n };\n}\n"]}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Masar HTTP Client
3
+ *
4
+ * Calls the Masar server's /generate endpoint via HTTP instead of
5
+ * orchestrating the neural pipeline (GFlowNet + LLM fix loop) directly.
6
+ *
7
+ * The Masar server runs the full pipeline server-side and returns
8
+ * a NeuralPipelineResult-compatible response.
9
+ */
10
+ import type { NeuralPipelineResult } from './types.js';
11
+ /** Options for constructing a MasarClient. */
12
+ export interface MasarClientOptions {
13
+ /** Base URL of the Masar server. Defaults to MASAR_URL env var or http://localhost:8080 */
14
+ baseUrl?: string;
15
+ /** Request timeout in milliseconds. Defaults to 120000 (2 minutes). */
16
+ timeoutMs?: number;
17
+ /** Optional callback for progress updates. */
18
+ onProgress?: (phase: string, detail: string) => void;
19
+ }
20
+ /**
21
+ * HTTP client for the Masar schema generation server.
22
+ *
23
+ * Usage:
24
+ * ```ts
25
+ * const client = new MasarClient();
26
+ * const result = await client.generate('Build a todo app with projects and tasks');
27
+ * ```
28
+ */
29
+ export declare class MasarClient {
30
+ private readonly baseUrl;
31
+ private readonly timeoutMs;
32
+ private readonly onProgress;
33
+ constructor(options?: MasarClientOptions);
34
+ /**
35
+ * Generate an .orb schema from a natural language prompt.
36
+ *
37
+ * Sends the prompt to the Masar server which runs the full neural pipeline
38
+ * (goal parsing, GFlowNet generation, validation, LLM fix loop) and returns
39
+ * the result.
40
+ */
41
+ generate(prompt: string): Promise<NeuralPipelineResult>;
42
+ }
@@ -0,0 +1,111 @@
1
+ /**
2
+ * Neural Pipeline Types
3
+ *
4
+ * Shared types for the GFlowNet-based schema generation pipeline.
5
+ */
6
+ /**
7
+ * Structural goal vector extracted from a natural language prompt.
8
+ * Used by the GFlowNet to generate schema skeletons.
9
+ */
10
+ export interface GoalSpec {
11
+ entities: number;
12
+ fields: number;
13
+ traits: number;
14
+ states: number;
15
+ transitions: number;
16
+ pages: number;
17
+ events: number;
18
+ effects: number;
19
+ entityNames: string[];
20
+ fieldNames: string[];
21
+ projectName: string;
22
+ }
23
+ export interface NeuralGenerateResult {
24
+ success: boolean;
25
+ schema?: Record<string, unknown>;
26
+ actions?: string[];
27
+ steps?: number;
28
+ goalMatch?: number;
29
+ error?: string;
30
+ }
31
+ export interface NeuralPipelineResult {
32
+ success: boolean;
33
+ validationPass: boolean;
34
+ compilationPass: boolean;
35
+ goalMatch: number;
36
+ totalSteps: number;
37
+ fixRounds: number;
38
+ llmCalls: number;
39
+ durationMs: number;
40
+ /** Generated .orb schema JSON string (returned by Masar server). */
41
+ schema: string | null;
42
+ /** @deprecated Use `schema` instead. Legacy field for file-based pipeline. */
43
+ schemaPath: string | null;
44
+ actions: string[];
45
+ validationErrors: string[];
46
+ compilationErrors: string[];
47
+ error: string | null;
48
+ }
49
+ export interface NeuralPipelineOptions {
50
+ provider: string;
51
+ model: string;
52
+ /** Working directory for writing schemas */
53
+ workDir: string;
54
+ maxFixRounds?: number;
55
+ samples?: number;
56
+ temperature?: number;
57
+ onProgress?: (phase: string, detail: string) => void;
58
+ }
59
+ /**
60
+ * Abstraction for running shell commands.
61
+ * Server uses temp files, CLI uses real paths, tests use mocks.
62
+ */
63
+ export interface CommandExecutor {
64
+ /**
65
+ * Run `orbital validate` on a schema string or file path.
66
+ */
67
+ validateSchema(schema: string): Promise<ValidationResult>;
68
+ /**
69
+ * Run `orbital compile` on a schema file.
70
+ */
71
+ compileSchema?(schemaPath: string): Promise<CompileResult>;
72
+ }
73
+ /**
74
+ * Abstraction for running GFlowNet inference (Python subprocess).
75
+ */
76
+ export interface PythonExecutor {
77
+ /**
78
+ * Run GFlowNet inference on a goal spec.
79
+ */
80
+ infer(goal: GoalSpec, options: InferOptions): Promise<InferResult>;
81
+ }
82
+ export interface InferOptions {
83
+ samples?: number;
84
+ temperature?: number;
85
+ bestOf?: boolean;
86
+ }
87
+ export interface InferResult {
88
+ samples: Array<{
89
+ schema: Record<string, unknown>;
90
+ actions: string[];
91
+ steps: number;
92
+ goal_match: number;
93
+ sample_idx: number;
94
+ }>;
95
+ goal: GoalSpec;
96
+ temperature: number;
97
+ }
98
+ export interface ValidationError {
99
+ code: string;
100
+ message: string;
101
+ path?: string;
102
+ }
103
+ export interface ValidationResult {
104
+ success: boolean;
105
+ errors: ValidationError[];
106
+ warnings: ValidationError[];
107
+ }
108
+ export interface CompileResult {
109
+ success: boolean;
110
+ errors: string[];
111
+ }
@@ -5,6 +5,7 @@
5
5
  */
6
6
  export type { SessionMetadata, SessionRecord, PersistenceMode, Session, } from './types.js';
7
7
  export { MemorySessionBackend } from './memory-backend.js';
8
+ export { LocalSessionBackend, type LocalSessionBackendOptions, } from './local-session-backend.js';
8
9
  export { FirestoreCheckpointer, type FirestoreCheckpointerOptions, type FirestoreDb, type FirestoreTimestamp, } from './firestore-checkpointer.js';
9
10
  export { FirestoreSessionStore, type FirestoreSessionStoreOptions, } from './firestore-session-store.js';
10
11
  export { FirestoreStore, type FirestoreStoreOptions, } from './firestore-store.js';
@@ -1,3 +1,6 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import os from 'os';
1
4
  import { BaseCheckpointSaver, BaseStore } from '@langchain/langgraph-checkpoint';
2
5
 
3
6
  // src/persistence/memory-backend.ts
@@ -39,6 +42,194 @@ var MemorySessionBackend = class {
39
42
  return this.sessions.has(threadId);
40
43
  }
41
44
  };
45
+ var DEFAULT_SESSIONS_DIR = path.join(os.homedir(), ".almadar", "sessions");
46
+ var LocalSessionBackend = class {
47
+ constructor(options = {}) {
48
+ this.sessionsDir = options.sessionsDir ?? DEFAULT_SESSIONS_DIR;
49
+ fs.mkdirSync(this.sessionsDir, { recursive: true });
50
+ }
51
+ sessionDir(threadId) {
52
+ return path.join(this.sessionsDir, threadId);
53
+ }
54
+ sessionFilePath(threadId) {
55
+ return path.join(this.sessionDir(threadId), "session.orb");
56
+ }
57
+ checkpointFilePath(threadId) {
58
+ return path.join(this.sessionDir(threadId), "checkpoint.orb");
59
+ }
60
+ eventsFilePath(threadId) {
61
+ return path.join(this.sessionDir(threadId), "events.orb");
62
+ }
63
+ /**
64
+ * Store session metadata as an .orb file.
65
+ */
66
+ store(threadId, metadata) {
67
+ const dir = this.sessionDir(threadId);
68
+ fs.mkdirSync(dir, { recursive: true });
69
+ const schema = {
70
+ name: `session-${threadId}`,
71
+ version: "1.0.0",
72
+ orbitals: [
73
+ {
74
+ name: "SessionRecord",
75
+ entity: {
76
+ name: "Session",
77
+ fields: [
78
+ { name: "skill", type: "string" },
79
+ { name: "workDir", type: "string" },
80
+ { name: "createdAt", type: "number" },
81
+ { name: "lastActivityAt", type: "number" },
82
+ { name: "approveAll", type: "boolean" }
83
+ ]
84
+ },
85
+ instances: [
86
+ {
87
+ id: threadId,
88
+ skill: metadata.skill,
89
+ workDir: metadata.workDir,
90
+ createdAt: metadata.createdAt,
91
+ lastActivityAt: metadata.lastActivityAt,
92
+ approveAll: metadata.approveAll ?? false
93
+ }
94
+ ]
95
+ }
96
+ ]
97
+ };
98
+ fs.writeFileSync(this.sessionFilePath(threadId), JSON.stringify(schema, null, 2));
99
+ }
100
+ /**
101
+ * Get session metadata from .orb file.
102
+ */
103
+ get(threadId) {
104
+ const filePath = this.sessionFilePath(threadId);
105
+ if (!fs.existsSync(filePath)) return void 0;
106
+ try {
107
+ const raw = JSON.parse(fs.readFileSync(filePath, "utf-8"));
108
+ const instance = raw?.orbitals?.[0]?.instances?.[0];
109
+ if (!instance) return void 0;
110
+ return {
111
+ skill: instance.skill,
112
+ workDir: instance.workDir,
113
+ createdAt: instance.createdAt,
114
+ lastActivityAt: instance.lastActivityAt,
115
+ approveAll: instance.approveAll
116
+ };
117
+ } catch {
118
+ return void 0;
119
+ }
120
+ }
121
+ /**
122
+ * Delete session directory.
123
+ */
124
+ delete(threadId) {
125
+ const dir = this.sessionDir(threadId);
126
+ if (!fs.existsSync(dir)) return false;
127
+ fs.rmSync(dir, { recursive: true, force: true });
128
+ return true;
129
+ }
130
+ /**
131
+ * List all sessions.
132
+ */
133
+ list() {
134
+ if (!fs.existsSync(this.sessionsDir)) return [];
135
+ const entries = fs.readdirSync(this.sessionsDir, { withFileTypes: true });
136
+ const records = [];
137
+ for (const entry of entries) {
138
+ if (!entry.isDirectory()) continue;
139
+ const meta = this.get(entry.name);
140
+ if (meta) {
141
+ records.push({ threadId: entry.name, ...meta });
142
+ }
143
+ }
144
+ return records.sort((a, b) => b.lastActivityAt - a.lastActivityAt);
145
+ }
146
+ /**
147
+ * Check if a session exists.
148
+ */
149
+ has(threadId) {
150
+ return fs.existsSync(this.sessionFilePath(threadId));
151
+ }
152
+ /**
153
+ * Store a checkpoint blob for the session.
154
+ */
155
+ storeCheckpoint(threadId, checkpoint) {
156
+ const dir = this.sessionDir(threadId);
157
+ fs.mkdirSync(dir, { recursive: true });
158
+ const schema = {
159
+ name: `checkpoint-${threadId}`,
160
+ version: "1.0.0",
161
+ orbitals: [
162
+ {
163
+ name: "Checkpoint",
164
+ entity: {
165
+ name: "CheckpointData",
166
+ fields: [{ name: "data", type: "json" }]
167
+ },
168
+ instances: [{ id: "latest", data: checkpoint }]
169
+ }
170
+ ]
171
+ };
172
+ fs.writeFileSync(this.checkpointFilePath(threadId), JSON.stringify(schema, null, 2));
173
+ }
174
+ /**
175
+ * Load the latest checkpoint for a session.
176
+ */
177
+ loadCheckpoint(threadId) {
178
+ const filePath = this.checkpointFilePath(threadId);
179
+ if (!fs.existsSync(filePath)) return void 0;
180
+ try {
181
+ const raw = JSON.parse(fs.readFileSync(filePath, "utf-8"));
182
+ return raw?.orbitals?.[0]?.instances?.[0]?.data;
183
+ } catch {
184
+ return void 0;
185
+ }
186
+ }
187
+ /**
188
+ * Append events to the session's event stream.
189
+ */
190
+ appendEvents(threadId, events) {
191
+ const dir = this.sessionDir(threadId);
192
+ fs.mkdirSync(dir, { recursive: true });
193
+ const filePath = this.eventsFilePath(threadId);
194
+ let existing = [];
195
+ if (fs.existsSync(filePath)) {
196
+ try {
197
+ const raw = JSON.parse(fs.readFileSync(filePath, "utf-8"));
198
+ existing = raw?.orbitals?.[0]?.instances ?? [];
199
+ } catch {
200
+ }
201
+ }
202
+ const merged = [...existing, ...events];
203
+ const schema = {
204
+ name: `events-${threadId}`,
205
+ version: "1.0.0",
206
+ orbitals: [
207
+ {
208
+ name: "EventStream",
209
+ entity: {
210
+ name: "Event",
211
+ fields: [{ name: "data", type: "json" }]
212
+ },
213
+ instances: merged
214
+ }
215
+ ]
216
+ };
217
+ fs.writeFileSync(filePath, JSON.stringify(schema, null, 2));
218
+ }
219
+ /**
220
+ * Read all events for a session.
221
+ */
222
+ readEvents(threadId) {
223
+ const filePath = this.eventsFilePath(threadId);
224
+ if (!fs.existsSync(filePath)) return [];
225
+ try {
226
+ const raw = JSON.parse(fs.readFileSync(filePath, "utf-8"));
227
+ return raw?.orbitals?.[0]?.instances ?? [];
228
+ } catch {
229
+ return [];
230
+ }
231
+ }
232
+ };
42
233
  var FirestoreCheckpointer = class extends BaseCheckpointSaver {
43
234
  constructor(options) {
44
235
  super();
@@ -462,9 +653,9 @@ var FirestoreStore = class extends BaseStore {
462
653
  let query = this.db.collection(this.collection);
463
654
  if (op.matchConditions) {
464
655
  for (const condition of op.matchConditions) {
465
- const path = condition.path.filter((p) => p !== "*").join("/");
656
+ const path2 = condition.path.filter((p) => p !== "*").join("/");
466
657
  if (condition.matchType === "prefix") {
467
- query = query.where("namespaceKey", ">=", path).where("namespaceKey", "<", path + "\uFFFF");
658
+ query = query.where("namespaceKey", ">=", path2).where("namespaceKey", "<", path2 + "\uFFFF");
468
659
  }
469
660
  }
470
661
  }
@@ -484,6 +675,6 @@ var FirestoreStore = class extends BaseStore {
484
675
  }
485
676
  };
486
677
 
487
- export { FirestoreCheckpointer, FirestoreSessionStore, FirestoreStore, MemorySessionBackend };
678
+ export { FirestoreCheckpointer, FirestoreSessionStore, FirestoreStore, LocalSessionBackend, MemorySessionBackend };
488
679
  //# sourceMappingURL=index.js.map
489
680
  //# sourceMappingURL=index.js.map