lockin-mcp 1.0.7 → 1.0.8

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/README.md +29 -21
  2. package/dist/blocker.d.ts +4 -1
  3. package/dist/blocker.d.ts.map +1 -1
  4. package/dist/blocker.js +18 -1
  5. package/dist/blocker.js.map +1 -1
  6. package/dist/brand.d.ts +1 -1
  7. package/dist/brand.d.ts.map +1 -1
  8. package/dist/brand.js +1 -1
  9. package/dist/brand.js.map +1 -1
  10. package/dist/cloud-activity.d.ts +10 -0
  11. package/dist/cloud-activity.d.ts.map +1 -0
  12. package/dist/cloud-activity.js +173 -0
  13. package/dist/cloud-activity.js.map +1 -0
  14. package/dist/index.js +94 -18
  15. package/dist/index.js.map +1 -1
  16. package/dist/installer/agents.d.ts.map +1 -1
  17. package/dist/installer/agents.js +7 -4
  18. package/dist/installer/agents.js.map +1 -1
  19. package/dist/installer/auto-update.d.ts +9 -0
  20. package/dist/installer/auto-update.d.ts.map +1 -0
  21. package/dist/installer/auto-update.js +194 -0
  22. package/dist/installer/auto-update.js.map +1 -0
  23. package/dist/installer/background-service.d.ts +1 -0
  24. package/dist/installer/background-service.d.ts.map +1 -1
  25. package/dist/installer/background-service.js +68 -1
  26. package/dist/installer/background-service.js.map +1 -1
  27. package/dist/installer/daemon-windows.d.ts +3 -0
  28. package/dist/installer/daemon-windows.d.ts.map +1 -1
  29. package/dist/installer/daemon-windows.js +12 -1
  30. package/dist/installer/daemon-windows.js.map +1 -1
  31. package/dist/installer/license.d.ts.map +1 -1
  32. package/dist/installer/license.js +1 -1
  33. package/dist/installer/license.js.map +1 -1
  34. package/dist/installer/port.d.ts +3 -0
  35. package/dist/installer/port.d.ts.map +1 -1
  36. package/dist/installer/port.js +70 -3
  37. package/dist/installer/port.js.map +1 -1
  38. package/dist/installer/relay-provision.d.ts +1 -0
  39. package/dist/installer/relay-provision.d.ts.map +1 -1
  40. package/dist/installer/relay-provision.js +2 -1
  41. package/dist/installer/relay-provision.js.map +1 -1
  42. package/dist/installer/run.d.ts.map +1 -1
  43. package/dist/installer/run.js +12 -6
  44. package/dist/installer/run.js.map +1 -1
  45. package/dist/license-token.d.ts +5 -0
  46. package/dist/license-token.d.ts.map +1 -0
  47. package/dist/license-token.js +87 -0
  48. package/dist/license-token.js.map +1 -0
  49. package/dist/relay-manager.d.ts +1 -0
  50. package/dist/relay-manager.d.ts.map +1 -1
  51. package/dist/relay-manager.js +7 -0
  52. package/dist/relay-manager.js.map +1 -1
  53. package/dist/server.d.ts.map +1 -1
  54. package/dist/server.js +7 -0
  55. package/dist/server.js.map +1 -1
  56. package/package.json +2 -1
package/README.md CHANGED
@@ -148,10 +148,10 @@ cd web && npx convex deploy
148
148
 
149
149
  1. Convex `MDB_APP_URL` is `https://www.lockinmcp.com` (not `localhost`).
150
150
  2. Vercel `MDB_SERVER_SECRET` === Convex `MDB_SERVER_SECRET`.
151
- 2. Stripe webhook enables `checkout.session.created` and `checkout.session.expired`.
152
- 3. Preview email: `./scripts/send-abandoned-checkout-preview.sh you@example.com`
153
- 4. Dev smoke test (60s delay): `npx convex env set CHECKOUT_FOLLOW_UP_DELAY_MS 60000` then `./scripts/test-abandoned-checkout-schedule.sh <userId>`
154
- 5. Inspect jobs: `./scripts/list-checkout-follow-ups.sh scheduled`
151
+ 3. Stripe webhook enables `checkout.session.created` and `checkout.session.expired`.
152
+ 4. Preview email: `./scripts/send-abandoned-checkout-preview.sh you@example.com`
153
+ 5. Dev smoke test (60s delay): `npx convex env set CHECKOUT_FOLLOW_UP_DELAY_MS 60000` then `./scripts/test-abandoned-checkout-schedule.sh <userId>`
154
+ 6. Inspect jobs: `./scripts/list-checkout-follow-ups.sh scheduled`
155
155
 
156
156
  Optional Convex env: `CHECKOUT_FOLLOW_UP_DELAY_MS` (default `86400000` = 24h).
157
157
 
@@ -214,12 +214,12 @@ iwr -useb https://raw.githubusercontent.com/Kiog-Aser/LockIn/main/install.ps1 |
214
214
  ### npm
215
215
 
216
216
  ```bash
217
- npx -y lockin-mcp@1.0.4 install
217
+ npx -y lockin-mcp@1.0.7 install
218
218
  # or from a local clone:
219
219
  npm run install:local
220
220
  ```
221
221
 
222
- The npm package `lockin-mcp` (v1.0.4) replaces the legacy `mac-distraction-blocker-mcp` name. Legacy bin aliases (`mac-distraction-blocker-mcp`, `mdb-install`) still work.
222
+ The npm package `lockin-mcp` (v1.0.7) replaces the legacy `mac-distraction-blocker-mcp` name. Legacy bin aliases (`mac-distraction-blocker-mcp`, `mdb-install`) still work.
223
223
 
224
224
  ### What the installer does
225
225
 
@@ -229,7 +229,7 @@ The npm package `lockin-mcp` (v1.0.4) replaces the legacy `mac-distraction-block
229
229
  4. **Applies initial blocks** to `/etc/hosts`
230
230
  5. **Starts the MCP HTTP server** locally with an outbound relay connection (background LaunchAgent on macOS)
231
231
  6. **Provisions a stable relay URL** (`https://relay.lockinmcp.com/device/{id}/mcp`) so Poke, Claude, and ChatGPT can reach your Mac
232
- 7. **Connects your AI agent** — Poke and Claude Desktop use your API key; Claude (web) and ChatGPT use OAuth via lockinmcp.com
232
+ 7. **Connects your AI agent** — Poke, Claude (web), and ChatGPT use OAuth via lockinmcp.com; Claude Desktop uses your API key via mcp-remote
233
233
 
234
234
  ### Installer flags (non-interactive)
235
235
 
@@ -244,6 +244,9 @@ npx -y lockin-mcp install --license-key lockin_pro_xxx --sites all --poke-recipe
244
244
  | `--license-key <key>` | Pro license key |
245
245
  | `--browser-login` | Verify license via browser device flow (default) |
246
246
  | `--skip-tunnel` | Local MCP only (no relay URL) |
247
+ | `--skip-block` | Skip initial domain blocking |
248
+ | `--skip-poke` | Skip Poke URL generation |
249
+ | `--port <number>` | Local MCP HTTP port (default 3000) |
247
250
  | `--sites all` | Block all presets |
248
251
  | `--custom-domains a.com,b.com` | Extra domains |
249
252
  | `--poke-recipe` | Generate distraction-coach recipe URL |
@@ -287,12 +290,14 @@ Your MCP URL and API key are in `~/.lockin/setup-manifest.json`:
287
290
 
288
291
  ### Poke
289
292
 
290
- ```bash
291
- npx poke@latest login
292
- npx poke@latest mcp add 'https://YOUR_RELAY_HOST/device/YOUR_ID/mcp' -n 'LockIn MCP' --api-key 'mdb_...'
293
- ```
293
+ The installer copies your relay MCP URL and opens [poke.com/integrations/new](https://poke.com/integrations/new). In Poke:
294
+
295
+ 1. Paste the MCP URL (ends with `/mcp`)
296
+ 2. Choose **OAuth** authentication (do not paste your API key in the integration form)
297
+ 3. Sign in on lockinmcp.com when prompted
298
+ 4. Install the [LockIn recipe](https://poke.com/r/KQ7myvC_Xpo)
294
299
 
295
- Or set URL + API key in [poke.com/integrations](https://poke.com/integrations).
300
+ Legacy CLI (optional): `npx poke@latest mcp add 'https://YOUR_RELAY_HOST/device/YOUR_ID/mcp' -n 'LockIn MCP'` with OAuth in the Poke UI.
296
301
 
297
302
  ### Claude (claude.ai)
298
303
 
@@ -431,14 +436,7 @@ Call `get_block_status` — `hostsFileWritable: true` means the server can updat
431
436
 
432
437
  ## Hooking up to [poke.com/kitchen](https://poke.com/kitchen)
433
438
 
434
- The installer tunnels your local MCP over HTTPS so Poke can connect remotely — no extra terminal tab.
435
-
436
- ```bash
437
- npx poke@latest login
438
- npx poke@latest mcp add 'https://YOUR_RELAY_HOST/device/YOUR_ID/mcp' -n 'LockIn MCP' --api-key 'mdb_...'
439
- ```
440
-
441
- The installer runs this automatically when you choose Poke. Credentials are in `setup-manifest.json`.
439
+ The installer tunnels your local MCP over HTTPS so Poke can connect remotely — no extra terminal tab. When you choose Poke during install, it copies your relay URL and opens the integrations page for OAuth setup.
442
440
 
443
441
  ### Recipe / Kitchen (recommended)
444
442
 
@@ -510,6 +508,16 @@ cd relay && npm test # relay token hashing tests
510
508
 
511
509
  CI (`.github/workflows/ci.yml`) runs lint, test, build, and `npm audit --audit-level=high` for the MCP server, web app, and relay worker.
512
510
 
511
+ **Reset local install state** (development only):
512
+
513
+ ```bash
514
+ npx lockin-mcp dev-reset # reset hosts, manifest, relay config
515
+ npx lockin-mcp dev-reset --full # also remove LaunchAgent / background service
516
+ npx lockin-mcp dev-reset --wipe-license # clear saved license
517
+ ```
518
+
519
+ See `relay/README.md` for Cloudflare WebSocket hibernation details on the device relay worker.
520
+
513
521
  ## Troubleshooting
514
522
 
515
523
  | Issue | Fix |
@@ -517,7 +525,7 @@ CI (`.github/workflows/ci.yml`) runs lint, test, build, and `npm audit --audit-l
517
525
  | `EACCES` on block/unblock | Run with `sudo` or configure passwordless sudo (see above) |
518
526
  | Site still loads | Hard-refresh browser; DNS cache may take a moment. Try private window. |
519
527
  | Temp unblock didn't re-block | Keep the MCP server process running (expiry watcher runs in-process) |
520
- | Poke can't connect | Check manifest relay URL + `/health` returns `lockin-mcp` with `relay.connected: true`. If offline, re-run `npx lockin-mcp install` once — the daemon self-heals reconnects automatically. |
528
+ | Poke can't connect | Re-run install and confirm OAuth completed in Poke. Check manifest relay URL + `/health` returns `lockin-mcp` with `relay.connected: true`. If offline, re-run `npx lockin-mcp install` once — the daemon self-heals reconnects automatically. |
521
529
  | Wrong platform | macOS, Linux, and Windows are supported; DNS flush behavior differs by OS |
522
530
 
523
531
  ## License
package/dist/blocker.d.ts CHANGED
@@ -1,8 +1,11 @@
1
1
  import { type BlockStatusResult, type BlockerState, type DomainStatus } from "./types.js";
2
2
  export declare function startExpiryWatcher(intervalMs?: number): void;
3
3
  export declare function stopExpiryWatcher(): void;
4
- export declare function blockDomains(domains: string[]): Promise<{
4
+ export declare function blockDomains(domains: string[], options?: {
5
+ syncActivity?: boolean;
6
+ }): Promise<{
5
7
  blocked: string[];
8
+ newlyBlocked: string[];
6
9
  message: string;
7
10
  }>;
8
11
  export declare function unblockDomains(domains: string[]): Promise<{
@@ -1 +1 @@
1
- {"version":3,"file":"blocker.d.ts","sourceRoot":"","sources":["../src/blocker.ts"],"names":[],"mappings":"AAcA,OAAO,EACL,KAAK,iBAAiB,EACtB,KAAK,YAAY,EACjB,KAAK,YAAY,EAGlB,MAAM,YAAY,CAAC;AAKpB,wBAAgB,kBAAkB,CAChC,UAAU,SAAS,GAClB,IAAI,CAUN;AAED,wBAAgB,iBAAiB,IAAI,IAAI,CAKxC;AAsCD,wBAAsB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;IAC7D,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC,CA4CD;AAED,wBAAsB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;IAC/D,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC,CA8BD;AAED,wBAAsB,yBAAyB,CAC7C,OAAO,EAAE,MAAM,EAAE,EACjB,eAAe,EAAE,MAAM,GACtB,OAAO,CAAC;IACT,oBAAoB,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACnE,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC,CA4CD;AAED,wBAAsB,cAAc,IAAI,OAAO,CAAC,iBAAiB,CAAC,CAiCjE;AAED,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAG7D;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,GAAG,YAAY,CAgBhF;AAED,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAGzE"}
1
+ {"version":3,"file":"blocker.d.ts","sourceRoot":"","sources":["../src/blocker.ts"],"names":[],"mappings":"AAeA,OAAO,EACL,KAAK,iBAAiB,EACtB,KAAK,YAAY,EACjB,KAAK,YAAY,EAGlB,MAAM,YAAY,CAAC;AAKpB,wBAAgB,kBAAkB,CAChC,UAAU,SAAS,GAClB,IAAI,CAUN;AAED,wBAAgB,iBAAiB,IAAI,IAAI,CAKxC;AAsCD,wBAAsB,YAAY,CAChC,OAAO,EAAE,MAAM,EAAE,EACjB,OAAO,CAAC,EAAE;IAAE,YAAY,CAAC,EAAE,OAAO,CAAA;CAAE,GACnC,OAAO,CAAC;IACT,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC,CAmDD;AAUD,wBAAsB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;IAC/D,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC,CAkCD;AAED,wBAAsB,yBAAyB,CAC7C,OAAO,EAAE,MAAM,EAAE,EACjB,eAAe,EAAE,MAAM,GACtB,OAAO,CAAC;IACT,oBAAoB,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACnE,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC,CA4CD;AAED,wBAAsB,cAAc,IAAI,OAAO,CAAC,iBAAiB,CAAC,CAiCjE;AAED,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAG7D;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,GAAG,YAAY,CAgBhF;AAED,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAGzE"}
package/dist/blocker.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { canWriteHostsFile, syncHostsFile, } from "./hosts-manager.js";
2
+ import { pushCloudActivity } from "./cloud-activity.js";
2
3
  import { dedupeDomains, getDomainsToBlockInHosts, getActiveTemporaryUnblock, isDomainBlocked, loadState, pruneExpiredUnblocks, saveState, appendAuditEntry, } from "./state.js";
3
4
  import { isValidDomain, normalizeDomain, } from "./types.js";
4
5
  let expiryTimer;
@@ -48,7 +49,8 @@ function validateDomains(domains) {
48
49
  }
49
50
  return normalized;
50
51
  }
51
- export async function blockDomains(domains) {
52
+ export async function blockDomains(domains, options) {
53
+ const syncActivity = options?.syncActivity !== false;
52
54
  const validated = validateDomains(domains);
53
55
  const state = await loadState();
54
56
  const blockedSet = new Set(state.blockedDomains);
@@ -68,17 +70,29 @@ export async function blockDomains(domains) {
68
70
  await saveState(nextState);
69
71
  }
70
72
  const method = await applyHostsFromState(nextState);
73
+ if (!stateUnchanged && syncActivity) {
74
+ void syncBlockingStatus(nextState);
75
+ }
71
76
  if (method === "unchanged" && newDomains.length === 0) {
72
77
  return {
73
78
  blocked: validated,
79
+ newlyBlocked: [],
74
80
  message: `${validated.length} site(s) already blocked.`,
75
81
  };
76
82
  }
77
83
  return {
78
84
  blocked: validated,
85
+ newlyBlocked: newDomains,
79
86
  message: `Blocked ${validated.length} site(s) via /etc/hosts (${method}).`,
80
87
  };
81
88
  }
89
+ async function syncBlockingStatus(state) {
90
+ const activeDomains = getDomainsToBlockInHosts(state);
91
+ void pushCloudActivity({
92
+ blockingActive: activeDomains.length > 0,
93
+ blockedDomainCount: activeDomains.length,
94
+ });
95
+ }
82
96
  export async function unblockDomains(domains) {
83
97
  const validated = validateDomains(domains);
84
98
  const state = await loadState();
@@ -91,6 +105,9 @@ export async function unblockDomains(domains) {
91
105
  }, "unblock_domains", unblocked);
92
106
  await saveState(nextState);
93
107
  const method = await applyHostsFromState(nextState);
108
+ if (unblocked.length > 0) {
109
+ void syncBlockingStatus(nextState);
110
+ }
94
111
  return {
95
112
  unblocked,
96
113
  message: `Unblocked ${unblocked.length} domain(s) and updated /etc/hosts (${method}).`,
@@ -1 +1 @@
1
- {"version":3,"file":"blocker.js","sourceRoot":"","sources":["../src/blocker.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"blocker.js","sourceRoot":"","sources":["../src/blocker.ts"],"names":[],"mappings":"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"}
package/dist/brand.d.ts CHANGED
@@ -7,7 +7,7 @@ export declare const RELAY_HOST = "relay.lockinmcp.com";
7
7
  export declare const RELAY_PUBLIC_ORIGIN = "https://relay.lockinmcp.com";
8
8
  export declare const LICENSE_PRICE_ORIGINAL = "$19.99";
9
9
  export declare const LICENSE_PRICE = "$9.99";
10
- export declare const LICENSE_DISCOUNT_LABEL = "50% off \u2014 forever";
10
+ export declare const LICENSE_DISCOUNT_LABEL = "Launch promo \u2014 50% off";
11
11
  export declare const POKE_LOCKIN_RECIPE_URL = "https://poke.com/r/KQ7myvC_Xpo";
12
12
  export declare const ICON_URL = "https://www.lockinmcp.com/icon.png";
13
13
  //# sourceMappingURL=brand.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"brand.d.ts","sourceRoot":"","sources":["../src/brand.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,QAAQ,eAAe,CAAC;AACrC,eAAO,MAAM,QAAQ,eAAe,CAAC;AACrC,eAAO,MAAM,WAAW,uCAAuC,CAAC;AAChE,eAAO,MAAM,UAAU,kBAAkB,CAAC;AAC1C,eAAO,MAAM,gBAAgB,8BAA8B,CAAC;AAC5D,eAAO,MAAM,UAAU,wBAAwB,CAAC;AAChD,eAAO,MAAM,mBAAmB,gCAA0B,CAAC;AAC3D,eAAO,MAAM,sBAAsB,WAAW,CAAC;AAC/C,eAAO,MAAM,aAAa,UAAU,CAAC;AACrC,eAAO,MAAM,sBAAsB,2BAAsB,CAAC;AAC1D,eAAO,MAAM,sBAAsB,mCAAmC,CAAC;AACvE,eAAO,MAAM,QAAQ,uCAAiC,CAAC"}
1
+ {"version":3,"file":"brand.d.ts","sourceRoot":"","sources":["../src/brand.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,QAAQ,eAAe,CAAC;AACrC,eAAO,MAAM,QAAQ,eAAe,CAAC;AACrC,eAAO,MAAM,WAAW,uCAAuC,CAAC;AAChE,eAAO,MAAM,UAAU,kBAAkB,CAAC;AAC1C,eAAO,MAAM,gBAAgB,8BAA8B,CAAC;AAC5D,eAAO,MAAM,UAAU,wBAAwB,CAAC;AAChD,eAAO,MAAM,mBAAmB,gCAA0B,CAAC;AAC3D,eAAO,MAAM,sBAAsB,WAAW,CAAC;AAC/C,eAAO,MAAM,aAAa,UAAU,CAAC;AACrC,eAAO,MAAM,sBAAsB,gCAA2B,CAAC;AAC/D,eAAO,MAAM,sBAAsB,mCAAmC,CAAC;AACvE,eAAO,MAAM,QAAQ,uCAAiC,CAAC"}
package/dist/brand.js CHANGED
@@ -7,7 +7,7 @@ export const RELAY_HOST = `relay.${APP_DOMAIN}`;
7
7
  export const RELAY_PUBLIC_ORIGIN = `https://${RELAY_HOST}`;
8
8
  export const LICENSE_PRICE_ORIGINAL = "$19.99";
9
9
  export const LICENSE_PRICE = "$9.99";
10
- export const LICENSE_DISCOUNT_LABEL = "50% off — forever";
10
+ export const LICENSE_DISCOUNT_LABEL = "Launch promo — 50% off";
11
11
  export const POKE_LOCKIN_RECIPE_URL = "https://poke.com/r/KQ7myvC_Xpo";
12
12
  export const ICON_URL = `${CANONICAL_ORIGIN}/icon.png`;
13
13
  //# sourceMappingURL=brand.js.map
package/dist/brand.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"brand.js","sourceRoot":"","sources":["../src/brand.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,QAAQ,GAAG,YAAY,CAAC;AACrC,MAAM,CAAC,MAAM,QAAQ,GAAG,YAAY,CAAC;AACrC,MAAM,CAAC,MAAM,WAAW,GAAG,oCAAoC,CAAC;AAChE,MAAM,CAAC,MAAM,UAAU,GAAG,eAAe,CAAC;AAC1C,MAAM,CAAC,MAAM,gBAAgB,GAAG,2BAA2B,CAAC;AAC5D,MAAM,CAAC,MAAM,UAAU,GAAG,SAAS,UAAU,EAAE,CAAC;AAChD,MAAM,CAAC,MAAM,mBAAmB,GAAG,WAAW,UAAU,EAAE,CAAC;AAC3D,MAAM,CAAC,MAAM,sBAAsB,GAAG,QAAQ,CAAC;AAC/C,MAAM,CAAC,MAAM,aAAa,GAAG,OAAO,CAAC;AACrC,MAAM,CAAC,MAAM,sBAAsB,GAAG,mBAAmB,CAAC;AAC1D,MAAM,CAAC,MAAM,sBAAsB,GAAG,gCAAgC,CAAC;AACvE,MAAM,CAAC,MAAM,QAAQ,GAAG,GAAG,gBAAgB,WAAW,CAAC"}
1
+ {"version":3,"file":"brand.js","sourceRoot":"","sources":["../src/brand.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,QAAQ,GAAG,YAAY,CAAC;AACrC,MAAM,CAAC,MAAM,QAAQ,GAAG,YAAY,CAAC;AACrC,MAAM,CAAC,MAAM,WAAW,GAAG,oCAAoC,CAAC;AAChE,MAAM,CAAC,MAAM,UAAU,GAAG,eAAe,CAAC;AAC1C,MAAM,CAAC,MAAM,gBAAgB,GAAG,2BAA2B,CAAC;AAC5D,MAAM,CAAC,MAAM,UAAU,GAAG,SAAS,UAAU,EAAE,CAAC;AAChD,MAAM,CAAC,MAAM,mBAAmB,GAAG,WAAW,UAAU,EAAE,CAAC;AAC3D,MAAM,CAAC,MAAM,sBAAsB,GAAG,QAAQ,CAAC;AAC/C,MAAM,CAAC,MAAM,aAAa,GAAG,OAAO,CAAC;AACrC,MAAM,CAAC,MAAM,sBAAsB,GAAG,wBAAwB,CAAC;AAC/D,MAAM,CAAC,MAAM,sBAAsB,GAAG,gCAAgC,CAAC;AACvE,MAAM,CAAC,MAAM,QAAQ,GAAG,GAAG,gBAAgB,WAAW,CAAC"}
@@ -0,0 +1,10 @@
1
+ export declare function pushCloudActivity(payload: {
2
+ focusMinutes?: number;
3
+ sessionDelta?: number;
4
+ blockingActive?: boolean;
5
+ blockedDomainCount?: number;
6
+ relayConnected?: boolean;
7
+ }): Promise<void>;
8
+ export declare function recordFocusSession(blockedDomainCount: number): Promise<void>;
9
+ export declare function pushRelayStatusSnapshot(): Promise<void>;
10
+ //# sourceMappingURL=cloud-activity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cloud-activity.d.ts","sourceRoot":"","sources":["../src/cloud-activity.ts"],"names":[],"mappings":"AAgHA,wBAAsB,iBAAiB,CAAC,OAAO,EAAE;IAC/C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B,GAAG,OAAO,CAAC,IAAI,CAAC,CA4DhB;AAED,wBAAsB,kBAAkB,CAAC,kBAAkB,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAOlF;AAED,wBAAsB,uBAAuB,IAAI,OAAO,CAAC,IAAI,CAAC,CAgB7D"}
@@ -0,0 +1,173 @@
1
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ import { randomBytes } from "node:crypto";
4
+ import { getBlockStatus } from "./blocker.js";
5
+ import { getLicenseApiUrl } from "./config.js";
6
+ import { refreshSyncTokenAfterAuthFailure, resolveSyncToken, } from "./license-token.js";
7
+ import { fetchLockInHealthSnapshot } from "./installer/port.js";
8
+ import { getInstallDir } from "./installer/platform.js";
9
+ const LOCAL_DEVICE_ID_FILE = "local-device-id";
10
+ const SETUP_MANIFEST_FILE = "setup-manifest.json";
11
+ let cachedDeviceId;
12
+ let deviceIdResolution;
13
+ async function resolveDeviceIdFromDisk() {
14
+ try {
15
+ const { readRelayCredentials } = await import("./installer/relay-credentials.js");
16
+ const credentials = await readRelayCredentials();
17
+ if (credentials?.deviceId) {
18
+ cachedDeviceId = credentials.deviceId;
19
+ return cachedDeviceId;
20
+ }
21
+ }
22
+ catch {
23
+ // no relay credentials
24
+ }
25
+ try {
26
+ const raw = await readFile(join(getInstallDir(), SETUP_MANIFEST_FILE), "utf8");
27
+ const manifest = JSON.parse(raw);
28
+ if (manifest.relayDeviceId?.trim()) {
29
+ cachedDeviceId = manifest.relayDeviceId.trim();
30
+ return cachedDeviceId;
31
+ }
32
+ }
33
+ catch {
34
+ // no manifest
35
+ }
36
+ const localIdPath = join(getInstallDir(), LOCAL_DEVICE_ID_FILE);
37
+ try {
38
+ const persisted = (await readFile(localIdPath, "utf8")).trim();
39
+ if (persisted) {
40
+ cachedDeviceId = persisted;
41
+ return cachedDeviceId;
42
+ }
43
+ }
44
+ catch {
45
+ // generate below
46
+ }
47
+ const generated = `local_${randomBytes(16).toString("hex")}`;
48
+ try {
49
+ await mkdir(getInstallDir(), { recursive: true });
50
+ await writeFile(localIdPath, `${generated}\n`, { mode: 0o600 });
51
+ }
52
+ catch {
53
+ // Install dir may be unwritable — use in-memory id for this process.
54
+ }
55
+ cachedDeviceId = generated;
56
+ return cachedDeviceId;
57
+ }
58
+ function readDeviceIdFromEnv() {
59
+ return process.env.MDB_DEVICE_ID?.trim() || undefined;
60
+ }
61
+ /** Resolve a stable device id for cloud sync (env → relay creds → manifest → local file). */
62
+ async function resolveDeviceId() {
63
+ const fromEnv = readDeviceIdFromEnv();
64
+ if (fromEnv) {
65
+ return fromEnv;
66
+ }
67
+ if (cachedDeviceId) {
68
+ return cachedDeviceId;
69
+ }
70
+ deviceIdResolution ??= resolveDeviceIdFromDisk().finally(() => {
71
+ deviceIdResolution = undefined;
72
+ });
73
+ return deviceIdResolution;
74
+ }
75
+ async function readRelayConnected() {
76
+ const port = Number(process.env.MDB_HTTP_PORT ?? 3847);
77
+ const snapshot = await fetchLockInHealthSnapshot(port);
78
+ return snapshot?.relayConnected === true;
79
+ }
80
+ function deviceLocalDateKey() {
81
+ const date = new Date();
82
+ const year = date.getFullYear();
83
+ const month = String(date.getMonth() + 1).padStart(2, "0");
84
+ const day = String(date.getDate()).padStart(2, "0");
85
+ return `${year}-${month}-${day}`;
86
+ }
87
+ function formatSyncFailure(status, body) {
88
+ if (status === 404) {
89
+ return `${status} — activity sync API not deployed yet`;
90
+ }
91
+ const trimmed = body.replace(/\s+/g, " ").trim();
92
+ if (!trimmed || trimmed.startsWith("<!DOCTYPE") || trimmed.startsWith("<html")) {
93
+ return `${status}`;
94
+ }
95
+ return `${status} ${trimmed.slice(0, 120)}`;
96
+ }
97
+ export async function pushCloudActivity(payload) {
98
+ let token = await resolveSyncToken();
99
+ if (!token)
100
+ return;
101
+ const deviceId = await resolveDeviceId();
102
+ const relayConnected = payload.relayConnected ?? (await readRelayConnected());
103
+ const apiUrl = getLicenseApiUrl();
104
+ const body = {
105
+ deviceId,
106
+ relayConnected,
107
+ date: deviceLocalDateKey(),
108
+ };
109
+ if (payload.focusMinutes !== undefined) {
110
+ body.focusMinutes = payload.focusMinutes;
111
+ }
112
+ if (payload.sessionDelta !== undefined) {
113
+ body.sessionDelta = payload.sessionDelta;
114
+ }
115
+ if (payload.blockingActive !== undefined) {
116
+ body.blockingActive = payload.blockingActive;
117
+ }
118
+ if (payload.blockedDomainCount !== undefined) {
119
+ body.blockedDomainCount = payload.blockedDomainCount;
120
+ }
121
+ async function postOnce(authToken) {
122
+ return fetch(`${apiUrl}/activity/sync`, {
123
+ method: "POST",
124
+ headers: {
125
+ "Content-Type": "application/json",
126
+ Authorization: `Bearer ${authToken}`,
127
+ },
128
+ body: JSON.stringify(body),
129
+ });
130
+ }
131
+ try {
132
+ let response = await postOnce(token);
133
+ if (response.status === 401) {
134
+ const refreshed = await refreshSyncTokenAfterAuthFailure();
135
+ if (refreshed) {
136
+ token = refreshed;
137
+ response = await postOnce(token);
138
+ }
139
+ }
140
+ if (!response.ok) {
141
+ const errorBody = await response.text();
142
+ console.warn(`[cloud-activity] sync failed: ${formatSyncFailure(response.status, errorBody)}`);
143
+ }
144
+ }
145
+ catch (error) {
146
+ console.warn("[cloud-activity] sync error:", error instanceof Error ? error.message : error);
147
+ }
148
+ }
149
+ export async function recordFocusSession(blockedDomainCount) {
150
+ await pushCloudActivity({
151
+ focusMinutes: 30,
152
+ sessionDelta: 1,
153
+ blockingActive: true,
154
+ blockedDomainCount,
155
+ });
156
+ }
157
+ export async function pushRelayStatusSnapshot() {
158
+ let blockingActive;
159
+ let blockedDomainCount;
160
+ try {
161
+ const status = await getBlockStatus();
162
+ blockingActive = status.blocked.length > 0;
163
+ blockedDomainCount = status.blocked.length;
164
+ }
165
+ catch {
166
+ // Health snapshot still reports relay connectivity.
167
+ }
168
+ await pushCloudActivity({
169
+ blockingActive,
170
+ blockedDomainCount,
171
+ });
172
+ }
173
+ //# sourceMappingURL=cloud-activity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cloud-activity.js","sourceRoot":"","sources":["../src/cloud-activity.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -11,7 +11,7 @@ import { APP_SLUG } from "./brand.js";
11
11
  import { startExpiryWatcher } from "./blocker.js";
12
12
  import { verifyTokenWithBackend, } from "./license-check.js";
13
13
  import { readMcpAuthTokenFromManifest } from "./installer/setup-manifest.js";
14
- import { describePortConflict, fetchLockInHealthSnapshot, stopLockInListenersOnPort, } from "./installer/port.js";
14
+ import { describePortConflict, fetchLockInHealthSnapshot, isLikelyLockInListenerOnPort, stopLockInListenersOnPort, } from "./installer/port.js";
15
15
  import { reconcileHostsOnStartup } from "./hosts-manager.js";
16
16
  import { bearerTokenMatches, generateHttpMcpAuthToken, resolveHttpMcpAuth, } from "./http-auth.js";
17
17
  import { RELAY_PUBLIC_ORIGIN } from "./relay-urls.js";
@@ -126,11 +126,70 @@ async function assertHttpPortAvailable(port) {
126
126
  log(`Replacing stale LockIn MCP on port ${port} (relay offline) so this instance can connect`);
127
127
  await stopLockInListenersOnPort(port);
128
128
  }
129
+ const { waitForPortAvailable } = await import("./installer/port.js");
130
+ await waitForPortAvailable(port);
129
131
  const conflict = await describePortConflict(port);
130
132
  if (conflict) {
131
133
  throw new Error(`${conflict}. Free port ${port} or run with --port <number>. Check: lsof -i :${port}`);
132
134
  }
133
135
  }
136
+ function tryListen(app, port, host) {
137
+ return new Promise((resolve, reject) => {
138
+ const server = app.listen(port, host, () => {
139
+ server.removeListener("error", reject);
140
+ resolve(server);
141
+ });
142
+ server.once("error", reject);
143
+ });
144
+ }
145
+ /**
146
+ * Bind the HTTP port, retrying briefly on EADDRINUSE. A stale LockIn instance
147
+ * that is shutting down (or a slow OS port release after we replaced one) can
148
+ * leave the port momentarily occupied; rather than crash and rely on the
149
+ * service supervisor to loop, we attempt to clear stale LockIn listeners and
150
+ * retry a few times so the daemon self-heals.
151
+ */
152
+ async function listenWithRetry(app, port, host, maxAttempts = 6) {
153
+ let lastError = null;
154
+ for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
155
+ try {
156
+ const server = await tryListen(app, port, host);
157
+ log(`Running on HTTP at http://${host}:${port}/mcp`);
158
+ return server;
159
+ }
160
+ catch (error) {
161
+ const err = error;
162
+ if (err.code !== "EADDRINUSE") {
163
+ throw err;
164
+ }
165
+ lastError = err;
166
+ // If a healthy LockIn is already serving the port, defer to it instead of
167
+ // fighting over the socket forever.
168
+ const existing = await fetchLockInHealthSnapshot(port);
169
+ if (existing?.relayConnected) {
170
+ log(`Port ${port} already served by a relay-connected LockIn MCP — exiting in favor of it`);
171
+ process.exit(0);
172
+ }
173
+ if (attempt < maxAttempts) {
174
+ const snapshot = await fetchLockInHealthSnapshot(port);
175
+ if (snapshot) {
176
+ log(`Port ${port} busy (attempt ${attempt}/${maxAttempts}) — clearing stale LockIn listeners and retrying`);
177
+ await stopLockInListenersOnPort(port);
178
+ }
179
+ else {
180
+ log(`Port ${port} busy (attempt ${attempt}/${maxAttempts}) — waiting for port to free`);
181
+ if (attempt >= 3 &&
182
+ (await isLikelyLockInListenerOnPort(port))) {
183
+ log(`Port ${port} still held by a likely LockIn listener — clearing and retrying`);
184
+ await stopLockInListenersOnPort(port);
185
+ }
186
+ }
187
+ await new Promise((resolve) => setTimeout(resolve, 500 * attempt));
188
+ }
189
+ }
190
+ }
191
+ throw new Error(`Port ${port} is already in use after ${maxAttempts} attempts. Stop the other process: lsof -i :${port}`, { cause: lastError ?? undefined });
192
+ }
134
193
  async function runHttp(port) {
135
194
  process.env.MDB_HTTP_PORT = String(port);
136
195
  await assertHttpPortAvailable(port);
@@ -173,11 +232,38 @@ async function runHttp(port) {
173
232
  relayUrl: process.env.MDB_RELAY_URL,
174
233
  deviceId: process.env.MDB_DEVICE_ID,
175
234
  });
176
- const shutdown = () => {
177
- relayManager?.stop();
235
+ let httpServer = null;
236
+ let shuttingDown = false;
237
+ const shutdown = (signal) => {
238
+ if (shuttingDown) {
239
+ return;
240
+ }
241
+ shuttingDown = true;
242
+ log(`Received ${signal} — shutting down`);
243
+ try {
244
+ relayManager?.stop();
245
+ }
246
+ catch {
247
+ // best-effort: never let cleanup block exit
248
+ }
249
+ // Force-exit guard: long-lived SSE/keep-alive sockets can keep the event
250
+ // loop (and the port) alive forever, so we never wait more than a moment.
251
+ const forceExit = setTimeout(() => process.exit(0), 2_000);
252
+ forceExit.unref();
253
+ const finish = () => {
254
+ clearTimeout(forceExit);
255
+ process.exit(0);
256
+ };
257
+ if (httpServer) {
258
+ httpServer.closeAllConnections?.();
259
+ httpServer.close(() => finish());
260
+ }
261
+ else {
262
+ finish();
263
+ }
178
264
  };
179
- process.once("SIGTERM", shutdown);
180
- process.once("SIGINT", shutdown);
265
+ process.once("SIGTERM", () => shutdown("SIGTERM"));
266
+ process.once("SIGINT", () => shutdown("SIGINT"));
181
267
  app.use(express.json({ limit: "4mb" }));
182
268
  const protectedPaths = ["/mcp", "/sse", "/message"];
183
269
  const deviceId = process.env.MDB_DEVICE_ID;
@@ -291,20 +377,10 @@ async function runHttp(port) {
291
377
  res.status(200).json({ closed: true });
292
378
  });
293
379
  const listenHost = process.env.MDB_HTTP_HOST ?? "127.0.0.1";
294
- await new Promise((resolve, reject) => {
295
- const server = app.listen(port, listenHost, () => {
296
- log(`Running on HTTP at http://${listenHost}:${port}/mcp`);
297
- resolve();
298
- });
299
- server.on("error", (error) => {
300
- if (error.code === "EADDRINUSE") {
301
- reject(new Error(`Port ${port} is already in use. Stop the other process: lsof -i :${port}`));
302
- return;
303
- }
304
- reject(error);
305
- });
306
- });
380
+ httpServer = await listenWithRetry(app, port, listenHost);
307
381
  relayManager = await startRelayManager((message) => log(`[relay] ${message}`));
382
+ const { startAutoUpdateWatcher } = await import("./installer/auto-update.js");
383
+ startAutoUpdateWatcher((message) => log(`[update] ${message}`));
308
384
  }
309
385
  async function main() {
310
386
  const { ensureDataDirMigrated } = await import("./installer/data-dir.js");