@bryce3310687963/android-toolkit 1.0.50 → 1.0.55

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
@@ -99,3 +99,24 @@ WebView cookies, and login data are outside the cleanup scope. Missing cache
99
99
  directories are skipped; invalid package names and cleanup errors fail the call.
100
100
  Each actor chooses whether to call this method; `Launch.run` does not clear caches
101
101
  automatically.
102
+
103
+ ## Reset Rebuildable App Databases
104
+
105
+ `DeviceSQLite.reset(ctx, { dbNamePrefix })` requires root ADB access and a stopped
106
+ app. It removes regular files beginning with the explicitly supplied prefix from
107
+ `/data/data/<package>/databases`, including their WAL, SHM, and journal files.
108
+ The app recreates those databases when launched. This resets entire matching
109
+ databases, not individual table rows; use it only for databases the app can rebuild.
110
+ Other databases, preferences, files, and login configuration are preserved.
111
+ Missing databases are skipped. Invalid targets, symbolic links, unexpected
112
+ directories, and deletion errors fail the call.
113
+
114
+ ```js
115
+ await Device.forceStopApp(ctx);
116
+ await Device.clearAppCache(ctx);
117
+ await DeviceSQLite.reset(ctx, { dbNamePrefix: 'chat_database_' });
118
+ await Device.startLauncher(ctx);
119
+ ```
120
+
121
+ Database prefixes belong in actor code. Local resets do not delete cloud history;
122
+ the app may download old conversations again after launching.
package/dist/index.cjs CHANGED
@@ -1965,8 +1965,32 @@ var import_node_util2 = require("node:util");
1965
1965
  var execFileAsync2 = (0, import_node_util2.promisify)(import_node_child_process2.execFile);
1966
1966
  var DeviceSQLite = {
1967
1967
  query,
1968
- health
1968
+ health,
1969
+ reset
1969
1970
  };
1971
+ async function reset(ctx, options = {}) {
1972
+ const packageName = requireNonEmpty2(ctx?.packageName, "packageName");
1973
+ const dbNamePrefix = requireNonEmpty2(options.dbNamePrefix, "dbNamePrefix");
1974
+ if (!/^[A-Za-z_]\w*(?:\.[A-Za-z_]\w*)+$/.test(packageName) || !/^[A-Za-z_][A-Za-z0-9_.-]*$/.test(dbNamePrefix)) {
1975
+ throw new CrawlerError({ message: "invalid_request: invalid database reset target", code: Code.InvalidRequest });
1976
+ }
1977
+ const command = [
1978
+ "set -e",
1979
+ `db_dir=${shellQuote(`/data/data/${packageName}/databases`)}`,
1980
+ 'if [ -L "$db_dir" ]; then echo "refusing symlink database directory" >&2; exit 1; fi',
1981
+ 'if [ ! -d "$db_dir" ]; then exit 0; fi',
1982
+ `for db_file in "$db_dir"/${shellQuote(dbNamePrefix)}*; do`,
1983
+ ' [ -e "$db_file" ] || [ -L "$db_file" ] || continue',
1984
+ ' if [ -L "$db_file" ] || [ ! -f "$db_file" ]; then echo "refusing unexpected database entry: $db_file" >&2; exit 1; fi',
1985
+ "done",
1986
+ // 主库和 WAL/SHM/journal 一起删除,避免旧日志在重建时恢复聊天记录。
1987
+ `rm -f -- "$db_dir"/${shellQuote(dbNamePrefix)}*`
1988
+ ].join("\n");
1989
+ await adbSuShell(ctx, command, { timeoutMs: 3e4, maxBuffer: 4096 }).catch((error) => {
1990
+ throw CrawlerError.from(error, { code: Code.AutomationFailed, context: { packageName, dbNamePrefix } });
1991
+ });
1992
+ Logger.info("DeviceSQLite.reset", { packageName, dbNamePrefix });
1993
+ }
1970
1994
  async function query(ctx, options = {}) {
1971
1995
  if (!options.sql) {
1972
1996
  throw new CrawlerError({