lexmount 0.2.5 → 0.2.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -149,6 +149,14 @@ const details = await client.contexts.get(context.id);
149
149
  console.log(details.status);
150
150
  ```
151
151
 
152
+ Fork an available context into a new context:
153
+
154
+ ```ts
155
+ const source = await client.contexts.create();
156
+ const forked = await client.contexts.fork(source.id);
157
+ console.log(forked.id);
158
+ ```
159
+
152
160
  List contexts:
153
161
 
154
162
  ```ts
@@ -164,6 +172,13 @@ Force release a stuck lock:
164
172
  await client.contexts.forceRelease('context-id');
165
173
  ```
166
174
 
175
+ Current `context fork` limitations:
176
+
177
+ - Only supports offline snapshot copy from an `available` context
178
+ - Does not support hot fork from a `locked` context
179
+ - Does not support copy-on-write
180
+ - Does not support parent/child lineage tracking
181
+
167
182
  ### Extensions
168
183
 
169
184
  Upload an extension archive:
@@ -271,6 +286,7 @@ Example scripts live in [examples](./examples):
271
286
  - `playwright-basic.ts`
272
287
  - `session-management.ts`
273
288
  - `context-basic.ts`
289
+ - `context-fork.ts`
274
290
  - `context-list-get.ts`
275
291
  - `context-modes.ts`
276
292
  - `context-lock-handling.ts`
@@ -283,6 +299,7 @@ Run them with:
283
299
  ```bash
284
300
  cd examples
285
301
  npm install
302
+ npm run context-fork
286
303
  npm run playwright-basic
287
304
  npm run session-management
288
305
  npm run extension-basic
@@ -450,6 +467,14 @@ const details = await client.contexts.get(context.id);
450
467
  console.log(details.status);
451
468
  ```
452
469
 
470
+ 基于一个 `available` context 创建新的 fork:
471
+
472
+ ```ts
473
+ const source = await client.contexts.create();
474
+ const forked = await client.contexts.fork(source.id);
475
+ console.log(forked.id);
476
+ ```
477
+
453
478
  列出 context:
454
479
 
455
480
  ```ts
@@ -465,6 +490,13 @@ const contexts = await client.contexts.list({
465
490
  await client.contexts.forceRelease('context-id');
466
491
  ```
467
492
 
493
+ 当前 `context fork` 第一版限制:
494
+
495
+ - 只支持对 `available context` 做离线快照复制
496
+ - 不支持 `locked` context 的热 fork
497
+ - 不支持 copy-on-write
498
+ - 不支持父子链追踪
499
+
468
500
  ### Extensions
469
501
 
470
502
  上传扩展压缩包:
@@ -572,6 +604,7 @@ npm run docs:html
572
604
  - `playwright-basic.ts`
573
605
  - `session-management.ts`
574
606
  - `context-basic.ts`
607
+ - `context-fork.ts`
575
608
  - `context-list-get.ts`
576
609
  - `context-modes.ts`
577
610
  - `context-lock-handling.ts`
@@ -584,6 +617,7 @@ npm run docs:html
584
617
  ```bash
585
618
  cd examples
586
619
  npm install
620
+ npm run context-fork
587
621
  npm run playwright-basic
588
622
  npm run session-management
589
623
  npm run extension-basic
package/dist/index.d.mts CHANGED
@@ -269,6 +269,19 @@ interface SessionDownloadsDeleteResponseShape {
269
269
  status: string;
270
270
  deletedCount: number;
271
271
  }
272
+ /**
273
+ * Session target metadata returned by `/json`.
274
+ */
275
+ interface SessionTargetInfoShape {
276
+ id: string;
277
+ title: string;
278
+ type: string;
279
+ url: string;
280
+ description: string;
281
+ inspectUrl: string | null;
282
+ webSocketDebuggerUrl: string | null;
283
+ webSocketDebuggerUrlTransformed: string | null;
284
+ }
272
285
  /**
273
286
  * Session pagination metadata.
274
287
  */
@@ -334,6 +347,10 @@ declare class ContextsResource {
334
347
  * Fetch a single context.
335
348
  */
336
349
  get(contextId: string): Promise<ContextInfo>;
350
+ /**
351
+ * Fork an existing persistent context into a new context.
352
+ */
353
+ fork(contextId: string): Promise<ContextInfo>;
337
354
  /**
338
355
  * Delete a persistent context.
339
356
  */
@@ -478,6 +495,20 @@ declare class SessionDownloadsDeleteResponse implements SessionDownloadsDeleteRe
478
495
  readonly deletedCount: number;
479
496
  constructor(shape: SessionDownloadsDeleteResponseShape);
480
497
  }
498
+ /**
499
+ * Session target metadata returned by `/json`.
500
+ */
501
+ declare class SessionTargetInfo implements SessionTargetInfoShape {
502
+ readonly id: string;
503
+ readonly title: string;
504
+ readonly type: string;
505
+ readonly url: string;
506
+ readonly description: string;
507
+ readonly inspectUrl: string | null;
508
+ readonly webSocketDebuggerUrl: string | null;
509
+ readonly webSocketDebuggerUrlTransformed: string | null;
510
+ constructor(shape: SessionTargetInfoShape);
511
+ }
481
512
  /**
482
513
  * Session download operations.
483
514
  */
@@ -520,6 +551,10 @@ declare class SessionsResource {
520
551
  * Delete a browser session.
521
552
  */
522
553
  delete(options: SessionDeleteOptions): Promise<void>;
554
+ /**
555
+ * List target/page metadata for a session via `/json`.
556
+ */
557
+ listTargets(sessionId: string): Promise<SessionTargetInfo[]>;
523
558
  /**
524
559
  * Fetch the debugger WebSocket URL for a session.
525
560
  *
@@ -530,8 +565,10 @@ declare class SessionsResource {
530
565
  private handleCreateError;
531
566
  private handleGetError;
532
567
  private handleListError;
568
+ private handleListTargetsError;
533
569
  private handleDeleteError;
534
570
  private mapSessionInfo;
571
+ private mapSessionTarget;
535
572
  private _getCreatedSession;
536
573
  }
537
574
 
@@ -669,4 +706,4 @@ declare class TimeoutError extends LexmountError {
669
706
  */
670
707
  declare const VERSION = "0.2.5";
671
708
 
672
- export { APIError, AuthenticationError, type BrowserMode, type ContextAccessMode, type ContextCreateOptions, ContextInfo, type ContextListOptions, ContextListResponse, ContextLockedError, type ContextMetadata, ContextNotFoundError, type ContextStatus, ContextsResource, ExtensionInfo, type ExtensionInfoShape, type ExtensionListOptions, type ExtensionUploadOptions, ExtensionsResource, type ForceReleaseResponse, Lexmount, type LexmountConfig, LexmountError, LexmountLogger, type LogLevel, NetworkError, PaginationInfo, type PaginationInfoShape, type SessionContext, type SessionCreateOptions, type SessionCreateResponse, type SessionDeleteOptions, SessionDownloadInfo, type SessionDownloadInfoShape, SessionDownloadsDeleteResponse, type SessionDownloadsDeleteResponseShape, SessionDownloadsListResponse, type SessionDownloadsListResponseShape, SessionDownloadsResource, SessionInfo, type SessionListOptions, SessionListResponse, SessionNotFoundError, type SessionProxyConfig, type SessionStatus, SessionsResource, TimeoutError, VERSION, ValidationError, Lexmount as default, disableLogging, enableLogging, getLogger, setLogLevel };
709
+ export { APIError, AuthenticationError, type BrowserMode, type ContextAccessMode, type ContextCreateOptions, ContextInfo, type ContextListOptions, ContextListResponse, ContextLockedError, type ContextMetadata, ContextNotFoundError, type ContextStatus, ContextsResource, ExtensionInfo, type ExtensionInfoShape, type ExtensionListOptions, type ExtensionUploadOptions, ExtensionsResource, type ForceReleaseResponse, Lexmount, type LexmountConfig, LexmountError, LexmountLogger, type LogLevel, NetworkError, PaginationInfo, type PaginationInfoShape, type SessionContext, type SessionCreateOptions, type SessionCreateResponse, type SessionDeleteOptions, SessionDownloadInfo, type SessionDownloadInfoShape, SessionDownloadsDeleteResponse, type SessionDownloadsDeleteResponseShape, SessionDownloadsListResponse, type SessionDownloadsListResponseShape, SessionDownloadsResource, SessionInfo, type SessionListOptions, SessionListResponse, SessionNotFoundError, type SessionProxyConfig, type SessionStatus, SessionTargetInfo, type SessionTargetInfoShape, SessionsResource, TimeoutError, VERSION, ValidationError, Lexmount as default, disableLogging, enableLogging, getLogger, setLogLevel };
package/dist/index.d.ts CHANGED
@@ -269,6 +269,19 @@ interface SessionDownloadsDeleteResponseShape {
269
269
  status: string;
270
270
  deletedCount: number;
271
271
  }
272
+ /**
273
+ * Session target metadata returned by `/json`.
274
+ */
275
+ interface SessionTargetInfoShape {
276
+ id: string;
277
+ title: string;
278
+ type: string;
279
+ url: string;
280
+ description: string;
281
+ inspectUrl: string | null;
282
+ webSocketDebuggerUrl: string | null;
283
+ webSocketDebuggerUrlTransformed: string | null;
284
+ }
272
285
  /**
273
286
  * Session pagination metadata.
274
287
  */
@@ -334,6 +347,10 @@ declare class ContextsResource {
334
347
  * Fetch a single context.
335
348
  */
336
349
  get(contextId: string): Promise<ContextInfo>;
350
+ /**
351
+ * Fork an existing persistent context into a new context.
352
+ */
353
+ fork(contextId: string): Promise<ContextInfo>;
337
354
  /**
338
355
  * Delete a persistent context.
339
356
  */
@@ -478,6 +495,20 @@ declare class SessionDownloadsDeleteResponse implements SessionDownloadsDeleteRe
478
495
  readonly deletedCount: number;
479
496
  constructor(shape: SessionDownloadsDeleteResponseShape);
480
497
  }
498
+ /**
499
+ * Session target metadata returned by `/json`.
500
+ */
501
+ declare class SessionTargetInfo implements SessionTargetInfoShape {
502
+ readonly id: string;
503
+ readonly title: string;
504
+ readonly type: string;
505
+ readonly url: string;
506
+ readonly description: string;
507
+ readonly inspectUrl: string | null;
508
+ readonly webSocketDebuggerUrl: string | null;
509
+ readonly webSocketDebuggerUrlTransformed: string | null;
510
+ constructor(shape: SessionTargetInfoShape);
511
+ }
481
512
  /**
482
513
  * Session download operations.
483
514
  */
@@ -520,6 +551,10 @@ declare class SessionsResource {
520
551
  * Delete a browser session.
521
552
  */
522
553
  delete(options: SessionDeleteOptions): Promise<void>;
554
+ /**
555
+ * List target/page metadata for a session via `/json`.
556
+ */
557
+ listTargets(sessionId: string): Promise<SessionTargetInfo[]>;
523
558
  /**
524
559
  * Fetch the debugger WebSocket URL for a session.
525
560
  *
@@ -530,8 +565,10 @@ declare class SessionsResource {
530
565
  private handleCreateError;
531
566
  private handleGetError;
532
567
  private handleListError;
568
+ private handleListTargetsError;
533
569
  private handleDeleteError;
534
570
  private mapSessionInfo;
571
+ private mapSessionTarget;
535
572
  private _getCreatedSession;
536
573
  }
537
574
 
@@ -669,4 +706,4 @@ declare class TimeoutError extends LexmountError {
669
706
  */
670
707
  declare const VERSION = "0.2.5";
671
708
 
672
- export { APIError, AuthenticationError, type BrowserMode, type ContextAccessMode, type ContextCreateOptions, ContextInfo, type ContextListOptions, ContextListResponse, ContextLockedError, type ContextMetadata, ContextNotFoundError, type ContextStatus, ContextsResource, ExtensionInfo, type ExtensionInfoShape, type ExtensionListOptions, type ExtensionUploadOptions, ExtensionsResource, type ForceReleaseResponse, Lexmount, type LexmountConfig, LexmountError, LexmountLogger, type LogLevel, NetworkError, PaginationInfo, type PaginationInfoShape, type SessionContext, type SessionCreateOptions, type SessionCreateResponse, type SessionDeleteOptions, SessionDownloadInfo, type SessionDownloadInfoShape, SessionDownloadsDeleteResponse, type SessionDownloadsDeleteResponseShape, SessionDownloadsListResponse, type SessionDownloadsListResponseShape, SessionDownloadsResource, SessionInfo, type SessionListOptions, SessionListResponse, SessionNotFoundError, type SessionProxyConfig, type SessionStatus, SessionsResource, TimeoutError, VERSION, ValidationError, Lexmount as default, disableLogging, enableLogging, getLogger, setLogLevel };
709
+ export { APIError, AuthenticationError, type BrowserMode, type ContextAccessMode, type ContextCreateOptions, ContextInfo, type ContextListOptions, ContextListResponse, ContextLockedError, type ContextMetadata, ContextNotFoundError, type ContextStatus, ContextsResource, ExtensionInfo, type ExtensionInfoShape, type ExtensionListOptions, type ExtensionUploadOptions, ExtensionsResource, type ForceReleaseResponse, Lexmount, type LexmountConfig, LexmountError, LexmountLogger, type LogLevel, NetworkError, PaginationInfo, type PaginationInfoShape, type SessionContext, type SessionCreateOptions, type SessionCreateResponse, type SessionDeleteOptions, SessionDownloadInfo, type SessionDownloadInfoShape, SessionDownloadsDeleteResponse, type SessionDownloadsDeleteResponseShape, SessionDownloadsListResponse, type SessionDownloadsListResponseShape, SessionDownloadsResource, SessionInfo, type SessionListOptions, SessionListResponse, SessionNotFoundError, type SessionProxyConfig, type SessionStatus, SessionTargetInfo, type SessionTargetInfoShape, SessionsResource, TimeoutError, VERSION, ValidationError, Lexmount as default, disableLogging, enableLogging, getLogger, setLogLevel };
package/dist/index.js CHANGED
@@ -51,6 +51,7 @@ __export(index_exports, {
51
51
  SessionInfo: () => SessionInfo,
52
52
  SessionListResponse: () => SessionListResponse,
53
53
  SessionNotFoundError: () => SessionNotFoundError,
54
+ SessionTargetInfo: () => SessionTargetInfo,
54
55
  SessionsResource: () => SessionsResource,
55
56
  TimeoutError: () => TimeoutError,
56
57
  VERSION: () => VERSION,
@@ -360,6 +361,37 @@ var ContextsResource = class {
360
361
  getLogger().info(`Retrieved context '${contextInfo.id}' (status: ${contextInfo.status})`);
361
362
  return contextInfo;
362
363
  }
364
+ /**
365
+ * Fork an existing persistent context into a new context.
366
+ */
367
+ async fork(contextId) {
368
+ const url = `${this.client.baseUrl}/instance/v1/contexts/${contextId}/fork`;
369
+ const payload = {
370
+ api_key: this.client.apiKey,
371
+ project_id: this.client.projectId
372
+ };
373
+ const response = await this.client._post(url, payload);
374
+ if (response.status >= 400) {
375
+ this.handleError(response, "fork", contextId);
376
+ }
377
+ const result = asRecord(response.data);
378
+ const forkedContextId = getString(result.context_id);
379
+ if (!forkedContextId) {
380
+ throw new APIError("Failed to fork context: context_id missing from response", {
381
+ statusCode: response.status,
382
+ response: response.data
383
+ });
384
+ }
385
+ const contextInfo = new ContextInfo({
386
+ id: forkedContextId,
387
+ status: normalizeContextStatus(result.locked),
388
+ metadata: result.metadata ?? {},
389
+ createdAt: parseTimestamp(result.created_at),
390
+ updatedAt: parseTimestamp(result.updated_at)
391
+ });
392
+ getLogger().info(`Successfully forked context '${contextId}' -> '${contextInfo.id}'`);
393
+ return contextInfo;
394
+ }
363
395
  /**
364
396
  * Delete a persistent context.
365
397
  */
@@ -406,7 +438,7 @@ var ContextsResource = class {
406
438
  const suffix = contextId ? `: ${contextId}` : "";
407
439
  throw new ContextNotFoundError(`Context not found${suffix}`);
408
440
  }
409
- if (response.status === 409 && errorCode === "context_locked") {
441
+ if (response.status === 409 && (errorCode === "context_locked" || errorCode === "CONTEXT_FORK_SOURCE_LOCKED")) {
410
442
  throw new ContextLockedError(errorMessage, {
411
443
  activeSessionId: getString(metadata.activeSessionId),
412
444
  retryAfter: typeof metadata.retryAfter === "number" ? metadata.retryAfter : void 0
@@ -697,6 +729,18 @@ var SessionDownloadsDeleteResponse = class {
697
729
  this.deletedCount = shape.deletedCount;
698
730
  }
699
731
  };
732
+ var SessionTargetInfo = class {
733
+ constructor(shape) {
734
+ this.id = shape.id;
735
+ this.title = shape.title;
736
+ this.type = shape.type;
737
+ this.url = shape.url;
738
+ this.description = shape.description;
739
+ this.inspectUrl = shape.inspectUrl;
740
+ this.webSocketDebuggerUrl = shape.webSocketDebuggerUrl;
741
+ this.webSocketDebuggerUrlTransformed = shape.webSocketDebuggerUrlTransformed;
742
+ }
743
+ };
700
744
  var SessionDownloadsResource = class {
701
745
  constructor(client) {
702
746
  this.client = client;
@@ -927,6 +971,19 @@ var SessionsResource = class {
927
971
  }
928
972
  getLogger().info(`Session deleted successfully: ${options.sessionId}`);
929
973
  }
974
+ /**
975
+ * List target/page metadata for a session via `/json`.
976
+ */
977
+ async listTargets(sessionId) {
978
+ const response = await this.client._get(`${this.client.baseUrl}/json`, {
979
+ session_id: sessionId
980
+ });
981
+ if (response.status >= 400) {
982
+ this.handleListTargetsError(response, sessionId);
983
+ }
984
+ const result = Array.isArray(response.data) ? response.data : [];
985
+ return result.map((item) => this.mapSessionTarget(asRecord3(item)));
986
+ }
930
987
  /**
931
988
  * Fetch the debugger WebSocket URL for a session.
932
989
  *
@@ -1022,6 +1079,24 @@ var SessionsResource = class {
1022
1079
  response: response.data
1023
1080
  });
1024
1081
  }
1082
+ handleListTargetsError(response, sessionId) {
1083
+ const errorData = asRecord3(response.data);
1084
+ const errorMessage = getString3(errorData.error) ?? getString3(errorData.message) ?? "Unknown error";
1085
+ if (response.status === 401) {
1086
+ throw new AuthenticationError(
1087
+ `Authentication failed: ${errorMessage}. Please check your API key and project ID.`
1088
+ );
1089
+ }
1090
+ if (response.status === 404) {
1091
+ throw new SessionNotFoundError(
1092
+ `Session not found: ${errorMessage}. Session ID '${sessionId}' may not exist in this project.`
1093
+ );
1094
+ }
1095
+ throw new APIError(`Failed to list session targets: ${errorMessage}`, {
1096
+ statusCode: response.status,
1097
+ response: response.data
1098
+ });
1099
+ }
1025
1100
  handleDeleteError(response, sessionId) {
1026
1101
  const errorData = asRecord3(response.data);
1027
1102
  const errorMessage = getString3(errorData.error) ?? getString3(errorData.message) ?? "Unknown error";
@@ -1055,6 +1130,18 @@ var SessionsResource = class {
1055
1130
  client: this.client
1056
1131
  });
1057
1132
  }
1133
+ mapSessionTarget(raw) {
1134
+ return new SessionTargetInfo({
1135
+ id: getString3(raw.id) ?? "",
1136
+ title: getString3(raw.title) ?? "",
1137
+ type: getString3(raw.type) ?? "",
1138
+ url: getString3(raw.url) ?? "",
1139
+ description: getString3(raw.description) ?? "",
1140
+ inspectUrl: getString3(raw.inspectUrl) ?? getString3(raw.inspect_url) ?? null,
1141
+ webSocketDebuggerUrl: getString3(raw.webSocketDebuggerUrl) ?? getString3(raw.web_socket_debugger_url) ?? null,
1142
+ webSocketDebuggerUrlTransformed: getString3(raw.webSocketDebuggerUrlTransformed) ?? getString3(raw.web_socket_debugger_url_transformed) ?? null
1143
+ });
1144
+ }
1058
1145
  async _getCreatedSession(sessionId, projectId) {
1059
1146
  try {
1060
1147
  return await this.get(sessionId, projectId);
@@ -1218,6 +1305,7 @@ var VERSION = "0.2.5";
1218
1305
  SessionInfo,
1219
1306
  SessionListResponse,
1220
1307
  SessionNotFoundError,
1308
+ SessionTargetInfo,
1221
1309
  SessionsResource,
1222
1310
  TimeoutError,
1223
1311
  VERSION,