alterlab-mcp-server 1.6.1 → 1.8.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.
Files changed (70) hide show
  1. package/README.md +7 -7
  2. package/dist/auth.d.ts +30 -0
  3. package/dist/auth.d.ts.map +1 -0
  4. package/dist/auth.js +423 -0
  5. package/dist/auth.js.map +1 -0
  6. package/dist/client.d.ts +22 -1
  7. package/dist/client.d.ts.map +1 -1
  8. package/dist/client.js +56 -1
  9. package/dist/client.js.map +1 -1
  10. package/dist/config.d.ts +21 -1
  11. package/dist/config.d.ts.map +1 -1
  12. package/dist/config.js +85 -8
  13. package/dist/config.js.map +1 -1
  14. package/dist/errors.d.ts.map +1 -1
  15. package/dist/errors.js +28 -6
  16. package/dist/errors.js.map +1 -1
  17. package/dist/format.d.ts +16 -2
  18. package/dist/format.d.ts.map +1 -1
  19. package/dist/format.js +154 -10
  20. package/dist/format.js.map +1 -1
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +63 -1
  23. package/dist/index.js.map +1 -1
  24. package/dist/tools/balance.d.ts.map +1 -1
  25. package/dist/tools/balance.js +4 -2
  26. package/dist/tools/balance.js.map +1 -1
  27. package/dist/tools/batch.d.ts +8 -8
  28. package/dist/tools/batch.d.ts.map +1 -1
  29. package/dist/tools/batch.js +3 -2
  30. package/dist/tools/batch.js.map +1 -1
  31. package/dist/tools/crawl.d.ts +41 -0
  32. package/dist/tools/crawl.d.ts.map +1 -1
  33. package/dist/tools/crawl.js +76 -7
  34. package/dist/tools/crawl.js.map +1 -1
  35. package/dist/tools/estimate.d.ts +1 -1
  36. package/dist/tools/estimate.d.ts.map +1 -1
  37. package/dist/tools/estimate.js +6 -4
  38. package/dist/tools/estimate.js.map +1 -1
  39. package/dist/tools/extract.d.ts +5 -5
  40. package/dist/tools/extract.d.ts.map +1 -1
  41. package/dist/tools/extract.js +14 -12
  42. package/dist/tools/extract.js.map +1 -1
  43. package/dist/tools/map.d.ts +5 -2
  44. package/dist/tools/map.d.ts.map +1 -1
  45. package/dist/tools/map.js +12 -4
  46. package/dist/tools/map.js.map +1 -1
  47. package/dist/tools/scrape.d.ts +91 -9
  48. package/dist/tools/scrape.d.ts.map +1 -1
  49. package/dist/tools/scrape.js +201 -24
  50. package/dist/tools/scrape.js.map +1 -1
  51. package/dist/tools/screenshot.d.ts.map +1 -1
  52. package/dist/tools/screenshot.js +16 -7
  53. package/dist/tools/screenshot.js.map +1 -1
  54. package/dist/tools/search.d.ts +3 -0
  55. package/dist/tools/search.d.ts.map +1 -1
  56. package/dist/tools/search.js +12 -4
  57. package/dist/tools/search.js.map +1 -1
  58. package/dist/tools/simple_batch.d.ts +28 -0
  59. package/dist/tools/simple_batch.d.ts.map +1 -0
  60. package/dist/tools/simple_batch.js +141 -0
  61. package/dist/tools/simple_batch.js.map +1 -0
  62. package/dist/tools/usage.d.ts +7 -0
  63. package/dist/tools/usage.d.ts.map +1 -0
  64. package/dist/tools/usage.js +51 -0
  65. package/dist/tools/usage.js.map +1 -0
  66. package/dist/types.d.ts +99 -3
  67. package/dist/types.d.ts.map +1 -1
  68. package/dist/types.js.map +1 -1
  69. package/package.json +1 -1
  70. package/server.json +34 -2
package/dist/client.js CHANGED
@@ -3,22 +3,68 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.AlterLabClient = void 0;
4
4
  // Read version from package.json at build time is complex with ESM,
5
5
  // so we hardcode it and keep in sync with package.json.
6
- const VERSION = "1.1.0";
6
+ const VERSION = "1.7.1";
7
7
  const MAX_RETRIES = 2;
8
8
  class AlterLabClient {
9
9
  apiKey;
10
10
  apiUrl;
11
11
  userAgent;
12
+ sourceHeader;
13
+ /**
14
+ * Stores the most recent balance warning parsed from response headers.
15
+ * Updated after every successful API call. Null when no warning headers
16
+ * were present in the last response, or before the first call.
17
+ */
18
+ _lastBalanceWarning = null;
12
19
  constructor(config) {
13
20
  this.apiKey = config.apiKey;
14
21
  this.apiUrl = config.apiUrl;
15
22
  this.userAgent = `alterlab-mcp-server/${VERSION}`;
23
+ this.sourceHeader = `mcp-server/${VERSION}`;
24
+ }
25
+ /**
26
+ * Returns the balance warning from the most recent API response, or null
27
+ * if no warning headers were present. Tool handlers call this after each
28
+ * API request to append a proactive warning when balance is low.
29
+ */
30
+ getLastBalanceWarning() {
31
+ return this._lastBalanceWarning;
32
+ }
33
+ /**
34
+ * Parse X-AlterLab-Balance and X-AlterLab-Balance-Warning headers from an
35
+ * HTTP response and store the result. Both headers must be present and the
36
+ * warning level must be 'low', 'critical', or 'exhausted' — otherwise the
37
+ * stored warning is cleared to null (healthy balance = no warning).
38
+ */
39
+ parseBalanceWarningHeaders(response) {
40
+ const balanceHeader = response.headers.get("X-AlterLab-Balance");
41
+ const warningHeader = response.headers.get("X-AlterLab-Balance-Warning");
42
+ if (!balanceHeader || !warningHeader) {
43
+ this._lastBalanceWarning = null;
44
+ return;
45
+ }
46
+ const level = warningHeader.trim().toLowerCase();
47
+ if (level !== "low" && level !== "critical" && level !== "exhausted") {
48
+ // Healthy balance or unknown level — clear warning
49
+ this._lastBalanceWarning = null;
50
+ return;
51
+ }
52
+ // Parse the dollar amount from the balance header (e.g. '$0.42')
53
+ const balanceStr = balanceHeader.trim();
54
+ const parsed = parseFloat(balanceStr.replace(/[^0-9.]/g, ""));
55
+ const balance_usd = isNaN(parsed) ? null : parsed;
56
+ this._lastBalanceWarning = {
57
+ level: level,
58
+ balance: balanceStr,
59
+ balance_usd,
60
+ };
16
61
  }
17
62
  async request(method, path, body, retryCount = 0) {
18
63
  const url = `${this.apiUrl}${path}`;
19
64
  const headers = {
20
65
  "X-API-Key": this.apiKey,
21
66
  "User-Agent": this.userAgent,
67
+ "X-AlterLab-Source": this.sourceHeader,
22
68
  "Content-Type": "application/json",
23
69
  };
24
70
  const response = await fetch(url, {
@@ -37,6 +83,9 @@ class AlterLabClient {
37
83
  return this.request(method, path, body, retryCount + 1);
38
84
  }
39
85
  if (!response.ok) {
86
+ // Still parse balance warning headers on error responses — the server may
87
+ // send them even on 402/4xx to alert about the balance state.
88
+ this.parseBalanceWarningHeaders(response);
40
89
  let detail;
41
90
  try {
42
91
  const errorBody = await response.json();
@@ -51,6 +100,8 @@ class AlterLabClient {
51
100
  const apiError = { status: response.status, detail };
52
101
  throw apiError;
53
102
  }
103
+ // Parse balance warning headers from successful responses
104
+ this.parseBalanceWarningHeaders(response);
54
105
  return (await response.json());
55
106
  }
56
107
  async scrape(params) {
@@ -62,6 +113,9 @@ class AlterLabClient {
62
113
  async getBalance() {
63
114
  return this.request("GET", "/api/v1/billing/balance");
64
115
  }
116
+ async getUsage() {
117
+ return this.request("GET", "/api/v1/billing/usage");
118
+ }
65
119
  async listSessions() {
66
120
  return this.request("GET", "/api/v1/sessions/");
67
121
  }
@@ -149,6 +203,7 @@ class AlterLabClient {
149
203
  headers: {
150
204
  "X-API-Key": this.apiKey,
151
205
  "User-Agent": this.userAgent,
206
+ "X-AlterLab-Source": this.sourceHeader,
152
207
  },
153
208
  });
154
209
  if (!response.ok) {
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
package/dist/config.d.ts CHANGED
@@ -2,5 +2,25 @@ export interface Config {
2
2
  apiKey: string;
3
3
  apiUrl: string;
4
4
  }
5
- export declare function loadConfig(): Config;
5
+ /** Path to the user-level AlterLab config file. */
6
+ export declare const CONFIG_FILE_PATH: string;
7
+ /** Base API URL, respecting the ALTERLAB_API_URL override. */
8
+ export declare function getApiUrl(): string;
9
+ /**
10
+ * Load config from the user-level config file (~/.alterlab/config.json).
11
+ * Returns null if the file does not exist or does not contain a valid apiKey.
12
+ */
13
+ export declare function loadConfigFromFile(): Config | null;
14
+ /**
15
+ * Save the API key to the user-level config file (~/.alterlab/config.json).
16
+ * Creates the directory if it does not exist.
17
+ * File is written with mode 0o600 (owner read/write only).
18
+ */
19
+ export declare function saveConfigToFile(apiKey: string): void;
20
+ /**
21
+ * Load config from environment variable only.
22
+ * Returns null instead of exiting when the key is absent —
23
+ * callers use ensureAuth() for the full fallback chain.
24
+ */
25
+ export declare function loadConfig(): Config | null;
6
26
  //# sourceMappingURL=config.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,MAAM;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,UAAU,IAAI,MAAM,CAiBnC"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,MAAM;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,mDAAmD;AACnD,eAAO,MAAM,gBAAgB,QAI5B,CAAC;AAEF,8DAA8D;AAC9D,wBAAgB,SAAS,IAAI,MAAM,CAKlC;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,GAAG,IAAI,CAclD;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAKrD;AAED;;;;GAIG;AACH,wBAAgB,UAAU,IAAI,MAAM,GAAG,IAAI,CAM1C"}
package/dist/config.js CHANGED
@@ -1,17 +1,94 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
2
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.CONFIG_FILE_PATH = void 0;
37
+ exports.getApiUrl = getApiUrl;
38
+ exports.loadConfigFromFile = loadConfigFromFile;
39
+ exports.saveConfigToFile = saveConfigToFile;
3
40
  exports.loadConfig = loadConfig;
41
+ const fs = __importStar(require("fs"));
42
+ const path = __importStar(require("path"));
43
+ const os = __importStar(require("os"));
44
+ /** Path to the user-level AlterLab config file. */
45
+ exports.CONFIG_FILE_PATH = path.join(os.homedir(), ".alterlab", "config.json");
46
+ /** Base API URL, respecting the ALTERLAB_API_URL override. */
47
+ function getApiUrl() {
48
+ return (process.env.ALTERLAB_API_URL?.replace(/\/+$/, "") ||
49
+ "https://api.alterlab.io");
50
+ }
51
+ /**
52
+ * Load config from the user-level config file (~/.alterlab/config.json).
53
+ * Returns null if the file does not exist or does not contain a valid apiKey.
54
+ */
55
+ function loadConfigFromFile() {
56
+ try {
57
+ if (!fs.existsSync(exports.CONFIG_FILE_PATH)) {
58
+ return null;
59
+ }
60
+ const raw = fs.readFileSync(exports.CONFIG_FILE_PATH, "utf-8");
61
+ const parsed = JSON.parse(raw);
62
+ if (typeof parsed.apiKey === "string" && parsed.apiKey.length > 0) {
63
+ return { apiKey: parsed.apiKey, apiUrl: getApiUrl() };
64
+ }
65
+ return null;
66
+ }
67
+ catch {
68
+ return null;
69
+ }
70
+ }
71
+ /**
72
+ * Save the API key to the user-level config file (~/.alterlab/config.json).
73
+ * Creates the directory if it does not exist.
74
+ * File is written with mode 0o600 (owner read/write only).
75
+ */
76
+ function saveConfigToFile(apiKey) {
77
+ const dir = path.dirname(exports.CONFIG_FILE_PATH);
78
+ fs.mkdirSync(dir, { recursive: true, mode: 0o700 });
79
+ const content = JSON.stringify({ apiKey, apiUrl: getApiUrl() }, null, 2);
80
+ fs.writeFileSync(exports.CONFIG_FILE_PATH, content, { encoding: "utf-8", mode: 0o600 });
81
+ }
82
+ /**
83
+ * Load config from environment variable only.
84
+ * Returns null instead of exiting when the key is absent —
85
+ * callers use ensureAuth() for the full fallback chain.
86
+ */
4
87
  function loadConfig() {
5
88
  const apiKey = process.env.ALTERLAB_API_KEY;
6
89
  if (!apiKey) {
7
- console.error("Error: ALTERLAB_API_KEY environment variable is required.\n\n" +
8
- "Get your API key at https://alterlab.io/dashboard/api-keys\n\n" +
9
- "Then add it to your MCP config:\n" +
10
- ' "env": { "ALTERLAB_API_KEY": "sk_live_..." }');
11
- process.exit(1);
90
+ return null;
12
91
  }
13
- const apiUrl = process.env.ALTERLAB_API_URL?.replace(/\/+$/, "") ||
14
- "https://api.alterlab.io";
15
- return { apiKey, apiUrl };
92
+ return { apiKey, apiUrl: getApiUrl() };
16
93
  }
17
94
  //# sourceMappingURL=config.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":";;AAKA,gCAiBC;AAjBD,SAAgB,UAAU;IACxB,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;IAC5C,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,CAAC,KAAK,CACX,+DAA+D;YAC7D,gEAAgE;YAChE,mCAAmC;YACnC,gDAAgD,CACnD,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,MAAM,GACV,OAAO,CAAC,GAAG,CAAC,gBAAgB,EAAE,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;QACjD,yBAAyB,CAAC;IAE5B,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;AAC5B,CAAC"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiBA,8BAKC;AAMD,gDAcC;AAOD,4CAKC;AAOD,gCAMC;AAnED,uCAAyB;AACzB,2CAA6B;AAC7B,uCAAyB;AAOzB,mDAAmD;AACtC,QAAA,gBAAgB,GAAG,IAAI,CAAC,IAAI,CACvC,EAAE,CAAC,OAAO,EAAE,EACZ,WAAW,EACX,aAAa,CACd,CAAC;AAEF,8DAA8D;AAC9D,SAAgB,SAAS;IACvB,OAAO,CACL,OAAO,CAAC,GAAG,CAAC,gBAAgB,EAAE,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;QACjD,yBAAyB,CAC1B,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,SAAgB,kBAAkB;IAChC,IAAI,CAAC;QACH,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,wBAAgB,CAAC,EAAE,CAAC;YACrC,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,wBAAgB,EAAE,OAAO,CAAC,CAAC;QACvD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAA4B,CAAC;QAC1D,IAAI,OAAO,MAAM,CAAC,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAClE,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,CAAC;QACxD,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,SAAgB,gBAAgB,CAAC,MAAc;IAC7C,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,wBAAgB,CAAC,CAAC;IAC3C,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACpD,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IACzE,EAAE,CAAC,aAAa,CAAC,wBAAgB,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;AAClF,CAAC;AAED;;;;GAIG;AACH,SAAgB,UAAU;IACxB,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;IAC5C,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,CAAC;AACzC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAEzE,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,QAAQ,GAAG,KAAK,EACvB,OAAO,CAAC,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GACzB,cAAc,CAuJhB"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAEzE,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,QAAQ,GAAG,KAAK,EACvB,OAAO,CAAC,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GACzB,cAAc,CA4KhB"}
package/dist/errors.js CHANGED
@@ -83,10 +83,12 @@ function formatErrorResult(error, context) {
83
83
  {
84
84
  type: "text",
85
85
  text: `Access denied${url}: ${detail}\n\n` +
86
- "The site may have blocked the request. Suggested actions:\n" +
87
- "- Try with `render_js: true` to use a headless browser\n" +
88
- "- Try with `use_proxy: true` to route through a premium proxy\n" +
89
- "- Some sites may not be scrapable",
86
+ "The site blocked this request. Suggested actions:\n" +
87
+ "- Try `render_js: true` — headless browser bypass (escalates to tier 4, ~$0.001/req)\n" +
88
+ "- Try `use_proxy: true` — premium proxy rotation (+~$0.0002/req)\n" +
89
+ "- Try both together (`render_js: true, use_proxy: true`) for maximum bypass capability\n" +
90
+ "- Use `alterlab_estimate_cost` to preview cost before retrying\n" +
91
+ "- Some sites actively block all scrapers and cannot be scraped",
90
92
  },
91
93
  ],
92
94
  };
@@ -112,7 +114,24 @@ function formatErrorResult(error, context) {
112
114
  },
113
115
  ],
114
116
  };
115
- case 504:
117
+ case 504: {
118
+ // The API returns credits_status and estimated_completion_s in the 504 body
119
+ let creditsNote = "";
120
+ let completionNote = "";
121
+ try {
122
+ if (detail) {
123
+ const parsed = JSON.parse(detail);
124
+ if (parsed.credits_status) {
125
+ creditsNote = `\nCredits: ${parsed.credits_status}`;
126
+ }
127
+ if (parsed.estimated_completion_s) {
128
+ completionNote = `\nEstimated completion: ~${parsed.estimated_completion_s}s`;
129
+ }
130
+ }
131
+ }
132
+ catch {
133
+ // detail is plain text, not JSON — use default messaging
134
+ }
116
135
  return {
117
136
  isError: true,
118
137
  content: [
@@ -121,10 +140,13 @@ function formatErrorResult(error, context) {
121
140
  text: `Gateway timeout${url}.\n\n` +
122
141
  "The scraping job may still be running on the server.\n" +
123
142
  "Do NOT retry immediately — credits may have been consumed.\n" +
124
- "Wait and check your balance before retrying.",
143
+ "Wait and check your balance before retrying." +
144
+ creditsNote +
145
+ completionNote,
125
146
  },
126
147
  ],
127
148
  };
149
+ }
128
150
  default:
129
151
  return {
130
152
  isError: true,
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":";;AAQA,8CA0JC;AA1JD,SAAgB,iBAAiB,CAC/B,KAAuB,EACvB,OAA0B;IAE1B,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;QAC3B,yBAAyB;QACzB,MAAM,GAAG,GAAG,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC,QAAQ,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACtD,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;YACrE,OAAO;gBACL,OAAO,EAAE,IAAI;gBACb,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EACF,oBAAoB,GAAG,OAAO;4BAC9B,sBAAsB;4BACtB,iDAAiD;4BACjD,4DAA4D;4BAC5D,sDAAsD;qBACzD;iBACF;aACF,CAAC;QACJ,CAAC;QACD,OAAO;YACL,OAAO,EAAE,IAAI;YACb,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,iBAAiB,GAAG,KAAK,KAAK,CAAC,OAAO,EAAE;iBAC/C;aACF;SACF,CAAC;IACJ,CAAC;IAED,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG;QACnB,CAAC,CAAC,QAAQ,KAAK,CAAC,GAAG,EAAE;QACrB,CAAC,CAAC,OAAO,EAAE,GAAG;YACZ,CAAC,CAAC,QAAQ,OAAO,CAAC,GAAG,EAAE;YACvB,CAAC,CAAC,EAAE,CAAC;IACT,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,IAAI,eAAe,CAAC;IAE/C,QAAQ,KAAK,CAAC,MAAM,EAAE,CAAC;QACrB,KAAK,GAAG;YACN,OAAO;gBACL,OAAO,EAAE,IAAI;gBACb,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EACF,cAAc,GAAG,KAAK,MAAM,MAAM;4BAClC,sDAAsD;4BACtD,wBAAwB;4BACxB,sCAAsC;qBACzC;iBACF;aACF,CAAC;QAEJ,KAAK,GAAG;YACN,OAAO;gBACL,OAAO,EAAE,IAAI;gBACb,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EACF,6CAA6C;4BAC7C,iDAAiD;4BACjD,0DAA0D;qBAC7D;iBACF;aACF,CAAC;QAEJ,KAAK,GAAG;YACN,OAAO;gBACL,OAAO,EAAE,IAAI;gBACb,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EACF,uBAAuB,GAAG,KAAK,MAAM,MAAM;4BAC3C,sBAAsB;4BACtB,8DAA8D;4BAC9D,yDAAyD;4BACzD,+DAA+D;qBAClE;iBACF;aACF,CAAC;QAEJ,KAAK,GAAG;YACN,OAAO;gBACL,OAAO,EAAE,IAAI;gBACb,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EACF,gBAAgB,GAAG,KAAK,MAAM,MAAM;4BACpC,6DAA6D;4BAC7D,0DAA0D;4BAC1D,iEAAiE;4BACjE,mCAAmC;qBACtC;iBACF;aACF,CAAC;QAEJ,KAAK,GAAG;YACN,OAAO;gBACL,OAAO,EAAE,IAAI;gBACb,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,mBAAmB,GAAG,KAAK,MAAM,EAAE;qBAC1C;iBACF;aACF,CAAC;QAEJ,KAAK,GAAG;YACN,OAAO;gBACL,OAAO,EAAE,IAAI;gBACb,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EACF,eAAe,GAAG,OAAO;4BACzB,mDAAmD;4BACnD,yDAAyD;qBAC5D;iBACF;aACF,CAAC;QAEJ,KAAK,GAAG;YACN,OAAO;gBACL,OAAO,EAAE,IAAI;gBACb,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EACF,kBAAkB,GAAG,OAAO;4BAC5B,wDAAwD;4BACxD,8DAA8D;4BAC9D,8CAA8C;qBACjD;iBACF;aACF,CAAC;QAEJ;YACE,OAAO;gBACL,OAAO,EAAE,IAAI;gBACb,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,cAAc,KAAK,CAAC,MAAM,IAAI,GAAG,KAAK,MAAM,EAAE;qBACrD;iBACF;aACF,CAAC;IACN,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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"}
package/dist/format.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { type BalanceResponse, type BetaFeatureListResponse, type BetaFeatureMyResponse, type BetaFeatureToggleResponse, type CostEstimate, type SessionCreateResponse, type SessionDetailResponse, type SessionListResponse, type SessionValidateResponse, type UnifiedScrapeResponse } from "./types.js";
1
+ import { type BalanceResponse, type BalanceWarning, type BetaFeatureListResponse, type BetaFeatureMyResponse, type BetaFeatureToggleResponse, type CostEstimate, type SessionCreateResponse, type SessionDetailResponse, type SessionListResponse, type SessionValidateResponse, type UnifiedScrapeResponse } from "./types.js";
2
2
  /**
3
3
  * Format a scrape response as LLM-optimized markdown.
4
4
  * Returns primary content + a compact metadata footer.
@@ -8,14 +8,28 @@ export declare function formatScrapeResponse(response: UnifiedScrapeResponse): s
8
8
  * Format an extraction response — structured JSON as markdown code block.
9
9
  */
10
10
  export declare function formatExtractResponse(response: UnifiedScrapeResponse): string;
11
+ /**
12
+ * Format a cost estimate as a compact inline header (one line).
13
+ * Used by estimate_first in alterlab_scrape to prepend before scrape results.
14
+ */
15
+ export declare function formatEstimateInline(estimate: CostEstimate): string;
11
16
  /**
12
17
  * Format a cost estimate as readable text.
13
18
  */
14
19
  export declare function formatEstimateResponse(estimate: CostEstimate): string;
15
20
  /**
16
- * Format a balance response as readable text.
21
+ * Format a balance response as readable text, including balance status and
22
+ * estimated runway (days at current spending rate).
17
23
  */
18
24
  export declare function formatBalanceResponse(balance: BalanceResponse): string;
25
+ /**
26
+ * Format a balance warning from response headers into a human-readable suffix.
27
+ *
28
+ * Returns a non-empty string (starting with a newline) when the balance is
29
+ * low, critical, or exhausted. Returns an empty string when warning is null
30
+ * (healthy balance — no suffix appended).
31
+ */
32
+ export declare function formatBalanceWarning(warning: BalanceWarning | null): string;
19
33
  /**
20
34
  * Format a session list response as readable text.
21
35
  */
@@ -1 +1 @@
1
- {"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../src/format.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,eAAe,EACpB,KAAK,uBAAuB,EAC5B,KAAK,qBAAqB,EAC1B,KAAK,yBAAyB,EAC9B,KAAK,YAAY,EACjB,KAAK,qBAAqB,EAC1B,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,EACxB,KAAK,uBAAuB,EAC5B,KAAK,qBAAqB,EAC3B,MAAM,YAAY,CAAC;AAEpB;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,qBAAqB,GAAG,MAAM,CAsF5E;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,qBAAqB,GAAG,MAAM,CA2C7E;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,YAAY,GAAG,MAAM,CAarE;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,eAAe,GAAG,MAAM,CAWtE;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,mBAAmB,GAC5B,MAAM,CAkCR;AAED;;GAEG;AACH,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,qBAAqB,GAC9B,MAAM,CASR;AAED;;GAEG;AACH,wBAAgB,6BAA6B,CAC3C,QAAQ,EAAE,uBAAuB,GAChC,MAAM,CAsBR;AAED;;GAEG;AACH,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,qBAAqB,GAC9B,MAAM,CA4CR;AAED;;GAEG;AACH,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,qBAAqB,GAC9B,MAAM,CAUR;AAED;;GAEG;AACH,wBAAgB,4BAA4B,CAC1C,QAAQ,EAAE,qBAAqB,GAC9B,MAAM,CAWR;AAED;;GAEG;AACH,wBAAgB,8BAA8B,CAC5C,QAAQ,EAAE,uBAAuB,GAChC,MAAM,CAgCR;AAED;;GAEG;AACH,wBAAgB,4BAA4B,CAC1C,QAAQ,EAAE,qBAAqB,GAC9B,MAAM,CAgBR;AAED;;GAEG;AACH,wBAAgB,+BAA+B,CAC7C,QAAQ,EAAE,yBAAyB,GAClC,MAAM,CAQR"}
1
+ {"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../src/format.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,uBAAuB,EAC5B,KAAK,qBAAqB,EAC1B,KAAK,yBAAyB,EAC9B,KAAK,YAAY,EACjB,KAAK,qBAAqB,EAC1B,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,EACxB,KAAK,uBAAuB,EAC5B,KAAK,qBAAqB,EAC3B,MAAM,YAAY,CAAC;AAEpB;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,qBAAqB,GAAG,MAAM,CA6L5E;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,qBAAqB,GAAG,MAAM,CA2C7E;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,YAAY,GAAG,MAAM,CAQnE;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,YAAY,GAAG,MAAM,CAarE;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,eAAe,GAAG,MAAM,CAiCtE;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI,GAAG,MAAM,CAuB3E;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,mBAAmB,GAC5B,MAAM,CAkCR;AAED;;GAEG;AACH,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,qBAAqB,GAC9B,MAAM,CASR;AAED;;GAEG;AACH,wBAAgB,6BAA6B,CAC3C,QAAQ,EAAE,uBAAuB,GAChC,MAAM,CAsBR;AAED;;GAEG;AACH,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,qBAAqB,GAC9B,MAAM,CA4CR;AAED;;GAEG;AACH,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,qBAAqB,GAC9B,MAAM,CAUR;AAED;;GAEG;AACH,wBAAgB,4BAA4B,CAC1C,QAAQ,EAAE,qBAAqB,GAC9B,MAAM,CAWR;AAED;;GAEG;AACH,wBAAgB,8BAA8B,CAC5C,QAAQ,EAAE,uBAAuB,GAChC,MAAM,CAgCR;AAED;;GAEG;AACH,wBAAgB,4BAA4B,CAC1C,QAAQ,EAAE,qBAAqB,GAC9B,MAAM,CAgBR;AAED;;GAEG;AACH,wBAAgB,+BAA+B,CAC7C,QAAQ,EAAE,yBAAyB,GAClC,MAAM,CAQR"}
package/dist/format.js CHANGED
@@ -2,8 +2,10 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.formatScrapeResponse = formatScrapeResponse;
4
4
  exports.formatExtractResponse = formatExtractResponse;
5
+ exports.formatEstimateInline = formatEstimateInline;
5
6
  exports.formatEstimateResponse = formatEstimateResponse;
6
7
  exports.formatBalanceResponse = formatBalanceResponse;
8
+ exports.formatBalanceWarning = formatBalanceWarning;
7
9
  exports.formatSessionListResponse = formatSessionListResponse;
8
10
  exports.formatSessionCreateResponse = formatSessionCreateResponse;
9
11
  exports.formatSessionValidateResponse = formatSessionValidateResponse;
@@ -67,6 +69,24 @@ function formatScrapeResponse(response) {
67
69
  else if (typeof content === "string") {
68
70
  parts.push(content);
69
71
  }
72
+ // LLM extraction result (from extraction_schema or extraction_prompt)
73
+ if (response.extraction_result && !hasFilteredContent) {
74
+ parts.push("\n**Extraction Result**\n```json\n" +
75
+ JSON.stringify(response.extraction_result, null, 2) +
76
+ "\n```");
77
+ }
78
+ // Browser action results (from advanced.actions)
79
+ if (response.action_results && response.action_results.length > 0) {
80
+ const actionSummary = response.action_results
81
+ .map((a, i) => {
82
+ const status = a.success ? "ok" : "failed";
83
+ const type = String(a.type ?? "action");
84
+ const result = a.result ? ` → ${String(a.result)}` : "";
85
+ return ` ${i + 1}. [${status}] ${type}${result}`;
86
+ })
87
+ .join("\n");
88
+ parts.push(`\n**Action Results**\n${actionSummary}`);
89
+ }
70
90
  // Metadata footer
71
91
  const tier = response.billing.tier_used;
72
92
  const tierName = types_js_1.TIER_NAMES[tier] || tier;
@@ -74,21 +94,84 @@ function formatScrapeResponse(response) {
74
94
  const cost = response.billing.final_cost_microcents
75
95
  ? `$${(response.billing.final_cost_microcents / 1_000_000).toFixed(6)}`
76
96
  : `${response.billing.total_credits} credits`;
97
+ const sourceUrl = response.redirected && response.final_url
98
+ ? `${response.url} → ${response.final_url}`
99
+ : response.url;
77
100
  parts.push("\n---\n" +
78
- `Source: ${response.url} | ` +
101
+ `Source: ${sourceUrl} | ` +
79
102
  `Tier: ${tierName} (${tierPrice}/req) | ` +
80
103
  `Cost: ${cost} | ` +
81
104
  `Time: ${response.response_time_ms}ms` +
82
- (response.cached ? " | Cached" : ""));
105
+ (response.cached ? " | Cached" : "") +
106
+ (response.billing.byop_applied ? " | BYOP" : ""));
107
+ if (response.redirect_chain && response.redirect_chain.length > 0) {
108
+ const chain = response.redirect_chain
109
+ .map((hop) => `${hop.status_code} → ${hop.url}`)
110
+ .join("\n ");
111
+ parts.push(`Redirect chain:\n ${chain}`);
112
+ }
113
+ if (response.billing.escalations &&
114
+ response.billing.escalations.length > 1) {
115
+ const escalationSummary = response.billing.escalations
116
+ .map((e) => {
117
+ const tierLabel = types_js_1.TIER_NAMES[e.tier] || e.tier;
118
+ const durationLabel = e.duration_ms ? ` (${e.duration_ms}ms)` : "";
119
+ return `${tierLabel}: ${e.result}${durationLabel}`;
120
+ })
121
+ .join(" → ");
122
+ parts.push(`Escalation path: ${escalationSummary}`);
123
+ }
83
124
  if (response.billing.optimization_suggestion) {
84
125
  parts.push(`Tip: ${response.billing.optimization_suggestion}`);
85
126
  }
127
+ // API warning messages — surface all warning variants
128
+ if (response.warning) {
129
+ parts.push(`Warning: ${response.warning}`);
130
+ }
131
+ if (response.domain_warning) {
132
+ let detail = "";
133
+ if (response.domain_difficulty) {
134
+ const d = response.domain_difficulty;
135
+ const rate = d.success_rate !== undefined
136
+ ? ` (success rate: ${(Number(d.success_rate) * 100).toFixed(0)}%)`
137
+ : "";
138
+ detail = rate;
139
+ }
140
+ parts.push(`Domain Warning: ${response.domain_warning}${detail}`);
141
+ }
142
+ if (response.tier_cap_warning) {
143
+ const w = response.tier_cap_warning;
144
+ const domainMin = w.domain_min_tier !== undefined
145
+ ? ` Domain requires tier ${w.domain_min_tier}.`
146
+ : "";
147
+ if (w.your_max_tier !== undefined) {
148
+ parts.push(`Tier Cap Warning: Your max_tier (${w.your_max_tier}) is below the domain minimum.${domainMin}`);
149
+ }
150
+ else if (w.your_force_tier !== undefined) {
151
+ parts.push(`Tier Cap Warning: Your force_tier (${w.your_force_tier}) is below the domain minimum.${domainMin}`);
152
+ }
153
+ }
86
154
  if (response.content_truncated) {
87
155
  const t = response.content_truncated;
88
156
  const truncatedMB = (t.truncated_at_bytes / 1_048_576).toFixed(1);
89
157
  const originalMB = (t.original_size_bytes / 1_048_576).toFixed(1);
90
- parts.push(`Warning: Content truncated at ${truncatedMB} MB (original: ${originalMB} MB, reason: ${t.truncation_reason}). ` +
91
- `Increase max_response_bytes or use a more targeted selector to capture the full page.`);
158
+ const truncationPrefix = `Warning: Content truncated at ${truncatedMB} MB (original: ${originalMB} MB, reason: ${t.truncation_reason}). `;
159
+ if (t.truncation_reason === "response_body_cap") {
160
+ parts.push(truncationPrefix +
161
+ `Increase max_response_bytes or use a more targeted selector to capture the full page.`);
162
+ }
163
+ else {
164
+ // readability_input_cap or readability_output_cap — server-side caps that
165
+ // max_response_bytes cannot affect. Advising users to increase it would be misleading.
166
+ parts.push(truncationPrefix +
167
+ `This is a server-side readability cap and cannot be raised via max_response_bytes. ` +
168
+ `Use a more targeted CSS selector to reduce the content region size.`);
169
+ }
170
+ }
171
+ if (response.quality_warning) {
172
+ const qw = response.quality_warning;
173
+ parts.push(`Quality warning: ${qw.reason} (code: ${qw.code}, word_count: ${qw.word_count}). ` +
174
+ `Content was delivered but may contain anti-bot artifacts.`);
92
175
  }
93
176
  return parts.join("\n");
94
177
  }
@@ -128,6 +211,16 @@ function formatExtractResponse(response) {
128
211
  `Time: ${response.response_time_ms}ms`);
129
212
  return parts.join("\n");
130
213
  }
214
+ /**
215
+ * Format a cost estimate as a compact inline header (one line).
216
+ * Used by estimate_first in alterlab_scrape to prepend before scrape results.
217
+ */
218
+ function formatEstimateInline(estimate) {
219
+ const tierName = types_js_1.TIER_NAMES[estimate.estimated_tier] || estimate.estimated_tier;
220
+ const tierPrice = types_js_1.TIER_PRICES[estimate.estimated_tier] || "unknown";
221
+ return (`> **Pre-flight estimate**: ${tierPrice}/req (${tierName}, tier ${estimate.estimated_tier}) — ` +
222
+ `confidence: ${estimate.confidence}. ${estimate.reasoning}\n`);
223
+ }
131
224
  /**
132
225
  * Format a cost estimate as readable text.
133
226
  */
@@ -142,16 +235,67 @@ function formatEstimateResponse(estimate) {
142
235
  `${estimate.reasoning}`);
143
236
  }
144
237
  /**
145
- * Format a balance response as readable text.
238
+ * Format a balance response as readable text, including balance status and
239
+ * estimated runway (days at current spending rate).
146
240
  */
147
241
  function formatBalanceResponse(balance) {
148
242
  const deposited = (balance.total_deposited_cents / 100).toFixed(2);
149
243
  const spent = (balance.total_spent_cents / 100).toFixed(2);
150
- return (`**Account Balance**\n\n` +
151
- `- Balance: **${balance.balance_display}**\n` +
152
- `- Total deposited: $${deposited}\n` +
153
- `- Total spent: $${spent}\n\n` +
154
- `Add funds: https://alterlab.io/dashboard/billing`);
244
+ const balanceUsd = balance.balance_microcents / 1_000_000;
245
+ // Balance status classification
246
+ let status;
247
+ if (balanceUsd <= 0) {
248
+ status = "Exhausted — top up to continue scraping";
249
+ }
250
+ else if (balanceUsd < 0.10) {
251
+ status = "Critical (< $0.10)";
252
+ }
253
+ else if (balanceUsd < 0.50) {
254
+ status = "Low (< $0.50)";
255
+ }
256
+ else {
257
+ status = "Healthy";
258
+ }
259
+ // Estimated runway: days at current average daily spend rate.
260
+ // Uses total_spent_cents as a proxy for lifetime spend, but since we don't
261
+ // know the account age, we can only compute runway if daily spend is
262
+ // non-zero. The balance endpoint doesn't expose daily spend directly, so
263
+ // we skip runway here and recommend alterlab_get_usage for that detail.
264
+ const lines = [
265
+ `**Account Balance**\n`,
266
+ `- Balance: **${balance.balance_display}**`,
267
+ `- Status: ${status}`,
268
+ `- Total deposited: $${deposited}`,
269
+ `- Total spent: $${spent}`,
270
+ `\nFor spending breakdown and estimated runway: use \`alterlab_get_usage\``,
271
+ `Add funds: https://alterlab.io/dashboard/billing`,
272
+ ];
273
+ return lines.join("\n");
274
+ }
275
+ /**
276
+ * Format a balance warning from response headers into a human-readable suffix.
277
+ *
278
+ * Returns a non-empty string (starting with a newline) when the balance is
279
+ * low, critical, or exhausted. Returns an empty string when warning is null
280
+ * (healthy balance — no suffix appended).
281
+ */
282
+ function formatBalanceWarning(warning) {
283
+ if (!warning)
284
+ return "";
285
+ const fundUrl = "https://alterlab.io/dashboard/billing";
286
+ switch (warning.level) {
287
+ case "exhausted":
288
+ return (`\n\n> **Balance exhausted**: ${warning.balance} remaining. ` +
289
+ `Add funds to continue scraping: ${fundUrl}`);
290
+ case "critical":
291
+ return (`\n\n> **Critical balance**: ${warning.balance} remaining. ` +
292
+ `Top up soon to avoid interruptions: ${fundUrl}`);
293
+ case "low":
294
+ return (`\n\n> **Low balance**: ${warning.balance} remaining. ` +
295
+ `Add funds: ${fundUrl}`);
296
+ default:
297
+ return "";
298
+ }
155
299
  }
156
300
  /**
157
301
  * Format a session list response as readable text.