@cursorpool-dev/cli 0.5.8 → 0.5.9

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 (42) hide show
  1. package/node_modules/@cursor-pool/extension/dist/extension.js +46 -116
  2. package/node_modules/@cursor-pool/extension/package.json +3 -3
  3. package/node_modules/@cursor-pool/extension/src/api.ts +2 -17
  4. package/node_modules/@cursor-pool/extension/src/panel.ts +3 -26
  5. package/node_modules/@cursor-pool/extension/test/panel.test.ts +1 -34
  6. package/node_modules/@cursor-pool/patcher/package.json +2 -2
  7. package/node_modules/@cursor-pool/patcher/src/marker.ts +72 -7
  8. package/node_modules/@cursor-pool/patcher/src/workbenchAuthGateMarker.ts +80 -17
  9. package/node_modules/@cursor-pool/patcher/test/patchCursorAgentExec.test.ts +88 -13
  10. package/node_modules/@cursor-pool/patcher/test/patchCursorWorkbench.test.ts +151 -149
  11. package/node_modules/@cursor-pool/service/package.json +2 -2
  12. package/node_modules/@cursor-pool/service/src/platformSession.ts +7 -30
  13. package/node_modules/@cursor-pool/service/src/server.ts +1 -1
  14. package/node_modules/@cursor-pool/service/test/platformSession.test.ts +4 -5
  15. package/node_modules/@cursor-pool/service/test/server.test.ts +1 -130
  16. package/node_modules/@cursor-pool/shared/package.json +1 -1
  17. package/node_modules/@cursor-pool/shared/src/manifest.ts +0 -35
  18. package/node_modules/@cursor-pool/shared/test/manifest.test.ts +9 -43
  19. package/package.json +5 -7
  20. package/src/compat.ts +124 -196
  21. package/src/extensionBundle.ts +1 -1
  22. package/src/extensionLink.ts +8 -29
  23. package/src/install.ts +9 -62
  24. package/src/installRecord.ts +0 -2
  25. package/src/patchSet.ts +6 -12
  26. package/src/platform.ts +3 -3
  27. package/src/repair.ts +2 -10
  28. package/src/restore.ts +4 -12
  29. package/src/status.ts +0 -6
  30. package/src/trial.ts +2 -3
  31. package/test/compat.test.ts +59 -195
  32. package/test/e2e-install.test.ts +0 -53
  33. package/test/extensionLink.test.ts +26 -49
  34. package/test/install.test.ts +4 -64
  35. package/test/repair.test.ts +0 -1
  36. package/test/status.test.ts +0 -1
  37. package/test/trial.test.ts +15 -1
  38. package/node_modules/@cursor-pool/takeover-plans/package.json +0 -12
  39. package/node_modules/@cursor-pool/takeover-plans/src/index.ts +0 -22
  40. package/node_modules/@cursor-pool/takeover-plans/src/plans.ts +0 -37
  41. package/node_modules/@cursor-pool/takeover-plans/src/types.ts +0 -9
  42. package/node_modules/@cursor-pool/takeover-plans/test/registry.test.ts +0 -23
@@ -1,7 +1,7 @@
1
- // ../extension/src/api.ts
1
+ // packages/extension/src/api.ts
2
2
  import { arch, hostname, platform as osPlatform } from "node:os";
3
3
 
4
- // ../service/src/health.ts
4
+ // packages/service/src/health.ts
5
5
  function buildHealth(runtime) {
6
6
  return {
7
7
  ok: true,
@@ -11,7 +11,7 @@ function buildHealth(runtime) {
11
11
  };
12
12
  }
13
13
 
14
- // ../shared/src/metadata.ts
14
+ // packages/shared/src/metadata.ts
15
15
  var SAFE_METADATA_KEYS = [
16
16
  "requestId",
17
17
  "model",
@@ -31,7 +31,7 @@ function sanitizeRequestMetadata(input) {
31
31
  return output;
32
32
  }
33
33
 
34
- // ../service/src/metadata.ts
34
+ // packages/service/src/metadata.ts
35
35
  var EXTENSION_STATUS_KEYS = ["connected", "cursorVersion", "clientVersion"];
36
36
  function sanitizeServiceMetadata(input) {
37
37
  return {
@@ -49,7 +49,7 @@ function sanitizeExtensionStatus(input) {
49
49
  return output;
50
50
  }
51
51
 
52
- // ../service/src/platformSession.ts
52
+ // packages/service/src/platformSession.ts
53
53
  import { chmod, mkdir, readFile, rm, writeFile } from "node:fs/promises";
54
54
  import { homedir } from "node:os";
55
55
  import { dirname, join } from "node:path";
@@ -95,7 +95,7 @@ function asStatus(session) {
95
95
  state: "logged-in",
96
96
  user: session.user,
97
97
  device: session.device,
98
- mode: statusModeFromSession(session)
98
+ mode: platformModeFromSession(session)
99
99
  };
100
100
  }
101
101
  function isPlatformModeReleaseReason(value) {
@@ -121,24 +121,6 @@ function platformModeFromSession(session) {
121
121
  }
122
122
  return inactiveModeFromSession(session);
123
123
  }
124
- function routeStateFromSession(session) {
125
- const routeToken = session?.routeToken;
126
- if (!routeToken) {
127
- return { state: "missing" };
128
- }
129
- const expiresAt = Date.parse(routeToken.expiresAt);
130
- if (Number.isNaN(expiresAt)) {
131
- return { state: "missing" };
132
- }
133
- if (expiresAt <= Date.now()) {
134
- return { state: "expired", expiresAt: routeToken.expiresAt };
135
- }
136
- return { state: "ready", expiresAt: routeToken.expiresAt };
137
- }
138
- function statusModeFromSession(session) {
139
- const mode = platformModeFromSession(session);
140
- return mode.state === "active" ? { ...mode, route: routeStateFromSession(session) } : mode;
141
- }
142
124
  function clearPlatformMode(session) {
143
125
  const {
144
126
  platformMode: _platformMode,
@@ -397,10 +379,10 @@ function poolFailureToModeResult(reason, product, currentCredits) {
397
379
  async function statusFromRequestError(error, session, options = {}) {
398
380
  if (error.status === 401) {
399
381
  const currentSession = await readPlatformSession(options) ?? session;
400
- const { mode } = options.releaseActiveModeOnUnauthorized ? await releaseActivePlatformMode(currentSession, "invalid-token", options) : { mode: statusModeFromSession(currentSession) };
382
+ const { mode } = options.releaseActiveModeOnUnauthorized ? await releaseActivePlatformMode(currentSession, "invalid-token", options) : { mode: platformModeFromSession(currentSession) };
401
383
  return { state: "invalid-token", user: currentSession.user, device: currentSession.device, mode };
402
384
  }
403
- return { state: "offline", user: session.user, device: session.device, mode: statusModeFromSession(session) };
385
+ return { state: "offline", user: session.user, device: session.device, mode: platformModeFromSession(session) };
404
386
  }
405
387
  async function loginWithCode(options) {
406
388
  const tokenResponse = await (options.exchangeDeviceToken ?? exchangeDeviceToken)({
@@ -460,7 +442,7 @@ async function platformStatus(options = {}) {
460
442
  state: "logged-in",
461
443
  user: released.session.user,
462
444
  device: released.session.device,
463
- mode: released.mode.state === "active" ? statusModeFromSession(released.session) : released.mode
445
+ mode: released.mode
464
446
  };
465
447
  }
466
448
  async function platformCatalog(options = {}) {
@@ -512,7 +494,7 @@ async function platformCatalog(options = {}) {
512
494
  return {
513
495
  state: "logged-in",
514
496
  account: { credits: account.value.credits },
515
- mode: mode.state === "active" ? statusModeFromSession(updatedSession) : mode,
497
+ mode,
516
498
  ...selectedProductId ? { selectedProductId } : {},
517
499
  products: catalogProducts
518
500
  };
@@ -683,7 +665,7 @@ async function sendHeartbeat(options = {}) {
683
665
  state: "logged-in",
684
666
  user: released.session.user,
685
667
  device: released.session.device,
686
- mode: released.mode.state === "active" ? statusModeFromSession(released.session) : released.mode
668
+ mode: released.mode
687
669
  };
688
670
  }
689
671
  async function logoutPlatform(options = {}) {
@@ -698,17 +680,17 @@ async function logoutPlatform(options = {}) {
698
680
  return { state: "logged-out" };
699
681
  }
700
682
 
701
- // ../service/src/runtime.ts
683
+ // packages/service/src/runtime.ts
702
684
  import { mkdir as mkdir2, readFile as readFile2, writeFile as writeFile2 } from "node:fs/promises";
703
685
  import { homedir as homedir2 } from "node:os";
704
686
  import { dirname as dirname2, join as join2 } from "node:path";
705
687
  import { randomUUID } from "node:crypto";
706
688
 
707
- // ../shared/src/runtime.ts
689
+ // packages/shared/src/runtime.ts
708
690
  var DEFAULT_RUNTIME_FILE = "~/.cursor-pool/runtime.json";
709
691
  var DEFAULT_DIAGNOSTICS_FILE = "~/.cursor-pool/diagnostics.jsonl";
710
692
 
711
- // ../service/src/runtime.ts
693
+ // packages/service/src/runtime.ts
712
694
  function createRuntimeId() {
713
695
  return randomUUID();
714
696
  }
@@ -739,7 +721,7 @@ async function readRuntimeInfo(options = {}) {
739
721
  }
740
722
  }
741
723
 
742
- // ../service/src/requestCheck.ts
724
+ // packages/service/src/requestCheck.ts
743
725
  import { randomUUID as randomUUID2 } from "node:crypto";
744
726
  var SAFE_MODEL_PATTERN = /^[A-Za-z0-9._:-]{1,96}$/;
745
727
  var SECRET_PATTERN = /(api[_-]?key|authorization|bearer|cursor[_-]?auth|provider[_-]?secret|secret|token|sk-[A-Za-z0-9])/i;
@@ -781,10 +763,10 @@ function createRequestCheckStore() {
781
763
  };
782
764
  }
783
765
 
784
- // ../service/src/server.ts
766
+ // packages/service/src/server.ts
785
767
  import { createServer } from "node:http";
786
768
 
787
- // ../service/src/canary.ts
769
+ // packages/service/src/canary.ts
788
770
  import { randomUUID as randomUUID3 } from "node:crypto";
789
771
  var isValidRequestId2 = (value) => typeof value === "string" && value.length > 0 && value.length <= 128;
790
772
  function sanitizeAgentCanary(input, options) {
@@ -813,12 +795,12 @@ function createCanaryStore() {
813
795
  };
814
796
  }
815
797
 
816
- // ../service/src/diagnostics.ts
798
+ // packages/service/src/diagnostics.ts
817
799
  import { mkdir as mkdir3, readFile as readFile3, writeFile as writeFile3 } from "node:fs/promises";
818
800
  import { dirname as dirname3, join as join3 } from "node:path";
819
801
  import { homedir as homedir3 } from "node:os";
820
802
 
821
- // ../service/src/requestGateway.ts
803
+ // packages/service/src/requestGateway.ts
822
804
  import { randomUUID as randomUUID4 } from "node:crypto";
823
805
  var SAFE_MODEL_PATTERN2 = /^[A-Za-z0-9._:-]{1,96}$/;
824
806
  var SAFE_REQUEST_ID_PATTERN = /^[A-Za-z0-9._:-]{1,128}$/;
@@ -1054,7 +1036,7 @@ function createGatewayStore() {
1054
1036
  };
1055
1037
  }
1056
1038
 
1057
- // ../service/src/diagnostics.ts
1039
+ // packages/service/src/diagnostics.ts
1058
1040
  var DEFAULT_MAX_DIAGNOSTICS = 20;
1059
1041
  var BLOCKED_GATE_REASONS = /* @__PURE__ */ new Set([
1060
1042
  "logged-out",
@@ -1317,7 +1299,7 @@ async function appendAgentGatewayDiagnostic(gateway, options = {}) {
1317
1299
  await writeFile3(diagnosticsFile, content, "utf8");
1318
1300
  }
1319
1301
 
1320
- // ../service/src/requestGate.ts
1302
+ // packages/service/src/requestGate.ts
1321
1303
  var INVALID_SESSION_GATE = { state: "blocked", reason: "invalid-session" };
1322
1304
  function invalidSessionGate() {
1323
1305
  return { ...INVALID_SESSION_GATE };
@@ -1374,7 +1356,7 @@ async function evaluateRouteState(options = {}) {
1374
1356
  return { state: "ready", expiresAt: routeToken.expiresAt };
1375
1357
  }
1376
1358
 
1377
- // ../service/src/takeover.ts
1359
+ // packages/service/src/takeover.ts
1378
1360
  import { randomUUID as randomUUID5 } from "node:crypto";
1379
1361
  var SAFE_TOKEN_PATTERN = /^[A-Za-z0-9._:-]{1,128}$/;
1380
1362
  var SAFE_MODEL_PATTERN3 = /^[A-Za-z0-9._:-]{1,96}$/;
@@ -1425,7 +1407,7 @@ function createAgentTakeoverStore() {
1425
1407
  };
1426
1408
  }
1427
1409
 
1428
- // ../shared/src/clientConfig.ts
1410
+ // packages/shared/src/clientConfig.ts
1429
1411
  import { mkdir as mkdir4, readFile as readFile4, writeFile as writeFile4 } from "node:fs/promises";
1430
1412
  import { homedir as homedir4 } from "node:os";
1431
1413
  import { dirname as dirname4, join as join4 } from "node:path";
@@ -1453,13 +1435,9 @@ async function readClientConfig(options = {}) {
1453
1435
  }
1454
1436
  }
1455
1437
 
1456
- // ../service/src/server.ts
1438
+ // packages/service/src/server.ts
1457
1439
  var LOOPBACK_HOST = "127.0.0.1";
1458
1440
  var DEFAULT_PORT = 56393;
1459
- var TRUSTED_RENDERER_ORIGINS = /* @__PURE__ */ new Set([
1460
- "vscode-file://vscode-app",
1461
- "null"
1462
- ]);
1463
1441
  var localServices = /* @__PURE__ */ new Map();
1464
1442
  async function resolvePlatformApiBaseUrl(options) {
1465
1443
  if (options.platformApiBaseUrl) {
@@ -1492,37 +1470,18 @@ function writeJson(response, statusCode, payload) {
1492
1470
  const body = JSON.stringify(payload);
1493
1471
  response.writeHead(statusCode, {
1494
1472
  "content-type": "application/json",
1495
- "content-length": Buffer.byteLength(body)
1473
+ "content-length": Buffer.byteLength(body),
1474
+ "access-control-allow-origin": "*",
1475
+ "access-control-allow-methods": "GET,POST,OPTIONS",
1476
+ "access-control-allow-headers": "content-type"
1496
1477
  });
1497
1478
  response.end(body);
1498
1479
  }
1499
- function trustedRendererOrigin(request) {
1500
- const origin = request.headers.origin;
1501
- if (typeof origin !== "string") {
1502
- return void 0;
1503
- }
1504
- if (TRUSTED_RENDERER_ORIGINS.has(origin) || origin.startsWith("vscode-webview://")) {
1505
- return origin;
1506
- }
1507
- return void 0;
1508
- }
1509
- function applyCorsHeaders(request, response) {
1510
- const origin = trustedRendererOrigin(request);
1511
- if (!origin) {
1512
- return false;
1513
- }
1514
- response.setHeader("access-control-allow-origin", origin);
1515
- response.setHeader("access-control-allow-methods", "GET,POST,OPTIONS");
1516
- response.setHeader("access-control-allow-headers", "content-type,authorization");
1517
- return true;
1518
- }
1519
- function writeCorsPreflight(request, response) {
1520
- if (!applyCorsHeaders(request, response)) {
1521
- response.writeHead(403);
1522
- response.end();
1523
- return;
1524
- }
1480
+ function writeCorsPreflight(response) {
1525
1481
  response.writeHead(204, {
1482
+ "access-control-allow-origin": "*",
1483
+ "access-control-allow-methods": "GET,POST,OPTIONS",
1484
+ "access-control-allow-headers": "content-type",
1526
1485
  "access-control-max-age": "600"
1527
1486
  });
1528
1487
  response.end();
@@ -1537,7 +1496,10 @@ function writeEventStream(response, events) {
1537
1496
  "content-type": "text/event-stream; charset=utf-8",
1538
1497
  "cache-control": "no-cache",
1539
1498
  "connection": "keep-alive",
1540
- "content-length": Buffer.byteLength(body)
1499
+ "content-length": Buffer.byteLength(body),
1500
+ "access-control-allow-origin": "*",
1501
+ "access-control-allow-methods": "GET,POST,OPTIONS",
1502
+ "access-control-allow-headers": "content-type,authorization"
1541
1503
  });
1542
1504
  response.end(body);
1543
1505
  }
@@ -1761,10 +1723,9 @@ async function completeForwardAfterClientResponse(context) {
1761
1723
  async function routeRequest(request, response, runtime, options, canaryStore, requestCheckStore, gatewayStore, takeoverStore, stop) {
1762
1724
  try {
1763
1725
  if (request.method === "OPTIONS") {
1764
- writeCorsPreflight(request, response);
1726
+ writeCorsPreflight(response);
1765
1727
  return;
1766
1728
  }
1767
- applyCorsHeaders(request, response);
1768
1729
  if (request.method === "GET" && request.url === "/health") {
1769
1730
  writeJson(response, 200, buildHealth(runtime));
1770
1731
  return;
@@ -2089,7 +2050,7 @@ async function routeRequest(request, response, runtime, options, canaryStore, re
2089
2050
  if (request.method === "POST" && request.url === "/shutdown") {
2090
2051
  writeJson(response, 200, { ok: true });
2091
2052
  response.once("finish", () => {
2092
- void stop().then(() => options.onShutdown?.());
2053
+ void stop();
2093
2054
  });
2094
2055
  return;
2095
2056
  }
@@ -2176,7 +2137,7 @@ async function startServer(options = {}) {
2176
2137
  }
2177
2138
  }
2178
2139
 
2179
- // ../extension/src/runtime.ts
2140
+ // packages/extension/src/runtime.ts
2180
2141
  async function readRuntimeInfo2(options = {}) {
2181
2142
  return readRuntimeInfo({ runtimeFile: options.runtimeFile });
2182
2143
  }
@@ -2184,7 +2145,7 @@ async function writeRuntimeInfo2(runtime, options = {}) {
2184
2145
  await writeRuntimeInfo(runtime, { runtimeFile: options.runtimeFile });
2185
2146
  }
2186
2147
 
2187
- // ../extension/src/api.ts
2148
+ // packages/extension/src/api.ts
2188
2149
  var DEFAULT_SERVICE_PORT = 56393;
2189
2150
  var localExtensionServices = /* @__PURE__ */ new Map();
2190
2151
  function buildExtensionDeviceInfo() {
@@ -2192,7 +2153,7 @@ function buildExtensionDeviceInfo() {
2192
2153
  name: hostname(),
2193
2154
  os: osPlatform(),
2194
2155
  arch: arch(),
2195
- extensionVersion: "0.5.8"
2156
+ extensionVersion: "0.5.9"
2196
2157
  };
2197
2158
  }
2198
2159
  function serviceUrl(runtime, path) {
@@ -2287,16 +2248,6 @@ function normalizePlatformMode(value) {
2287
2248
  };
2288
2249
  }
2289
2250
  if (mode?.state === "active" && typeof mode.productId === "string" && typeof mode.startedAt === "string") {
2290
- const route = mode.route;
2291
- if (route?.state === "ready" && typeof route.expiresAt === "string") {
2292
- return { state: "active", productId: mode.productId, startedAt: mode.startedAt, route };
2293
- }
2294
- if (route?.state === "expired" && typeof route.expiresAt === "string") {
2295
- return { state: "active", productId: mode.productId, startedAt: mode.startedAt, route };
2296
- }
2297
- if (route?.state === "missing") {
2298
- return { state: "active", productId: mode.productId, startedAt: mode.startedAt, route };
2299
- }
2300
2251
  return { state: "active", productId: mode.productId, startedAt: mode.startedAt };
2301
2252
  }
2302
2253
  return null;
@@ -2498,22 +2449,7 @@ async function logoutPlatform2(runtimeFile, options = {}) {
2498
2449
  return postJson({ runtimeFile, ...options }, "/platform/logout");
2499
2450
  }
2500
2451
 
2501
- // ../extension/src/panel.ts
2502
- function panelModeIsTakeoverReady(mode) {
2503
- return mode.startsWith("active ") && mode.endsWith(" route-ready");
2504
- }
2505
- function panelModeDisplay(mode) {
2506
- if (panelModeIsTakeoverReady(mode)) {
2507
- return "\u5E73\u53F0\u63A5\u7BA1";
2508
- }
2509
- if (mode.endsWith(" route-missing")) {
2510
- return "\u5E73\u53F0\u672A\u63A5\u7BA1\uFF08\u8DEF\u7531\u7F3A\u5931\uFF09";
2511
- }
2512
- if (mode.endsWith(" route-expired")) {
2513
- return "\u5E73\u53F0\u672A\u63A5\u7BA1\uFF08\u8DEF\u7531\u8FC7\u671F\uFF09";
2514
- }
2515
- return "\u5B98\u65B9\u6A21\u5F0F";
2516
- }
2452
+ // packages/extension/src/panel.ts
2517
2453
  function createPanelViewModel(status) {
2518
2454
  const rows = [
2519
2455
  { label: "patch", value: status.patch },
@@ -2541,7 +2477,7 @@ function createPanelViewModel(status) {
2541
2477
  rows.push({ label: "current product", value: status.selectedProductId });
2542
2478
  }
2543
2479
  const platformState = status.platform ?? "logged-out";
2544
- const takeoverActive = panelModeIsTakeoverReady(status.mode);
2480
+ const takeoverActive = status.mode.startsWith("active ");
2545
2481
  const platformLoggedIn = platformState === "logged-in" || platformState === "offline" || platformState === "invalid-token";
2546
2482
  return {
2547
2483
  title: "Cursor Pool \u53F7\u6C60\u5BA2\u6237\u7AEF",
@@ -2562,13 +2498,7 @@ function createPanelViewModel(status) {
2562
2498
  }
2563
2499
  function formatPanelMode(mode) {
2564
2500
  if (mode?.state === "active") {
2565
- if (mode.route?.state === "ready") {
2566
- return `active ${mode.productId} route-ready`;
2567
- }
2568
- if (mode.route?.state === "expired") {
2569
- return `active ${mode.productId} route-expired`;
2570
- }
2571
- return `active ${mode.productId} route-missing`;
2501
+ return `active ${mode.productId}`;
2572
2502
  }
2573
2503
  if (mode?.state === "inactive" && mode.releaseReason) {
2574
2504
  return `inactive ${mode.releaseReason}`;
@@ -2654,7 +2584,7 @@ function buildPanelHtml(viewModel) {
2654
2584
  ...valueFor("credits", "") ? [{ label: "\u79EF\u5206\u4F59\u989D", value: valueFor("credits") }] : [],
2655
2585
  ...valueFor("user", "") ? [{
2656
2586
  label: "\u5F53\u524D\u6A21\u5F0F",
2657
- value: panelModeDisplay(valueFor("mode"))
2587
+ value: valueFor("mode").startsWith("active ") ? "\u5E73\u53F0\u63A5\u7BA1" : "\u5B98\u65B9\u6A21\u5F0F"
2658
2588
  }] : []
2659
2589
  ];
2660
2590
  const rows = statusItems.map((row) => `<li><span>${escapeHtml(row.label)}</span><strong>${escapeHtml(row.value)}</strong></li>`).join("");
@@ -2905,7 +2835,7 @@ function registerStatusPanel(context, vscode, options = {}) {
2905
2835
  return provider;
2906
2836
  }
2907
2837
 
2908
- // ../extension/src/extension.ts
2838
+ // packages/extension/src/extension.ts
2909
2839
  async function appendDiagnostic(message) {
2910
2840
  try {
2911
2841
  const os = await new Function("specifier", "return import(specifier)")("node:os");
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cursor-pool/extension",
3
- "version": "0.5.8",
3
+ "version": "0.5.9",
4
4
  "displayName": "Cursor Pool 平台模式",
5
5
  "publisher": "cursor-pool",
6
6
  "engines": {
@@ -21,8 +21,8 @@
21
21
  "./runtime": "./src/runtime.ts"
22
22
  },
23
23
  "dependencies": {
24
- "@cursor-pool/service": "0.5.8",
25
- "@cursor-pool/shared": "0.5.8"
24
+ "@cursor-pool/service": "0.5.9",
25
+ "@cursor-pool/shared": "0.5.9"
26
26
  },
27
27
  "contributes": {
28
28
  "viewsContainers": {
@@ -23,12 +23,7 @@ export type PlatformModeReleaseReason =
23
23
  | 'device-inactive';
24
24
  export type PlatformModeSnapshot =
25
25
  | { state: 'inactive'; releaseReason?: PlatformModeReleaseReason; releasedAt?: string }
26
- | {
27
- state: 'active';
28
- productId: string;
29
- startedAt: string;
30
- route?: { state: 'missing' } | { state: 'ready'; expiresAt: string } | { state: 'expired'; expiresAt: string };
31
- };
26
+ | { state: 'active'; productId: string; startedAt: string };
32
27
  export type PlatformModeResult =
33
28
  | PlatformModeSnapshot
34
29
  | { state: 'logged-out' }
@@ -119,7 +114,7 @@ export function buildExtensionDeviceInfo() {
119
114
  name: hostname(),
120
115
  os: osPlatform(),
121
116
  arch: arch(),
122
- extensionVersion: '0.5.8',
117
+ extensionVersion: '0.5.9',
123
118
  };
124
119
  }
125
120
 
@@ -260,16 +255,6 @@ function normalizePlatformMode(value: unknown): PlatformModeSnapshot | null {
260
255
  typeof mode.productId === 'string' &&
261
256
  typeof mode.startedAt === 'string'
262
257
  ) {
263
- const route = mode.route;
264
- if (route?.state === 'ready' && typeof route.expiresAt === 'string') {
265
- return { state: 'active', productId: mode.productId, startedAt: mode.startedAt, route };
266
- }
267
- if (route?.state === 'expired' && typeof route.expiresAt === 'string') {
268
- return { state: 'active', productId: mode.productId, startedAt: mode.startedAt, route };
269
- }
270
- if (route?.state === 'missing') {
271
- return { state: 'active', productId: mode.productId, startedAt: mode.startedAt, route };
272
- }
273
258
  return { state: 'active', productId: mode.productId, startedAt: mode.startedAt };
274
259
  }
275
260
  return null;
@@ -49,23 +49,6 @@ export type PanelViewModel = {
49
49
  error?: string;
50
50
  };
51
51
 
52
- function panelModeIsTakeoverReady(mode: string) {
53
- return mode.startsWith('active ') && mode.endsWith(' route-ready');
54
- }
55
-
56
- function panelModeDisplay(mode: string) {
57
- if (panelModeIsTakeoverReady(mode)) {
58
- return '平台接管';
59
- }
60
- if (mode.endsWith(' route-missing')) {
61
- return '平台未接管(路由缺失)';
62
- }
63
- if (mode.endsWith(' route-expired')) {
64
- return '平台未接管(路由过期)';
65
- }
66
- return '官方模式';
67
- }
68
-
69
52
  type ExtensionContext = {
70
53
  subscriptions?: { push: (subscription: unknown) => unknown };
71
54
  };
@@ -146,7 +129,7 @@ export function createPanelViewModel(status: PanelStatus): PanelViewModel {
146
129
  }
147
130
 
148
131
  const platformState = status.platform ?? 'logged-out';
149
- const takeoverActive = panelModeIsTakeoverReady(status.mode);
132
+ const takeoverActive = status.mode.startsWith('active ');
150
133
  const platformLoggedIn =
151
134
  platformState === 'logged-in' || platformState === 'offline' || platformState === 'invalid-token';
152
135
 
@@ -171,13 +154,7 @@ export function createPanelViewModel(status: PanelStatus): PanelViewModel {
171
154
 
172
155
  function formatPanelMode(mode: PlatformStatus['mode']) {
173
156
  if (mode?.state === 'active') {
174
- if (mode.route?.state === 'ready') {
175
- return `active ${mode.productId} route-ready`;
176
- }
177
- if (mode.route?.state === 'expired') {
178
- return `active ${mode.productId} route-expired`;
179
- }
180
- return `active ${mode.productId} route-missing`;
157
+ return `active ${mode.productId}`;
181
158
  }
182
159
  if (mode?.state === 'inactive' && mode.releaseReason) {
183
160
  return `inactive ${mode.releaseReason}`;
@@ -277,7 +254,7 @@ export function buildPanelHtml(viewModel: PanelViewModel): string {
277
254
  ...(valueFor('user', '')
278
255
  ? [{
279
256
  label: '当前模式',
280
- value: panelModeDisplay(valueFor('mode')),
257
+ value: valueFor('mode').startsWith('active ') ? '平台接管' : '官方模式',
281
258
  }]
282
259
  : []),
283
260
  ];
@@ -652,39 +652,6 @@ test('panel keeps active platform mode out of rendered status list', () => {
652
652
  assert.doesNotMatch(html, /active prod_basic/);
653
653
  });
654
654
 
655
- test('panel only displays takeover when active route is ready', () => {
656
- const ready = buildPanelHtml(createPanelViewModel({
657
- patch: 'applied',
658
- service: 'running',
659
- compat: 'supported',
660
- mode: 'active prod_basic route-ready',
661
- platform: 'logged-in',
662
- user: 'user@example.test',
663
- }));
664
- const missing = buildPanelHtml(createPanelViewModel({
665
- patch: 'applied',
666
- service: 'running',
667
- compat: 'supported',
668
- mode: 'active prod_basic route-missing',
669
- platform: 'logged-in',
670
- user: 'user@example.test',
671
- }));
672
- const expired = buildPanelHtml(createPanelViewModel({
673
- patch: 'applied',
674
- service: 'running',
675
- compat: 'supported',
676
- mode: 'active prod_basic route-expired',
677
- platform: 'logged-in',
678
- user: 'user@example.test',
679
- }));
680
-
681
- assert.match(ready, /当前模式<\/span><strong>平台接管<\/strong>/);
682
- assert.match(missing, /当前模式<\/span><strong>平台未接管(路由缺失)<\/strong>/);
683
- assert.match(expired, /当前模式<\/span><strong>平台未接管(路由过期)<\/strong>/);
684
- assert.doesNotMatch(missing, /当前模式<\/span><strong>平台接管<\/strong>/);
685
- assert.doesNotMatch(expired, /当前模式<\/span><strong>平台接管<\/strong>/);
686
- });
687
-
688
655
  test('sidebar view model shows inactive mode release reason', () => {
689
656
  const viewModel = createPanelViewModel({
690
657
  patch: 'applied',
@@ -1688,7 +1655,7 @@ test('API can login and logout through local service platform routes', async ()
1688
1655
  assert.equal(typeof (requests[0]?.body.device as Record<string, unknown>).name, 'string');
1689
1656
  assert.equal(typeof (requests[0]?.body.device as Record<string, unknown>).os, 'string');
1690
1657
  assert.equal(typeof (requests[0]?.body.device as Record<string, unknown>).arch, 'string');
1691
- assert.equal((requests[0]?.body.device as Record<string, unknown>).extensionVersion, '0.5.8');
1658
+ assert.equal((requests[0]?.body.device as Record<string, unknown>).extensionVersion, '0.5.9');
1692
1659
  assert.equal(requests[1]?.method, 'POST');
1693
1660
  assert.equal(requests[1]?.url, '/platform/logout');
1694
1661
  } finally {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cursor-pool/patcher",
3
- "version": "0.5.8",
3
+ "version": "0.5.9",
4
4
  "type": "module",
5
5
  "main": "./src/index.ts",
6
6
  "exports": {
@@ -9,7 +9,7 @@
9
9
  "./marker": "./src/marker.ts"
10
10
  },
11
11
  "dependencies": {
12
- "@cursor-pool/shared": "0.5.8"
12
+ "@cursor-pool/shared": "0.5.9"
13
13
  },
14
14
  "scripts": {
15
15
  "test": "tsx --test test/*.test.ts"