@cybermem/cli 0.9.12 → 0.13.3

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.
Files changed (56) hide show
  1. package/dist/commands/install.js +430 -0
  2. package/dist/commands/reset.js +18 -2
  3. package/dist/commands/uninstall.js +145 -0
  4. package/dist/commands/upgrade.js +91 -52
  5. package/dist/index.js +18 -5
  6. package/dist/templates/ansible/playbooks/deploy-cybermem.yml +201 -24
  7. package/dist/templates/ansible/playbooks/reset-db.yml +44 -0
  8. package/dist/templates/auth-sidecar/Dockerfile +2 -10
  9. package/dist/templates/auth-sidecar/package.json +1 -3
  10. package/dist/templates/auth-sidecar/server.js +149 -110
  11. package/dist/templates/charts/cybermem/.helmignore +13 -0
  12. package/dist/templates/charts/cybermem/templates/dashboard-deployment.yaml +31 -7
  13. package/dist/templates/charts/cybermem/templates/dashboard-service.yaml +4 -4
  14. package/dist/templates/charts/cybermem/templates/openmemory-deployment.yaml +14 -8
  15. package/dist/templates/charts/cybermem/templates/openmemory-service.yaml +3 -3
  16. package/dist/templates/charts/cybermem/templates/secret.yaml +9 -0
  17. package/dist/templates/charts/cybermem/templates/traefik-config.yaml +67 -0
  18. package/dist/templates/charts/cybermem/templates/traefik-deployment.yaml +53 -0
  19. package/dist/templates/charts/cybermem/templates/traefik-service.yaml +17 -0
  20. package/dist/templates/charts/cybermem/values-vps.yaml +8 -4
  21. package/dist/templates/charts/cybermem/values.yaml +17 -9
  22. package/dist/templates/docker-compose.yml +103 -78
  23. package/dist/templates/monitoring/log_exporter/exporter.py +22 -29
  24. package/dist/templates/monitoring/traefik/traefik.yml +1 -4
  25. package/package.json +9 -3
  26. package/templates/ansible/playbooks/deploy-cybermem.yml +201 -24
  27. package/templates/ansible/playbooks/reset-db.yml +44 -0
  28. package/templates/auth-sidecar/Dockerfile +2 -10
  29. package/templates/auth-sidecar/package.json +1 -3
  30. package/templates/auth-sidecar/server.js +149 -110
  31. package/templates/charts/cybermem/.helmignore +13 -0
  32. package/templates/charts/cybermem/templates/dashboard-deployment.yaml +31 -7
  33. package/templates/charts/cybermem/templates/dashboard-service.yaml +4 -4
  34. package/templates/charts/cybermem/templates/openmemory-deployment.yaml +14 -8
  35. package/templates/charts/cybermem/templates/openmemory-service.yaml +3 -3
  36. package/templates/charts/cybermem/templates/secret.yaml +9 -0
  37. package/templates/charts/cybermem/templates/traefik-config.yaml +67 -0
  38. package/templates/charts/cybermem/templates/traefik-deployment.yaml +53 -0
  39. package/templates/charts/cybermem/templates/traefik-service.yaml +17 -0
  40. package/templates/charts/cybermem/values-vps.yaml +8 -4
  41. package/templates/charts/cybermem/values.yaml +17 -9
  42. package/templates/docker-compose.yml +103 -78
  43. package/templates/monitoring/log_exporter/exporter.py +22 -29
  44. package/templates/monitoring/traefik/traefik.yml +1 -4
  45. package/dist/commands/__tests__/backup.test.js +0 -75
  46. package/dist/commands/__tests__/restore.test.js +0 -70
  47. package/dist/commands/deploy.js +0 -239
  48. package/dist/commands/init.js +0 -362
  49. package/dist/commands/login.js +0 -165
  50. package/dist/templates/envs/local.example +0 -27
  51. package/dist/templates/envs/rpi.example +0 -27
  52. package/dist/templates/envs/vps.example +0 -25
  53. package/dist/templates/monitoring/instructions_injector/Dockerfile +0 -15
  54. package/dist/templates/monitoring/instructions_injector/injector.py +0 -137
  55. package/dist/templates/monitoring/instructions_injector/requirements.txt +0 -3
  56. package/dist/templates/openmemory/Dockerfile +0 -19
@@ -1,14 +1,24 @@
1
1
  # Default values for cybermem.
2
2
 
3
+ # Global settings for SSoT
4
+ global:
5
+ traefik:
6
+ port: 8625
7
+ openmemory:
8
+ serviceName: "openmemory"
9
+ port: 8080
10
+ dashboard:
11
+ serviceName: "dashboard"
12
+ port: 3000
13
+
3
14
  openmemory:
4
15
  image:
5
- repository: cybermem-openmemory
6
- pullPolicy: IfNotPresent
16
+ repository: ghcr.io/mikhailkogan17/cybermem-mcp
17
+ pullPolicy: Always
7
18
  tag: "latest"
8
19
  replicaCount: 1
9
20
  service:
10
21
  type: ClusterIP
11
- port: 8080
12
22
  persistence:
13
23
  enabled: true
14
24
  size: 10Gi
@@ -20,23 +30,21 @@ openmemory:
20
30
  requests:
21
31
  cpu: 100m
22
32
  memory: 256Mi
23
- env:
24
- # Passed to the container
25
- OM_PORT: "8080"
33
+ env: {}
26
34
 
27
35
  dashboard:
28
36
  image:
29
- repository: cybermem-dashboard
37
+ repository: ghcr.io/mikhailkogan17/cybermem-dashboard
30
38
  pullPolicy: IfNotPresent
31
39
  tag: "latest"
32
40
  replicaCount: 1
33
41
  service:
34
42
  type: ClusterIP
35
- port: 3000
36
43
  nodePort: 30000 # For k3d/local access if needed
37
44
  resources: {}
38
45
 
39
46
  env:
40
47
  # Shared secrets
41
- OPENMEMORY_API_KEY: "dev-secret-key"
48
+ OPENMEMORY_API_KEY: "sk-74d94d0021f1a9a525e1c311cfd16575"
42
49
  OPENAI_API_KEY: ""
50
+ CYBERMEM_ENV: "staging"
@@ -6,21 +6,28 @@
6
6
  services:
7
7
  traefik:
8
8
  image: traefik:v3.0
9
- container_name: cybermem-traefik
9
+ # container_name removed for simultaneity
10
10
  command:
11
- - --api.dashboard=true
12
- - --api.insecure=true
13
- - --providers.docker=true
14
- - --providers.docker.exposedbydefault=false
15
- - --entrypoints.web.address=:8626
11
+ - --entryPoints.web.address=:${TRAEFIK_PORT:-8626}
12
+ - --ping=true
13
+ - --ping.entryPoint=web
14
+ - --log.level=INFO
16
15
  - --accesslog=true
17
16
  - --accesslog.filepath=/var/log/traefik/access.log
18
17
  - --accesslog.format=json
18
+ - --accesslog.fields.headers.names.X-Client-Name=keep
19
+ - --accesslog.fields.headers.names.X-Client-Version=keep
20
+ - --providers.docker=true
21
+ - --providers.docker.exposedbydefault=false
22
+ - --providers.docker.constraints=Label(`com.docker.compose.project`, `${PROJECT_NAME:-cybermem}`)
23
+ - --providers.file.directory=/etc/traefik/dynamic
24
+ - --providers.file.watch=true
25
+ - --api.dashboard=true
26
+ - --api.insecure=true
19
27
  ports:
20
- - "8626:8626"
28
+ - "${TRAEFIK_PORT:-8626}:${TRAEFIK_PORT:-8626}"
21
29
  volumes:
22
30
  - /var/run/docker.sock:/var/run/docker.sock:ro
23
- - ./monitoring/traefik/traefik.yml:/etc/traefik/traefik.yml:ro
24
31
  - ./monitoring/traefik/dynamic:/etc/traefik/dynamic:ro
25
32
  - traefik-logs:/var/log/traefik
26
33
  labels:
@@ -35,62 +42,67 @@ services:
35
42
  context: ../../mcp
36
43
  dockerfile: Dockerfile
37
44
  image: ghcr.io/mikhailkogan17/cybermem-mcp:latest
38
- # Note: platform omitted - docker auto-detects (amd64 for CI, arm64 for RPi)
45
+ command:
46
+ [
47
+ "node",
48
+ "dist/index.js",
49
+ "--http",
50
+ "--port",
51
+ "8080",
52
+ "--env",
53
+ "${CYBERMEM_ENV:-prod}",
54
+ ]
39
55
  restart: unless-stopped
40
- container_name: cybermem-mcp
56
+ # container_name removed for simultaneity
41
57
  environment:
42
- OM_TIER: "hybrid"
43
- PORT: "8080"
44
- OM_PORT: "0"
45
58
  OM_DB_PATH: /data/openmemory.sqlite
59
+ CYBERMEM_ENV: ${CYBERMEM_ENV:-prod}
60
+ CYBERMEM_INSTANCE: ${CYBERMEM_INSTANCE:-local}
61
+ CYBERMEM_TAILSCALE: ${CYBERMEM_TAILSCALE:-false}
46
62
  volumes:
47
63
  - ${CYBERMEM_ENV_PATH:-${HOME}/.cybermem/.env}:/.env
48
- - ${HOME}/.cybermem/data:/data
64
+ - ${DATA_DIR:-${HOME}/.cybermem/data}:/data
65
+ - ${SECRETS_DIR:-./secrets}/om_api_key:/run/secrets/om_api_key:ro
49
66
  depends_on:
50
67
  - traefik
51
68
  - auth-sidecar
69
+ # Secrets removed to avoid CI read-only mount issues
70
+ # secrets:
71
+ # - om_api_key
52
72
  labels:
53
73
  - traefik.enable=true
54
- # Middleware definitions (must be on a service that starts BEFORE routes reference them)
55
- # Authenticated routes
56
- - traefik.http.routers.mcp.rule=PathPrefix(`/mcp`) || PathPrefix(`/sse`)
57
- - traefik.http.routers.mcp.entrypoints=web
58
- - traefik.http.routers.mcp.priority=100
59
- - traefik.http.routers.mcp.service=mcp-service
60
- - traefik.http.routers.mcp.middlewares=auth-check
61
- # Public routes (Health/Metrics)
62
- - traefik.http.routers.mcp-public.rule=PathPrefix(`/health`) || PathPrefix(`/metrics`)
63
- - traefik.http.routers.mcp-public.entrypoints=web
64
- - traefik.http.routers.mcp-public.priority=100
65
- - traefik.http.routers.mcp-public.service=mcp-service
66
- - traefik.http.services.mcp-service.loadbalancer.server.port=8080
67
- # Legacy API support (for simple REST clients)
68
- - traefik.http.routers.legacy-api.rule=PathPrefix(`/add`) || PathPrefix(`/query`) || PathPrefix(`/all`)
69
- - traefik.http.routers.legacy-api.entrypoints=web
70
- - traefik.http.routers.legacy-api.priority=100
71
- - traefik.http.routers.legacy-api.service=mcp-service
72
- - traefik.http.routers.legacy-api.middlewares=auth-check
74
+ - traefik.http.routers.${PROJECT_NAME:-cybermem}-mcp.rule=PathPrefix(`/mcp`) || PathPrefix(`/sse`)
75
+ - traefik.http.routers.${PROJECT_NAME:-cybermem}-mcp.entrypoints=web
76
+ - traefik.http.routers.${PROJECT_NAME:-cybermem}-mcp.priority=100
77
+ - traefik.http.routers.${PROJECT_NAME:-cybermem}-mcp.service=${PROJECT_NAME:-cybermem}-mcp-service
78
+ - traefik.http.routers.${PROJECT_NAME:-cybermem}-mcp.middlewares=auth-check
79
+ - traefik.http.routers.${PROJECT_NAME:-cybermem}-mcp-public.rule=PathPrefix(`/health`)
80
+ - traefik.http.routers.${PROJECT_NAME:-cybermem}-mcp-public.entrypoints=web
81
+ - traefik.http.routers.${PROJECT_NAME:-cybermem}-mcp-public.priority=100
82
+ - traefik.http.routers.${PROJECT_NAME:-cybermem}-mcp-public.service=${PROJECT_NAME:-cybermem}-mcp-service
83
+ - traefik.http.services.${PROJECT_NAME:-cybermem}-mcp-service.loadbalancer.server.port=8080
84
+ - traefik.http.routers.${PROJECT_NAME:-cybermem}-legacy-api.rule=PathPrefix(`/add`) || PathPrefix(`/query`) || PathPrefix(`/all`) || PathPrefix(`/memory`)
85
+ - traefik.http.routers.${PROJECT_NAME:-cybermem}-legacy-api.entrypoints=web
86
+ - traefik.http.routers.${PROJECT_NAME:-cybermem}-legacy-api.priority=130
87
+ - traefik.http.routers.${PROJECT_NAME:-cybermem}-legacy-api.service=${PROJECT_NAME:-cybermem}-mcp-service
88
+ - traefik.http.routers.${PROJECT_NAME:-cybermem}-legacy-api.middlewares=auth-check
73
89
 
74
- # Support legacy /cybermem redirect to root
75
- - traefik.http.middlewares.cybermem-redirect.redirectregex.regex=^https?://[^/]+/cybermem(/.*)?$$
76
- - traefik.http.middlewares.cybermem-redirect.redirectregex.replacement=/$${1}
77
- - traefik.http.middlewares.cybermem-redirect.redirectregex.permanent=false
78
- - traefik.http.routers.cybermem-legacy.rule=PathPrefix(`/cybermem`)
79
- - traefik.http.routers.cybermem-legacy.entrypoints=web
80
- - traefik.http.routers.cybermem-legacy.middlewares=cybermem-redirect
81
- - traefik.http.routers.cybermem-legacy.priority=50
82
-
83
- # Auth sidecar for JWT/API key validation (ForwardAuth)
84
90
  auth-sidecar:
91
+ build:
92
+ context: ./auth-sidecar
93
+ dockerfile: Dockerfile
85
94
  image: ghcr.io/mikhailkogan17/cybermem-auth-sidecar:latest
86
- container_name: cybermem-auth-sidecar
95
+ # container_name removed for simultaneity
87
96
  environment:
88
97
  PORT: "3001"
89
98
  OM_DB_PATH: /data/openmemory.sqlite
90
- API_KEY_FILE: /.env
99
+ CYBERMEM_ENV: ${CYBERMEM_ENV:-prod}
100
+ CYBERMEM_INSTANCE: ${CYBERMEM_INSTANCE:-local}
101
+ CYBERMEM_TAILSCALE: ${CYBERMEM_TAILSCALE:-false}
91
102
  volumes:
92
103
  - ${CYBERMEM_ENV_PATH:-${HOME}/.cybermem/.env}:/.env:ro
93
- - ${HOME}/.cybermem/data:/data
104
+ - ${DATA_DIR:-${HOME}/.cybermem/data}:/data
105
+ - ${SECRETS_DIR:-./secrets}/om_api_key:/run/secrets/om_api_key:ro
94
106
  labels:
95
107
  - traefik.enable=true
96
108
  healthcheck:
@@ -107,27 +119,29 @@ services:
107
119
  timeout: 5s
108
120
  retries: 3
109
121
  restart: unless-stopped
110
-
111
- # Memory engine (MCP + Persistence)
112
- # Uses embedded SQLite stored at ~/.cybermem/data/openmemory.sqlite
122
+ # secrets:
123
+ # - om_api_key
113
124
 
114
125
  db-exporter:
126
+ build:
127
+ context: ./monitoring/db_exporter
128
+ dockerfile: Dockerfile
115
129
  image: ghcr.io/mikhailkogan17/cybermem-db_exporter:latest
116
- container_name: cybermem-db-exporter
130
+ # container_name removed for simultaneity
117
131
  environment:
118
132
  DB_PATH: /data/openmemory.sqlite
119
133
  SCRAPE_INTERVAL: "15"
120
134
  EXPORTER_PORT: "8000"
121
- ports:
122
- - "8000:8000"
123
135
  volumes:
124
- # Mount host openmemory data dir (created by SDK)
125
- - ${HOME}/.cybermem/data:/data
136
+ - ${DATA_DIR:-${HOME}/.cybermem/data}:/data
126
137
  restart: unless-stopped
127
138
 
128
139
  log-exporter:
140
+ build:
141
+ context: ./monitoring/log_exporter
142
+ dockerfile: Dockerfile
129
143
  image: ghcr.io/mikhailkogan17/cybermem-log_exporter:latest
130
- container_name: cybermem-log-exporter
144
+ # container_name removed for simultaneity
131
145
  environment:
132
146
  LOG_FILE: /var/log/traefik/access.log
133
147
  SCRAPE_INTERVAL: "5"
@@ -135,7 +149,7 @@ services:
135
149
  DB_PATH: /data/openmemory.sqlite
136
150
  volumes:
137
151
  - traefik-logs:/var/log/traefik:ro
138
- - ${HOME}/.cybermem/data:/data
152
+ - ${DATA_DIR:-${HOME}/.cybermem/data}:/data
139
153
  - ./monitoring/log_exporter/exporter.py:/app/exporter.py:ro
140
154
  restart: unless-stopped
141
155
  depends_on:
@@ -143,7 +157,7 @@ services:
143
157
 
144
158
  postgres:
145
159
  image: postgres:15-alpine
146
- container_name: cybermem-postgres
160
+ # container_name removed for simultaneity
147
161
  environment:
148
162
  POSTGRES_DB: ${PG_DB:-openmemory}
149
163
  POSTGRES_USER: ${PG_USER:-openmemory}
@@ -163,7 +177,7 @@ services:
163
177
 
164
178
  ollama:
165
179
  image: ollama/ollama:latest
166
- container_name: cybermem-ollama
180
+ # container_name removed for simultaneity
167
181
  ports:
168
182
  - "11434:11434"
169
183
  volumes:
@@ -173,49 +187,60 @@ services:
173
187
  - ollama
174
188
 
175
189
  dashboard:
190
+ build:
191
+ context: ../../dashboard
192
+ dockerfile: Dockerfile
176
193
  image: ghcr.io/mikhailkogan17/cybermem-dashboard:latest
177
- # Note: platform omitted - docker auto-detects (amd64 for CI, arm64 for RPi)
178
- container_name: cybermem-dashboard
194
+ # container_name removed for simultaneity
195
+ # ports:
196
+ # - "${DASHBOARD_PORT:-3000}:3000"
179
197
  environment:
180
198
  DB_EXPORTER_URL: http://db-exporter:8000
181
- # Required for Health Check to find the MCP API internally
182
- CYBERMEM_URL: http://mcp-server:8080
199
+ INTERNAL_MCP_URL: http://mcp-server:8080
183
200
  OM_DB_PATH: /data/openmemory.sqlite
184
- OM_API_KEY: ${OM_API_KEY:-dev-secret-key}
185
- # Tailscale domain for remote config (optional, auto-detected if not set)
186
201
  TAILSCALE_DOMAIN: ${TAILSCALE_DOMAIN:-}
187
- ports:
188
- - "3000:3000"
202
+ CYBERMEM_ENV: ${CYBERMEM_ENV:-prod}
203
+ CYBERMEM_INSTANCE: ${CYBERMEM_INSTANCE:-local}
204
+ CYBERMEM_TAILSCALE: ${CYBERMEM_TAILSCALE:-false}
189
205
  volumes:
190
- - ${HOME}/.cybermem/data:/data
206
+ - ${DATA_DIR:-${HOME}/.cybermem/data}:/data
191
207
  - /var/run/docker.sock:/var/run/docker.sock
192
208
  - ${CYBERMEM_ENV_PATH:-${HOME}/.cybermem/.env}:/app/shared.env
193
209
  labels:
194
210
  - traefik.enable=true
195
- # Dashboard route: root -> dashboard on port 3000
196
- - traefik.http.routers.dashboard.entrypoints=web
197
- - traefik.http.routers.dashboard.rule=PathPrefix(`/`)
198
- - traefik.http.routers.dashboard.priority=1
199
- - traefik.http.routers.dashboard.middlewares=auth-check
200
- - traefik.http.services.dashboard.loadbalancer.server.port=3000
211
+ - traefik.http.routers.${PROJECT_NAME:-cybermem}-dashboard-public.rule=PathPrefix(`/auth`) || PathPrefix(`/_next`) || PathPrefix(`/static`) || PathPrefix(`/api/auth`)
212
+ - traefik.http.routers.${PROJECT_NAME:-cybermem}-dashboard-public.entrypoints=web
213
+ - traefik.http.routers.${PROJECT_NAME:-cybermem}-dashboard-public.priority=120
214
+ - traefik.http.routers.${PROJECT_NAME:-cybermem}-dashboard-public.service=${PROJECT_NAME:-cybermem}-dashboard
215
+ - traefik.http.routers.${PROJECT_NAME:-cybermem}-dashboard.rule=PathPrefix(`/`)
216
+ - traefik.http.routers.${PROJECT_NAME:-cybermem}-dashboard.entrypoints=web
217
+ - traefik.http.routers.${PROJECT_NAME:-cybermem}-dashboard.priority=1
218
+ - traefik.http.routers.${PROJECT_NAME:-cybermem}-dashboard.middlewares=auth-check
219
+ - traefik.http.services.${PROJECT_NAME:-cybermem}-dashboard.loadbalancer.server.port=3000
201
220
  restart: unless-stopped
221
+ # secrets:
222
+ # - om_api_key
202
223
  depends_on:
203
224
  - db-exporter
204
225
 
205
226
  volumes:
206
227
  openmemory-data:
207
- name: cybermem-data
228
+ name: ${PROJECT_NAME:-cybermem}-data
208
229
  driver: local
209
230
  postgres-data:
210
- name: cybermem-postgres-data
231
+ name: ${PROJECT_NAME:-cybermem}-postgres-data
211
232
  driver: local
212
233
  ollama-models:
213
- name: cybermem-ollama-models
234
+ name: ${PROJECT_NAME:-cybermem}-ollama-models
214
235
  driver: local
215
236
  traefik-logs:
216
- name: cybermem-traefik-logs
237
+ name: ${PROJECT_NAME:-cybermem}-traefik-logs
217
238
  driver: local
218
239
 
240
+ # secrets:
241
+ # om_api_key:
242
+ # file: ${SECRETS_DIR:-./secrets}/om_api_key
243
+
219
244
  networks:
220
245
  default:
221
- name: cybermem-network
246
+ name: ${PROJECT_NAME:-cybermem}-network
@@ -190,20 +190,13 @@ def parse_and_export():
190
190
  status = str(data.get("DownstreamStatus", 0))
191
191
 
192
192
  # Extract MCP client info from custom headers
193
- client_name = data.get("request_X-Client-Name", "unknown")
193
+ client_name = data.get("request_X-Client-Name", "unknown").lower()
194
194
  client_version = data.get("request_X-Client-Version", "unknown")
195
195
 
196
- # Fallback to User-Agent if client_name is unknown
196
+ # Fallback invalid
197
197
  if client_name == "unknown":
198
- ua = data.get("request_User-Agent", "")
199
- if ua and ua != "-":
200
- # Simple heuristic: take the first part before '/' or space
201
- # e.g. "curl/7.64.1" -> "curl", "Mozilla/5.0" -> "Mozilla"
202
- parts = ua.split("/")
203
- if len(parts) > 0:
204
- potential_name = parts[0].split(" ")[0].strip()
205
- if potential_name:
206
- client_name = potential_name
198
+ # STRICT mode: Do NOT fallback to User-Agent
199
+ pass
207
200
 
208
201
  # Remove query params first
209
202
  endpoint = path.split("?")[0]
@@ -234,29 +227,29 @@ def parse_and_export():
234
227
  ):
235
228
  endpoint = "/memory/:id"
236
229
 
237
- # Only track requests to OpenMemory API (/memory/* and /mcp endpoints)
238
230
  # Exclude /health checks - they pollute Top/Last Reader metrics
239
231
  if endpoint.startswith("/memory") or endpoint.startswith("/mcp"):
240
232
  # Check if it's an error (4xx or 5xx)
241
233
  is_error = status.startswith("4") or status.startswith("5")
242
234
 
243
- # Write aggregate stats
244
- increment_stat(client_name, operation, is_error)
245
-
246
- # Log individual request to access_log
247
- log_access(
248
- client_name,
249
- client_version,
250
- method,
251
- endpoint,
252
- operation,
253
- status,
254
- is_error,
255
- )
256
-
257
- print(
258
- f"[{time.strftime('%H:%M:%S')}] {client_name}/{client_version} {method} {endpoint} ({operation}) -> {status}"
259
- )
235
+ # Write aggregate stats AND audit log ONLY for known clients
236
+ if client_name != "unknown" and "health" not in endpoint:
237
+ increment_stat(client_name, operation, is_error)
238
+
239
+ # Log individual request to access_log
240
+ log_access(
241
+ client_name,
242
+ client_version,
243
+ method,
244
+ endpoint,
245
+ operation,
246
+ status,
247
+ is_error,
248
+ )
249
+
250
+ print(
251
+ f"[{time.strftime('%H:%M:%S')}] {client_name}/{client_version} {method} {endpoint} ({operation}) -> {status}"
252
+ )
260
253
 
261
254
  except json.JSONDecodeError:
262
255
  # Skip invalid JSON lines
@@ -26,7 +26,4 @@ providers:
26
26
  file:
27
27
  directory: /etc/traefik/dynamic
28
28
  watch: true
29
-
30
- entryPoints:
31
- web:
32
- address: ":8626"
29
+ # entryPoints and ping moved to docker-compose.yml command for dynamic port support
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cybermem/cli",
3
- "version": "0.9.12",
3
+ "version": "0.13.3",
4
4
  "description": "CyberMem — Universal Long-Term Memory for AI Agents",
5
5
  "homepage": "https://cybermem.dev",
6
6
  "repository": {
@@ -16,10 +16,15 @@
16
16
  "templates"
17
17
  ],
18
18
  "scripts": {
19
- "build": "tsc && cp -r templates dist/",
19
+ "build": "mkdir -p dist && tsc && cp -r templates dist/",
20
20
  "lint": "eslint src/ --ext .ts",
21
21
  "start": "ts-node src/index.ts",
22
- "test:e2e": "ts-node e2e/test-mcp.ts",
22
+ "test:e2e": "playwright test",
23
+ "test:e2e:mcp": "npm run test:e2e -w packages/mcp",
24
+ "test:e2e:dashboard": "npm run test:e2e -w packages/dashboard",
25
+ "test:e2e:dashboard:api": "npm run test:e2e -w packages/dashboard -- --project=api",
26
+ "test:e2e:dashboard:ui": "npm run test:e2e -w packages/dashboard -- --project=ui",
27
+ "test:e2e:cli": "playwright test --project=integration",
23
28
  "prepublishOnly": "npm run build"
24
29
  },
25
30
  "keywords": [
@@ -51,6 +56,7 @@
51
56
  "@typescript-eslint/parser": "^8.52.0",
52
57
  "eslint": "^9.39.2",
53
58
  "ts-node": "^10.9.1",
59
+ "@playwright/test": "^1.57.0",
54
60
  "typescript": "^5.0.0"
55
61
  }
56
62
  }