@maximem/synap-js-sdk 0.1.1 → 0.1.4

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/README.md CHANGED
@@ -1,88 +1,52 @@
1
1
  # @maximem/synap-js-sdk
2
2
 
3
- JavaScript SDK wrapper for the Synap Python SDK.
3
+ Node.js wrapper for the Synap Python SDK.
4
4
 
5
- This package gives Node.js apps a normal SDK interface, while internally running a Python bridge process that executes the real `maximem_synap` SDK.
5
+ ## Prerequisites
6
6
 
7
- ## Why this wrapper exists
7
+ - Node.js 18+
8
+ - Python 3.8+
8
9
 
9
- The Synap Python SDK currently has the full feature surface (gRPC anticipation, ingestion lifecycle, context fetch modes, telemetry hooks). This JS SDK keeps your app code in Node while delegating memory operations to Python.
10
-
11
- ## Architecture
10
+ ## Install
12
11
 
13
- ```text
14
- Your Node app
15
- -> @maximem/synap-js-sdk (JS API)
16
- -> BridgeManager (JSON-RPC over stdin/stdout)
17
- -> synap_bridge.py
18
- -> maximem_synap (Python SDK)
19
- -> Synap API + gRPC
12
+ ```bash
13
+ npm install @maximem/synap-js-sdk
20
14
  ```
21
15
 
22
- ## Flow and failure map
23
-
24
- ```text
25
- [1] App calls createClient()/client.init()
26
- ->
27
- [2] BridgeManager resolves python path + bridge path
28
- -> FAIL A: python not found / bridge file missing
29
- ->
30
- [3] Node spawns synap_bridge.py child process
31
- -> FAIL B: process spawn/runtime error
32
- ->
33
- [4] Node sends JSON-RPC "init"
34
- ->
35
- [5] Python imports maximem_synap + builds SDK config
36
- -> FAIL C: maximem_synap not installed in chosen python/venv
37
- ->
38
- [6] SDK initialize() + optional gRPC listen
39
- -> FAIL D: invalid instance/auth OR API/gRPC endpoint unreachable
40
- ->
41
- [7] App calls add/search/get/delete
42
- ->
43
- [8] Node sends JSON-RPC method
44
- -> FAIL E: IPC timeout / broken pipe / bridge crash
45
- ->
46
- [9] Python executes SDK operation
47
- -> FAIL F: SDK/server error, bad input, ingestion timeout
48
- ->
49
- [10] Python returns JSON result
50
- ->
51
- [11] Node resolves promise and returns to app
52
- ```
16
+ ## Setup (JS Runtime)
53
17
 
54
- ## What this means operationally
18
+ Install the Python runtime used by the wrapper:
55
19
 
56
- Because this is a wrapper SDK, your deployment must include both runtimes:
20
+ ```bash
21
+ npx synap-js-sdk setup --sdk-version 0.1.1
22
+ ```
57
23
 
58
- 1. Node.js (for your app + wrapper)
59
- 2. Python (for the bridge + Synap Python SDK)
60
- 3. A virtualenv containing `maximem-synap`
24
+ If you want the latest Python SDK version, omit `--sdk-version`.
61
25
 
62
- This is the main difference versus pure JS SDKs.
26
+ ## Verify Runtime
63
27
 
64
- ## Install
28
+ macOS/Linux:
65
29
 
66
30
  ```bash
67
- npm install @maximem/synap-js-sdk
31
+ ~/.synap-js-sdk/.venv/bin/python -c "import maximem_synap; print(maximem_synap.__version__)"
68
32
  ```
69
33
 
70
- Then set up the Python runtime used by the wrapper (JS runtime flow):
34
+ Windows:
71
35
 
72
- ```bash
73
- npx synap-js-sdk setup --sdk-version <PY_SDK_VERSION>
36
+ ```powershell
37
+ $env:USERPROFILE\.synap-js-sdk\.venv\Scripts\python.exe -c "import maximem_synap; print(maximem_synap.__version__)"
74
38
  ```
75
39
 
76
- If you omit `--sdk-version`, it installs the latest package configured as `maximem-synap`.
77
- This wrapper installs the Python SDK from package indexes (PyPI by default), not from local source paths.
40
+ ## Required Environment Variables
78
41
 
79
- If you want TypeScript support from the start, run:
42
+ - `SYNAP_INSTANCE_ID`
43
+ - `SYNAP_BOOTSTRAP_TOKEN` (required for first-time initialization/new instance)
44
+ - `SYNAP_BASE_URL`
45
+ - `SYNAP_GRPC_HOST`
46
+ - `SYNAP_GRPC_PORT`
47
+ - `SYNAP_GRPC_TLS`
80
48
 
81
- ```bash
82
- npm install @maximem/synap-js-sdk && npx synap-js-sdk setup --sdk-version <PY_SDK_VERSION> && npx synap-js-sdk setup-ts
83
- ```
84
-
85
- ## Quick start in a Node project
49
+ ## Quick Start (JavaScript)
86
50
 
87
51
  ```js
88
52
  const { createClient } = require('@maximem/synap-js-sdk');
@@ -101,10 +65,7 @@ async function run() {
101
65
 
102
66
  await synap.addMemory({
103
67
  userId: 'user-123',
104
- messages: [
105
- { role: 'user', content: 'My name is Alex and I live in Austin.' },
106
- { role: 'assistant', content: 'Got it.' },
107
- ],
68
+ messages: [{ role: 'user', content: 'My name is Alex and I live in Austin.' }],
108
69
  });
109
70
 
110
71
  const result = await synap.searchMemory({
@@ -120,147 +81,28 @@ async function run() {
120
81
  run().catch(console.error);
121
82
  ```
122
83
 
123
- ## API
124
-
125
- ### `createClient(options)` / `new SynapClient(options)`
84
+ ## TypeScript Extension Setup
126
85
 
127
- Options:
128
-
129
- - `instanceId`: explicit Synap instance id. If omitted, the SDK tries `SYNAP_INSTANCE_ID`, then `~/.synap/instances/*/metadata.json`.
130
- - `bootstrapToken`: one-time bootstrap token/key (env: `SYNAP_BOOTSTRAP_TOKEN` or `SYNAP_BOOTSTRAP_KEY`). Required on first initialization of a new instance.
131
- - `baseUrl`, `grpcHost`, `grpcPort`, `grpcUseTls`: Synap endpoints.
132
- - `pythonBin`: explicit Python path for the bridge.
133
- - `bridgeScriptPath`: override Python bridge script path.
134
- - `sdkHome`: home for managed runtime (default `~/.synap-js-sdk`).
135
- - `venvPath`: override managed venv path.
136
- - `pythonPackage`: pip package name (default `maximem-synap`).
137
- - `pythonSdkVersion`: pip version pin.
138
- - `noDeps`: use pip `--no-deps` during auto setup.
139
- - `noBuildIsolation`: use pip `--no-build-isolation` during auto setup.
140
- - `upgrade`: use pip `--upgrade` during auto setup.
141
- - `forceRecreateVenv`: recreate managed venv during auto setup.
142
- - `autoSetup`: if `true`, runtime setup is attempted automatically when Python is missing.
143
-
144
- ### Methods
145
-
146
- - `init()`
147
- - `addMemory({ userId, messages })`
148
- - `searchMemory({ userId, query, maxResults })`
149
- - `getMemories({ userId })`
150
- - `deleteMemory({ userId, memoryId })`
151
- - `shutdown()`
152
-
153
- ## CLI
86
+ Add TypeScript support to an existing JS project:
154
87
 
155
88
  ```bash
156
- synap-js-sdk setup [options]
157
- synap-js-sdk setup-ts [options]
89
+ npx synap-js-sdk setup-ts
158
90
  ```
159
91
 
160
- Options:
161
-
162
- `setup`:
163
- - `--python <bin>`: bootstrap Python command (default `python3`)
164
- - `--sdk-home <path>`: runtime home directory
165
- - `--venv <path>`: virtualenv path
166
- - `--package <name>`: Python package name
167
- - `--sdk-version <ver>`: Python SDK version pin
168
- - `--no-deps`: install package with no dependency resolution
169
- - `--no-build-isolation`: disable pip build isolation
170
- - `--upgrade`: use pip `--upgrade`
171
- - `--force-recreate-venv`: recreate venv
92
+ This command can:
93
+ - install `typescript` and `@types/node`
94
+ - generate `tsconfig.json` (if missing)
95
+ - generate `src/synap.ts` typed wrapper (if missing)
172
96
 
173
- `setup-ts`:
174
- - `--project-dir <path>`: target Node project (default: current working directory)
175
- - `--package-manager <name>`: one of `npm`, `pnpm`, `yarn`, `bun` (auto-detected by lockfile if omitted)
176
- - `--skip-install`: skip TypeScript dependency install (`typescript`, `@types/node`)
177
- - `--tsconfig-path <path>`: output path for generated tsconfig (default: `tsconfig.json`)
178
- - `--wrapper-path <path>`: output path for generated typed wrapper (default: `src/synap.ts`)
179
- - `--no-wrapper`: do not generate typed wrapper file
180
- - `--force`: overwrite generated files if they already exist
181
-
182
- ## TypeScript Extension Flow
183
-
184
- Use this when a project already has `@maximem/synap-js-sdk` installed and wants type safety without rewriting runtime JS:
185
-
186
- 1. Run `npx synap-js-sdk setup-ts`
187
- 2. This installs `typescript` and `@types/node` (unless `--skip-install`)
188
- 3. This generates `tsconfig.json` (if missing)
189
- 4. This generates `src/synap.ts` typed wrapper (unless `--no-wrapper`)
190
-
191
- Programmatic alternative:
192
-
193
- ```js
194
- const { setupTypeScriptExtension } = require('@maximem/synap-js-sdk');
195
-
196
- setupTypeScriptExtension({ projectDir: process.cwd() });
197
- ```
198
-
199
- ## Environment template
200
-
201
- Use the provided template:
97
+ ## Single-Flow Setup (JS + TS)
202
98
 
203
99
  ```bash
204
- cp .env.example .env
205
- ```
206
-
207
- Template file: `.env.example`
208
-
209
- ## EC2 + Docker flow (recommended)
210
-
211
- Build time should install Node deps and Python runtime once, not on every container start.
212
-
213
- ```dockerfile
214
- FROM node:20-bullseye
215
-
216
- RUN apt-get update && apt-get install -y python3 python3-venv && rm -rf /var/lib/apt/lists/*
217
-
218
- WORKDIR /app
219
- COPY package*.json ./
220
- RUN npm ci
221
-
222
- # Install wrapper python runtime deterministically
223
- RUN npx synap-js-sdk setup --python python3 --sdk-home /opt/synap-js-sdk --sdk-version <PY_SDK_VERSION>
224
-
225
- COPY . .
226
-
227
- ENV SYNAP_JS_SDK_HOME=/opt/synap-js-sdk
228
- ENV SYNAP_BASE_URL=http://<synap-api-host>:8000
229
- ENV SYNAP_GRPC_HOST=<synap-grpc-host>
230
- ENV SYNAP_GRPC_PORT=50051
231
- ENV SYNAP_GRPC_TLS=false
232
-
233
- CMD ["node", "server.js"]
100
+ npm install @maximem/synap-js-sdk && npx synap-js-sdk setup --sdk-version 0.1.1 && npx synap-js-sdk setup-ts
234
101
  ```
235
102
 
236
- Runtime flow in container:
237
-
238
- 1. Node app starts.
239
- 2. First Synap call starts Python bridge process.
240
- 3. Bridge sends `init` to Python SDK.
241
- 4. API methods run through JSON-RPC.
242
- 5. On shutdown, wrapper sends `shutdown` and stops bridge.
243
-
244
- ## Versioning and compatibility matrix
245
-
246
- Recommended policy:
247
-
248
- 1. Keep JS and Python SDK on the same semantic version (`x.y.z`).
249
- 2. Publish JS only after Python package `x.y.z` is available.
250
- 3. CI release pipeline should verify `pip install maximem-synap==x.y.z` before npm publish.
251
-
252
- Even with same-version policy, keep a compatibility table in docs for rollback safety:
103
+ ## CLI Commands
253
104
 
254
- ```text
255
- JS 1.3.x -> Python 1.3.x
256
- JS 1.2.x -> Python 1.2.x
105
+ ```bash
106
+ synap-js-sdk setup [options]
107
+ synap-js-sdk setup-ts [options]
257
108
  ```
258
-
259
- ## Failure modes to expect
260
-
261
- - Python not installed or not found
262
- - Bridge process crash/restart
263
- - pip install failure due to network/private index
264
- - auth/instance id missing or expired
265
-
266
- Treat this SDK as a managed dual-runtime component in production.
@@ -168,11 +168,12 @@ async def handle_add_memory(params: dict) -> dict:
168
168
  start = time.perf_counter()
169
169
 
170
170
  step = time.perf_counter()
171
+ mode = params.get("mode", "long-range")
171
172
  create_result = await sdk.memories.create(
172
173
  document=transcript,
173
174
  document_type="ai-chat-conversation",
174
175
  user_id=user_id,
175
- mode="long-range",
176
+ mode=mode,
176
177
  )
177
178
  append_step(timings, "memories_create", step)
178
179
 
@@ -243,6 +244,7 @@ async def handle_search_memory(params: dict) -> dict:
243
244
  user_id = params["user_id"]
244
245
  query = params["query"]
245
246
  max_results = params.get("max_results", 10)
247
+ mode = params.get("mode", "fast")
246
248
 
247
249
  start = time.perf_counter()
248
250
 
@@ -252,7 +254,7 @@ async def handle_search_memory(params: dict) -> dict:
252
254
  search_query=[query],
253
255
  max_results=max_results,
254
256
  types=["all"],
255
- mode="fast",
257
+ mode=mode,
256
258
  )
257
259
  append_step(timings, "context_fetch", step)
258
260
 
@@ -293,6 +295,7 @@ async def handle_get_memories(params: dict) -> dict:
293
295
  timings: List[dict] = []
294
296
 
295
297
  user_id = params["user_id"]
298
+ mode = params.get("mode", "fast")
296
299
 
297
300
  start = time.perf_counter()
298
301
 
@@ -302,7 +305,7 @@ async def handle_get_memories(params: dict) -> dict:
302
305
  search_query=[],
303
306
  max_results=100,
304
307
  types=["all"],
305
- mode="fast",
308
+ mode=mode,
306
309
  )
307
310
  append_step(timings, "context_fetch_all", step)
308
311
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@maximem/synap-js-sdk",
3
- "version": "0.1.1",
3
+ "version": "0.1.4",
4
4
  "description": "JavaScript wrapper around the Synap Python SDK",
5
5
  "main": "src/index.js",
6
6
  "types": "types/index.d.ts",
@@ -14,32 +14,33 @@ class SynapClient {
14
14
  await this.bridge.ensureStarted();
15
15
  }
16
16
 
17
- async addMemory({ userId, messages }) {
17
+ async addMemory({ userId, messages, mode }) {
18
18
  this.#assert(userId, 'userId is required');
19
19
  this.#assert(Array.isArray(messages), 'messages must be an array');
20
20
 
21
- return this.bridge.call(
22
- 'add_memory',
23
- { user_id: userId, messages },
24
- this.options.ingestTimeoutMs
25
- );
21
+ const params = { user_id: userId, messages };
22
+ if (mode !== undefined) params.mode = mode;
23
+
24
+ return this.bridge.call('add_memory', params, this.options.ingestTimeoutMs);
26
25
  }
27
26
 
28
- async searchMemory({ userId, query, maxResults = 10 }) {
27
+ async searchMemory({ userId, query, maxResults = 10, mode }) {
29
28
  this.#assert(userId, 'userId is required');
30
29
  this.#assert(query, 'query is required');
31
30
 
32
- return this.bridge.call('search_memory', {
33
- user_id: userId,
34
- query,
35
- max_results: maxResults,
36
- });
31
+ const params = { user_id: userId, query, max_results: maxResults };
32
+ if (mode !== undefined) params.mode = mode;
33
+
34
+ return this.bridge.call('search_memory', params);
37
35
  }
38
36
 
39
- async getMemories({ userId }) {
37
+ async getMemories({ userId, mode }) {
40
38
  this.#assert(userId, 'userId is required');
41
39
 
42
- return this.bridge.call('get_memories', { user_id: userId });
40
+ const params = { user_id: userId };
41
+ if (mode !== undefined) params.mode = mode;
42
+
43
+ return this.bridge.call('get_memories', params);
43
44
  }
44
45
 
45
46
  async deleteMemory({ userId, memoryId = null }) {