@skrillex1224/android-toolkit 1.0.8 → 1.0.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.
package/dist/browser.js CHANGED
@@ -25,7 +25,7 @@ var Code = Object.freeze({
25
25
  ContentUnavailable: 30010003,
26
26
  SourceExtractionFailed: 30010004,
27
27
  AutomationFailed: 30010005,
28
- DataAccessUnavailable: 30010008,
28
+ AppRuntimeUnavailable: 30010008,
29
29
  AppNotInstalled: 30010009
30
30
  });
31
31
  var Status = Object.freeze({
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/constants.js", "../src/errors.js", "../entrys/browser.js"],
4
- "sourcesContent": ["export const Code = Object.freeze({\n Success: 0,\n UnknownError: -1,\n NotLogin: 30000001,\n Timeout: 30000003,\n InitialTimeout: 30000004,\n OverallTimeout: 30000005,\n InvalidRequest: 30010001,\n AdbUnavailable: 30010002,\n ContentUnavailable: 30010003,\n SourceExtractionFailed: 30010004,\n AutomationFailed: 30010005,\n DataAccessUnavailable: 30010008,\n AppNotInstalled: 30010009,\n});\n\nexport const Status = Object.freeze({\n Success: 'SUCCESS',\n Failed: 'FAILED',\n});\n\nexport const UnicodeIme = Object.freeze({\n packageName: 'io.appium.settings',\n component: 'io.appium.settings/.UnicodeIME',\n inputAction: 'ADB_INPUT_TEXT',\n});\n\nexport const AppiumSettings = Object.freeze({\n packageName: 'io.appium.settings',\n clipboardReceiver: 'io.appium.settings/.receivers.ClipboardReceiver',\n clipboardGetAction: 'io.appium.settings.clipboard.get',\n});\n\nconst normalizeShare = (share) => {\n const source = share && typeof share === 'object' ? share : {};\n return {\n mode: 'clipboard',\n prefix: String(source.prefix || '').trim(),\n xurl: Array.isArray(source.xurl) ? source.xurl : [],\n };\n};\n\nconst createActorInfo = (info) => {\n const key = String(info.key || '').trim();\n return Object.freeze({\n key,\n name: String(info.name || key),\n icon: String(info.icon || `https://static.heartbitai.com/general/actors/${key}.png`),\n share: Object.freeze(normalizeShare(info.share)),\n });\n};\n\nexport const ActorInfo = Object.freeze({\n 'doubao.android': createActorInfo({\n key: 'doubao.android',\n name: '\u8C46\u5305 Android',\n share: {\n prefix: 'https://www.doubao.com/thread/',\n xurl: [],\n },\n }),\n});\n", "import { Code } from './constants.js';\n\nexport class CrawlerError extends Error {\n constructor(input = {}, options = {}) {\n const payload = typeof input === 'string' ? { message: input } : input;\n super(payload.message || 'Android crawler error', options);\n this.name = 'CrawlerError';\n this.code = payload.code || Code.UnknownError;\n this.context = payload.context || {};\n }\n\n static isCrawlerError(error) {\n return error instanceof CrawlerError || error?.name === 'CrawlerError';\n }\n\n static from(error, fallback = {}) {\n if (CrawlerError.isCrawlerError(error)) return error;\n return new CrawlerError({\n message: error?.message || String(error),\n code: fallback.code || Code.UnknownError,\n context: fallback.context || {},\n });\n }\n}\n\nexport function serializeError(error) {\n if (!error) return { message: '' };\n return {\n name: error.name || 'Error',\n message: error.message || String(error),\n stack: error.stack || '',\n code: error.code || '',\n context: error.context || undefined,\n };\n}\n", "import * as Constants from '../src/constants.js';\nimport * as Errors from '../src/errors.js';\n\nconst ToolkitMode = Object.freeze({\n default: 'default',\n});\n\nexport const useAndroidToolKit = () => {\n return {\n Constants,\n Errors,\n };\n};\n\nuseAndroidToolKit.Mode = ToolkitMode;\n"],
4
+ "sourcesContent": ["export const Code = Object.freeze({\n Success: 0,\n UnknownError: -1,\n NotLogin: 30000001,\n Timeout: 30000003,\n InitialTimeout: 30000004,\n OverallTimeout: 30000005,\n InvalidRequest: 30010001,\n AdbUnavailable: 30010002,\n ContentUnavailable: 30010003,\n SourceExtractionFailed: 30010004,\n AutomationFailed: 30010005,\n AppRuntimeUnavailable: 30010008,\n AppNotInstalled: 30010009,\n});\n\nexport const Status = Object.freeze({\n Success: 'SUCCESS',\n Failed: 'FAILED',\n});\n\nexport const UnicodeIme = Object.freeze({\n packageName: 'io.appium.settings',\n component: 'io.appium.settings/.UnicodeIME',\n inputAction: 'ADB_INPUT_TEXT',\n});\n\nexport const AppiumSettings = Object.freeze({\n packageName: 'io.appium.settings',\n clipboardReceiver: 'io.appium.settings/.receivers.ClipboardReceiver',\n clipboardGetAction: 'io.appium.settings.clipboard.get',\n});\n\nconst normalizeShare = (share) => {\n const source = share && typeof share === 'object' ? share : {};\n return {\n mode: 'clipboard',\n prefix: String(source.prefix || '').trim(),\n xurl: Array.isArray(source.xurl) ? source.xurl : [],\n };\n};\n\nconst createActorInfo = (info) => {\n const key = String(info.key || '').trim();\n return Object.freeze({\n key,\n name: String(info.name || key),\n icon: String(info.icon || `https://static.heartbitai.com/general/actors/${key}.png`),\n share: Object.freeze(normalizeShare(info.share)),\n });\n};\n\nexport const ActorInfo = Object.freeze({\n 'doubao.android': createActorInfo({\n key: 'doubao.android',\n name: '\u8C46\u5305 Android',\n share: {\n prefix: 'https://www.doubao.com/thread/',\n xurl: [],\n },\n }),\n});\n", "import { Code } from './constants.js';\n\nexport class CrawlerError extends Error {\n constructor(input = {}, options = {}) {\n const payload = typeof input === 'string' ? { message: input } : input;\n super(payload.message || 'Android crawler error', options);\n this.name = 'CrawlerError';\n this.code = payload.code || Code.UnknownError;\n this.context = payload.context || {};\n }\n\n static isCrawlerError(error) {\n return error instanceof CrawlerError || error?.name === 'CrawlerError';\n }\n\n static from(error, fallback = {}) {\n if (CrawlerError.isCrawlerError(error)) return error;\n return new CrawlerError({\n message: error?.message || String(error),\n code: fallback.code || Code.UnknownError,\n context: fallback.context || {},\n });\n }\n}\n\nexport function serializeError(error) {\n if (!error) return { message: '' };\n return {\n name: error.name || 'Error',\n message: error.message || String(error),\n stack: error.stack || '',\n code: error.code || '',\n context: error.context || undefined,\n };\n}\n", "import * as Constants from '../src/constants.js';\nimport * as Errors from '../src/errors.js';\n\nconst ToolkitMode = Object.freeze({\n default: 'default',\n});\n\nexport const useAndroidToolKit = () => {\n return {\n Constants,\n Errors,\n };\n};\n\nuseAndroidToolKit.Mode = ToolkitMode;\n"],
5
5
  "mappings": "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",
6
6
  "names": []
7
7
  }
package/dist/index.cjs CHANGED
@@ -57,7 +57,7 @@ var Code = Object.freeze({
57
57
  ContentUnavailable: 30010003,
58
58
  SourceExtractionFailed: 30010004,
59
59
  AutomationFailed: 30010005,
60
- DataAccessUnavailable: 30010008,
60
+ AppRuntimeUnavailable: 30010008,
61
61
  AppNotInstalled: 30010009
62
62
  });
63
63
  var Status = Object.freeze({
@@ -1190,8 +1190,8 @@ async function query(ctx, options = {}) {
1190
1190
  const dbPaths = await resolveDeviceDbPaths(ctx, config);
1191
1191
  if (dbPaths.length === 0) {
1192
1192
  throw new CrawlerError({
1193
- message: "data_access_unavailable: sqlite database not found",
1194
- code: Code.DataAccessUnavailable,
1193
+ message: "app_runtime_unavailable: sqlite database not found",
1194
+ code: Code.AppRuntimeUnavailable,
1195
1195
  context: { dbDir: config.dbDir, dbPath: config.dbPath, dbNamePrefix: config.dbNamePrefix }
1196
1196
  });
1197
1197
  }
@@ -1240,8 +1240,8 @@ async function resolveDeviceDbPaths(ctx, config) {
1240
1240
  maxBuffer: 2 * 1024 * 1024
1241
1241
  }).catch((error) => {
1242
1242
  throw new CrawlerError({
1243
- message: `data_access_unavailable: sqlite dbDir unavailable ${error?.message || String(error)}`,
1244
- code: Code.DataAccessUnavailable,
1243
+ message: `app_runtime_unavailable: sqlite dbDir unavailable ${error?.message || String(error)}`,
1244
+ code: Code.AppRuntimeUnavailable,
1245
1245
  context: { dbDir: config.dbDir }
1246
1246
  });
1247
1247
  });
@@ -1266,8 +1266,8 @@ async function pullDatabaseSnapshot(ctx, dbPath, localDir) {
1266
1266
  await adbSuShell(ctx, copyCommand, { timeoutMs: 3e4, maxBuffer: 4 * 1024 * 1024 });
1267
1267
  await adbPull(adbPath, serial, remoteDb, localDb).catch((error) => {
1268
1268
  throw new CrawlerError({
1269
- message: `data_access_unavailable: sqlite snapshot pull failed ${error?.message || String(error)}`,
1270
- code: Code.DataAccessUnavailable,
1269
+ message: `app_runtime_unavailable: sqlite snapshot pull failed ${error?.message || String(error)}`,
1270
+ code: Code.AppRuntimeUnavailable,
1271
1271
  context: { dbPath }
1272
1272
  });
1273
1273
  });
@@ -1726,17 +1726,28 @@ async function captureScreen(ctx, options = {}) {
1726
1726
  const frameBuffers = [];
1727
1727
  const seen = /* @__PURE__ */ new Set();
1728
1728
  const targetSelector = options.selector || { id: "message_list" };
1729
- await Device.hideKeyboard(ctx, { attempts: 2, settleMs: 350 }).catch(() => {
1729
+ const shouldHideKeyboard = options.hideKeyboard !== false;
1730
+ if (shouldHideKeyboard) await Device.hideKeyboard(ctx, { attempts: 2, settleMs: 350 }).catch(() => {
1730
1731
  });
1731
- await DeviceInput.scrollToTop(ctx, targetSelector, {
1732
- maxSwipes: Number(options.scrollToTopMaxSwipes || 12),
1733
- stableRounds: 2,
1734
- settleMs: 400
1735
- }).catch((error) => {
1732
+ try {
1733
+ const topResult = await DeviceInput.scrollToTop(ctx, targetSelector, {
1734
+ maxSwipes: Number(options.scrollToTopMaxSwipes || 12),
1735
+ stableRounds: Number(options.scrollToTopStableRounds || 2),
1736
+ settleMs: 400,
1737
+ stability: options.scrollStability || options.stability || "view"
1738
+ });
1739
+ Logger.info("captureScreen scrollToTop", {
1740
+ swipes: topResult?.swipes,
1741
+ stableRounds: topResult?.stableRounds,
1742
+ hashSource: topResult?.hashSource,
1743
+ capped: topResult?.capped === true
1744
+ });
1745
+ } catch (error) {
1746
+ if (options.strictScrollToTop === true) throw error;
1736
1747
  Logger.warn("captureScreen scrollToTop skipped", { message: error?.message || String(error) });
1737
- });
1748
+ }
1738
1749
  for (let index = 0; index < DEFAULT_CAPTURE_COUNT; index += 1) {
1739
- await Device.hideKeyboard(ctx, { attempts: 1, settleMs: 250 }).catch(() => {
1750
+ if (shouldHideKeyboard) await Device.hideKeyboard(ctx, { attempts: 1, settleMs: 250 }).catch(() => {
1740
1751
  });
1741
1752
  await sleep(DEFAULT_SETTLE_MS);
1742
1753
  const png = await Device.screenshotPng(ctx);