@wipcomputer/memory-crystal 0.7.10

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 (157) hide show
  1. package/.env.example +20 -0
  2. package/CHANGELOG.md +367 -0
  3. package/LICENSE +21 -0
  4. package/README-ENTERPRISE.md +226 -0
  5. package/README.md +127 -0
  6. package/RELAY.md +199 -0
  7. package/TECHNICAL.md +628 -0
  8. package/_trash/RELEASE-NOTES-v0-7-4.md +64 -0
  9. package/_trash/RELEASE-NOTES-v0-7-5.md +19 -0
  10. package/cloud/README.md +116 -0
  11. package/cloud/docs/gpt-system-instructions.md +69 -0
  12. package/cloud/migrations/0001_init.sql +52 -0
  13. package/dist/bridge.d.ts +7 -0
  14. package/dist/bridge.js +14 -0
  15. package/dist/bulk-copy.d.ts +17 -0
  16. package/dist/bulk-copy.js +90 -0
  17. package/dist/cc-hook.d.ts +8 -0
  18. package/dist/cc-hook.js +368 -0
  19. package/dist/cc-poller.d.ts +1 -0
  20. package/dist/cc-poller.js +550 -0
  21. package/dist/chunk-25LXQJ4Z.js +110 -0
  22. package/dist/chunk-2DRXIRQW.js +97 -0
  23. package/dist/chunk-2ZNH5F6E.js +1281 -0
  24. package/dist/chunk-3G3SFYYI.js +288 -0
  25. package/dist/chunk-3RG5ZIWI.js +10 -0
  26. package/dist/chunk-3S6TI23B.js +97 -0
  27. package/dist/chunk-3VFIJYS4.js +818 -0
  28. package/dist/chunk-52QE3YI3.js +1169 -0
  29. package/dist/chunk-57RP3DIN.js +1205 -0
  30. package/dist/chunk-5HSZ4W2P.js +62 -0
  31. package/dist/chunk-645IPXW3.js +290 -0
  32. package/dist/chunk-7A7ELD4C.js +1205 -0
  33. package/dist/chunk-7FYY4GZM.js +1205 -0
  34. package/dist/chunk-7IUE7ODU.js +254 -0
  35. package/dist/chunk-7RMLKZIS.js +108 -0
  36. package/dist/chunk-AA3OPP4Z.js +432 -0
  37. package/dist/chunk-ASSZDR6I.js +108 -0
  38. package/dist/chunk-AYRJVWUC.js +1205 -0
  39. package/dist/chunk-CCYI5O3D.js +148 -0
  40. package/dist/chunk-D3I3ZSE2.js +411 -0
  41. package/dist/chunk-DACSKLY6.js +219 -0
  42. package/dist/chunk-DW5B4BL7.js +108 -0
  43. package/dist/chunk-EKSACBTJ.js +1070 -0
  44. package/dist/chunk-EXEZZADG.js +248 -0
  45. package/dist/chunk-F3Y7EL7K.js +83 -0
  46. package/dist/chunk-FHRZNOMW.js +1205 -0
  47. package/dist/chunk-IM7N24MT.js +129 -0
  48. package/dist/chunk-IPNYIXFK.js +1178 -0
  49. package/dist/chunk-J7MRSZIO.js +167 -0
  50. package/dist/chunk-JITKI2OI.js +106 -0
  51. package/dist/chunk-JWZXYVET.js +1068 -0
  52. package/dist/chunk-KCQUXVYT.js +108 -0
  53. package/dist/chunk-KOQ43OX6.js +1281 -0
  54. package/dist/chunk-KYVWO6ZM.js +1069 -0
  55. package/dist/chunk-L3VHARQH.js +413 -0
  56. package/dist/chunk-LBWDS6BE.js +288 -0
  57. package/dist/chunk-LOVAHSQV.js +411 -0
  58. package/dist/chunk-LQOYCAGG.js +446 -0
  59. package/dist/chunk-LWAIPJ2W.js +146 -0
  60. package/dist/chunk-M5DHKW7M.js +127 -0
  61. package/dist/chunk-MBKCIJHM.js +1328 -0
  62. package/dist/chunk-MK42FMEG.js +147 -0
  63. package/dist/chunk-MOBMYHKL.js +1205 -0
  64. package/dist/chunk-MPLTNMRG.js +67 -0
  65. package/dist/chunk-NIJCVN3O.js +147 -0
  66. package/dist/chunk-NZCFSZQ7.js +1205 -0
  67. package/dist/chunk-O2UITJGH.js +465 -0
  68. package/dist/chunk-OCRA44AZ.js +108 -0
  69. package/dist/chunk-P3KJR66H.js +117 -0
  70. package/dist/chunk-PEK6JH65.js +432 -0
  71. package/dist/chunk-PJ6FFKEX.js +77 -0
  72. package/dist/chunk-PLUBBZYR.js +800 -0
  73. package/dist/chunk-PNKVD2UK.js +26 -0
  74. package/dist/chunk-PSQZURHO.js +229 -0
  75. package/dist/chunk-SGL6ISBJ.js +1061 -0
  76. package/dist/chunk-SJABZZT5.js +97 -0
  77. package/dist/chunk-TD3P3K32.js +1199 -0
  78. package/dist/chunk-TMDZJJKV.js +288 -0
  79. package/dist/chunk-UNHVZB5G.js +411 -0
  80. package/dist/chunk-VAFTWSTE.js +1061 -0
  81. package/dist/chunk-VNFXFQBB.js +217 -0
  82. package/dist/chunk-X3GVFKSJ.js +1205 -0
  83. package/dist/chunk-XZ3S56RQ.js +1061 -0
  84. package/dist/chunk-Y72C7F6O.js +148 -0
  85. package/dist/chunk-YLICP577.js +1205 -0
  86. package/dist/chunk-YX6AXLVK.js +159 -0
  87. package/dist/chunk-ZCQYHTNU.js +146 -0
  88. package/dist/cli.d.ts +1 -0
  89. package/dist/cli.js +1105 -0
  90. package/dist/cloud-crystal.js +6 -0
  91. package/dist/core.d.ts +232 -0
  92. package/dist/core.js +12 -0
  93. package/dist/crypto.d.ts +20 -0
  94. package/dist/crypto.js +27 -0
  95. package/dist/crystal-capture.sh +29 -0
  96. package/dist/crystal-serve.d.ts +4 -0
  97. package/dist/crystal-serve.js +252 -0
  98. package/dist/dev-update-SZ2Z4WCQ.js +6 -0
  99. package/dist/discover.d.ts +30 -0
  100. package/dist/discover.js +177 -0
  101. package/dist/doctor.d.ts +9 -0
  102. package/dist/doctor.js +334 -0
  103. package/dist/dream-weaver.d.ts +8 -0
  104. package/dist/dream-weaver.js +56 -0
  105. package/dist/file-sync.d.ts +48 -0
  106. package/dist/file-sync.js +18 -0
  107. package/dist/installer.d.ts +61 -0
  108. package/dist/installer.js +618 -0
  109. package/dist/ldm-backup.sh +116 -0
  110. package/dist/ldm.d.ts +50 -0
  111. package/dist/ldm.js +32 -0
  112. package/dist/mcp-server.d.ts +1 -0
  113. package/dist/mcp-server.js +265 -0
  114. package/dist/migrate.d.ts +1 -0
  115. package/dist/migrate.js +89 -0
  116. package/dist/mirror-sync.d.ts +1 -0
  117. package/dist/mirror-sync.js +159 -0
  118. package/dist/oc-backfill.d.ts +19 -0
  119. package/dist/oc-backfill.js +74 -0
  120. package/dist/openclaw.d.ts +5 -0
  121. package/dist/openclaw.js +423 -0
  122. package/dist/pair.d.ts +4 -0
  123. package/dist/pair.js +75 -0
  124. package/dist/poller.d.ts +1 -0
  125. package/dist/poller.js +634 -0
  126. package/dist/role.d.ts +24 -0
  127. package/dist/role.js +13 -0
  128. package/dist/search-pipeline-4K4OJSSS.js +255 -0
  129. package/dist/search-pipeline-4PRS6LI7.js +280 -0
  130. package/dist/search-pipeline-7UJMXPLO.js +280 -0
  131. package/dist/search-pipeline-DQTRLGBH.js +74 -0
  132. package/dist/search-pipeline-HNG37REH.js +282 -0
  133. package/dist/search-pipeline-IZFPLBUB.js +280 -0
  134. package/dist/search-pipeline-MID6F26Q.js +73 -0
  135. package/dist/search-pipeline-N52JZFNN.js +282 -0
  136. package/dist/search-pipeline-OPB2PRQQ.js +280 -0
  137. package/dist/search-pipeline-VXTE5HAD.js +262 -0
  138. package/dist/staging.d.ts +29 -0
  139. package/dist/staging.js +21 -0
  140. package/dist/summarize.d.ts +19 -0
  141. package/dist/summarize.js +10 -0
  142. package/dist/worker-demo.js +186 -0
  143. package/dist/worker-mcp.js +404 -0
  144. package/dist/worker.js +137 -0
  145. package/migrations/0001_init.sql +51 -0
  146. package/migrations/0002_cloud_storage.sql +49 -0
  147. package/openclaw.plugin.json +11 -0
  148. package/package.json +57 -0
  149. package/scripts/crystal-capture 2.sh +29 -0
  150. package/scripts/crystal-capture.sh +29 -0
  151. package/scripts/deploy-cloud 2.sh +153 -0
  152. package/scripts/deploy-cloud.sh +153 -0
  153. package/scripts/ldm-backup.sh +116 -0
  154. package/scripts/migrate-lance-to-sqlite.mjs +217 -0
  155. package/skills/memory/SKILL.md +427 -0
  156. package/wrangler-demo.toml +8 -0
  157. package/wrangler-mcp.toml +24 -0
@@ -0,0 +1,64 @@
1
+ # Memory Crystal v0.7.4 ... MCP Fix + AgentId Config
2
+
3
+ **Date:** 2026-03-11
4
+ **Authors:** Parker Todd Brooks, Lēsa, Claude Code
5
+
6
+ ---
7
+
8
+ ## What's in this release
9
+
10
+ ### Agent identity reads from config, not hardcoded strings
11
+
12
+ The agent_id used when ingesting conversations was hardcoded in three places: `cc-mini` in the CC hook, `main` in the OpenClaw plugin, and `cc-mini` as the fallback in `ldm.ts`. This caused ID drift. The same agent got recorded under multiple IDs, and we had to manually merge 141K+ chunks in the database.
13
+
14
+ Now `getAgentId()` scans `~/.ldm/agents/*/config.json` for a matching harness type. The CC hook passes `'claude-code'`, the OC plugin passes `'openclaw'`, and the config file is the source of truth. `CRYSTAL_AGENT_ID` env var still works as an override.
15
+
16
+ New exports: `AgentConfig`, `loadAgentConfig()`, `saveAgentConfig()`. The installer writes `agentId` to config.json during `crystal init`.
17
+
18
+ **Closes #33.**
19
+
20
+ ### MCP registrations moved to user-level
21
+
22
+ MCP server registrations moved from project-level `~/.openclaw/.mcp.json` to user-level `~/.claude.json`. The old file was a Claude Code convention that only loaded when running from `~/.openclaw/`. Now all 4 MCP servers (memory-crystal, lesa-bridge, wip-agent-pay, wip-repos) load from any directory as "User MCPs".
23
+
24
+ OpenClaw doesn't read `.mcp.json` at all. It uses its own plugin system. The file was moved to `~/.openclaw/_trash/`.
25
+
26
+ ### OPENCLAW_HOME env var fix (v0.7.3)
27
+
28
+ The MCP server registration was missing the `OPENCLAW_HOME` env var. Without it, the memory-crystal MCP server couldn't find Lēsa's OpenClaw installation for private-mode checks. Fixed in v0.7.3, deployed in this release.
29
+
30
+ ### Branch cleanup
31
+
32
+ 33 stale branches renamed with `--merged-` suffix. Zero active branches besides main.
33
+
34
+ ### QMD v1.1.6 analysis documented
35
+
36
+ Deep analysis of the search quality system with four recommendations: intent parameter for search, structured search API, persistent reranker cache, and explain mode for debugging. See `ai/product/notes/2026-03-09--cc-mini--qmd-v1.1.6-analysis-and-recommendations.md`.
37
+
38
+ ---
39
+
40
+ ## Files changed
41
+
42
+ | File | What |
43
+ |------|------|
44
+ | `src/ldm.ts` | `AgentConfig` interface, `loadAgentConfig()`, `saveAgentConfig()`, `getAgentId()` now scans config |
45
+ | `src/cc-hook.ts` | Uses `getAgentId('claude-code')` instead of hardcoded fallback |
46
+ | `src/openclaw.ts` | Uses `OC_AGENT_ID` instead of `'main'` fallback |
47
+ | `src/installer.ts` | Writes `agentId` to config.json during install |
48
+
49
+ ---
50
+
51
+ ## Install
52
+
53
+ ```bash
54
+ npm install -g memory-crystal@0.7.4
55
+ ```
56
+
57
+ Or update your local clone:
58
+ ```bash
59
+ git pull origin main
60
+ ```
61
+
62
+ ---
63
+
64
+ Built by Parker Todd Brooks, Lēsa (OpenClaw, Claude Opus 4.6), Claude Code (Claude Opus 4.6).
@@ -0,0 +1,19 @@
1
+ # Release Notes: Memory Crystal v0.7.5
2
+
3
+ ## LDM OS Integration
4
+
5
+ Memory Crystal now works with LDM OS when it's available.
6
+
7
+ ### crystal init delegates to ldm install
8
+
9
+ When the `ldm` CLI exists on PATH, `crystal init` delegates generic deployment to it. LDM OS handles the scaffold, interface detection, and extension deployment. Memory Crystal keeps its own setup: database backup, role configuration, pairing, cron jobs.
10
+
11
+ When `ldm` isn't available, `crystal init` works standalone like it always has. No new dependencies. No breaking changes.
12
+
13
+ ### LDM OS tip
14
+
15
+ After install completes, Memory Crystal prints a tip: "Run `ldm install` to see more skills you can add." Helps users discover the rest of the ecosystem.
16
+
17
+ ### Part of LDM OS
18
+
19
+ README now includes a "Part of LDM OS" section linking back to the LDM OS repo. Memory Crystal installs into LDM OS, the local runtime for AI agents.
@@ -0,0 +1,116 @@
1
+ # Memory Crystal Cloud
2
+
3
+ Remote MCP server for ChatGPT + Claude. Persistent memory across sessions on all six surfaces (macOS, iOS, web for both ChatGPT and Claude).
4
+
5
+ ## Architecture
6
+
7
+ One MCP server, two tiers:
8
+
9
+ **Tier 1 (Sovereign):** Write-only relay. Memories are encrypted (AES-256-GCM) and relayed to your home machine. The cloud cannot read your data. Search is available only on local devices.
10
+
11
+ **Tier 2 (Convenience):** Cloud search enabled. A mirror of your memory database is pushed to Cloudflare D1 + Vectorize. ChatGPT/Claude can search your memories directly. Privacy trade-off is clearly disclosed.
12
+
13
+ ## Data Flow
14
+
15
+ Every conversation turn, attachment, and explicit memory flows to the Mini:
16
+
17
+ ```
18
+ ChatGPT/Claude → memory_log (every turn) → [encrypt] → R2 relay → Mini poller → crystal.db
19
+ memory_remember (explicit) → [encrypt] → R2 relay → Mini poller → crystal.db
20
+ memory_upload (files/media) → [encrypt] → R2 relay → Mini poller → attachments/
21
+ memory_forget (deprecation) → [encrypt] → R2 relay → Mini poller → crystal.db
22
+ ```
23
+
24
+ The Mini receives the same data it would have if this was a local Claude Code or OpenClaw session:
25
+ - Full conversation JSON (raw messages, tool calls, results)
26
+ - Inline images and file references
27
+ - Binary attachments (images, audio, video, documents)
28
+ - Explicit memories and deprecations
29
+
30
+ ## Setup
31
+
32
+ ```bash
33
+ # From the memory-crystal-private root:
34
+
35
+ # 1. Create D1 database
36
+ cd cloud && npx wrangler d1 create memory-crystal-cloud
37
+ # Copy the database_id into cloud/wrangler.toml
38
+
39
+ # 2. Run migrations
40
+ npm run cloud:db:migrate
41
+
42
+ # 3. Set secrets
43
+ cd cloud
44
+ npx wrangler secret put CRYSTAL_RELAY_KEY # base64, 32 bytes (same as relay)
45
+ npx wrangler secret put OAUTH_SIGNING_SECRET # any random string
46
+ npx wrangler secret put OPENAI_API_KEY # for Tier 2 embeddings
47
+
48
+ # 4. Deploy
49
+ npm run cloud:deploy
50
+ ```
51
+
52
+ ## Development
53
+
54
+ ```bash
55
+ npm run cloud:dev # local dev server
56
+ npm run cloud:db:migrate # apply D1 migrations locally
57
+ ```
58
+
59
+ ## Endpoints
60
+
61
+ | Path | Method | Auth | Description |
62
+ |------|--------|------|-------------|
63
+ | `/health` | GET | No | Health check |
64
+ | `/.well-known/oauth-protected-resource` | GET | No | OAuth resource metadata |
65
+ | `/.well-known/oauth-authorization-server` | GET | No | OAuth server metadata |
66
+ | `/oauth/register` | POST | No | Dynamic Client Registration |
67
+ | `/oauth/authorize` | GET/POST | No | Authorization + consent page |
68
+ | `/oauth/token` | POST | No | Token exchange (PKCE S256) |
69
+ | `/mcp` | POST | Bearer | MCP JSON-RPC endpoint |
70
+
71
+ ## MCP Tools
72
+
73
+ | Tool | Description | Annotation |
74
+ |------|-------------|-----------|
75
+ | `memory_search` | Search memories | readOnly |
76
+ | `memory_remember` | Store a memory (fact, preference, event, opinion, skill) | write |
77
+ | `memory_forget` | Deprecate a memory by ID | destructive |
78
+ | `memory_status` | Show status, pending drops, tier info | readOnly |
79
+ | `memory_log` | Log a conversation turn (call every exchange) | write, idempotent |
80
+ | `memory_upload` | Upload a file attachment (image, audio, video, doc) | write |
81
+
82
+ ### memory_log
83
+
84
+ This is the key tool for full data capture. The system prompt instructs the AI to call `memory_log` after every exchange with:
85
+ - `role` + `content` (the text)
86
+ - `raw_json` (the complete message object as JSON string)
87
+ - `tool_calls` (any tools called in the turn)
88
+ - `attachments` (inline images, files, audio)
89
+ - `session_id` + `turn_index` (for conversation grouping)
90
+
91
+ The Mini processes these through the same chunking and embedding pipeline used for local sessions.
92
+
93
+ ### memory_upload
94
+
95
+ Handles binary files. The AI encodes the file as base64 and calls this tool. The file is encrypted (AES-256-GCM) and stored as a separate R2 object. A metadata drop references the blob. The Mini poller picks up both.
96
+
97
+ Supports: images (png, jpg, webp, gif), audio (mp3, mp4, wav, ogg), video (mp4, webm, mov), documents (pdf, txt, csv).
98
+
99
+ Max file size: 100MB (R2 single-put limit).
100
+
101
+ ## Files
102
+
103
+ ```
104
+ cloud/
105
+ wrangler.toml -- Cloudflare Worker config
106
+ migrations/
107
+ 0001_init.sql -- D1 schema (OAuth + users)
108
+ README.md -- this file
109
+
110
+ src/cloud/
111
+ index.ts -- Worker entry point, request router
112
+ auth.ts -- OAuth 2.1 (DCR, authorize, token)
113
+ mcp.ts -- MCP tool definitions + handlers (6 tools)
114
+ relay.ts -- Encrypt + drop to relay (Web Crypto)
115
+ types.ts -- Shared types
116
+ ```
@@ -0,0 +1,69 @@
1
+ # Memory Crystal - System Instructions
2
+
3
+ These instructions are for the Custom GPT / Claude connector that uses the Memory Crystal MCP server.
4
+
5
+ ---
6
+
7
+ ## Identity
8
+
9
+ You are Memory Crystal, a persistent memory layer for your conversations. Every message in this conversation is captured and sent to the user's home machine, where it becomes part of their searchable memory.
10
+
11
+ ## Core Behavior
12
+
13
+ ### 1. Log Every Turn
14
+
15
+ After EVERY user message and EVERY assistant response, call `memory_log` with:
16
+
17
+ - `role`: "user" or "assistant"
18
+ - `content`: the full message text
19
+ - `session_id`: generate a unique ID at the start of each conversation (e.g. UUID) and reuse it for all turns
20
+ - `turn_index`: increment from 0 for each message in the conversation
21
+ - `model`: your model name (assistant turns only, e.g. "gpt-4o")
22
+
23
+ If the user's message includes images, files, or audio:
24
+ - Include them in the `attachments` array with `type`, `filename`, and `mime_type`
25
+ - For small files (under 64KB), include `data_base64`
26
+ - For larger files, note the reference in `context`
27
+
28
+ If your response includes tool calls:
29
+ - Include them in the `tool_calls` array with `tool_name`, `arguments`, and `result`
30
+
31
+ ### 2. Remember When Asked
32
+
33
+ When the user says things like "remember this", "save this", "note that":
34
+ - Call `memory_remember` with the specific fact/preference/observation
35
+ - Choose the right category: fact, preference, event, opinion, skill
36
+
37
+ ### 3. Forget When Asked
38
+
39
+ When the user says "forget that" or "remove that memory":
40
+ - Call `memory_forget` with the memory ID
41
+
42
+ ### 4. Search When Asked
43
+
44
+ When the user asks "do you remember...", "what did I say about...", "find my notes on...":
45
+ - Call `memory_search` with their query
46
+ - If in Sovereign mode, explain that search is available on their local devices
47
+
48
+ ### 5. Upload Files
49
+
50
+ When the user shares images, documents, audio, or video:
51
+ - Call `memory_upload` with the file data (base64 encoded)
52
+ - Include `filename`, `mime_type`, and optional `context`
53
+ - This ensures all media gets saved to their home machine
54
+
55
+ ## Important Rules
56
+
57
+ - ALWAYS log both sides of the conversation. Never skip a turn.
58
+ - The `session_id` must be consistent within a single conversation.
59
+ - Do not mention the logging process unless the user asks about it.
60
+ - When Memory Crystal is in Sovereign mode, search returns a guidance message. This is by design. The user's data stays on their hardware.
61
+ - Be concise. The memory system captures everything automatically.
62
+
63
+ ## Status
64
+
65
+ Call `memory_status` when the user asks about their memory system, connection health, or tier information.
66
+
67
+ ## Privacy
68
+
69
+ All data is encrypted in transit (AES-256-GCM). In Sovereign mode, the cloud cannot read any data. Memories flow to the user's home machine and are deleted from the relay after pickup.
@@ -0,0 +1,52 @@
1
+ -- Memory Crystal Cloud: initial schema
2
+ -- OAuth tables for auth + user accounts
3
+ -- Tier 1: relay-only (sovereign)
4
+ -- Tier 2: adds chunks + memories tables (separate migration)
5
+
6
+ -- ── OAuth Clients (Dynamic Client Registration) ──
7
+ CREATE TABLE IF NOT EXISTS oauth_clients (
8
+ client_id TEXT PRIMARY KEY,
9
+ redirect_uris TEXT NOT NULL DEFAULT '[]',
10
+ client_name TEXT,
11
+ created_at TEXT NOT NULL,
12
+ last_used_at TEXT
13
+ );
14
+
15
+ -- ── Authorization Codes (PKCE flow) ──
16
+ CREATE TABLE IF NOT EXISTS authorization_codes (
17
+ code TEXT PRIMARY KEY,
18
+ client_id TEXT NOT NULL,
19
+ user_id TEXT NOT NULL,
20
+ code_challenge TEXT NOT NULL,
21
+ code_challenge_method TEXT NOT NULL DEFAULT 'S256',
22
+ redirect_uri TEXT NOT NULL,
23
+ scope TEXT,
24
+ expires_at TEXT NOT NULL,
25
+ used INTEGER DEFAULT 0
26
+ );
27
+
28
+ -- ── Access Tokens ──
29
+ CREATE TABLE IF NOT EXISTS access_tokens (
30
+ token_hash TEXT PRIMARY KEY,
31
+ client_id TEXT NOT NULL,
32
+ user_id TEXT NOT NULL,
33
+ scope TEXT,
34
+ tier TEXT NOT NULL DEFAULT 'sovereign',
35
+ expires_at TEXT NOT NULL,
36
+ created_at TEXT NOT NULL
37
+ );
38
+
39
+ -- ── Users ──
40
+ CREATE TABLE IF NOT EXISTS users (
41
+ user_id TEXT PRIMARY KEY,
42
+ email TEXT NOT NULL UNIQUE,
43
+ tier TEXT NOT NULL DEFAULT 'sovereign',
44
+ relay_token TEXT,
45
+ created_at TEXT NOT NULL
46
+ );
47
+
48
+ -- ── Indexes ──
49
+ CREATE INDEX IF NOT EXISTS idx_auth_codes_client ON authorization_codes(client_id);
50
+ CREATE INDEX IF NOT EXISTS idx_tokens_user ON access_tokens(user_id);
51
+ CREATE INDEX IF NOT EXISTS idx_tokens_expires ON access_tokens(expires_at);
52
+ CREATE INDEX IF NOT EXISTS idx_clients_last_used ON oauth_clients(last_used_at);
@@ -0,0 +1,7 @@
1
+ declare function isBridgeInstalled(): boolean;
2
+ declare function isBridgeRegistered(): boolean;
3
+ declare function isBridgeDesktopRegistered(): boolean;
4
+ declare function registerBridgeMcp(): void;
5
+ declare function registerBridgeDesktop(): boolean;
6
+
7
+ export { isBridgeDesktopRegistered, isBridgeInstalled, isBridgeRegistered, registerBridgeDesktop, registerBridgeMcp };
package/dist/bridge.js ADDED
@@ -0,0 +1,14 @@
1
+ import {
2
+ isBridgeDesktopRegistered,
3
+ isBridgeInstalled,
4
+ isBridgeRegistered,
5
+ registerBridgeDesktop,
6
+ registerBridgeMcp
7
+ } from "./chunk-MPLTNMRG.js";
8
+ export {
9
+ isBridgeDesktopRegistered,
10
+ isBridgeInstalled,
11
+ isBridgeRegistered,
12
+ registerBridgeDesktop,
13
+ registerBridgeMcp
14
+ };
@@ -0,0 +1,17 @@
1
+ interface BulkCopyResult {
2
+ filesCopied: number;
3
+ filesSkipped: number;
4
+ bytesWritten: number;
5
+ durationMs: number;
6
+ }
7
+ interface BulkCopyOptions {
8
+ workspace?: boolean;
9
+ workspaceSrc?: string;
10
+ }
11
+ /** Copy session JSONL files from source locations to LDM transcripts.
12
+ * sessionPaths: array of absolute paths to JSONL files.
13
+ * agentId: target agent in ~/.ldm/agents/{agentId}/.
14
+ * Returns copy stats. */
15
+ declare function bulkCopyToLdm(sessionPaths: string[], agentId: string, options?: BulkCopyOptions): BulkCopyResult;
16
+
17
+ export { type BulkCopyOptions, type BulkCopyResult, bulkCopyToLdm };
@@ -0,0 +1,90 @@
1
+ import {
2
+ ldmPaths
3
+ } from "./chunk-EXEZZADG.js";
4
+
5
+ // src/bulk-copy.ts
6
+ import { existsSync, mkdirSync, copyFileSync, statSync, readdirSync } from "fs";
7
+ import { join, basename } from "path";
8
+ function bulkCopyToLdm(sessionPaths, agentId, options) {
9
+ const start = Date.now();
10
+ const paths = ldmPaths(agentId);
11
+ let filesCopied = 0;
12
+ let filesSkipped = 0;
13
+ let bytesWritten = 0;
14
+ mkdirSync(paths.transcripts, { recursive: true });
15
+ for (const srcPath of sessionPaths) {
16
+ const destPath = join(paths.transcripts, basename(srcPath));
17
+ if (existsSync(destPath)) {
18
+ try {
19
+ const srcSize = statSync(srcPath).size;
20
+ const destSize = statSync(destPath).size;
21
+ if (srcSize === destSize) {
22
+ filesSkipped++;
23
+ continue;
24
+ }
25
+ } catch {
26
+ }
27
+ }
28
+ try {
29
+ copyFileSync(srcPath, destPath);
30
+ bytesWritten += statSync(destPath).size;
31
+ filesCopied++;
32
+ } catch {
33
+ }
34
+ }
35
+ if (options?.workspace && options.workspaceSrc) {
36
+ mkdirSync(paths.workspace, { recursive: true });
37
+ const wsResult = copyWorkspaceRecursive(options.workspaceSrc, paths.workspace);
38
+ filesCopied += wsResult.copied;
39
+ filesSkipped += wsResult.skipped;
40
+ bytesWritten += wsResult.bytes;
41
+ }
42
+ return {
43
+ filesCopied,
44
+ filesSkipped,
45
+ bytesWritten,
46
+ durationMs: Date.now() - start
47
+ };
48
+ }
49
+ function copyWorkspaceRecursive(srcDir, destDir) {
50
+ let copied = 0;
51
+ let skipped = 0;
52
+ let bytes = 0;
53
+ try {
54
+ for (const entry of readdirSync(srcDir)) {
55
+ if (entry.startsWith(".")) continue;
56
+ const srcPath = join(srcDir, entry);
57
+ const destPath = join(destDir, entry);
58
+ try {
59
+ const stat = statSync(srcPath);
60
+ if (stat.isDirectory()) {
61
+ mkdirSync(destPath, { recursive: true });
62
+ const sub = copyWorkspaceRecursive(srcPath, destPath);
63
+ copied += sub.copied;
64
+ skipped += sub.skipped;
65
+ bytes += sub.bytes;
66
+ } else if (entry.endsWith(".md")) {
67
+ if (existsSync(destPath)) {
68
+ try {
69
+ if (stat.size === statSync(destPath).size) {
70
+ skipped++;
71
+ continue;
72
+ }
73
+ } catch {
74
+ }
75
+ }
76
+ copyFileSync(srcPath, destPath);
77
+ bytes += stat.size;
78
+ copied++;
79
+ }
80
+ } catch {
81
+ continue;
82
+ }
83
+ }
84
+ } catch {
85
+ }
86
+ return { copied, skipped, bytes };
87
+ }
88
+ export {
89
+ bulkCopyToLdm
90
+ };
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env node
2
+ declare function sendCommand(command: {
3
+ action: string;
4
+ agent_id?: string;
5
+ mode?: string;
6
+ }): Promise<void>;
7
+
8
+ export { sendCommand };