@kaeawc/auto-mobile 0.0.87 → 0.0.89
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 +4 -4
- package/README.md.backup +4 -4
- package/dist/build-info.json +13 -10
- package/dist/schemas/test-plan.schema.json +276 -0
- package/dist/src/index.js +2030 -1166
- package/dist/src/utils/workers/iosBundleExtractWorker.js +3 -3
- package/mcp-skills/auto-mobile-usage/SKILL.md +44 -0
- package/node_modules/@borewit/text-codec/LICENSE.txt +9 -9
- package/node_modules/@borewit/text-codec/README.md +86 -86
- package/node_modules/@borewit/text-codec/lib/index.js +102 -120
- package/node_modules/@borewit/text-codec/package.json +71 -70
- package/node_modules/strtok3/README.md +186 -11
- package/node_modules/strtok3/lib/AbstractTokenizer.js +12 -4
- package/node_modules/strtok3/lib/BlobTokenizer.js +1 -0
- package/node_modules/strtok3/lib/BufferTokenizer.js +2 -1
- package/node_modules/strtok3/lib/FileTokenizer.js +11 -5
- package/node_modules/strtok3/lib/NotRegularFileError.js +8 -0
- package/node_modules/strtok3/lib/ReadStreamTokenizer.js +17 -2
- package/node_modules/strtok3/lib/TokenizerBoundaryError.js +10 -0
- package/node_modules/strtok3/lib/TokenizerView.js +184 -0
- package/node_modules/strtok3/lib/core.js +5 -18
- package/node_modules/strtok3/lib/index.js +29 -5
- package/node_modules/strtok3/lib/isRandomAccessTokenizer.js +10 -0
- package/node_modules/strtok3/lib/stream/StreamReader.js +29 -8
- package/node_modules/strtok3/package.json +10 -8
- package/package.json +21 -17
- package/schemas/test-plan.schema.json +276 -0
|
@@ -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
|
-
|
|
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
|
-
|
|
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,23 @@ 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';
|
|
7
|
+
async function waitForPendingOpen(stream) {
|
|
8
|
+
if (stream.pending !== true || stream.destroyed || stream.errored !== null) {
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
await new Promise(resolve => {
|
|
12
|
+
const settle = () => {
|
|
13
|
+
stream.removeListener('open', settle);
|
|
14
|
+
stream.removeListener('error', settle);
|
|
15
|
+
stream.removeListener('close', settle);
|
|
16
|
+
resolve();
|
|
17
|
+
};
|
|
18
|
+
stream.once('open', settle);
|
|
19
|
+
stream.once('error', settle);
|
|
20
|
+
stream.once('close', settle);
|
|
21
|
+
});
|
|
22
|
+
}
|
|
6
23
|
/**
|
|
7
24
|
* Construct ReadStreamTokenizer from given Stream.
|
|
8
25
|
* Will set fileSize, if provided given Stream has set the .path property.
|
|
@@ -12,11 +29,18 @@ export { FileTokenizer } from './FileTokenizer.js';
|
|
|
12
29
|
*/
|
|
13
30
|
export async function fromStream(stream, options) {
|
|
14
31
|
const rst = coreFromStream(stream, options);
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
32
|
+
try {
|
|
33
|
+
if (stream.path) {
|
|
34
|
+
const stat = await fsStat(stream.path);
|
|
35
|
+
rst.fileInfo.path = stream.path;
|
|
36
|
+
rst.fileInfo.size = stat.size;
|
|
37
|
+
}
|
|
38
|
+
return rst;
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
await waitForPendingOpen(stream);
|
|
42
|
+
await rst.close();
|
|
43
|
+
throw error;
|
|
19
44
|
}
|
|
20
|
-
return rst;
|
|
21
45
|
}
|
|
22
46
|
export const fromFile = FileTokenizer.fromFile;
|
|
@@ -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
|
+
}
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import { AbstractStreamReader } from './AbstractStreamReader.js';
|
|
2
2
|
import { Deferred } from './Deferred.js';
|
|
3
3
|
import { AbortError } from './Errors.js';
|
|
4
|
+
function handlePostEndError() {
|
|
5
|
+
this.removeListener('close', removePostEndErrorHandler);
|
|
6
|
+
}
|
|
7
|
+
function removePostEndErrorHandler() {
|
|
8
|
+
this.removeListener('error', handlePostEndError);
|
|
9
|
+
}
|
|
4
10
|
/**
|
|
5
11
|
* Node.js Readable Stream Reader
|
|
6
12
|
* Ref: https://nodejs.org/api/stream.html#readable-streams
|
|
@@ -13,23 +19,32 @@ export class StreamReader extends AbstractStreamReader {
|
|
|
13
19
|
* Pending requests waiting for data, tracked until completion or cancellation
|
|
14
20
|
*/
|
|
15
21
|
this.pendingRequests = new Set();
|
|
16
|
-
|
|
17
|
-
throw new Error('Expected an instance of stream.Readable');
|
|
18
|
-
}
|
|
19
|
-
this.s.once('end', () => {
|
|
22
|
+
this.onEnd = () => {
|
|
20
23
|
this.endOfStream = true;
|
|
24
|
+
this.removeLifecycleListeners();
|
|
25
|
+
// Auto-destruction may emit an error after `end`. These shared handlers do
|
|
26
|
+
// not retain this reader when `emitClose` is disabled.
|
|
27
|
+
this.s.once('error', handlePostEndError);
|
|
28
|
+
this.s.once('close', removePostEndErrorHandler);
|
|
21
29
|
for (const request of this.pendingRequests) {
|
|
22
30
|
this.removeRequest(request);
|
|
23
31
|
request.deferred.resolve(0);
|
|
24
32
|
}
|
|
25
|
-
}
|
|
26
|
-
this.
|
|
27
|
-
this.
|
|
33
|
+
};
|
|
34
|
+
this.onError = (err) => this.reject(err);
|
|
35
|
+
this.onClose = () => {
|
|
36
|
+
this.removeLifecycleListeners();
|
|
28
37
|
// Normal EOF may leave peeked bytes that the caller still needs to consume.
|
|
29
38
|
if (!this.endOfStream) {
|
|
30
39
|
void this.abort();
|
|
31
40
|
}
|
|
32
|
-
}
|
|
41
|
+
};
|
|
42
|
+
if (!s.read || !s.once) {
|
|
43
|
+
throw new Error('Expected an instance of stream.Readable');
|
|
44
|
+
}
|
|
45
|
+
this.s.once('end', this.onEnd);
|
|
46
|
+
this.s.once('error', this.onError);
|
|
47
|
+
this.s.once('close', this.onClose);
|
|
33
48
|
}
|
|
34
49
|
/**
|
|
35
50
|
* Read chunk from stream
|
|
@@ -87,7 +102,13 @@ export class StreamReader extends AbstractStreamReader {
|
|
|
87
102
|
this.s.removeListener('readable', request.onReadable);
|
|
88
103
|
this.pendingRequests.delete(request);
|
|
89
104
|
}
|
|
105
|
+
removeLifecycleListeners() {
|
|
106
|
+
this.s.removeListener('end', this.onEnd);
|
|
107
|
+
this.s.removeListener('error', this.onError);
|
|
108
|
+
this.s.removeListener('close', this.onClose);
|
|
109
|
+
}
|
|
90
110
|
reject(err) {
|
|
111
|
+
this.removeLifecycleListeners();
|
|
91
112
|
this.interrupted = true;
|
|
92
113
|
this.peekQueue = [];
|
|
93
114
|
for (const request of this.pendingRequests) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "strtok3",
|
|
3
|
-
"version": "10.
|
|
3
|
+
"version": "10.6.3",
|
|
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.
|
|
64
|
+
"@types/chai": "^5.2.3",
|
|
63
65
|
"@types/chai-as-promised": "^8.0.2",
|
|
64
|
-
"@types/debug": "^4.1.
|
|
66
|
+
"@types/debug": "^4.1.13",
|
|
65
67
|
"@types/mocha": "^10.0.10",
|
|
66
|
-
"@types/node": "^
|
|
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": "^
|
|
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.
|
|
3
|
+
"version": "0.0.89",
|
|
4
4
|
"description": "Mobile device interaction automation via MCP",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"adb",
|
|
@@ -32,7 +32,8 @@
|
|
|
32
32
|
"files": [
|
|
33
33
|
"dist",
|
|
34
34
|
"!dist/**/*.map",
|
|
35
|
-
"schemas"
|
|
35
|
+
"schemas",
|
|
36
|
+
"mcp-skills"
|
|
36
37
|
],
|
|
37
38
|
"main": "dist/src/index.js",
|
|
38
39
|
"publishConfig": {
|
|
@@ -53,17 +54,17 @@
|
|
|
53
54
|
"test:memory-leaks": "bun --expose-gc scripts/detect-memory-leaks.ts",
|
|
54
55
|
"test:integration:webrtc-mediamtx": "bash scripts/webrtc/run-mediamtx-publisher-integration.sh",
|
|
55
56
|
"test:integration:webrtc-device": "bash scripts/webrtc/run-mediamtx-device-integration.sh",
|
|
57
|
+
"test:prototype-web-screenshots": "bash scripts/prototype/web-screenshots.sh",
|
|
56
58
|
"gate:android-video-baseline": "bun scripts/webrtc/android-video-baseline-gate.ts",
|
|
57
59
|
"lint": "bash scripts/lint.sh",
|
|
58
60
|
"check:boundaries": "bash scripts/check-boundaries.sh",
|
|
59
61
|
"lint:prune": "bash scripts/oxlint-baseline.sh --update",
|
|
60
62
|
"lint:baseline": "bash scripts/oxlint-baseline.sh --update",
|
|
61
63
|
"lint:file-size:baseline": "bash scripts/file-size-baseline.sh --update",
|
|
62
|
-
"test:as-any:baseline": "bash scripts/test-as-any-baseline.sh --update",
|
|
63
64
|
"format": "oxfmt",
|
|
64
65
|
"format:check": "oxfmt --check",
|
|
65
66
|
"typecheck": "bash scripts/typecheck-baseline.sh",
|
|
66
|
-
"typecheck:
|
|
67
|
+
"typecheck:test": "bash scripts/typecheck-baseline.sh --project=test",
|
|
67
68
|
"docs:assets": "bun scripts/docs/build-docs-assets.ts",
|
|
68
69
|
"docs:assets:check": "bun scripts/docs/build-docs-assets.ts --check",
|
|
69
70
|
"watch": "bun --watch src/index.ts",
|
|
@@ -78,6 +79,7 @@
|
|
|
78
79
|
"benchmark-context": "bun scripts/benchmark-context-thresholds.ts",
|
|
79
80
|
"benchmark-tools": "bun scripts/benchmark-mcp-tools.ts",
|
|
80
81
|
"bench:settled-screenshot": "bun scripts/benchmark-settled-screenshot.ts",
|
|
82
|
+
"bench:agent": "bun run build 1>&2 && bun scripts/agent-benchmark/run.ts",
|
|
81
83
|
"benchmark-startup": "bash scripts/benchmark-startup.sh",
|
|
82
84
|
"benchmark-npm-unpacked-size": "bun scripts/benchmark-npm-unpacked-size.ts",
|
|
83
85
|
"profile:memory": "bun --expose-gc --inspect scripts/detect-memory-leaks.ts --mode=profile",
|
|
@@ -125,7 +127,7 @@
|
|
|
125
127
|
"loop": "bash scripts/validate-loop.sh"
|
|
126
128
|
},
|
|
127
129
|
"dependencies": {
|
|
128
|
-
"@borewit/text-codec": "0.2.
|
|
130
|
+
"@borewit/text-codec": "0.2.3",
|
|
129
131
|
"@emnapi/runtime": "1.11.3",
|
|
130
132
|
"@img/colour": "1.1.0",
|
|
131
133
|
"@jimp/core": "1.6.1",
|
|
@@ -181,7 +183,7 @@
|
|
|
181
183
|
"semver": "7.8.5",
|
|
182
184
|
"sharp": "0.35.5",
|
|
183
185
|
"simple-xml-to-json": "1.2.3",
|
|
184
|
-
"strtok3": "10.
|
|
186
|
+
"strtok3": "10.6.3",
|
|
185
187
|
"tinycolor2": "1.6.0",
|
|
186
188
|
"token-types": "6.1.2",
|
|
187
189
|
"tslib": "2.8.1",
|
|
@@ -192,11 +194,12 @@
|
|
|
192
194
|
"zod": "3.25.76"
|
|
193
195
|
},
|
|
194
196
|
"devDependencies": {
|
|
195
|
-
"@anthropic-ai/sdk": "^
|
|
197
|
+
"@anthropic-ai/sdk": "^1.1.0",
|
|
196
198
|
"@faker-js/faker": "^10.2.0",
|
|
197
|
-
"@modelcontextprotocol/client": "^2.
|
|
199
|
+
"@modelcontextprotocol/client": "^2.4.0",
|
|
198
200
|
"@modelcontextprotocol/node": "^2.1.1",
|
|
199
|
-
"@modelcontextprotocol/server": "^2.
|
|
201
|
+
"@modelcontextprotocol/server": "^2.4.0",
|
|
202
|
+
"@types/bun": "1.4.4",
|
|
200
203
|
"@types/node": "^26.0.0",
|
|
201
204
|
"@types/pngjs": "^6.0.5",
|
|
202
205
|
"@types/ws": "^8.18.1",
|
|
@@ -210,17 +213,18 @@
|
|
|
210
213
|
"js-tiktoken": "^1.0.21",
|
|
211
214
|
"js-yaml": "^5.1.0",
|
|
212
215
|
"knip": "^6.0.0",
|
|
213
|
-
"kysely": "0.29.
|
|
214
|
-
"oxc-parser": "0.
|
|
215
|
-
"oxfmt": "0.
|
|
216
|
-
"oxlint": "1.
|
|
217
|
-
"oxlint-tsgolint": "7.0.
|
|
216
|
+
"kysely": "0.29.7",
|
|
217
|
+
"oxc-parser": "0.156.0",
|
|
218
|
+
"oxfmt": "0.75.0",
|
|
219
|
+
"oxlint": "1.90.0",
|
|
220
|
+
"oxlint-tsgolint": "7.0.2005",
|
|
218
221
|
"pixelmatch": "^8.0.0",
|
|
222
|
+
"playwright-core": "1.63.0",
|
|
219
223
|
"pngjs": "^7.0.0",
|
|
220
224
|
"reflect-metadata": "^0.2.2",
|
|
221
225
|
"turbo": "^2.8.10",
|
|
222
226
|
"typescript": "6.0.3",
|
|
223
|
-
"werift": "^0.
|
|
227
|
+
"werift": "^0.26.0",
|
|
224
228
|
"ws": "^8.19.0",
|
|
225
229
|
"xml2js": "^0.6.2",
|
|
226
230
|
"zod-to-json-schema": "^3.25.1"
|
|
@@ -269,9 +273,9 @@
|
|
|
269
273
|
"tar": "^7.5.8"
|
|
270
274
|
},
|
|
271
275
|
"engines": {
|
|
272
|
-
"bun": ">=1.
|
|
276
|
+
"bun": ">=1.4.4"
|
|
273
277
|
},
|
|
274
|
-
"packageManager": "bun@1.
|
|
278
|
+
"packageManager": "bun@1.4.4",
|
|
275
279
|
"//overrides": {
|
|
276
280
|
"lodash": "CVE-2025-13465: prototype pollution in _.unset and _.omit",
|
|
277
281
|
"tar": "CVE-2026-26960 (GHSA-83g3-92jg-28cx): Arbitrary file read/write via hardlink target escape through symlink chain",
|