@appclaw/vision 1.1.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 (38) hide show
  1. package/README.md +27 -0
  2. package/dist/src/coordinates.d.ts +29 -0
  3. package/dist/src/coordinates.d.ts.map +1 -0
  4. package/dist/src/coordinates.js +92 -0
  5. package/dist/src/coordinates.js.map +1 -0
  6. package/dist/src/geminiClient.d.ts +54 -0
  7. package/dist/src/geminiClient.d.ts.map +1 -0
  8. package/dist/src/geminiClient.js +268 -0
  9. package/dist/src/geminiClient.js.map +1 -0
  10. package/dist/src/generated/promptB64.d.ts +10 -0
  11. package/dist/src/generated/promptB64.d.ts.map +1 -0
  12. package/dist/src/generated/promptB64.js +15 -0
  13. package/dist/src/generated/promptB64.js.map +1 -0
  14. package/dist/src/index.d.ts +29 -0
  15. package/dist/src/index.d.ts.map +1 -0
  16. package/dist/src/index.js +39 -0
  17. package/dist/src/index.js.map +1 -0
  18. package/dist/src/instructionParser.d.ts +24 -0
  19. package/dist/src/instructionParser.d.ts.map +1 -0
  20. package/dist/src/instructionParser.js +119 -0
  21. package/dist/src/instructionParser.js.map +1 -0
  22. package/dist/src/openaiCompatClient.d.ts +28 -0
  23. package/dist/src/openaiCompatClient.d.ts.map +1 -0
  24. package/dist/src/openaiCompatClient.js +119 -0
  25. package/dist/src/openaiCompatClient.js.map +1 -0
  26. package/dist/src/promptCodec.d.ts +2 -0
  27. package/dist/src/promptCodec.d.ts.map +1 -0
  28. package/dist/src/promptCodec.js +13 -0
  29. package/dist/src/promptCodec.js.map +1 -0
  30. package/dist/src/prompts.d.ts +7 -0
  31. package/dist/src/prompts.d.ts.map +1 -0
  32. package/dist/src/prompts.js +19 -0
  33. package/dist/src/prompts.js.map +1 -0
  34. package/dist/src/types.d.ts +86 -0
  35. package/dist/src/types.d.ts.map +1 -0
  36. package/dist/src/types.js +11 -0
  37. package/dist/src/types.js.map +1 -0
  38. package/package.json +48 -0
package/README.md ADDED
@@ -0,0 +1,27 @@
1
+ # @appclaw/vision
2
+
3
+ AI-powered vision element detection for [AppClaw](https://github.com/appclawhq/AppClaw) — locates on-screen UI elements from a screenshot using Gemini / OpenAI-compatible vision models.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install @appclaw/vision
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```ts
14
+ import { StarkVisionClient, parseInstruction } from '@appclaw/vision';
15
+ ```
16
+
17
+ ## Develop
18
+
19
+ ```bash
20
+ npm install
21
+ npm run build
22
+ npm run typecheck
23
+ ```
24
+
25
+ ## License
26
+
27
+ MIT
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Coordinate scaling and parsing utilities.
3
+ * Adapted from appium-stark-vision/src/utils.ts
4
+ */
5
+ import { BoundingBox, ScreenSize } from './types';
6
+ /**
7
+ * Scale normalized coordinates (0-1000) to device pixel coordinates.
8
+ * Gemini returns [y_min, x_min] in 0-1000 scale.
9
+ * Source: appium-stark-vision/src/utils.ts:138-181
10
+ */
11
+ export declare function scaleCoordinates(coordinates: [number, number], screenSize: ScreenSize): BoundingBox;
12
+ /**
13
+ * Find the first substring enclosed in square brackets.
14
+ * Used to extract bounding box arrays from LLM responses.
15
+ * Source: appium-stark-vision/src/utils.ts:183-186
16
+ */
17
+ export declare function findSubstringWithBrackets(message: string): string | null;
18
+ /**
19
+ * Parse a bracket-enclosed string like "[320, 500]" into number array.
20
+ * Source: appium-stark-vision/src/utils.ts:188-194
21
+ */
22
+ export declare function sanitizeOutput(arrayAsString: string): number[];
23
+ /**
24
+ * Parse a string response from LLM into a JSON object.
25
+ * Handles escaped JSON, markdown code blocks, etc.
26
+ * Source: appium-stark-vision/src/utils.ts:251-283
27
+ */
28
+ export declare function parseStringToObject(str: string): any;
29
+ //# sourceMappingURL=coordinates.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coordinates.d.ts","sourceRoot":"","sources":["../../src/coordinates.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAElD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,WAAW,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAC7B,UAAU,EAAE,UAAU,GACrB,WAAW,CAkBb;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAGxE;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,EAAE,CAM9D;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CA+BpD"}
@@ -0,0 +1,92 @@
1
+ "use strict";
2
+ /**
3
+ * Coordinate scaling and parsing utilities.
4
+ * Adapted from appium-stark-vision/src/utils.ts
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.scaleCoordinates = scaleCoordinates;
8
+ exports.findSubstringWithBrackets = findSubstringWithBrackets;
9
+ exports.sanitizeOutput = sanitizeOutput;
10
+ exports.parseStringToObject = parseStringToObject;
11
+ /**
12
+ * Scale normalized coordinates (0-1000) to device pixel coordinates.
13
+ * Gemini returns [y_min, x_min] in 0-1000 scale.
14
+ * Source: appium-stark-vision/src/utils.ts:138-181
15
+ */
16
+ function scaleCoordinates(coordinates, screenSize) {
17
+ const { width, height } = screenSize;
18
+ const [y_min, x_min] = coordinates;
19
+ const sy = (value) => (value * height) / 1000;
20
+ const sx = (value) => (value * width) / 1000;
21
+ return {
22
+ corners: {
23
+ min: { x: sx(x_min), y: sy(y_min) },
24
+ max: { x: sx(x_min), y: sy(y_min) },
25
+ },
26
+ center: {
27
+ x: sx(x_min),
28
+ y: sy(y_min),
29
+ },
30
+ container: { width, height },
31
+ };
32
+ }
33
+ /**
34
+ * Find the first substring enclosed in square brackets.
35
+ * Used to extract bounding box arrays from LLM responses.
36
+ * Source: appium-stark-vision/src/utils.ts:183-186
37
+ */
38
+ function findSubstringWithBrackets(message) {
39
+ const match = message.match(/\[.*?\]/);
40
+ return match ? match[0] : null;
41
+ }
42
+ /**
43
+ * Parse a bracket-enclosed string like "[320, 500]" into number array.
44
+ * Source: appium-stark-vision/src/utils.ts:188-194
45
+ */
46
+ function sanitizeOutput(arrayAsString) {
47
+ return arrayAsString
48
+ .slice(1, -1)
49
+ .trim()
50
+ .split(/[\s,]+/)
51
+ .map(Number);
52
+ }
53
+ /**
54
+ * Parse a string response from LLM into a JSON object.
55
+ * Handles escaped JSON, markdown code blocks, etc.
56
+ * Source: appium-stark-vision/src/utils.ts:251-283
57
+ */
58
+ function parseStringToObject(str) {
59
+ // Strip markdown code block wrappers
60
+ const cleaned = str
61
+ .trim()
62
+ .replace(/(^```json\s*|```\s*$)/g, '')
63
+ .trim();
64
+ try {
65
+ return JSON.parse(cleaned);
66
+ }
67
+ catch {
68
+ try {
69
+ // Handle escaped JSON string
70
+ const unescaped = JSON.parse(cleaned);
71
+ if (typeof unescaped === 'string') {
72
+ return JSON.parse(unescaped);
73
+ }
74
+ return unescaped;
75
+ }
76
+ catch {
77
+ try {
78
+ // Handle escaped characters
79
+ const furtherCleaned = cleaned
80
+ .replace(/\\n/g, '\n')
81
+ .replace(/\\"/g, '"')
82
+ .replace(/\\'/g, "'")
83
+ .replace(/\\\\/g, '\\');
84
+ return JSON.parse(furtherCleaned);
85
+ }
86
+ catch {
87
+ throw new Error('Failed to parse LLM response as JSON');
88
+ }
89
+ }
90
+ }
91
+ }
92
+ //# sourceMappingURL=coordinates.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coordinates.js","sourceRoot":"","sources":["../../src/coordinates.ts"],"names":[],"mappings":";AAAA;;;GAGG;;AASH,4CAqBC;AAOD,8DAGC;AAMD,wCAMC;AAOD,kDA+BC;AAtFD;;;;GAIG;AACH,SAAgB,gBAAgB,CAC9B,WAA6B,EAC7B,UAAsB;IAEtB,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,UAAU,CAAC;IACrC,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,WAAW,CAAC;IAEnC,MAAM,EAAE,GAAG,CAAC,KAAa,EAAE,EAAE,CAAC,CAAC,KAAK,GAAG,MAAM,CAAC,GAAG,IAAI,CAAC;IACtD,MAAM,EAAE,GAAG,CAAC,KAAa,EAAE,EAAE,CAAC,CAAC,KAAK,GAAG,KAAK,CAAC,GAAG,IAAI,CAAC;IAErD,OAAO;QACL,OAAO,EAAE;YACP,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE;YACnC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE;SACpC;QACD,MAAM,EAAE;YACN,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC;YACZ,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC;SACb;QACD,SAAS,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE;KAC7B,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,SAAgB,yBAAyB,CAAC,OAAe;IACvD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IACvC,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AACjC,CAAC;AAED;;;GAGG;AACH,SAAgB,cAAc,CAAC,aAAqB;IAClD,OAAO,aAAa;SACjB,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;SACZ,IAAI,EAAE;SACN,KAAK,CAAC,QAAQ,CAAC;SACf,GAAG,CAAC,MAAM,CAAC,CAAC;AACjB,CAAC;AAED;;;;GAIG;AACH,SAAgB,mBAAmB,CAAC,GAAW;IAC7C,qCAAqC;IACrC,MAAM,OAAO,GAAG,GAAG;SAChB,IAAI,EAAE;SACN,OAAO,CAAC,wBAAwB,EAAE,EAAE,CAAC;SACrC,IAAI,EAAE,CAAC;IAEV,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC7B,CAAC;IAAC,MAAM,CAAC;QACP,IAAI,CAAC;YACH,6BAA6B;YAC7B,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YACtC,IAAI,OAAO,SAAS,KAAK,QAAQ,EAAE,CAAC;gBAClC,OAAO,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;YAC/B,CAAC;YACD,OAAO,SAAS,CAAC;QACnB,CAAC;QAAC,MAAM,CAAC;YACP,IAAI,CAAC;gBACH,4BAA4B;gBAC5B,MAAM,cAAc,GAAG,OAAO;qBAC3B,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC;qBACrB,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;qBACpB,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;qBACpB,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;gBAC1B,OAAO,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;YACpC,CAAC;YAAC,MAAM,CAAC;gBACP,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;YAC1D,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Gemini API client for stark-vision.
3
+ * Adapted from appium-stark-vision/src/llm/Gemini.ts
4
+ * Stripped: Langfuse tracing, LangfuseMedia, Zod schemas, plugin references.
5
+ */
6
+ import { StarkVisionConfig } from './types';
7
+ export declare class StarkVisionClient {
8
+ private ai;
9
+ private model;
10
+ private disableThinking;
11
+ private localClient;
12
+ private onTokenUsage;
13
+ constructor(config: StarkVisionConfig);
14
+ /** Extract and emit token usage from a Gemini response's usageMetadata. */
15
+ private emitUsage;
16
+ /**
17
+ * Core Gemini call with retry logic.
18
+ * Adapted from appium-stark-vision/src/llm/Gemini.ts:21-164
19
+ */
20
+ private createMessage;
21
+ /**
22
+ * Combined instruction + vision: parse instruction and locate element coordinates.
23
+ * Returns raw JSON string from Gemini.
24
+ * Adapted from appium-stark-vision/src/llm/Gemini.ts:251-277
25
+ */
26
+ private static detectMimeType;
27
+ understandAndLocate(instruction: string, imageBase64: string): Promise<string>;
28
+ /**
29
+ * Check if an element is visible on the screenshot.
30
+ * Adapted from appium-stark-vision/src/llm/Gemini.ts:166-211
31
+ */
32
+ isElementVisible(imageBase64: string, instruction: string, withExplanation?: boolean): Promise<string>;
33
+ /**
34
+ * Get bounding box coordinates for a specific element.
35
+ * Adapted from appium-stark-vision/src/services/BoundingBoxService.ts:142-204
36
+ */
37
+ getBoundingBox(locator: string, imageBase64: string): Promise<string>;
38
+ /**
39
+ * Get element information / answer a question about the screen.
40
+ * Adapted from appium-stark-vision/src/llm/Gemini.ts:279-309
41
+ */
42
+ getElementInfo(imageBase64: string, instruction: string, withExplanation?: boolean): Promise<string>;
43
+ /**
44
+ * Find back navigation element on the screen.
45
+ * Adapted from appium-stark-vision/src/llm/Gemini.ts:311-332
46
+ */
47
+ findBackNavigation(imageBase64: string): Promise<string>;
48
+ /**
49
+ * Generate test code from execution history.
50
+ * Text-only Gemini call (no image).
51
+ */
52
+ generateCode(systemPrompt: string, userPrompt: string): Promise<string>;
53
+ }
54
+ //# sourceMappingURL=geminiClient.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"geminiClient.d.ts","sourceRoot":"","sources":["../../src/geminiClient.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAeH,OAAO,EAAE,iBAAiB,EAAoB,MAAM,SAAS,CAAC;AAE9D,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,EAAE,CAAc;IACxB,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,eAAe,CAAU;IACjC,OAAO,CAAC,WAAW,CAAmC;IACtD,OAAO,CAAC,YAAY,CAAkD;gBAE1D,MAAM,EAAE,iBAAiB;IAerC,2EAA2E;IAC3E,OAAO,CAAC,SAAS;IAWjB;;;OAGG;YACW,aAAa;IA8D3B;;;;OAIG;IACH,OAAO,CAAC,MAAM,CAAC,cAAc;IAIvB,mBAAmB,CAAC,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAyBpF;;;OAGG;IACG,gBAAgB,CACpB,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,EACnB,eAAe,UAAQ,GACtB,OAAO,CAAC,MAAM,CAAC;IA8BlB;;;OAGG;IACG,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAoD3E;;;OAGG;IACG,cAAc,CAClB,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,EACnB,eAAe,UAAQ,GACtB,OAAO,CAAC,MAAM,CAAC;IA0BlB;;;OAGG;IACG,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAmB9D;;;OAGG;IACG,YAAY,CAAC,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAc9E"}
@@ -0,0 +1,268 @@
1
+ "use strict";
2
+ /**
3
+ * Gemini API client for stark-vision.
4
+ * Adapted from appium-stark-vision/src/llm/Gemini.ts
5
+ * Stripped: Langfuse tracing, LangfuseMedia, Zod schemas, plugin references.
6
+ */
7
+ var __importDefault = (this && this.__importDefault) || function (mod) {
8
+ return (mod && mod.__esModule) ? mod : { "default": mod };
9
+ };
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.StarkVisionClient = void 0;
12
+ const genai_1 = require("@google/genai");
13
+ const async_retry_1 = __importDefault(require("async-retry"));
14
+ const openaiCompatClient_1 = require("./openaiCompatClient");
15
+ const prompts_1 = require("./prompts");
16
+ class StarkVisionClient {
17
+ constructor(config) {
18
+ this.localClient = null;
19
+ this.ai = new genai_1.GoogleGenAI({ apiKey: config.apiKey });
20
+ this.model = config.model;
21
+ this.disableThinking = config.disableThinking ?? false;
22
+ this.onTokenUsage = config.onTokenUsage;
23
+ if (config.baseUrl) {
24
+ this.localClient = new openaiCompatClient_1.OpenAICompatClient(config.baseUrl, config.model, config.apiKey, config.coordinateOrder ?? 'yx');
25
+ }
26
+ }
27
+ /** Extract and emit token usage from a Gemini response's usageMetadata. */
28
+ emitUsage(usageMetadata) {
29
+ if (!this.onTokenUsage || !usageMetadata)
30
+ return;
31
+ this.onTokenUsage({
32
+ inputTokens: usageMetadata.promptTokenCount ?? 0,
33
+ outputTokens: usageMetadata.candidatesTokenCount ?? 0,
34
+ totalTokens: usageMetadata.totalTokenCount ?? 0,
35
+ cachedTokens: usageMetadata.cachedContentTokenCount || undefined,
36
+ thoughtsTokens: usageMetadata.thoughtsTokenCount || undefined,
37
+ });
38
+ }
39
+ /**
40
+ * Core Gemini call with retry logic.
41
+ * Adapted from appium-stark-vision/src/llm/Gemini.ts:21-164
42
+ */
43
+ async createMessage(params) {
44
+ if (this.localClient) {
45
+ return this.localClient.createMessage(params);
46
+ }
47
+ const { system, contents, temperature = 0, maxTokens = 3000, responseMimeType = 'text/plain', } = params;
48
+ const response = await (0, async_retry_1.default)(async (bail) => {
49
+ try {
50
+ const config = {
51
+ ...(this.disableThinking
52
+ ? { thinkingConfig: { thinkingBudget: 0 } }
53
+ : { thinkingConfig: { thinkingLevel: genai_1.ThinkingLevel.MINIMAL } }),
54
+ temperature,
55
+ maxOutputTokens: maxTokens,
56
+ responseMimeType,
57
+ };
58
+ const result = await this.ai.models.generateContent({
59
+ model: this.model,
60
+ config: {
61
+ ...config,
62
+ ...(system ? { systemInstruction: system } : {}),
63
+ },
64
+ contents,
65
+ });
66
+ return result;
67
+ }
68
+ catch (error) {
69
+ if (error.status === 400 || error.status === 401) {
70
+ bail(error);
71
+ return;
72
+ }
73
+ throw error;
74
+ }
75
+ }, {
76
+ retries: 3,
77
+ factor: 1,
78
+ minTimeout: 1000,
79
+ randomize: true,
80
+ });
81
+ this.emitUsage(response?.usageMetadata);
82
+ return response?.candidates?.[0]?.content?.parts?.[0]?.text || '';
83
+ }
84
+ /**
85
+ * Combined instruction + vision: parse instruction and locate element coordinates.
86
+ * Returns raw JSON string from Gemini.
87
+ * Adapted from appium-stark-vision/src/llm/Gemini.ts:251-277
88
+ */
89
+ static detectMimeType(base64) {
90
+ return base64.startsWith('/9j/') ? 'image/jpeg' : 'image/png';
91
+ }
92
+ async understandAndLocate(instruction, imageBase64) {
93
+ return this.createMessage({
94
+ system: prompts_1.combinedInstructionPrompt,
95
+ contents: [
96
+ {
97
+ role: 'user',
98
+ parts: [
99
+ {
100
+ inlineData: {
101
+ data: imageBase64,
102
+ mimeType: StarkVisionClient.detectMimeType(imageBase64),
103
+ },
104
+ },
105
+ {
106
+ text: instruction,
107
+ },
108
+ ],
109
+ },
110
+ ],
111
+ temperature: 0.1,
112
+ maxTokens: 1024,
113
+ responseMimeType: 'application/json',
114
+ });
115
+ }
116
+ /**
117
+ * Check if an element is visible on the screenshot.
118
+ * Adapted from appium-stark-vision/src/llm/Gemini.ts:166-211
119
+ */
120
+ async isElementVisible(imageBase64, instruction, withExplanation = false) {
121
+ const visibleCheckPrompt = withExplanation
122
+ ? prompts_1.elementVisibilityWithExplanationPrompt
123
+ : prompts_1.elementVisibilityPrompt;
124
+ const prompt = `${visibleCheckPrompt} Can you see ${instruction} completely visible in the image?`;
125
+ return this.createMessage({
126
+ system: '',
127
+ contents: [
128
+ {
129
+ role: 'user',
130
+ parts: [
131
+ {
132
+ inlineData: {
133
+ data: imageBase64,
134
+ mimeType: StarkVisionClient.detectMimeType(imageBase64),
135
+ },
136
+ },
137
+ {
138
+ text: prompt,
139
+ },
140
+ ],
141
+ },
142
+ ],
143
+ temperature: 0,
144
+ maxTokens: 512,
145
+ responseMimeType: 'application/json',
146
+ });
147
+ }
148
+ /**
149
+ * Get bounding box coordinates for a specific element.
150
+ * Adapted from appium-stark-vision/src/services/BoundingBoxService.ts:142-204
151
+ */
152
+ async getBoundingBox(locator, imageBase64) {
153
+ const content = prompts_1.bboxPrompt.replace('${locator}', locator);
154
+ const promptConfig = [
155
+ { text: content },
156
+ {
157
+ inlineData: { mimeType: StarkVisionClient.detectMimeType(imageBase64), data: imageBase64 },
158
+ },
159
+ ];
160
+ const contents = [
161
+ { role: 'model', parts: [{ text: content }] },
162
+ { role: 'user', parts: promptConfig },
163
+ ];
164
+ if (this.localClient) {
165
+ return this.localClient.createMessage({
166
+ system: '',
167
+ contents,
168
+ temperature: 0.1,
169
+ responseMimeType: 'text/plain',
170
+ });
171
+ }
172
+ const response = await (0, async_retry_1.default)(async () => {
173
+ try {
174
+ const result = await this.ai.models.generateContent({
175
+ model: this.model,
176
+ contents,
177
+ config: {
178
+ temperature: 0.1,
179
+ responseMimeType: 'text/plain',
180
+ ...(this.disableThinking
181
+ ? { thinkingConfig: { thinkingBudget: 0 } }
182
+ : { thinkingConfig: { thinkingLevel: genai_1.ThinkingLevel.MINIMAL } }),
183
+ },
184
+ });
185
+ return result;
186
+ }
187
+ catch {
188
+ return null;
189
+ }
190
+ }, {
191
+ retries: 3,
192
+ factor: 1,
193
+ minTimeout: 1000,
194
+ });
195
+ this.emitUsage(response?.usageMetadata);
196
+ return response?.candidates?.[0]?.content?.parts?.[0]?.text || '';
197
+ }
198
+ /**
199
+ * Get element information / answer a question about the screen.
200
+ * Adapted from appium-stark-vision/src/llm/Gemini.ts:279-309
201
+ */
202
+ async getElementInfo(imageBase64, instruction, withExplanation = false) {
203
+ const infoPrompt = withExplanation ? prompts_1.getInformationWithExplanationPrompt : prompts_1.getInformationPrompt;
204
+ return this.createMessage({
205
+ system: infoPrompt,
206
+ contents: [
207
+ {
208
+ role: 'user',
209
+ parts: [
210
+ {
211
+ inlineData: {
212
+ data: imageBase64,
213
+ mimeType: StarkVisionClient.detectMimeType(imageBase64),
214
+ },
215
+ },
216
+ {
217
+ text: instruction,
218
+ },
219
+ ],
220
+ },
221
+ ],
222
+ maxTokens: 512,
223
+ responseMimeType: 'application/json',
224
+ });
225
+ }
226
+ /**
227
+ * Find back navigation element on the screen.
228
+ * Adapted from appium-stark-vision/src/llm/Gemini.ts:311-332
229
+ */
230
+ async findBackNavigation(imageBase64) {
231
+ return this.createMessage({
232
+ system: prompts_1.backNavigationPrompt,
233
+ contents: [
234
+ {
235
+ role: 'user',
236
+ parts: [
237
+ {
238
+ inlineData: {
239
+ data: imageBase64,
240
+ mimeType: StarkVisionClient.detectMimeType(imageBase64),
241
+ },
242
+ },
243
+ ],
244
+ },
245
+ ],
246
+ });
247
+ }
248
+ /**
249
+ * Generate test code from execution history.
250
+ * Text-only Gemini call (no image).
251
+ */
252
+ async generateCode(systemPrompt, userPrompt) {
253
+ return this.createMessage({
254
+ system: systemPrompt,
255
+ contents: [
256
+ {
257
+ role: 'user',
258
+ parts: [{ text: userPrompt }],
259
+ },
260
+ ],
261
+ temperature: 0,
262
+ maxTokens: 8192,
263
+ responseMimeType: 'text/plain',
264
+ });
265
+ }
266
+ }
267
+ exports.StarkVisionClient = StarkVisionClient;
268
+ //# sourceMappingURL=geminiClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"geminiClient.js","sourceRoot":"","sources":["../../src/geminiClient.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ export declare const combinedInstructionPrompt: string;
2
+ export declare const elementVisibilityPrompt: string;
3
+ export declare const elementVisibilityWithExplanationPrompt: string;
4
+ export declare const bboxPrompt: string;
5
+ export declare const backNavigationPrompt: string;
6
+ export declare const getInformationWithExplanationPrompt: string;
7
+ export declare const getInformationPrompt: string;
8
+ export declare const createWDIOTestPrompt: string;
9
+ export declare const createAppiumJavaTestPrompt: string;
10
+ //# sourceMappingURL=promptB64.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"promptB64.d.ts","sourceRoot":"","sources":["../../../src/generated/promptB64.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,yBAAyB,QAErC,CAAC;AACF,eAAO,MAAM,uBAAuB,QAEnC,CAAC;AACF,eAAO,MAAM,sCAAsC,QAElD,CAAC;AACF,eAAO,MAAM,UAAU,QAEtB,CAAC;AACF,eAAO,MAAM,oBAAoB,QAEhC,CAAC;AACF,eAAO,MAAM,mCAAmC,QAE/C,CAAC;AACF,eAAO,MAAM,oBAAoB,QAEhC,CAAC;AACF,eAAO,MAAM,oBAAoB,QAEhC,CAAC;AACF,eAAO,MAAM,0BAA0B,QAEtC,CAAC"}
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createAppiumJavaTestPrompt = exports.createWDIOTestPrompt = exports.getInformationPrompt = exports.getInformationWithExplanationPrompt = exports.backNavigationPrompt = exports.bboxPrompt = exports.elementVisibilityWithExplanationPrompt = exports.elementVisibilityPrompt = exports.combinedInstructionPrompt = void 0;
4
+ /** Auto-generated by scripts/generate-prompt-b64.cjs from src/prompts.raw.ts — do not edit. */
5
+ const promptCodec_1 = require("../promptCodec");
6
+ exports.combinedInstructionPrompt = (0, promptCodec_1.decodeVisionPrompt)('H4sIAAAAAAAAA51Y3W7bRha+11Mc8CY2lmYkZ4tm1e0GiqG02lWkwnKaGIaxOCSPxKmHM9yZoWS2KNCrFnu76CMs9sHyJIszQ8qU7N0AuYltcnh+v/Odb3Kta0BDsBFbUoBgM0OkbKEd6DUglDoVkgCrClDlgAqEss7UmRNaJTDLSTmxbsAVBOgf+nNSZ+jIP303A5JUknKglX/y4COBS3K1UZBpbXKh0JEFtHDT/L0UKoZ7/nELQoHSpkQpfqQchmej4XAINkNJUGmhnFAbcNrb7lxdTBdX08tkMLicTlbLxWzxDXx3ubyYrlbw8ZffQShHRqEErWSTwETusLFApXCAkOmykuQI/rpaLkCnP1DmwNAGTS7JWi7MrhBZAalBlRWwFoZsAlcFQRRqEMFakMxBWJjM30+uV5CTEVvKYW106QPtlRG2ZFI4iTIpsrsohshhxT+Ig+RfpFYbqAxZy39tyYh1E8VALktOfbnL2jpYTL+fXkJKQGXlGtAGVC1lAkslQ398U7R5ZiHq1TvyFqISXVasMm0ogpwqUnnXrq2wIhVSuAaygrI7SEnqXTIYrBxVMErgu8nlanqcVALTe2cwc31ohEQ//vqvfaFC/HzEodmQ2zcwnGpDtje3SfsiOk1gmmwSCOXiIC2hyQoQGReeP2u97Qvamo76B7v4zxP4fraavZ7NZ1fXcPHt9OJvHiEcUqmtA1FW2jhUDqyjKoGJvRtDNLP+xPTD5OJqHzM/qS0ZyMlmRqSUcyg1StmEKkouEbhC2N4QvIpgUlVtjyyWBNahytHk0OgadrqWOZtliKOyOzJ7938Omf3Fg4MjEP0JexX5TBqyHgw6GZxBNL3HzEVQEqpgQwpHBuU+iX3sMSjNRdMluYJHzIpSSDQBMP7drsBe1pXRKaay8cZdxO5mmVY2wNMDDNIG3rxbXFzNlotg/wd+lzaQErvg1tgEJrAhNP4vnqHF8oqp6aF7fMKKjTqrK0hr5/rHpN4I1T71Iax9GTNUgMaJrJbMTJPFNRhCyxjXkOs6db5Y0Y6kjDknQ88sKN13y1bDK5itfESOuceGl4rQpM3HX/4T7QHUtsvH1gHuRQLTt7MrTy6BNGyBFfEhDDTU4eArz0790YUtyposZAWqDY1DdtbDGL6G6+nKwz/QWJiBP+w/3QlXcMrykGyZPfajD388Gw2TI7OLJTyY5WBWk7fTB/t46KFv/GYYw/D22EdKbkekYORfvAg1aM3tadM6ISVUuvLtannThzT6ChRtyUAqUd2BcKBrlwwG74smTFaJzpGxYzB+tzCs+kGttfFZ7Ayzaof6DGtLofSOrPPrBKveQT8CcUv8wsIaDey04bEsUPV8haQZoW36hmyllSWQ5IKHDKUkA7Y2a8yIN44kVBB1wfBcrHWt8gjIGK5swUu4rQmPutn6nfdQuEwrR/f7hcpvUbWboD2SGsK7gwB4dxuSjcdrrr3fXPsqJoPB9B55D/p914Ih4JmNL5Zw4sEUjMfwIxndr/OpR2dvyf0PvmbBAFuRk4ZKYsNl8eQFttA79uRnIEPrYsiwYlM29sjZU4R9kvQfAzHuo3CUHMfH/e6TRxtbG44Ht48FIVqJjYK6ijry6fvn5Q0n2nSRnH4ylPNHoTwsfEgxuwM0Ru+iEIPSvWf7tdKP4EAufLoMg4n/zo7BB8zrsorBkqTMxeBFSAyuqYgfqpz/5V5IQhNDTqyUYgiiJGaCEjnyE68VYtihcDE8hBRDXcWQ652KQdLaxWDEpnCxTyqGQpcUg8RaZUUM1mk+TFRJoe5iyA1uBm+0x4iW8rndicovH4jqKnoesdnoecR2o+eRNxyxnsRWkvCnvdr6D3vVSpj3lA71iduZhpvbZLCsXVWzAjAic7Lx5M37i7UijyyaJhkM5i0RmlqSZfzv5aCnJZXz28aD95DtH4vBfivaFgS5x6Ma+M8Pd9z+wVIvPhKpT4o3XbtMl+S1QCep4O271VVHLARv3s3nrQzw8wZCZbLOha+TvhclWzuhIMKMtvv9d+9585umZJl6zteFPO+G6XRwdojFQ4mfale0yj4+EPVByHM6bbQH2ykQEuWwWB5C3WeU0p6NF75KQm092ffXAS8WBFun1glXu/0V4om9FAg4Q2NEuytY9zyzvmft2jxuZ6gdWai0FfwEJfyjRinWgoyFE4/wVDuny6OBUH7A2qqesoR7qL6hNRlSGdmuEV31P3Dt+dPwW0pW5AQfmIYm8zlUaNweHMydzqBQLki0lHWHE3YtKE+6ZPiKo82DLg/uPkSnjGHeGB0FMbN7royhXbGt7m7Pddq0ooyTzxmtfnU4Q+j2HWWt5EfEPL4ahm4ydPvXlZPR2Wh4OoZC72A+u5peTubz60eN4PUYJrvtXRd3l5nElGQCrUhBS/4GJOleZCif+89bBcwdWC7m193eZOFpw2eNv1oyekZfP/JuCzTkReVOm9wGPj9w35VXAJaw0UJtIthaiN570ckXdday/sUrbulo+NhLJrXlpd7leuiAoYpOlJ2nw43Hvub8hLHT7umUJT+/WD38zdN8sVysZqur6eLiGi7fzafj/l75+M9/wwv4+NvvT/TPTxYLp50Oc4obQ8SKSepd38jTkpWp0+sdf7vcCi0xsPtTOrJWuF5TxhIybYAEq/eethkPbn4Kn4y767aX2ONoRXdoori7gI5vfmrrOI546BXf07yXKO4FN755cT6MvxgOb+OHPMZ/+vn259uep1aiBE+euZ9y4/la1+7IwcsvHjt4eeSg+y+CNpfXr1/3M/mcYDosBL3TkU1Hgb4aQvGK9BBM9f0TZfny5WHUXx5F3dctnwinMnrNkliUuKEjV+dPFOjzOtAXqoc+hvGh/dFn2T+Yvf/v4Jwd/Bezer3qrRMAAA==');
7
+ exports.elementVisibilityPrompt = (0, promptCodec_1.decodeVisionPrompt)('H4sIAAAAAAAAA31Ty27cMAy8+yuIXNoChnNPTw0aoCnQpOiihxxpi14zK4uuSG3WKAr0I/qF/ZJC8jq7faBHkdRoZjiqHiQBRoIpyp4dOXhiGwAD8IhbAgwOEL4kUmMJTfUgKYKh7oAVTIAdBeN+Bu7BBjreGlDLqU/eA3kaKdgCTAfsDEa0bijYQWDCaIx+KZI21QfcEWiKVDCSUgTUHblnJFYIYiB7ih6n6URabKC4jjXV7cLp7NqelVtPwEHZESA4Ri9bkAiTTGmqQcmgk+A4692gsfZMLku1mAh+fv+x4umKsoIuWFrs7KT0Irm13VT3wc//we/RK60+nnEe2DkKcH3z7vbu7YnyS26oqX8bpgOrKUgoVe0iUYA2FRRptUuR3OWZa+185kAAkwmkB7ZXxbqAxnuCUVo+ibssNl2O4tBDRsFY9sj53R5sngi8dJjVwURxZNUcnE9kKS68ZCrNfvH88/Smy+frZCYhxwYNniR5B+0SgJbUoGdrbrdBjqFYFl1Y6POeOajFVNBKAjHMOdaHkW0GzzuCQBhriLwdrAZPvdVZdA2tmMkIXmRXeJ2b2qKSO3qqdALMqtUid+Zn6MV7efqThTbVZp1wUhY0eeSQmdnAYQvYSrLTxylS2MAJ6bpPGH/7DpF0kpCDovCY1KAV8YQBUJcENbAx7nY5US1lUpJsSpZ1jWjNi9fVzWGizrKopYMK7zf3dyDtI3VWfa3+EdCr9Z26Ap3VaPyYd3de/nuZV3CRHQrbi7oq0bjvj7fWevWt+gUnEZ8GggQAAA==');
8
+ exports.elementVisibilityWithExplanationPrompt = (0, promptCodec_1.decodeVisionPrompt)('H4sIAAAAAAAAA31SzW7UMBC+5ylGvQBSlN4LQgJRiSLRIioOPU7iye50HY/xjLe7Qkg8BE/IkyA7m+4WEEd7PJ+/v+ZOMmAiiEm27MjBA9saMABPuCLA4ADhayY1ltA1d5ITGOoGWMEE2FEwHvfAI9iaDltr1Hoas/dAniYKNgPTDgeDCW1YV+wgEDEZo58vSbvmI24INCeqGFkpAeqG3CMSKwQxkC0ljzEeSYutKS3PuuZq5nSytmXl3hNwUHYECI7RywokQZSYYwtKBoMEx0XvLRrryOSKVEuZ4NePnwueLigL6Iyl1c5B6iyRW8ZdcxP8/j/4I3qlxccTzmt2jgK8vXx/df3uSPk5d9S1Tx7TjtUUJNRbHRJRgD5XFOl1yInc+Ylr/f7EgQAmEWQEthfVuoDGW4JJej6KO682nU/i0ENBwVRz5PLvCLaPBF4GLOogUppYtRTnM1lOMy+JdTjOnn+Jb4ZyfpvNJJTaoMGDZO+gnwvQkxqMbN3VKsihFHPQlYU+5sxBLeWKVhuIYV9qvZvY9uB5QxAIUwuJV2trwdNobRHdQi9mMoEX2VRep6b2qOQOniodAYtqtcSD+T2M4r08/MlCCzM2cEK6xAPTk3Yn0iih5K5wn9WgF/GEAVDnQnTPXjaXu0iDFRbZYrYy+3B7cw3S39NgzbfmH426WJDaBmgXPYaayQW8Ojm9bhvQvRpNn0oSpzt/R3MBZ0VvWJ21DdSkb8bD2jJovje/ATfufGJRBAAA');
9
+ exports.bboxPrompt = (0, promptCodec_1.decodeVisionPrompt)('H4sIAAAAAAAAA2WOwWrDQAxE7/6KOfTomv5F6KEtlEIPIQQlq8RL15LRalMvIf9ess6tIBCaYfTmeyRHzPCRcdAiIcoZB11wUmvi0zXpkVztNnRv9MPIxbg5R31WC1HIOYOMIerQC1uieeaA3+gjSCqEycCJJxbPQ/d6avGHgKCc8f7xBV5idkRpbpzozD2MvZhg+9LjMTuQhDtqvDfllHnoNvHCmNZWWnwuDsogAZlRxbbupyg9lnXV/URLu2jZDfhcESqptgdr5h/kD7bnbQIpAQAA');
10
+ exports.backNavigationPrompt = (0, promptCodec_1.decodeVisionPrompt)('H4sIAAAAAAAAA42Sy24aQRBF9/0VV3hhCaGR7OzYGQVFXsRYESyyo2amYCo0Xa3uGh6K8u9RDwYUJYts+3VP3dPuu/agxIhJD9Jyi6NYBwqQPW0ZugFhr7V4BsXopSETDRNQaHHWPsEo7yAZppCWg8nmDApnsOc9B4MGWMfYyoGvj1pHBvJej3nY6zOncj/QQbZkjJqaXVkomzHxQbTPyE1iDpVz4zEWq+X7aonx2D1V6CjPL2FTzFQ9U8CBfM9IHBPnAhW2OHZsXQnqODH4JNlyGfQKOlA1FFAPRC02mgaSI6X2yiYaKvdcXS9N8YJOtp0/o2Uj8dyi5dwkieVoqa/MsHq9pUgAIUvYeoaXwPfYjn2813Hr4t81TCCh8X1bBsuRG9lIk5H7pgNlGJ9sgqhZLrKkKRbOkQdtiT2ZHPh2oHLu9ev74tvy5W2Jt8VyPsVnRVD7CGGM1uv1j6xhVPgLjvYWe6uKi/mJ9tFzkfHwVLmfDn8YsdTzxOHe2GhW1AyKKSU9Xug+volphOeNodEUOI3cL+cenv9+dUM+87D56X8iv5TOUPdmGuCp5iLqcUbN7vGafBeMmhLIhtVazXRfMH4Dnksc2yoDAAA=');
11
+ exports.getInformationWithExplanationPrompt = (0, promptCodec_1.decodeVisionPrompt)('H4sIAAAAAAAAA72SMW/CMBCF9/sVJ7NFiKodo4itQzvAQDswmnDELuQusi+QCvHfqzgtUHWokKpuvif583vPB0tp0QbCyu+J0TL62laEltdp4KihLdULT/A1EqojNNQ1O8u2Vw2qgDrPW/SK6oK0lUu3t0RNr0VfNzsaJ00dMQaKjfAaD17dwLMcDxTMBB67hkqlNUqrTatoIz4v5jOU1RuVmhAsip4HOWrwXMERBkCOxXCYwpXDHIuraQonKKizvacpjO4nkGVP3L+1IFbikvIsQ7On4DfvSDuqifXTKnWKtlXBSFYxur62JlAkVgNZdjY/T+bzLIMjfGXL0SwpjlPe36k+nsFj+FZ3jublRgQK40pUpcbgK6dYSmAKKJvkJpaBiC+/8QNUCk8MnGD08I9lzeSGrvqd+IO+rjB9Z5dyUvzi7rw2H2Rypiw1AwAA');
12
+ exports.getInformationPrompt = (0, promptCodec_1.decodeVisionPrompt)('H4sIAAAAAAAAA7VSO0/DMBDe/StO6QIWagVsUVXEwFCEWqQuhM0xR2KUnCPfuQ2q+t+RE1Fg4LGw+fE97vNnVfgIJiBUbosEhsC1pkIw9DRsiCVEK87TVN03aBghoMRAcA1dQOt4xHK01pGAId5hAPEgNQL2EowVEOzlq9ZN36EVfAIfpYsChuF2s16BL1/QyiBJPnHGY5bgqJqqvRoNcpiPi4U6qDn2pu0aXKjJ+VRpvaSkuEESJIu51pBtMbjnV+hqTzhrkTlldNYTOAazNa4xZYOZ0vo42HoYLNda7VU2mmU5ZAXy2ZDtFy3g2u8cVSnZO+iheISdk/qDD2UsE3igexou2AZEytRBTS7+Pc7K/5QmVfBJ7qAml99MtOSx8AZbJIE7X/ko6YcwklzBSYE8W/nTP75wsprPjrW+AX8xYDmlAgAA');
13
+ exports.createWDIOTestPrompt = (0, promptCodec_1.decodeVisionPrompt)('H4sIAAAAAAAAA1WRT2vbQBDF7/oUj1xkg1CUtFCQcUFNDjU02CQpPYa1dhwNkXbU3Vk7xvi7F0kNOIeFZd78/b2k9mSUYKAUFCGyEnbioQ3hlfcE4705QnYISn2AcRZBPdfaHmHFpQpjLYw7gt771hllcTnuPyl/7ldr1NJ1Q/X4rE0Mz66eTQ9x4E0jjq7mH9o4fUutHFCLJaiMkY60ETvsIlH7qGAXeJAbgqVQ85awbaV+y5NaXFAYxhImHF2NGbugPtbDenMsv+OUAJ40egdzMKywnvfkc3qnOirN0j0HFldix87+OFarNBtrgItO2RiQfviHBDjPF8l5kVRtELCr22gJ1Qq76Mb08T4rbvEZmpmoTXC14QAOowlV33PsclT/kXj6G9mTHa5lT/Wd6c2WW1amqcA464Unxrx+yjFu0pk3Qoh+IjUZ3UhsLbaEg/g3dq857mSk6Se3JiaeOlGanZDn+RB+2VSP1cNThvpy8nm+mIomFcYTJgOqzWb1++Hl5/rpGUukN7ff8iIv8pt0kXxK2Kwfh4Sv326/fCgX47DEaYg6Gik+kvrjnUSnJYosaSSoMx2Vl9OypBev5WX/LOmNNiXS64O9buL2Os2SVl5/0Z7aEim7naRZMpy9E//MHUnUEjdFURRZ0kndmHWvocQp0Q/xdhLP2WD6P+3jD3JLAwAA');
14
+ exports.createAppiumJavaTestPrompt = (0, promptCodec_1.decodeVisionPrompt)('H4sIAAAAAAAAA51U32/iOBB+918x4gkkGlp6p5VYrbRZqLpIuw0iobo3ZJyBjNbxRP4B7Z72fz85pAV6vdPp8hLbM5/9fZ89I6YWpUeQ4NF5UFo6B1u24CuEHe3RgLRWPgNvwXlsHBzIVxw8SPMM+NRoaaQnNi6BosLjLq7ioEvAJ4+mhC/SYRGXpSkhOARJX1E3aBNJ/UF7WDoHxXUtTekSyIJvggc2+rllobhuNHo8ZxhJtMEta80HMjtw3gblg8WJEFQ3bD2w3SURZHaJNIZ9RzSS+ShEEzaaVLfhPRq00mPZMj0ydyfqfwoAgM9x3I467J6pbGnlCo20xP1Blxq/0Qha8NG34CLLC+1t5i/xS4ho3YVP6Xx6NOSYfmSJDqRFkNqiLJ/BoYfQtF5MxBWkTUOhnlnaowUy5Elq+tlqjtFXi6FGX3HpxFVL7+EezswRV5CjjTsoNlvaBduuTwRAuljMV9/XX7O8gE/Quxl/SK6T6+Smd4otsmWM/fZhfHtazO+Wj3fL9Wr5LcIq75vJaPSKnsTk0aEcVWHTEyI1pY2mKtnIDWnyhG4iVpQGz7X0bMdZ0xIF7v6fwOAB3sno/E0c+i5GbB5kjf3LaZI+zJbZfLZezdNVkX1Pi2w5PmFnuCeFLa7Xseudogst/ZZt/YjWEZt+72acXJ/FH/DQXWRBNXLw/VlnacLbHBWb0vVvrweDj0JQlr/R/cd0NY939L7mN9H/rHee5euIXRd3efG+UFpUbPBfdf7+v3Wme0labjTGR9k9xom4SS6Ko0fmWNHEpjeAq1gepM6esRifAfAJVfD4WjWX8CE4uceCp1JVOATUWKPxj+Roo3FaofoxhFo+5cqy1m4Irh3k9BPjwWm5l0ZheX727QXZe/Rzs+W/c75H/3IakIn+HctRvLSbU5d729z+sWmcdcoZg+G4s9KhxLYjO/ShAcVl1HnWnYfAFmRZUpxJ/dJPEvEXSDqHqwEGAAA=');
15
+ //# sourceMappingURL=promptB64.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"promptB64.js","sourceRoot":"","sources":["../../../src/generated/promptB64.ts"],"names":[],"mappings":";;;AAAA,+FAA+F;AAC/F,gDAAoD;AAEvC,QAAA,yBAAyB,GAAG,IAAA,gCAAkB,EACzD,s1FAAs1F,CACv1F,CAAC;AACW,QAAA,uBAAuB,GAAG,IAAA,gCAAkB,EACvD,8xBAA8xB,CAC/xB,CAAC;AACW,QAAA,sCAAsC,GAAG,IAAA,gCAAkB,EACtE,0vBAA0vB,CAC3vB,CAAC;AACW,QAAA,UAAU,GAAG,IAAA,gCAAkB,EAC1C,8RAA8R,CAC/R,CAAC;AACW,QAAA,oBAAoB,GAAG,IAAA,gCAAkB,EACpD,0mBAA0mB,CAC3mB,CAAC;AACW,QAAA,mCAAmC,GAAG,IAAA,gCAAkB,EACnE,kcAAkc,CACnc,CAAC;AACW,QAAA,oBAAoB,GAAG,IAAA,gCAAkB,EACpD,sbAAsb,CACvb,CAAC;AACW,QAAA,oBAAoB,GAAG,IAAA,gCAAkB,EACpD,srBAAsrB,CACvrB,CAAC;AACW,QAAA,0BAA0B,GAAG,IAAA,gCAAkB,EAC1D,k+BAAk+B,CACn+B,CAAC"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * df-vision (npm) — Device Farm packages/stark-vision
3
+ *
4
+ * AI-powered vision element detection for device-farm.
5
+ * Core logic extracted from appium-stark-vision, stripped of Appium/Prisma/Langfuse dependencies.
6
+ */
7
+ import { findSubstringWithBrackets, parseStringToObject, sanitizeOutput, scaleCoordinates } from './coordinates';
8
+ import { StarkVisionClient } from './geminiClient';
9
+ import { detectSimpleAction, parseInstruction } from './instructionParser';
10
+ export { StarkVisionClient } from './geminiClient';
11
+ export { parseInstruction, detectSimpleAction, SUPPORTED_ACTIONS } from './instructionParser';
12
+ export { scaleCoordinates, findSubstringWithBrackets, sanitizeOutput, parseStringToObject, } from './coordinates';
13
+ /** Prompt text lives in ./prompts (internal); not re-exported so npm typings do not publish prompt bodies. */
14
+ export type { StarkVisionAction, StarkVisionConfig, VisionTokenUsage, BoundingBox, ScreenSize, ExecutionConfig, ScrollSize, CommandType, VisibilityResult, } from './types';
15
+ export { DefaultExecutionConfig } from './types';
16
+ /** CJS `default` for consumers that use `import pkg from 'df-vision'` under ESM (e.g. AppClaw). */
17
+ declare const _default: {
18
+ StarkVisionClient: typeof StarkVisionClient;
19
+ parseInstruction: typeof parseInstruction;
20
+ detectSimpleAction: typeof detectSimpleAction;
21
+ SUPPORTED_ACTIONS: string[];
22
+ scaleCoordinates: typeof scaleCoordinates;
23
+ findSubstringWithBrackets: typeof findSubstringWithBrackets;
24
+ sanitizeOutput: typeof sanitizeOutput;
25
+ parseStringToObject: typeof parseStringToObject;
26
+ DefaultExecutionConfig: import("./types").ExecutionConfig;
27
+ };
28
+ export default _default;
29
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACL,yBAAyB,EACzB,mBAAmB,EACnB,cAAc,EACd,gBAAgB,EACjB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAqB,MAAM,qBAAqB,CAAC;AAG9F,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAC9F,OAAO,EACL,gBAAgB,EAChB,yBAAyB,EACzB,cAAc,EACd,mBAAmB,GACpB,MAAM,eAAe,CAAC;AACvB,8GAA8G;AAC9G,YAAY,EACV,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,WAAW,EACX,UAAU,EACV,eAAe,EACf,UAAU,EACV,WAAW,EACX,gBAAgB,GACjB,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAC;AAEjD,mGAAmG;;;;;;;;;;;;AACnG,wBAUE"}
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ /**
3
+ * df-vision (npm) — Device Farm packages/stark-vision
4
+ *
5
+ * AI-powered vision element detection for device-farm.
6
+ * Core logic extracted from appium-stark-vision, stripped of Appium/Prisma/Langfuse dependencies.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.DefaultExecutionConfig = exports.parseStringToObject = exports.sanitizeOutput = exports.findSubstringWithBrackets = exports.scaleCoordinates = exports.SUPPORTED_ACTIONS = exports.detectSimpleAction = exports.parseInstruction = exports.StarkVisionClient = void 0;
10
+ const coordinates_1 = require("./coordinates");
11
+ const geminiClient_1 = require("./geminiClient");
12
+ const instructionParser_1 = require("./instructionParser");
13
+ const types_1 = require("./types");
14
+ var geminiClient_2 = require("./geminiClient");
15
+ Object.defineProperty(exports, "StarkVisionClient", { enumerable: true, get: function () { return geminiClient_2.StarkVisionClient; } });
16
+ var instructionParser_2 = require("./instructionParser");
17
+ Object.defineProperty(exports, "parseInstruction", { enumerable: true, get: function () { return instructionParser_2.parseInstruction; } });
18
+ Object.defineProperty(exports, "detectSimpleAction", { enumerable: true, get: function () { return instructionParser_2.detectSimpleAction; } });
19
+ Object.defineProperty(exports, "SUPPORTED_ACTIONS", { enumerable: true, get: function () { return instructionParser_2.SUPPORTED_ACTIONS; } });
20
+ var coordinates_2 = require("./coordinates");
21
+ Object.defineProperty(exports, "scaleCoordinates", { enumerable: true, get: function () { return coordinates_2.scaleCoordinates; } });
22
+ Object.defineProperty(exports, "findSubstringWithBrackets", { enumerable: true, get: function () { return coordinates_2.findSubstringWithBrackets; } });
23
+ Object.defineProperty(exports, "sanitizeOutput", { enumerable: true, get: function () { return coordinates_2.sanitizeOutput; } });
24
+ Object.defineProperty(exports, "parseStringToObject", { enumerable: true, get: function () { return coordinates_2.parseStringToObject; } });
25
+ var types_2 = require("./types");
26
+ Object.defineProperty(exports, "DefaultExecutionConfig", { enumerable: true, get: function () { return types_2.DefaultExecutionConfig; } });
27
+ /** CJS `default` for consumers that use `import pkg from 'df-vision'` under ESM (e.g. AppClaw). */
28
+ exports.default = {
29
+ StarkVisionClient: geminiClient_1.StarkVisionClient,
30
+ parseInstruction: instructionParser_1.parseInstruction,
31
+ detectSimpleAction: instructionParser_1.detectSimpleAction,
32
+ SUPPORTED_ACTIONS: instructionParser_1.SUPPORTED_ACTIONS,
33
+ scaleCoordinates: coordinates_1.scaleCoordinates,
34
+ findSubstringWithBrackets: coordinates_1.findSubstringWithBrackets,
35
+ sanitizeOutput: coordinates_1.sanitizeOutput,
36
+ parseStringToObject: coordinates_1.parseStringToObject,
37
+ DefaultExecutionConfig: types_1.DefaultExecutionConfig,
38
+ };
39
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;AAEH,+CAKuB;AACvB,iDAAmD;AACnD,2DAA8F;AAC9F,mCAAiD;AAEjD,+CAAmD;AAA1C,iHAAA,iBAAiB,OAAA;AAC1B,yDAA8F;AAArF,qHAAA,gBAAgB,OAAA;AAAE,uHAAA,kBAAkB,OAAA;AAAE,sHAAA,iBAAiB,OAAA;AAChE,6CAKuB;AAJrB,+GAAA,gBAAgB,OAAA;AAChB,wHAAA,yBAAyB,OAAA;AACzB,6GAAA,cAAc,OAAA;AACd,kHAAA,mBAAmB,OAAA;AAcrB,iCAAiD;AAAxC,+GAAA,sBAAsB,OAAA;AAE/B,mGAAmG;AACnG,kBAAe;IACb,iBAAiB,EAAjB,gCAAiB;IACjB,gBAAgB,EAAhB,oCAAgB;IAChB,kBAAkB,EAAlB,sCAAkB;IAClB,iBAAiB,EAAjB,qCAAiB;IACjB,gBAAgB,EAAhB,8BAAgB;IAChB,yBAAyB,EAAzB,uCAAyB;IACzB,cAAc,EAAd,4BAAc;IACd,mBAAmB,EAAnB,iCAAmB;IACnB,sBAAsB,EAAtB,8BAAsB;CACvB,CAAC"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Instruction parsing — converts natural language to structured actions.
3
+ * Adapted from appium-stark-vision/src/llm.ts
4
+ */
5
+ import { StarkVisionClient } from './geminiClient';
6
+ import { StarkVisionAction } from './types';
7
+ /**
8
+ * Detect simple actions (scroll, back) without calling LLM.
9
+ * Returns null if instruction doesn't match any simple pattern.
10
+ * Source: appium-stark-vision/src/llm.ts:31-47
11
+ */
12
+ export declare function detectSimpleAction(instruction: string): StarkVisionAction | null;
13
+ /**
14
+ * Parse an instruction using Gemini vision + the combined instruction prompt.
15
+ * Takes a screenshot and instruction, returns structured actions with coordinates.
16
+ * Source: appium-stark-vision/src/llm.ts:55-151 (understandUserInstruction)
17
+ */
18
+ export declare function parseInstruction(client: StarkVisionClient, instruction: string, screenshotBase64: string): Promise<StarkVisionAction[]>;
19
+ /**
20
+ * Supported actions list.
21
+ * Source: appium-stark-vision/src/services/ActionService.ts:13-36
22
+ */
23
+ export declare const SUPPORTED_ACTIONS: string[];
24
+ //# sourceMappingURL=instructionParser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"instructionParser.d.ts","sourceRoot":"","sources":["../../src/instructionParser.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAyB5C;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,iBAAiB,GAAG,IAAI,CAoBhF;AAED;;;;GAIG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,iBAAiB,EACzB,WAAW,EAAE,MAAM,EACnB,gBAAgB,EAAE,MAAM,GACvB,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAsB9B;AAED;;;GAGG;AACH,eAAO,MAAM,iBAAiB,UAmC7B,CAAC"}
@@ -0,0 +1,119 @@
1
+ "use strict";
2
+ /**
3
+ * Instruction parsing — converts natural language to structured actions.
4
+ * Adapted from appium-stark-vision/src/llm.ts
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.SUPPORTED_ACTIONS = void 0;
8
+ exports.detectSimpleAction = detectSimpleAction;
9
+ exports.parseInstruction = parseInstruction;
10
+ const coordinates_1 = require("./coordinates");
11
+ /**
12
+ * Simple action patterns that bypass the LLM entirely.
13
+ * Source: appium-stark-vision/src/llm.ts:24-47
14
+ */
15
+ const SIMPLE_ACTION_PATTERNS = [
16
+ { pattern: /^(scroll|swipe|move|slide)\s*(up|upwards)$/i, action: 'up' },
17
+ { pattern: /^(scroll|swipe|move|slide)\s*(down|downwards)$/i, action: 'down' },
18
+ { pattern: /^(scroll|swipe|move|slide)\s*(left|leftwards)$/i, action: 'left' },
19
+ { pattern: /^(scroll|swipe|move|slide)\s*(right|rightwards)$/i, action: 'right' },
20
+ {
21
+ pattern: /^(scroll|swipe)\s*(up|down)\s*by\s*(\d+)%?$/i,
22
+ action: 'up',
23
+ valueExtractor: m => m[3],
24
+ },
25
+ { pattern: /^(go\s*)?back$/i, action: 'back' },
26
+ { pattern: /^(go\s*)?home$/i, action: 'home' },
27
+ { pattern: /^(navigate\s*)?home$/i, action: 'home' },
28
+ ];
29
+ /**
30
+ * Detect simple actions (scroll, back) without calling LLM.
31
+ * Returns null if instruction doesn't match any simple pattern.
32
+ * Source: appium-stark-vision/src/llm.ts:31-47
33
+ */
34
+ function detectSimpleAction(instruction) {
35
+ const trimmed = instruction.trim();
36
+ for (const { pattern, action, valueExtractor } of SIMPLE_ACTION_PATTERNS) {
37
+ const match = trimmed.match(pattern);
38
+ if (match) {
39
+ const directionMatch = match[2]?.toLowerCase();
40
+ const resolvedAction = action === 'up' && directionMatch === 'down'
41
+ ? 'down'
42
+ : action === 'down' && directionMatch === 'up'
43
+ ? 'up'
44
+ : action;
45
+ return {
46
+ action: resolvedAction,
47
+ value: valueExtractor ? valueExtractor(match) : null,
48
+ locators: [],
49
+ };
50
+ }
51
+ }
52
+ return null;
53
+ }
54
+ /**
55
+ * Parse an instruction using Gemini vision + the combined instruction prompt.
56
+ * Takes a screenshot and instruction, returns structured actions with coordinates.
57
+ * Source: appium-stark-vision/src/llm.ts:55-151 (understandUserInstruction)
58
+ */
59
+ async function parseInstruction(client, instruction, screenshotBase64) {
60
+ const response = await client.understandAndLocate(instruction, screenshotBase64);
61
+ const cleanedText = response.trim().replace(/(^```json|```$)/g, '');
62
+ const instructionParsed = (0, coordinates_1.parseStringToObject)(cleanedText);
63
+ const formattedInstruction = Array.isArray(instructionParsed)
64
+ ? instructionParsed
65
+ : [
66
+ {
67
+ action: instructionParsed.action,
68
+ value: instructionParsed.value,
69
+ locators: Array.isArray(instructionParsed.locators)
70
+ ? instructionParsed.locators
71
+ : [{ element: instructionParsed.locators?.element || '' }],
72
+ },
73
+ ];
74
+ if (formattedInstruction.length === 0) {
75
+ throw new Error(`Unable to find any actionable element for instruction: "${instruction}"`);
76
+ }
77
+ return formattedInstruction;
78
+ }
79
+ /**
80
+ * Supported actions list.
81
+ * Source: appium-stark-vision/src/services/ActionService.ts:13-36
82
+ */
83
+ exports.SUPPORTED_ACTIONS = [
84
+ 'back',
85
+ 'up',
86
+ 'down',
87
+ 'left',
88
+ 'right',
89
+ 'tap',
90
+ 'click',
91
+ 'touch',
92
+ 'select',
93
+ 'long press',
94
+ 'longpress',
95
+ 'enter',
96
+ 'type',
97
+ 'send',
98
+ 'sendkeys',
99
+ 'set',
100
+ 'set value',
101
+ 'clear',
102
+ 'delete',
103
+ 'remove',
104
+ 'drag',
105
+ 'verify',
106
+ 'validate',
107
+ 'wait',
108
+ 'check',
109
+ 'home',
110
+ 'launch',
111
+ 'launch app',
112
+ 'open app',
113
+ 'stop',
114
+ 'stop app',
115
+ 'terminate',
116
+ 'deeplink',
117
+ 'open url',
118
+ ];
119
+ //# sourceMappingURL=instructionParser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"instructionParser.js","sourceRoot":"","sources":["../../src/instructionParser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * OpenAI-compatible API client for local LLM servers (LM Studio, Ollama, etc.).
3
+ * Uses raw fetch — no extra dependencies.
4
+ */
5
+ interface OpenAICompatRequestParams {
6
+ system: string;
7
+ contents: Array<{
8
+ role: string;
9
+ parts: Array<any>;
10
+ }>;
11
+ temperature?: number;
12
+ maxTokens?: number;
13
+ responseMimeType?: string;
14
+ }
15
+ export declare class OpenAICompatClient {
16
+ private baseUrl;
17
+ private model;
18
+ private apiKey;
19
+ private coordinateOrder;
20
+ constructor(baseUrl: string, model: string, apiKey: string, coordinateOrder?: 'yx' | 'xy');
21
+ /**
22
+ * Convert Google GenAI content format to OpenAI chat messages.
23
+ */
24
+ private convertToMessages;
25
+ createMessage(params: OpenAICompatRequestParams): Promise<string>;
26
+ }
27
+ export {};
28
+ //# sourceMappingURL=openaiCompatClient.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openaiCompatClient.d.ts","sourceRoot":"","sources":["../../src/openaiCompatClient.ts"],"names":[],"mappings":"AAAA;;;GAGG;AASH,UAAU,yBAAyB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAA;KAAE,CAAC,CAAC;IACrD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAuBD,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,eAAe,CAAc;gBAEzB,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,GAAE,IAAI,GAAG,IAAW;IAO/F;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAgCnB,aAAa,CAAC,MAAM,EAAE,yBAAyB,GAAG,OAAO,CAAC,MAAM,CAAC;CA8DxE"}
@@ -0,0 +1,119 @@
1
+ "use strict";
2
+ /**
3
+ * OpenAI-compatible API client for local LLM servers (LM Studio, Ollama, etc.).
4
+ * Uses raw fetch — no extra dependencies.
5
+ */
6
+ var __importDefault = (this && this.__importDefault) || function (mod) {
7
+ return (mod && mod.__esModule) ? mod : { "default": mod };
8
+ };
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.OpenAICompatClient = void 0;
11
+ const async_retry_1 = __importDefault(require("async-retry"));
12
+ /**
13
+ * Walk a parsed JSON value and swap [x, y] → [y, x] in all coordinates arrays.
14
+ * Used for models that return coordinates in x-first order despite the prompt.
15
+ */
16
+ function swapCoordinates(value) {
17
+ if (Array.isArray(value)) {
18
+ if (value.length === 2 && typeof value[0] === 'number' && typeof value[1] === 'number') {
19
+ return [value[1], value[0]];
20
+ }
21
+ return value.map((item) => swapCoordinates(item));
22
+ }
23
+ if (value && typeof value === 'object') {
24
+ const out = {};
25
+ for (const [k, v] of Object.entries(value)) {
26
+ out[k] = swapCoordinates(v);
27
+ }
28
+ return out;
29
+ }
30
+ return value;
31
+ }
32
+ class OpenAICompatClient {
33
+ constructor(baseUrl, model, apiKey, coordinateOrder = 'yx') {
34
+ this.baseUrl = baseUrl.replace(/\/+$/, '');
35
+ this.model = model;
36
+ this.apiKey = apiKey;
37
+ this.coordinateOrder = coordinateOrder;
38
+ }
39
+ /**
40
+ * Convert Google GenAI content format to OpenAI chat messages.
41
+ */
42
+ convertToMessages(system, contents) {
43
+ const messages = [];
44
+ if (system) {
45
+ messages.push({ role: 'system', content: system });
46
+ }
47
+ for (const entry of contents) {
48
+ const role = entry.role === 'model' ? 'assistant' : entry.role;
49
+ const parts = [];
50
+ for (const part of entry.parts) {
51
+ if (part.text) {
52
+ parts.push({ type: 'text', text: part.text });
53
+ }
54
+ else if (part.inlineData) {
55
+ const { mimeType, data } = part.inlineData;
56
+ parts.push({
57
+ type: 'image_url',
58
+ image_url: { url: `data:${mimeType};base64,${data}` },
59
+ });
60
+ }
61
+ }
62
+ messages.push({ role, content: parts });
63
+ }
64
+ return messages;
65
+ }
66
+ async createMessage(params) {
67
+ const { system, contents, temperature = 0, maxTokens = 3000 } = params;
68
+ const messages = this.convertToMessages(system, contents);
69
+ const body = {
70
+ model: this.model,
71
+ messages,
72
+ temperature,
73
+ max_tokens: maxTokens,
74
+ };
75
+ const response = await (0, async_retry_1.default)(async (bail) => {
76
+ const res = await fetch(`${this.baseUrl}/v1/chat/completions`, {
77
+ method: 'POST',
78
+ headers: {
79
+ 'Content-Type': 'application/json',
80
+ ...(this.apiKey ? { Authorization: `Bearer ${this.apiKey}` } : {}),
81
+ },
82
+ body: JSON.stringify(body),
83
+ });
84
+ if (res.status === 400 || res.status === 401) {
85
+ const errBody = await res.text();
86
+ bail(new Error(`${res.status}: ${errBody}`));
87
+ return;
88
+ }
89
+ if (!res.ok) {
90
+ const errBody = await res.text();
91
+ throw new Error(`${res.status}: ${errBody}`);
92
+ }
93
+ return res.json();
94
+ }, {
95
+ retries: 3,
96
+ factor: 1,
97
+ minTimeout: 1000,
98
+ randomize: true,
99
+ });
100
+ let content = response?.choices?.[0]?.message?.content || '';
101
+ // If the model returns [x, y] instead of [y, x], swap them.
102
+ if (this.coordinateOrder === 'xy') {
103
+ try {
104
+ const cleaned = content
105
+ .trim()
106
+ .replace(/(^```json\s*|```\s*$)/g, '')
107
+ .trim();
108
+ const parsed = JSON.parse(cleaned);
109
+ content = JSON.stringify(swapCoordinates(parsed));
110
+ }
111
+ catch {
112
+ // Not JSON or not a coordinate response — leave as-is
113
+ }
114
+ }
115
+ return content;
116
+ }
117
+ }
118
+ exports.OpenAICompatClient = OpenAICompatClient;
119
+ //# sourceMappingURL=openaiCompatClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openaiCompatClient.js","sourceRoot":"","sources":["../../src/openaiCompatClient.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;AAEH,8DAAgC;AAehC;;;GAGG;AACH,SAAS,eAAe,CAAC,KAAU;IACjC,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,QAAQ,IAAI,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,QAAQ,EAAE,CAAC;YACvF,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9B,CAAC;QACD,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAS,EAAE,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC;IACzD,CAAC;IACD,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QACvC,MAAM,GAAG,GAAwB,EAAE,CAAC;QACpC,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YAC3C,GAAG,CAAC,CAAC,CAAC,GAAG,eAAe,CAAC,CAAC,CAAC,CAAC;QAC9B,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAa,kBAAkB;IAM7B,YAAY,OAAe,EAAE,KAAa,EAAE,MAAc,EAAE,kBAA+B,IAAI;QAC7F,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QAC3C,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,eAAe,GAAG,eAAe,CAAC;IACzC,CAAC;IAED;;OAEG;IACK,iBAAiB,CACvB,MAAc,EACd,QAAoD;QAEpD,MAAM,QAAQ,GAAkB,EAAE,CAAC;QAEnC,IAAI,MAAM,EAAE,CAAC;YACX,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QACrD,CAAC;QAED,KAAK,MAAM,KAAK,IAAI,QAAQ,EAAE,CAAC;YAC7B,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAE,KAAK,CAAC,IAA6B,CAAC;YACzF,MAAM,KAAK,GAAwE,EAAE,CAAC;YAEtF,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;gBAC/B,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;oBACd,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;gBAChD,CAAC;qBAAM,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;oBAC3B,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC,UAAU,CAAC;oBAC3C,KAAK,CAAC,IAAI,CAAC;wBACT,IAAI,EAAE,WAAW;wBACjB,SAAS,EAAE,EAAE,GAAG,EAAE,QAAQ,QAAQ,WAAW,IAAI,EAAE,EAAE;qBACtD,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;YAED,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QAC1C,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,MAAiC;QACnD,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,GAAG,CAAC,EAAE,SAAS,GAAG,IAAI,EAAE,GAAG,MAAM,CAAC;QAEvE,MAAM,QAAQ,GAAG,IAAI,CAAC,iBAAiB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QAE1D,MAAM,IAAI,GAAwB;YAChC,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,QAAQ;YACR,WAAW;YACX,UAAU,EAAE,SAAS;SACtB,CAAC;QAEF,MAAM,QAAQ,GAAG,MAAM,IAAA,qBAAK,EAC1B,KAAK,EAAC,IAAI,EAAC,EAAE;YACX,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,OAAO,sBAAsB,EAAE;gBAC7D,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE;oBACP,cAAc,EAAE,kBAAkB;oBAClC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,UAAU,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;iBACnE;gBACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;aAC3B,CAAC,CAAC;YAEH,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;gBAC7C,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;gBACjC,IAAI,CAAC,IAAI,KAAK,CAAC,GAAG,GAAG,CAAC,MAAM,KAAK,OAAO,EAAE,CAAC,CAAC,CAAC;gBAC7C,OAAO;YACT,CAAC;YAED,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;gBACZ,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;gBACjC,MAAM,IAAI,KAAK,CAAC,GAAG,GAAG,CAAC,MAAM,KAAK,OAAO,EAAE,CAAC,CAAC;YAC/C,CAAC;YAED,OAAO,GAAG,CAAC,IAAI,EAAkB,CAAC;QACpC,CAAC,EACD;YACE,OAAO,EAAE,CAAC;YACV,MAAM,EAAE,CAAC;YACT,UAAU,EAAE,IAAI;YAChB,SAAS,EAAE,IAAI;SAChB,CACF,CAAC;QAEF,IAAI,OAAO,GAAW,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,IAAI,EAAE,CAAC;QAErE,4DAA4D;QAC5D,IAAI,IAAI,CAAC,eAAe,KAAK,IAAI,EAAE,CAAC;YAClC,IAAI,CAAC;gBACH,MAAM,OAAO,GAAG,OAAO;qBACpB,IAAI,EAAE;qBACN,OAAO,CAAC,wBAAwB,EAAE,EAAE,CAAC;qBACrC,IAAI,EAAE,CAAC;gBACV,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;gBACnC,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC;YACpD,CAAC;YAAC,MAAM,CAAC;gBACP,sDAAsD;YACxD,CAAC;QACH,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;CACF;AA9GD,gDA8GC"}
@@ -0,0 +1,2 @@
1
+ export declare function decodeVisionPrompt(b64: string): string;
2
+ //# sourceMappingURL=promptCodec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"promptCodec.d.ts","sourceRoot":"","sources":["../../src/promptCodec.ts"],"names":[],"mappings":"AAOA,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEtD"}
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.decodeVisionPrompt = decodeVisionPrompt;
4
+ /**
5
+ * Decode build-time prompt payloads. The published npm bundle avoids shipping
6
+ * plain-text prompts: they are gzip-compressed then Base64-encoded at build time
7
+ * (see scripts/generate-prompt-b64.cjs) and inflated here at runtime.
8
+ */
9
+ const node_zlib_1 = require("node:zlib");
10
+ function decodeVisionPrompt(b64) {
11
+ return (0, node_zlib_1.gunzipSync)(Buffer.from(b64, 'base64')).toString('utf8');
12
+ }
13
+ //# sourceMappingURL=promptCodec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"promptCodec.js","sourceRoot":"","sources":["../../src/promptCodec.ts"],"names":[],"mappings":";;AAOA,gDAEC;AATD;;;;GAIG;AACH,yCAAuC;AAEvC,SAAgB,kBAAkB,CAAC,GAAW;IAC5C,OAAO,IAAA,sBAAU,EAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;AACjE,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Public prompt exports for stark-vision / df-vision.
3
+ * Human-readable source: `prompts.raw.ts` (not compiled). Published npm bundle uses Base64 payloads
4
+ * in `generated/promptB64.ts` (regenerate: `npm run gen:prompts`).
5
+ */
6
+ export { combinedInstructionPrompt, elementVisibilityPrompt, elementVisibilityWithExplanationPrompt, bboxPrompt, backNavigationPrompt, getInformationWithExplanationPrompt, getInformationPrompt, createWDIOTestPrompt, createAppiumJavaTestPrompt, } from './generated/promptB64';
7
+ //# sourceMappingURL=prompts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../src/prompts.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,yBAAyB,EACzB,uBAAuB,EACvB,sCAAsC,EACtC,UAAU,EACV,oBAAoB,EACpB,mCAAmC,EACnC,oBAAoB,EACpB,oBAAoB,EACpB,0BAA0B,GAC3B,MAAM,uBAAuB,CAAC"}
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ /**
3
+ * Public prompt exports for stark-vision / df-vision.
4
+ * Human-readable source: `prompts.raw.ts` (not compiled). Published npm bundle uses Base64 payloads
5
+ * in `generated/promptB64.ts` (regenerate: `npm run gen:prompts`).
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.createAppiumJavaTestPrompt = exports.createWDIOTestPrompt = exports.getInformationPrompt = exports.getInformationWithExplanationPrompt = exports.backNavigationPrompt = exports.bboxPrompt = exports.elementVisibilityWithExplanationPrompt = exports.elementVisibilityPrompt = exports.combinedInstructionPrompt = void 0;
9
+ var promptB64_1 = require("./generated/promptB64");
10
+ Object.defineProperty(exports, "combinedInstructionPrompt", { enumerable: true, get: function () { return promptB64_1.combinedInstructionPrompt; } });
11
+ Object.defineProperty(exports, "elementVisibilityPrompt", { enumerable: true, get: function () { return promptB64_1.elementVisibilityPrompt; } });
12
+ Object.defineProperty(exports, "elementVisibilityWithExplanationPrompt", { enumerable: true, get: function () { return promptB64_1.elementVisibilityWithExplanationPrompt; } });
13
+ Object.defineProperty(exports, "bboxPrompt", { enumerable: true, get: function () { return promptB64_1.bboxPrompt; } });
14
+ Object.defineProperty(exports, "backNavigationPrompt", { enumerable: true, get: function () { return promptB64_1.backNavigationPrompt; } });
15
+ Object.defineProperty(exports, "getInformationWithExplanationPrompt", { enumerable: true, get: function () { return promptB64_1.getInformationWithExplanationPrompt; } });
16
+ Object.defineProperty(exports, "getInformationPrompt", { enumerable: true, get: function () { return promptB64_1.getInformationPrompt; } });
17
+ Object.defineProperty(exports, "createWDIOTestPrompt", { enumerable: true, get: function () { return promptB64_1.createWDIOTestPrompt; } });
18
+ Object.defineProperty(exports, "createAppiumJavaTestPrompt", { enumerable: true, get: function () { return promptB64_1.createAppiumJavaTestPrompt; } });
19
+ //# sourceMappingURL=prompts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.js","sourceRoot":"","sources":["../../src/prompts.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;AAEH,mDAU+B;AAT7B,sHAAA,yBAAyB,OAAA;AACzB,oHAAA,uBAAuB,OAAA;AACvB,mIAAA,sCAAsC,OAAA;AACtC,uGAAA,UAAU,OAAA;AACV,iHAAA,oBAAoB,OAAA;AACpB,gIAAA,mCAAmC,OAAA;AACnC,iHAAA,oBAAoB,OAAA;AACpB,iHAAA,oBAAoB,OAAA;AACpB,uHAAA,0BAA0B,OAAA"}
@@ -0,0 +1,86 @@
1
+ export type ScrollSize = 'SMALL' | 'MEDIUM' | 'LARGE';
2
+ /** Token usage reported by a single Gemini API call inside StarkVisionClient. */
3
+ export interface VisionTokenUsage {
4
+ inputTokens: number;
5
+ outputTokens: number;
6
+ totalTokens: number;
7
+ /** Tokens served from Gemini implicit cache (~75% cost reduction). */
8
+ cachedTokens?: number;
9
+ /** Tokens consumed by extended thinking (Gemini 2.5+ with MINIMAL/AUTO thinking). */
10
+ thoughtsTokens?: number;
11
+ }
12
+ export type CommandType = 'find' | 'getInfo';
13
+ export interface StarkVisionConfig {
14
+ apiKey: string;
15
+ model: string;
16
+ /** Disable thinking (ThinkingLevel.NONE) for faster responses. Default: false (MINIMAL). */
17
+ disableThinking?: boolean;
18
+ /** Base URL for OpenAI-compatible local servers (e.g. LM Studio: http://127.0.0.1:1234). */
19
+ baseUrl?: string;
20
+ /**
21
+ * Coordinate order returned by the local model in the coordinates array.
22
+ * 'yx' (default): model returns [y, x] as the prompt instructs.
23
+ * 'xy': model returns [x, y] despite the prompt (e.g. some Qwen variants).
24
+ * When 'xy', coordinates are swapped before scaling.
25
+ */
26
+ coordinateOrder?: 'yx' | 'xy';
27
+ /**
28
+ * Optional callback invoked after every Gemini API call with token usage.
29
+ * Use this to accumulate and display token costs for vision operations.
30
+ */
31
+ onTokenUsage?: (usage: VisionTokenUsage) => void;
32
+ }
33
+ export interface ExecutionConfig {
34
+ scrollSize: ScrollSize;
35
+ elementVisibleCheck: boolean;
36
+ maxScrolls: number;
37
+ saveToCache: boolean;
38
+ visibleExplanation: boolean;
39
+ }
40
+ export declare const DefaultExecutionConfig: ExecutionConfig;
41
+ export interface StarkVisionAction {
42
+ action: string;
43
+ value: string | null;
44
+ locators: {
45
+ element: string;
46
+ coordinates?: [number, number];
47
+ /**
48
+ * How directly the original instruction described this element (1–10).
49
+ * 1 = vague/unrelated (model had to interpret heavily),
50
+ * 10 = exact/direct description.
51
+ * Only present when the combinedInstructionPrompt includes matchScore support.
52
+ */
53
+ matchScore?: number;
54
+ }[];
55
+ }
56
+ export interface BoundingBox {
57
+ corners: {
58
+ min: {
59
+ x: number;
60
+ y: number;
61
+ };
62
+ max: {
63
+ x: number;
64
+ y: number;
65
+ };
66
+ };
67
+ center: {
68
+ x: number;
69
+ y: number;
70
+ };
71
+ container: {
72
+ width: number;
73
+ height: number;
74
+ };
75
+ }
76
+ export interface ScreenSize {
77
+ width: number;
78
+ height: number;
79
+ }
80
+ export interface VisibilityResult {
81
+ elementState: boolean | string;
82
+ systemPopUp: boolean;
83
+ popUpActionButtons: string;
84
+ typeOfPopUp: string;
85
+ }
86
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;AAEtD,iFAAiF;AACjF,MAAM,WAAW,gBAAgB;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,sEAAsE;IACtE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,qFAAqF;IACrF,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,SAAS,CAAC;AAE7C,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,4FAA4F;IAC5F,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,4FAA4F;IAC5F,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;OAKG;IACH,eAAe,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IAC9B;;;OAGG;IACH,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,gBAAgB,KAAK,IAAI,CAAC;CAClD;AAED,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,UAAU,CAAC;IACvB,mBAAmB,EAAE,OAAO,CAAC;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,OAAO,CAAC;IACrB,kBAAkB,EAAE,OAAO,CAAC;CAC7B;AAED,eAAO,MAAM,sBAAsB,EAAE,eAMpC,CAAC;AAEF,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,QAAQ,EAAE;QACR,OAAO,EAAE,MAAM,CAAC;QAChB,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC/B;;;;;WAKG;QACH,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,EAAE,CAAC;CACL;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE;QAAE,GAAG,EAAE;YAAE,CAAC,EAAE,MAAM,CAAC;YAAC,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;QAAC,GAAG,EAAE;YAAE,CAAC,EAAE,MAAM,CAAC;YAAC,CAAC,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAC;IAC1E,MAAM,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACjC,SAAS,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CAC9C;AAED,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,gBAAgB;IAC/B,YAAY,EAAE,OAAO,GAAG,MAAM,CAAC;IAC/B,WAAW,EAAE,OAAO,CAAC;IACrB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,WAAW,EAAE,MAAM,CAAC;CACrB"}
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DefaultExecutionConfig = void 0;
4
+ exports.DefaultExecutionConfig = {
5
+ scrollSize: 'MEDIUM',
6
+ elementVisibleCheck: true,
7
+ maxScrolls: 0,
8
+ saveToCache: true,
9
+ visibleExplanation: false,
10
+ };
11
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":";;;AA4Ca,QAAA,sBAAsB,GAAoB;IACrD,UAAU,EAAE,QAAQ;IACpB,mBAAmB,EAAE,IAAI;IACzB,UAAU,EAAE,CAAC;IACb,WAAW,EAAE,IAAI;IACjB,kBAAkB,EAAE,KAAK;CAC1B,CAAC"}
package/package.json ADDED
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "@appclaw/vision",
3
+ "version": "1.1.0",
4
+ "description": "AI-powered vision element detection for AppClaw",
5
+ "main": "dist/src/index.js",
6
+ "types": "dist/src/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/src/index.d.ts",
10
+ "import": "./dist/src/index.js",
11
+ "require": "./dist/src/index.js",
12
+ "default": "./dist/src/index.js"
13
+ }
14
+ },
15
+ "scripts": {
16
+ "gen:prompts": "node scripts/generate-prompt-b64.cjs",
17
+ "clean": "rm -rf dist",
18
+ "build": "npm run clean && npm run gen:prompts && tsc",
19
+ "build:tsc": "tsc",
20
+ "build:watch": "tsc --watch",
21
+ "typecheck": "npm run gen:prompts && tsc --noEmit",
22
+ "prepublishOnly": "npm run build"
23
+ },
24
+ "license": "MIT",
25
+ "dependencies": {
26
+ "@google/genai": "^1.44.0",
27
+ "async-retry": "^1.3.3"
28
+ },
29
+ "devDependencies": {
30
+ "@semantic-release/changelog": "^6.0.3",
31
+ "@semantic-release/commit-analyzer": "^13.0.1",
32
+ "@semantic-release/git": "^10.0.1",
33
+ "@semantic-release/github": "^11.0.6",
34
+ "@semantic-release/npm": "^12.0.2",
35
+ "@semantic-release/release-notes-generator": "^14.1.0",
36
+ "@types/async-retry": "^1.4.9",
37
+ "@types/node": "^20.11.0",
38
+ "conventional-changelog-conventionalcommits": "^9.3.1",
39
+ "semantic-release": "^24.2.9",
40
+ "typescript": "5.6.2"
41
+ },
42
+ "files": [
43
+ "dist"
44
+ ],
45
+ "publishConfig": {
46
+ "access": "public"
47
+ }
48
+ }