@kaeawc/auto-mobile 0.0.86 → 0.0.88

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.
@@ -0,0 +1,184 @@
1
+ import { isRandomAccessTokenizer } from './isRandomAccessTokenizer.js';
2
+ import { EndOfStreamError } from './stream/index.js';
3
+ import { TokenizerBoundaryError } from './TokenizerBoundaryError.js';
4
+ function validateOffset(value, name) {
5
+ if (!Number.isSafeInteger(value) || value < 0) {
6
+ throw new RangeError(`${name} must be a non-negative safe integer`);
7
+ }
8
+ }
9
+ export function createTokenizerView(source, length) {
10
+ return isRandomAccessTokenizer(source)
11
+ ? new RandomAccessTokenizerView(source, length)
12
+ : new TokenizerView(source, length);
13
+ }
14
+ class TokenizerView {
15
+ constructor(source, size) {
16
+ this.source = source;
17
+ this.size = size;
18
+ this.closed = false;
19
+ this.closedPosition = 0;
20
+ this.busy = false;
21
+ validateOffset(size, 'length');
22
+ validateOffset(source.position, 'source position');
23
+ validateOffset(source.position + size, 'end position');
24
+ if (source instanceof TokenizerView) {
25
+ source.assertAvailable();
26
+ source.translateRange(size, source.position);
27
+ }
28
+ this.start = source.position;
29
+ // A chunk has its own size; the outer file's MIME type/path need not describe it.
30
+ this.fileInfo = { size };
31
+ }
32
+ get position() {
33
+ return this.closed ? this.closedPosition : this.source.position - this.start;
34
+ }
35
+ get remaining() {
36
+ return this.size - this.position;
37
+ }
38
+ supportsRandomAccess() {
39
+ return false;
40
+ }
41
+ createView(length) {
42
+ this.assertAvailable();
43
+ return createTokenizerView(this, length);
44
+ }
45
+ async readBuffer(buffer, options) {
46
+ return this.bufferOperation('readBuffer', buffer, options);
47
+ }
48
+ async peekBuffer(buffer, options) {
49
+ return this.bufferOperation('peekBuffer', buffer, options);
50
+ }
51
+ async bufferOperation(method, buffer, options) {
52
+ this.assertAvailable();
53
+ const length = options?.length ?? buffer.length;
54
+ const position = options?.position ?? this.position;
55
+ const absolutePosition = this.translateRange(length, position);
56
+ if (length > buffer.length) {
57
+ throw new RangeError('length must not exceed the target buffer length');
58
+ }
59
+ return this.run(() => this.source[method](buffer, { ...options, length, position: absolutePosition }));
60
+ }
61
+ async readToken(token, position = this.position) {
62
+ this.assertAvailable();
63
+ const absolutePosition = this.translateRange(token.len, position);
64
+ return this.run(() => this.source.readToken(token, absolutePosition));
65
+ }
66
+ async peekToken(token, position = this.position) {
67
+ this.assertAvailable();
68
+ const absolutePosition = this.translateRange(token.len, position ?? this.position);
69
+ return this.run(() => this.source.peekToken(token, absolutePosition));
70
+ }
71
+ async readNumber(token) {
72
+ this.assertAvailable();
73
+ this.translateRange(token.len, this.position);
74
+ return this.run(() => this.source.readNumber(token));
75
+ }
76
+ async peekNumber(token) {
77
+ this.assertAvailable();
78
+ this.translateRange(token.len, this.position);
79
+ return this.run(() => this.source.peekNumber(token));
80
+ }
81
+ async ignore(length) {
82
+ this.assertAvailable();
83
+ this.translateRange(length, this.position);
84
+ return this.run(() => this.source.ignore(length));
85
+ }
86
+ async consumeRemainder() {
87
+ this.assertAvailable();
88
+ const length = this.remaining;
89
+ const end = this.translateRange(length, this.position) + length;
90
+ return this.run(async () => {
91
+ if (length === 0) {
92
+ return 0;
93
+ }
94
+ if (isRandomAccessTokenizer(this.source)) {
95
+ // Unlike ignore()/setPosition(), this verifies that the final byte exists,
96
+ // including a file that was truncated after its initial stat. No large read.
97
+ if ((await this.source.peekBuffer(new Uint8Array(1), { position: end - 1 })) !== 1) {
98
+ throw new EndOfStreamError();
99
+ }
100
+ this.source.setPosition(end);
101
+ }
102
+ else {
103
+ const ignored = await this.source.ignore(length);
104
+ if (ignored !== length) {
105
+ throw new EndOfStreamError();
106
+ }
107
+ }
108
+ return length;
109
+ });
110
+ }
111
+ /** Release this view only. Never drain, close or abort the borrowed source. */
112
+ async close() {
113
+ if (this.closed) {
114
+ return;
115
+ }
116
+ if (this.busy) {
117
+ throw new Error('Cannot close a tokenizer view during an active operation');
118
+ }
119
+ this.closedPosition = this.position;
120
+ this.closed = true;
121
+ }
122
+ /** Explicit cancellation propagates to the shared source and affects its other users. */
123
+ async abort() {
124
+ if (this.closed) {
125
+ return;
126
+ }
127
+ try {
128
+ await this.source.abort();
129
+ }
130
+ finally {
131
+ this.closedPosition = this.position;
132
+ this.closed = true;
133
+ }
134
+ }
135
+ assertAvailable() {
136
+ if (this.closed) {
137
+ throw new Error('Tokenizer view is closed');
138
+ }
139
+ if (this.busy) {
140
+ throw new Error('Tokenizer views require sequential operations');
141
+ }
142
+ if (this.source instanceof TokenizerView) {
143
+ this.source.assertAvailable();
144
+ }
145
+ }
146
+ /** Validate the whole request before delegating or allowing a token allocation. */
147
+ translateRange(length, position) {
148
+ validateOffset(length, 'length');
149
+ validateOffset(position, 'position');
150
+ validateOffset(position + length, 'end position');
151
+ if (position > this.size || length > this.size - position) {
152
+ throw new TokenizerBoundaryError(position, length, this.size);
153
+ }
154
+ if (!this.supportsRandomAccess() && position < this.position) {
155
+ throw new Error('`options.position` must be equal or greater than `tokenizer.position`');
156
+ }
157
+ return this.start + position;
158
+ }
159
+ async run(operation) {
160
+ this.busy = true;
161
+ try {
162
+ return await operation();
163
+ }
164
+ finally {
165
+ this.busy = false;
166
+ }
167
+ }
168
+ }
169
+ class RandomAccessTokenizerView extends TokenizerView {
170
+ constructor(source, size) {
171
+ super(source, size);
172
+ }
173
+ supportsRandomAccess() {
174
+ return true;
175
+ }
176
+ setPosition(position) {
177
+ this.assertAvailable();
178
+ this.source.setPosition(this.translateRange(0, position));
179
+ }
180
+ createView(length) {
181
+ this.assertAvailable();
182
+ return createTokenizerView(this, length);
183
+ }
184
+ }
@@ -6,7 +6,10 @@ import { ReadStreamTokenizer } from './ReadStreamTokenizer.js';
6
6
  import { makeWebStreamReader, StreamReader } from './stream/index.js';
7
7
  export { AbstractTokenizer } from './AbstractTokenizer.js';
8
8
  export { BufferSizeError } from './BufferSizeError.js';
9
+ export { isRandomAccessTokenizer } from './isRandomAccessTokenizer.js';
9
10
  export { AbortError, EndOfStreamError } from './stream/index.js';
11
+ export { TokenizerBoundaryError } from './TokenizerBoundaryError.js';
12
+ export { createTokenizerView } from './TokenizerView.js';
10
13
  /**
11
14
  * Construct ReadStreamTokenizer from given Stream.
12
15
  * Will set fileSize, if provided given Stream has set the .path property/
@@ -18,15 +21,7 @@ export function fromStream(stream, options) {
18
21
  getMaxBufferSize(options);
19
22
  throwIfAborted(options?.abortSignal);
20
23
  const streamReader = new StreamReader(stream);
21
- const _options = options ?? {};
22
- const chainedClose = _options.onClose;
23
- _options.onClose = async () => {
24
- await streamReader.close();
25
- if (chainedClose) {
26
- return chainedClose();
27
- }
28
- };
29
- return new ReadStreamTokenizer(streamReader, _options);
24
+ return new ReadStreamTokenizer(streamReader, options);
30
25
  }
31
26
  /**
32
27
  * Construct ReadStreamTokenizer from given ReadableStream (WebStream API).
@@ -39,15 +34,7 @@ export function fromWebStream(webStream, options) {
39
34
  getMaxBufferSize(options);
40
35
  throwIfAborted(options?.abortSignal);
41
36
  const webStreamReader = makeWebStreamReader(webStream);
42
- const _options = options ?? {};
43
- const chainedClose = _options.onClose;
44
- _options.onClose = async () => {
45
- await webStreamReader.close();
46
- if (chainedClose) {
47
- return chainedClose();
48
- }
49
- };
50
- return new ReadStreamTokenizer(webStreamReader, _options);
37
+ return new ReadStreamTokenizer(webStreamReader, options);
51
38
  }
52
39
  /**
53
40
  * Construct ReadStreamTokenizer from given Buffer.
@@ -3,6 +3,7 @@ import { fromStream as coreFromStream } from './core.js';
3
3
  import { FileTokenizer } from './FileTokenizer.js';
4
4
  export * from './core.js';
5
5
  export { FileTokenizer } from './FileTokenizer.js';
6
+ export { NotRegularFileError } from './NotRegularFileError.js';
6
7
  /**
7
8
  * Construct ReadStreamTokenizer from given Stream.
8
9
  * Will set fileSize, if provided given Stream has set the .path property.
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Check for random-access capability, position control and a known file size.
3
+ * A known size alone does not imply random access.
4
+ */
5
+ export function isRandomAccessTokenizer(tokenizer) {
6
+ return (tokenizer.supportsRandomAccess() &&
7
+ 'setPosition' in tokenizer &&
8
+ typeof tokenizer.setPosition === 'function' &&
9
+ typeof tokenizer.fileInfo.size === 'number');
10
+ }
@@ -24,7 +24,12 @@ export class StreamReader extends AbstractStreamReader {
24
24
  }
25
25
  });
26
26
  this.s.once('error', err => this.reject(err));
27
- this.s.once('close', () => this.abort());
27
+ this.s.once('close', () => {
28
+ // Normal EOF may leave peeked bytes that the caller still needs to consume.
29
+ if (!this.endOfStream) {
30
+ void this.abort();
31
+ }
32
+ });
28
33
  }
29
34
  /**
30
35
  * Read chunk from stream
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "strtok3",
3
- "version": "10.4.0",
3
+ "version": "10.6.2",
4
4
  "description": "A promise based streaming tokenizer",
5
5
  "author": {
6
6
  "name": "Borewit",
@@ -13,9 +13,11 @@
13
13
  "scripts": {
14
14
  "clean": "del-cli 'lib/**/*.js' 'lib/**/*.js.map' 'lib/**/*.d.ts' 'test/**/*.js' 'test/**/*.js.map'",
15
15
  "compile-src": "tsc -p lib --sourceMap false",
16
+ "compile-src:dev": "tsc -p lib --sourceMap --inlineSources",
16
17
  "compile-test": "tsc -p test",
17
- "compile": "yarn run compile-src && yarn run compile-test",
18
+ "compile": "yarn run compile-src && yarn run compile-test && yarn run test:types",
18
19
  "build": "yarn run clean && yarn run compile",
20
+ "build:dev": "yarn run clean && yarn run compile-test && yarn run compile-src:dev && yarn run test:types",
19
21
  "prepublishOnly": "yarn run build",
20
22
  "eslint": "eslint lib test",
21
23
  "lint:md": "remark -u preset-lint-recommended .",
@@ -23,9 +25,9 @@
23
25
  "lint": "yarn run lint:md && yarn run lint:ts",
24
26
  "fix": "yarn run lint:ts:fix",
25
27
  "test": "mocha",
28
+ "test:types": "tsc -p test/types && tsc -p test/types/tsconfig.browser.json",
26
29
  "bun:test": "bun run --bun test",
27
30
  "test-coverage": "c8 yarn run test",
28
- "send-codacy": "c8 report --reporter=text-lcov | codacy-coverage",
29
31
  "start": "yarn run compile && yarn run lint && yarn run cover-test",
30
32
  "update-biome": "yarn add -D --exact @biomejs/biome && npx @biomejs/biome migrate --write",
31
33
  "lint:ts:fix": "biome check --write"
@@ -59,16 +61,16 @@
59
61
  },
60
62
  "devDependencies": {
61
63
  "@biomejs/biome": "2.5.15",
62
- "@types/chai": "^5.2.2",
64
+ "@types/chai": "^5.2.3",
63
65
  "@types/chai-as-promised": "^8.0.2",
64
- "@types/debug": "^4.1.12",
66
+ "@types/debug": "^4.1.13",
65
67
  "@types/mocha": "^10.0.10",
66
- "@types/node": "^24.19.1",
68
+ "@types/node": "^26.6.5",
67
69
  "c8": "^12.0.0",
68
70
  "chai": "^6.3.0",
69
71
  "chai-as-promised": "^8.0.2",
70
- "del-cli": "^7.0.0",
71
- "mocha": "^11",
72
+ "del-cli": "^8.0.1",
73
+ "mocha": "^11.8.0",
72
74
  "node-readable-to-web-readable-stream": "^0.4.2",
73
75
  "remark-cli": "^12.0.1",
74
76
  "remark-preset-lint-recommended": "^7.0.1",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kaeawc/auto-mobile",
3
- "version": "0.0.86",
3
+ "version": "0.0.88",
4
4
  "description": "Mobile device interaction automation via MCP",
5
5
  "keywords": [
6
6
  "adb",
@@ -31,6 +31,7 @@
31
31
  },
32
32
  "files": [
33
33
  "dist",
34
+ "!dist/**/*.map",
34
35
  "schemas"
35
36
  ],
36
37
  "main": "dist/src/index.js",
@@ -58,11 +59,10 @@
58
59
  "lint:prune": "bash scripts/oxlint-baseline.sh --update",
59
60
  "lint:baseline": "bash scripts/oxlint-baseline.sh --update",
60
61
  "lint:file-size:baseline": "bash scripts/file-size-baseline.sh --update",
61
- "test:as-any:baseline": "bash scripts/test-as-any-baseline.sh --update",
62
62
  "format": "oxfmt",
63
63
  "format:check": "oxfmt --check",
64
64
  "typecheck": "bash scripts/typecheck-baseline.sh",
65
- "typecheck:update": "bash scripts/typecheck-baseline.sh --update",
65
+ "typecheck:test": "bash scripts/typecheck-baseline.sh --project=test",
66
66
  "docs:assets": "bun scripts/docs/build-docs-assets.ts",
67
67
  "docs:assets:check": "bun scripts/docs/build-docs-assets.ts --check",
68
68
  "watch": "bun --watch src/index.ts",
@@ -86,19 +86,20 @@
86
86
  "check:bun-version-coherence": "bun scripts/check-bun-version-coherence.ts",
87
87
  "check:stdlib-first": "bash scripts/check-stdlib-first.sh",
88
88
  "check:host-shell-boundary": "bun scripts/check-host-shell-boundary.ts",
89
- "check:shell-quote-boundary": "bash scripts/check-no-local-shell-quote.sh",
89
+ "check:shell-quote-boundary": "bun scripts/check-no-local-shell-quote.ts",
90
90
  "check:simctl-boundary": "bash scripts/check-no-new-direct-simctl.sh",
91
91
  "check:plutil-boundary": "bun scripts/check-no-direct-plutil.ts",
92
92
  "check:security-boundary": "bash scripts/check-no-new-direct-security.sh",
93
- "check:git-metadata-boundary": "bash scripts/check-no-new-direct-git-metadata.sh",
94
- "check:utils-import-direction": "bash scripts/check-utils-import-direction.sh",
93
+ "check:git-metadata-boundary": "bun scripts/check-no-new-direct-git-metadata.ts",
94
+ "check:utils-import-direction": "bun scripts/check-utils-import-direction.ts",
95
+ "check:tier-import-direction": "bun scripts/check-tier-import-direction.ts",
95
96
  "check:xcodebuild-boundary": "bash scripts/check-no-new-direct-xcodebuild.sh",
96
- "check:android-emulator-boundary": "bash scripts/check-android-emulator-boundary.sh",
97
- "check:app-bundle-metadata-boundary": "bash scripts/check-app-bundle-metadata-boundary.sh",
98
- "check:ffmpeg-boundary": "bash scripts/check-ffmpeg-execution-boundary.sh",
99
- "check:simulator-tcc-sqlite-boundary": "bash scripts/check-simulator-tcc-sqlite-boundary.sh",
100
- "check:daemon-launcher-boundary": "bash scripts/check-daemon-launcher-boundary.sh",
101
- "check:ios-ctrl-proxy-process-boundary": "bash scripts/check-ios-ctrl-proxy-process-boundary.sh",
97
+ "check:android-emulator-boundary": "bun scripts/check-android-emulator-boundary.ts",
98
+ "check:app-bundle-metadata-boundary": "bun scripts/check-app-bundle-metadata-boundary.ts",
99
+ "check:ffmpeg-boundary": "bun scripts/check-ffmpeg-execution-boundary.ts",
100
+ "check:simulator-tcc-sqlite-boundary": "bun scripts/check-simulator-tcc-sqlite-boundary.ts",
101
+ "check:daemon-launcher-boundary": "bun scripts/check-daemon-launcher-boundary.ts",
102
+ "check:ios-ctrl-proxy-process-boundary": "bun scripts/check-ios-ctrl-proxy-process-boundary.ts",
102
103
  "dead-code:ts": "bash scripts/detect-dead-code-ts.sh",
103
104
  "dead-code:ts:knip": "bunx knip",
104
105
  "dead-code:ts:production": "bunx knip -c knip.production.json --include files",
@@ -179,7 +180,7 @@
179
180
  "semver": "7.8.5",
180
181
  "sharp": "0.35.5",
181
182
  "simple-xml-to-json": "1.2.3",
182
- "strtok3": "10.4.0",
183
+ "strtok3": "10.6.2",
183
184
  "tinycolor2": "1.6.0",
184
185
  "token-types": "6.1.2",
185
186
  "tslib": "2.8.1",
@@ -190,9 +191,12 @@
190
191
  "zod": "3.25.76"
191
192
  },
192
193
  "devDependencies": {
193
- "@anthropic-ai/sdk": "^0.133.0",
194
+ "@anthropic-ai/sdk": "^0.135.0",
194
195
  "@faker-js/faker": "^10.2.0",
195
- "@modelcontextprotocol/sdk": "^1.26.0",
196
+ "@modelcontextprotocol/client": "^2.3.1",
197
+ "@modelcontextprotocol/node": "^2.1.1",
198
+ "@modelcontextprotocol/server": "^2.3.1",
199
+ "@types/bun": "1.4.3",
196
200
  "@types/node": "^26.0.0",
197
201
  "@types/pngjs": "^6.0.5",
198
202
  "@types/ws": "^8.18.1",
@@ -206,10 +210,10 @@
206
210
  "js-tiktoken": "^1.0.21",
207
211
  "js-yaml": "^5.1.0",
208
212
  "knip": "^6.0.0",
209
- "kysely": "0.29.6",
210
- "oxc-parser": "0.153.0",
211
- "oxfmt": "0.72.0",
212
- "oxlint": "1.87.0",
213
+ "kysely": "0.29.7",
214
+ "oxc-parser": "0.155.0",
215
+ "oxfmt": "0.74.0",
216
+ "oxlint": "1.89.0",
213
217
  "oxlint-tsgolint": "7.0.2004",
214
218
  "pixelmatch": "^8.0.0",
215
219
  "pngjs": "^7.0.0",
@@ -218,7 +222,8 @@
218
222
  "typescript": "6.0.3",
219
223
  "werift": "^0.25.0",
220
224
  "ws": "^8.19.0",
221
- "xml2js": "^0.6.2"
225
+ "xml2js": "^0.6.2",
226
+ "zod-to-json-schema": "^3.25.1"
222
227
  },
223
228
  "optionalDependencies": {
224
229
  "@img/sharp-darwin-arm64": "0.35.5",
@@ -264,9 +269,9 @@
264
269
  "tar": "^7.5.8"
265
270
  },
266
271
  "engines": {
267
- "bun": ">=1.3.14"
272
+ "bun": ">=1.4.4"
268
273
  },
269
- "packageManager": "bun@1.3.14",
274
+ "packageManager": "bun@1.4.4",
270
275
  "//overrides": {
271
276
  "lodash": "CVE-2025-13465: prototype pollution in _.unset and _.omit",
272
277
  "tar": "CVE-2026-26960 (GHSA-83g3-92jg-28cx): Arbitrary file read/write via hardlink target escape through symlink chain",