surf-cli 2.14.0 → 2.15.0

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.
@@ -1,5 +1,6 @@
1
1
  const fs = require("fs");
2
2
  const networkFormatters = require("./formatters/network.cjs");
3
+ const { recoveryFor } = require("./surf-error.cjs");
3
4
 
4
5
  function buildProviderUploadMessage(provider, tabId, filePaths, id) {
5
6
  const normalizedProvider = String(provider || "").toLowerCase();
@@ -19,11 +20,22 @@ function formatToolError(error) {
19
20
  : typeof error === "string"
20
21
  ? error
21
22
  : error?.message || String(error);
22
- const result = { content: [{ type: "text", text: message }] };
23
+ const recoveryCommand = recoveryFor(error);
24
+ const display = recoveryCommand ? `${message}\nRecovery: ${recoveryCommand}` : message;
25
+ const result = { content: [{ type: "text", text: display }] };
23
26
  if (error && typeof error === "object") {
24
27
  result.message = message;
25
28
  if (typeof error.code === "string") result.code = error.code;
26
29
  if (typeof error.jobId === "string") result.jobId = error.jobId;
30
+ const details = typeof error.toJSON === "function" ? error.toJSON() : {};
31
+ for (const key of [
32
+ "session", "target", "lastUrl", "laneKey", "resourceKeys", "retryable", "queue", "reason",
33
+ "browserEpoch", "expectedBrowserEpoch", "recoveryCommand",
34
+ ]) {
35
+ if (error[key] !== undefined) details[key] = error[key];
36
+ }
37
+ if (recoveryCommand) details.recoveryCommand = recoveryCommand;
38
+ if (Object.keys(details).length > 0) result.details = details;
27
39
  }
28
40
  return result;
29
41
  }
@@ -38,6 +50,10 @@ function formatToolContent(result, log = () => {}, options = {}) {
38
50
  const text = (s) => [{ type: "text", text: s }];
39
51
 
40
52
  if (!result) return text("OK");
53
+
54
+ if (result.session || Array.isArray(result.sessions) || Object.hasOwn(result, "targetClosed")) {
55
+ return text(JSON.stringify(result, null, 2));
56
+ }
41
57
 
42
58
  if (result.aiResult) {
43
59
  if (result.mode === "find") {
@@ -805,7 +821,7 @@ function mapToolToMessage(tool, args, tabId) {
805
821
  case "switch_tab":
806
822
  return { type: "SWITCH_TAB", tabId: a.tab_id || a.tabId };
807
823
  case "close_tab":
808
- return { type: "CLOSE_TAB", tabId: a.tab_id || a.tabId, tabIds: a.tab_ids || a.tabIds };
824
+ return { type: "CLOSE_TAB", tabId: a.tab_id || a.tabId || tabId, tabIds: a.tab_ids || a.tabIds };
809
825
  case "tab.list":
810
826
  return { type: "LIST_TABS" };
811
827
  case "tab.new":
@@ -823,7 +839,7 @@ function mapToolToMessage(tool, args, tabId) {
823
839
  if (typeof id === "string" && !/^\d+$/.test(id)) {
824
840
  return { type: "NAMED_TAB_CLOSE", name: id };
825
841
  }
826
- return { type: "CLOSE_TAB", tabId: id, tabIds: ids };
842
+ return { type: "CLOSE_TAB", tabId: id ?? tabId, tabIds: ids };
827
843
  }
828
844
  case "tab.move": {
829
845
  const id = a.id || a.tab_id || a.tabId;
@@ -123,7 +123,7 @@ class HostSessionManager {
123
123
  context.stream = false;
124
124
  }
125
125
 
126
- beginRequest(context, { id, tool, deadlineMs }) {
126
+ beginRequest(context, { id, tool, deadlineMs, skipLease = false }) {
127
127
  if (context.closed) return Promise.reject(new Error("connection is closed"));
128
128
  if (context.workTimer) {
129
129
  clearTimeout(context.workTimer);
@@ -149,8 +149,15 @@ class HostSessionManager {
149
149
  controller,
150
150
  signal: controller.signal,
151
151
  tombstoned: false,
152
+ skipLease,
152
153
  };
153
154
  context.activeRequest = request;
155
+ if (skipLease) {
156
+ request.queued = false;
157
+ request.timer = setTimeout(() => this.onRequestTimeout(context, request), request.deadlineMs);
158
+ this.audit({ event: "admission", context, request, outcome: "accepted" });
159
+ return Promise.resolve(request);
160
+ }
154
161
  const grant = () => {
155
162
  if (context.closed) return Promise.reject(new Error("connection closed while waiting for browser lease"));
156
163
  request.queued = false;