@petukhovart/agent-view 0.12.0 → 0.13.1
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/.claude-plugin/plugin.json +21 -21
- package/LICENSE +21 -21
- package/README.md +41 -1
- package/dist/cdp/console-stream.d.ts +35 -0
- package/dist/cdp/console-stream.d.ts.map +1 -0
- package/dist/cdp/console-stream.js +103 -0
- package/dist/cdp/console-stream.js.map +1 -0
- package/dist/cdp/transport.d.ts.map +1 -1
- package/dist/cdp/transport.js +273 -12
- package/dist/cdp/transport.js.map +1 -1
- package/dist/cdp/types.d.ts +93 -0
- package/dist/cdp/types.d.ts.map +1 -1
- package/dist/cdp/types.js +15 -0
- package/dist/cdp/types.js.map +1 -1
- package/dist/cli/commands/dialog.d.ts +11 -0
- package/dist/cli/commands/dialog.d.ts.map +1 -0
- package/dist/cli/commands/dialog.js +30 -0
- package/dist/cli/commands/dialog.js.map +1 -0
- package/dist/cli/commands/upload.d.ts +10 -0
- package/dist/cli/commands/upload.d.ts.map +1 -0
- package/dist/cli/commands/upload.js +35 -0
- package/dist/cli/commands/upload.js.map +1 -0
- package/dist/cli/index.js +71 -2
- package/dist/cli/index.js.map +1 -1
- package/dist/inspectors/dialog/index.d.ts +20 -0
- package/dist/inspectors/dialog/index.d.ts.map +1 -0
- package/dist/inspectors/dialog/index.js +58 -0
- package/dist/inspectors/dialog/index.js.map +1 -0
- package/dist/inspectors/dom.d.ts +17 -0
- package/dist/inspectors/dom.d.ts.map +1 -0
- package/dist/inspectors/dom.js +131 -0
- package/dist/inspectors/dom.js.map +1 -0
- package/dist/inspectors/scene/pixi.d.ts +3 -0
- package/dist/inspectors/scene/pixi.d.ts.map +1 -0
- package/dist/inspectors/scene/pixi.js +52 -0
- package/dist/inspectors/scene/pixi.js.map +1 -0
- package/dist/server/server.d.ts +36 -5
- package/dist/server/server.d.ts.map +1 -1
- package/dist/server/server.js +288 -62
- package/dist/server/server.js.map +1 -1
- package/dist/server/tauri-dialog-shim.d.ts +27 -0
- package/dist/server/tauri-dialog-shim.d.ts.map +1 -0
- package/dist/server/tauri-dialog-shim.js +55 -0
- package/dist/server/tauri-dialog-shim.js.map +1 -0
- package/package.json +1 -1
- package/skills/verify/SKILL.md +119 -2
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/** Human wording of the standing answer, for `dialog` output and command echoes. */
|
|
2
|
+
export function describePolicy(policy) {
|
|
3
|
+
if (!policy.accept)
|
|
4
|
+
return 'dismiss';
|
|
5
|
+
return policy.promptText === undefined ? 'accept' : `accept, prompt text "${policy.promptText}"`;
|
|
6
|
+
}
|
|
7
|
+
export function describeArm(arm) {
|
|
8
|
+
if (!arm)
|
|
9
|
+
return 'not armed';
|
|
10
|
+
if (arm.kind === 'cancel')
|
|
11
|
+
return 'armed: cancel';
|
|
12
|
+
return `armed: ${arm.files.length} file(s) — ${arm.files.map(basename).join(', ')}`;
|
|
13
|
+
}
|
|
14
|
+
function basename(path) {
|
|
15
|
+
return path.split(/[\\/]/).pop() ?? path;
|
|
16
|
+
}
|
|
17
|
+
function describeAnswer(dialog) {
|
|
18
|
+
const { answer } = dialog;
|
|
19
|
+
if (!answer)
|
|
20
|
+
return 'OPEN — not answered';
|
|
21
|
+
const verb = answer.accept ? 'accepted' : 'dismissed';
|
|
22
|
+
const text = answer.promptText === undefined ? '' : ` "${answer.promptText}"`;
|
|
23
|
+
return `${verb}${text} (${answer.automatic ? 'auto' : 'manual'})`;
|
|
24
|
+
}
|
|
25
|
+
function describeChooser(event) {
|
|
26
|
+
if (event.answer === 'files')
|
|
27
|
+
return `answered with ${event.files?.map(basename).join(', ') ?? ''}`;
|
|
28
|
+
if (event.answer === 'cancel')
|
|
29
|
+
return event.matchedInput ? 'cancelled' : 'cancelled — no file input to fill';
|
|
30
|
+
return 'not answered';
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* `stamp` is injected rather than imported: the time format belongs to the log
|
|
34
|
+
* feed, and inspectors must not depend on the server layer.
|
|
35
|
+
*/
|
|
36
|
+
export function formatDialogStatus(status, stamp) {
|
|
37
|
+
const lines = [`JS dialog policy: ${describePolicy(status.policy)}`];
|
|
38
|
+
for (const dialog of status.dialogs) {
|
|
39
|
+
const message = dialog.message ? ` "${dialog.message}"` : '';
|
|
40
|
+
lines.push(` ${stamp(dialog.ts)} ${dialog.type}${message} → ${describeAnswer(dialog)}`);
|
|
41
|
+
}
|
|
42
|
+
if (status.dialogs.length === 0) {
|
|
43
|
+
lines.push(' no JS dialog seen on this window yet');
|
|
44
|
+
}
|
|
45
|
+
const engines = status.tauriPatched ? 'CDP + Tauri IPC' : 'CDP';
|
|
46
|
+
lines.push('', `File chooser (${engines}): ${describeArm(status.chooserArm)}`);
|
|
47
|
+
if (status.tauriArmed) {
|
|
48
|
+
lines.push(' Tauri IPC shim: armed in the page — survives a dropped session, not a navigation');
|
|
49
|
+
}
|
|
50
|
+
for (const chooser of status.choosers) {
|
|
51
|
+
lines.push(` ${stamp(chooser.ts)} ${chooser.mode} → ${describeChooser(chooser)}`);
|
|
52
|
+
}
|
|
53
|
+
if (status.choosers.length === 0) {
|
|
54
|
+
lines.push(' no file chooser intercepted on this window yet');
|
|
55
|
+
}
|
|
56
|
+
return lines.join('\n');
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/inspectors/dialog/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { AXNode } from '../cdp/types.js';
|
|
2
|
+
export type RefEntry = {
|
|
3
|
+
ref: number;
|
|
4
|
+
backendDOMNodeId: number;
|
|
5
|
+
};
|
|
6
|
+
export type DOMSnapshotOptions = {
|
|
7
|
+
filter?: string;
|
|
8
|
+
depth?: number;
|
|
9
|
+
startRef?: number;
|
|
10
|
+
};
|
|
11
|
+
export type DOMSnapshotResult = {
|
|
12
|
+
text: string;
|
|
13
|
+
refs: RefEntry[];
|
|
14
|
+
nextRef: number;
|
|
15
|
+
};
|
|
16
|
+
export declare function formatAccessibilityTree(nodes: AXNode[], options?: DOMSnapshotOptions): DOMSnapshotResult;
|
|
17
|
+
//# sourceMappingURL=dom.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dom.d.ts","sourceRoot":"","sources":["../../src/inspectors/dom.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AAE7C,MAAM,MAAM,QAAQ,GAAG;IACrB,GAAG,EAAE,MAAM,CAAA;IACX,gBAAgB,EAAE,MAAM,CAAA;CACzB,CAAA;AAED,MAAM,MAAM,kBAAkB,GAAG;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB,CAAA;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,QAAQ,EAAE,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,MAAM,EAAE,EACf,OAAO,GAAE,kBAAuB,GAC/B,iBAAiB,CAgInB"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
export function formatAccessibilityTree(nodes, options = {}) {
|
|
2
|
+
const { filter, depth: maxDepth } = options;
|
|
3
|
+
const refs = [];
|
|
4
|
+
let nextRef = options.startRef ?? 1;
|
|
5
|
+
const lines = [];
|
|
6
|
+
const nodeMap = new Map();
|
|
7
|
+
for (const node of nodes) {
|
|
8
|
+
nodeMap.set(node.nodeId, node);
|
|
9
|
+
}
|
|
10
|
+
const rootNodeId = nodes[0]?.nodeId;
|
|
11
|
+
if (!rootNodeId)
|
|
12
|
+
return { text: '(empty)', refs: [], nextRef };
|
|
13
|
+
const ALWAYS_SKIP_ROLES = new Set(['InlineTextBox']);
|
|
14
|
+
const SKIP_WHEN_EMPTY_ROLES = new Set(['none', 'generic', 'StaticText']);
|
|
15
|
+
// WAI-ARIA-like fallback: when a node has no accessible name,
|
|
16
|
+
// walk its children to find the first non-empty name, description, or title.
|
|
17
|
+
// This handles cases like v-list-item with title on a child v-icon.
|
|
18
|
+
function resolveNameFromChildren(node, depthLimit = 5) {
|
|
19
|
+
if (depthLimit <= 0 || !node.childIds)
|
|
20
|
+
return '';
|
|
21
|
+
for (const childId of node.childIds) {
|
|
22
|
+
const child = nodeMap.get(childId);
|
|
23
|
+
if (!child)
|
|
24
|
+
continue;
|
|
25
|
+
// Check child's own name
|
|
26
|
+
if (child.name?.value)
|
|
27
|
+
return child.name.value;
|
|
28
|
+
// Check description/title in AX properties
|
|
29
|
+
const desc = child.properties?.find(p => p.name === 'description');
|
|
30
|
+
if (desc?.value?.value && typeof desc.value.value === 'string')
|
|
31
|
+
return desc.value.value;
|
|
32
|
+
// Recurse into grandchildren
|
|
33
|
+
const deeper = resolveNameFromChildren(child, depthLimit - 1);
|
|
34
|
+
if (deeper)
|
|
35
|
+
return deeper;
|
|
36
|
+
}
|
|
37
|
+
return '';
|
|
38
|
+
}
|
|
39
|
+
// Collect all descendant text for heuristic filter matching.
|
|
40
|
+
// Searches name and description of all descendants, not just current node.
|
|
41
|
+
function getDescendantText(node, depthLimit = 10) {
|
|
42
|
+
const parts = [];
|
|
43
|
+
function collect(n, depth) {
|
|
44
|
+
if (depth > depthLimit || !n.childIds)
|
|
45
|
+
return;
|
|
46
|
+
for (const childId of n.childIds) {
|
|
47
|
+
const child = nodeMap.get(childId);
|
|
48
|
+
if (!child)
|
|
49
|
+
continue;
|
|
50
|
+
if (child.name?.value)
|
|
51
|
+
parts.push(child.name.value);
|
|
52
|
+
const desc = child.properties?.find(p => p.name === 'description');
|
|
53
|
+
if (desc?.value?.value && typeof desc.value.value === 'string')
|
|
54
|
+
parts.push(desc.value.value);
|
|
55
|
+
collect(child, depth + 1);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
collect(node, 0);
|
|
59
|
+
return parts.join(' ').toLowerCase();
|
|
60
|
+
}
|
|
61
|
+
function hasMatchingDescendant(node, lowerFilter) {
|
|
62
|
+
if (!node.childIds)
|
|
63
|
+
return false;
|
|
64
|
+
for (const childId of node.childIds) {
|
|
65
|
+
const child = nodeMap.get(childId);
|
|
66
|
+
if (!child)
|
|
67
|
+
continue;
|
|
68
|
+
const childRole = child.role?.value ?? '';
|
|
69
|
+
if (ALWAYS_SKIP_ROLES.has(childRole))
|
|
70
|
+
continue;
|
|
71
|
+
const childName = child.name?.value?.toLowerCase() ?? '';
|
|
72
|
+
if (childName.includes(lowerFilter) || childRole.toLowerCase().includes(lowerFilter))
|
|
73
|
+
return true;
|
|
74
|
+
if (hasMatchingDescendant(child, lowerFilter))
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
const HARD_MAX_DEPTH = 100;
|
|
80
|
+
function walk(nodeId, depth, indent) {
|
|
81
|
+
if (indent > HARD_MAX_DEPTH)
|
|
82
|
+
return;
|
|
83
|
+
if (maxDepth !== undefined && indent > maxDepth)
|
|
84
|
+
return;
|
|
85
|
+
const node = nodeMap.get(nodeId);
|
|
86
|
+
if (!node)
|
|
87
|
+
return;
|
|
88
|
+
const role = node.role?.value ?? '';
|
|
89
|
+
const ownName = node.name?.value ?? '';
|
|
90
|
+
// Fallback: resolve name from children when node has no accessible name
|
|
91
|
+
const fallbackName = !ownName ? resolveNameFromChildren(node) : '';
|
|
92
|
+
const name = ownName || fallbackName;
|
|
93
|
+
if (ALWAYS_SKIP_ROLES.has(role))
|
|
94
|
+
return;
|
|
95
|
+
const skip = SKIP_WHEN_EMPTY_ROLES.has(role) && !name;
|
|
96
|
+
if (!skip) {
|
|
97
|
+
if (filter) {
|
|
98
|
+
const lowerFilter = filter.toLowerCase();
|
|
99
|
+
const matchesName = name.toLowerCase().includes(lowerFilter);
|
|
100
|
+
const matchesRole = role.toLowerCase().includes(lowerFilter);
|
|
101
|
+
// Heuristic: also search descendant names/descriptions
|
|
102
|
+
const matchesDescendants = !matchesName && !matchesRole
|
|
103
|
+
? getDescendantText(node, 10).includes(lowerFilter)
|
|
104
|
+
: false;
|
|
105
|
+
if (!matchesName && !matchesRole && !matchesDescendants && !hasMatchingDescendant(node, lowerFilter)) {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
const ref = nextRef++;
|
|
110
|
+
if (node.backendDOMNodeId) {
|
|
111
|
+
refs.push({ ref, backendDOMNodeId: node.backendDOMNodeId });
|
|
112
|
+
}
|
|
113
|
+
const padding = ' '.repeat(indent);
|
|
114
|
+
const isFallback = !ownName && fallbackName;
|
|
115
|
+
const nameStr = name ? ` "${name}"${isFallback ? ' [fallback]' : ''}` : '';
|
|
116
|
+
lines.push(`${padding}${role}${nameStr} [ref=${ref}]`);
|
|
117
|
+
}
|
|
118
|
+
if (node.childIds) {
|
|
119
|
+
for (const childId of node.childIds) {
|
|
120
|
+
walk(childId, depth + 1, skip ? indent : indent + 1);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
walk(rootNodeId, 0, 0);
|
|
125
|
+
return {
|
|
126
|
+
text: lines.join('\n') || '(no matching elements)',
|
|
127
|
+
refs,
|
|
128
|
+
nextRef,
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=dom.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dom.js","sourceRoot":"","sources":["../../src/inspectors/dom.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pixi.d.ts","sourceRoot":"","sources":["../../../src/inspectors/scene/pixi.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAa,MAAM,YAAY,CAAA;AA8C3D,eAAO,MAAM,aAAa,EAAE,cAM3B,CAAA"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { WebGLEngine } from '../../types.js';
|
|
2
|
+
// Depth limit is also enforced in JS to guard against stack overflow
|
|
3
|
+
// in the target process for pathologically deep trees
|
|
4
|
+
const EXTRACT_JS = `
|
|
5
|
+
(function() {
|
|
6
|
+
const devtools = window.__PIXI_DEVTOOLS__;
|
|
7
|
+
if (!devtools) return null;
|
|
8
|
+
const app = devtools.app || devtools.stage?.parent;
|
|
9
|
+
if (!app) return null;
|
|
10
|
+
const stage = app.stage || devtools.stage;
|
|
11
|
+
if (!stage) return null;
|
|
12
|
+
|
|
13
|
+
function serialize(node, depth) {
|
|
14
|
+
if (depth > 100) return null;
|
|
15
|
+
const result = {
|
|
16
|
+
type: node.constructor?.name || 'Unknown',
|
|
17
|
+
name: node.label || node.name || '',
|
|
18
|
+
x: Math.round(node.x || 0),
|
|
19
|
+
y: Math.round(node.y || 0),
|
|
20
|
+
visible: node.visible !== false,
|
|
21
|
+
tint: typeof node.tint === 'number' ? '#' + node.tint.toString(16).padStart(6, '0') : '0xffffff',
|
|
22
|
+
alpha: node.alpha ?? 1,
|
|
23
|
+
scaleX: node.scale?.x ?? 1,
|
|
24
|
+
scaleY: node.scale?.y ?? 1,
|
|
25
|
+
rotation: Math.round((node.rotation || 0) * 180 / Math.PI * 100) / 100,
|
|
26
|
+
width: Math.round(node.width || 0),
|
|
27
|
+
height: Math.round(node.height || 0),
|
|
28
|
+
};
|
|
29
|
+
const kids = node.children || [];
|
|
30
|
+
if (kids.length > 0) {
|
|
31
|
+
result.children = kids.map(c => serialize(c, depth + 1)).filter(Boolean);
|
|
32
|
+
}
|
|
33
|
+
return result;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return serialize(stage, 0);
|
|
37
|
+
})()
|
|
38
|
+
`;
|
|
39
|
+
function isSceneNode(val) {
|
|
40
|
+
if (!val || typeof val !== 'object')
|
|
41
|
+
return false;
|
|
42
|
+
const n = val;
|
|
43
|
+
return typeof n.type === 'string' && typeof n.name === 'string';
|
|
44
|
+
}
|
|
45
|
+
export const pixiExtractor = {
|
|
46
|
+
engine: WebGLEngine.Pixi,
|
|
47
|
+
async extract(conn) {
|
|
48
|
+
const result = await conn.evaluate(EXTRACT_JS);
|
|
49
|
+
return isSceneNode(result) ? result : null;
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
//# sourceMappingURL=pixi.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pixi.js","sourceRoot":"","sources":["../../../src/inspectors/scene/pixi.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAI5C,qEAAqE;AACrE,sDAAsD;AACtD,MAAM,UAAU,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkClB,CAAA;AAED,SAAS,WAAW,CAAC,GAAY;IAC/B,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAA;IACjD,MAAM,CAAC,GAAG,GAA8B,CAAA;IACxC,OAAO,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,IAAI,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAA;AACjE,CAAC;AAED,MAAM,CAAC,MAAM,aAAa,GAAmB;IAC3C,MAAM,EAAE,WAAW,CAAC,IAAI;IACxB,KAAK,CAAC,OAAO,CAAC,IAAoB;QAChC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAA;QAC9C,OAAO,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAA;IAC5C,CAAC;CACF,CAAA"}
|
package/dist/server/server.d.ts
CHANGED
|
@@ -12,6 +12,17 @@ type ParsedFilter = {
|
|
|
12
12
|
export declare function resolveDepth(filter: string | undefined, explicit: number | undefined): number | undefined;
|
|
13
13
|
export declare function textContentFallback(conn: PageSession, filter: string): Promise<string>;
|
|
14
14
|
export declare function parseFilter(filter: string): ParsedFilter;
|
|
15
|
+
/**
|
|
16
|
+
* CDP takes any path without complaint and the app then reads an empty `File`,
|
|
17
|
+
* so this is the only place a bad path stays diagnosable. A directory has to be
|
|
18
|
+
* rejected too — it passes an existence check and produces that same empty
|
|
19
|
+
* `File`, which is the failure the check exists to prevent.
|
|
20
|
+
*/
|
|
21
|
+
export declare function resolveUploadPath(cwd: string, raw: string): {
|
|
22
|
+
path: string;
|
|
23
|
+
} | {
|
|
24
|
+
error: string;
|
|
25
|
+
};
|
|
15
26
|
export declare class AgentViewServer {
|
|
16
27
|
private server;
|
|
17
28
|
private connections;
|
|
@@ -20,17 +31,16 @@ export declare class AgentViewServer {
|
|
|
20
31
|
private sceneCache;
|
|
21
32
|
private domTextCache;
|
|
22
33
|
private axTreeCache;
|
|
23
|
-
private
|
|
24
|
-
private networkStream;
|
|
25
|
-
private networkRefs;
|
|
26
|
-
private networkNextRef;
|
|
34
|
+
private portStates;
|
|
27
35
|
private token;
|
|
28
36
|
private activeWatches;
|
|
29
|
-
private logRecorder;
|
|
30
37
|
private readonly handlers;
|
|
31
38
|
private readonly streamingCommands;
|
|
32
39
|
private readonly validCommands;
|
|
33
40
|
start(): Promise<void>;
|
|
41
|
+
/** Per-port state bucket, created on first use. */
|
|
42
|
+
private stateFor;
|
|
43
|
+
private isAnyRecording;
|
|
34
44
|
private resetIdleTimer;
|
|
35
45
|
private handleSocket;
|
|
36
46
|
private processRequest;
|
|
@@ -60,6 +70,27 @@ export declare class AgentViewServer {
|
|
|
60
70
|
private handleDrag;
|
|
61
71
|
private resolveDragPoint;
|
|
62
72
|
private handleFill;
|
|
73
|
+
/**
|
|
74
|
+
* Puts files straight into a file input. The native chooser never opens, so
|
|
75
|
+
* there is nothing to close and nothing to arm — this is the cheapest path
|
|
76
|
+
* whenever the input exists in the DOM before the click.
|
|
77
|
+
*/
|
|
78
|
+
private handleUpload;
|
|
79
|
+
/**
|
|
80
|
+
* `dialog` covers JS modals only — `alert`/`confirm`/`prompt`/`beforeunload`.
|
|
81
|
+
* They are answered automatically the moment they open (see
|
|
82
|
+
* `attachJsDialogSubscription`); the commands here read that log, change the
|
|
83
|
+
* standing answer, and force an answer for a dialog that was already open
|
|
84
|
+
* before agent-view attached.
|
|
85
|
+
*/
|
|
86
|
+
private handleDialog;
|
|
87
|
+
/**
|
|
88
|
+
* Arms both engines at once. Which one fires depends on how the app opens its
|
|
89
|
+
* dialog — a webview `<input>` goes through CDP, `@tauri-apps/plugin-dialog`
|
|
90
|
+
* goes through the IPC shim — and the caller has no reason to know which.
|
|
91
|
+
*/
|
|
92
|
+
private armFileChooser;
|
|
93
|
+
private readTauriShimStatus;
|
|
63
94
|
private handleWait;
|
|
64
95
|
private captureScreenshotToFile;
|
|
65
96
|
private handleScreenshot;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/server/server.ts"],"names":[],"mappings":"AAcA,OAAO,EAKL,KAAK,WAAW,EAEhB,KAAK,UAAU,
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/server/server.ts"],"names":[],"mappings":"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"}
|