@thinkrun/cli 0.1.29 → 0.1.30
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 +25 -0
- package/dist/bin/thinkrun.js +2 -0
- package/dist/bin/thinkrun.js.map +1 -1
- package/dist/src/adapters/local.d.ts +8 -0
- package/dist/src/adapters/local.d.ts.map +1 -1
- package/dist/src/adapters/local.js +260 -32
- package/dist/src/adapters/local.js.map +1 -1
- package/dist/src/commands/actions.d.ts.map +1 -1
- package/dist/src/commands/actions.js +26 -5
- package/dist/src/commands/actions.js.map +1 -1
- package/dist/src/commands/audit.d.ts +4 -0
- package/dist/src/commands/audit.d.ts.map +1 -0
- package/dist/src/commands/audit.js +101 -0
- package/dist/src/commands/audit.js.map +1 -0
- package/dist/src/commands/doctor.d.ts +4 -0
- package/dist/src/commands/doctor.d.ts.map +1 -1
- package/dist/src/commands/doctor.js +17 -0
- package/dist/src/commands/doctor.js.map +1 -1
- package/dist/src/config/store.d.ts.map +1 -1
- package/dist/src/config/store.js +42 -5
- package/dist/src/config/store.js.map +1 -1
- package/dist/src/session/cli-session-sync.d.ts +10 -2
- package/dist/src/session/cli-session-sync.d.ts.map +1 -1
- package/dist/src/session/cli-session-sync.js +68 -28
- package/dist/src/session/cli-session-sync.js.map +1 -1
- package/package.json +8 -4
package/README.md
CHANGED
|
@@ -77,6 +77,28 @@ Use `thinkrun doctor` anytime to verify endpoint mode, health, bridge status, an
|
|
|
77
77
|
When changing CLI behavior in this repository, use the agent DX release checklist in [docs/AGENT_CLI_DX_CHECKLIST.md](../../docs/AGENT_CLI_DX_CHECKLIST.md).
|
|
78
78
|
Parity-sensitive CLI/MCP screenshot and observation claims are backed by [docs/mcp-cli-parity-evidence.md](../../docs/mcp-cli-parity-evidence.md).
|
|
79
79
|
|
|
80
|
+
## Local Audit Mode
|
|
81
|
+
|
|
82
|
+
Audit mode is a local-only capture toggle for attached Chromium tabs. When enabled, ThinkRun attempts an extra screenshot after each state-changing action so the Activity Feed and session detail page show an audit trail without requiring manual `screenshot` calls.
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
thinkrun tabs
|
|
86
|
+
thinkrun attach <tabId>
|
|
87
|
+
thinkrun audit on
|
|
88
|
+
thinkrun navigate "https://example.com"
|
|
89
|
+
thinkrun click "a.more"
|
|
90
|
+
thinkrun audit status
|
|
91
|
+
thinkrun audit off
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Rules:
|
|
95
|
+
|
|
96
|
+
- `thinkrun audit on|off|status` operates on the current attached local tab
|
|
97
|
+
- audit mode only applies to local attached-tab sessions, not cloud sessions
|
|
98
|
+
- observation commands (`extract`, `evaluate`, `snapshot`, `url`, `title`, `html`, `console`, `network`, `wait`) do not trigger audit screenshots
|
|
99
|
+
- screenshots are fire-and-forget best effort; browser actions do not fail just because audit capture fails
|
|
100
|
+
- explicit precedence is: `--audit` attach flag > `THINKRUN_AUDIT` env var > stored per-tab toggle
|
|
101
|
+
|
|
80
102
|
## AI Agent Workflow
|
|
81
103
|
|
|
82
104
|
The `snapshot` command returns an accessibility tree — ideal for AI agents that need to understand page structure without screenshots:
|
|
@@ -104,6 +126,7 @@ thinkrun cloud stop
|
|
|
104
126
|
| `cloud artifacts` | List session artifacts (screenshots, logs, actions) |
|
|
105
127
|
| `cloud use <id>` | Switch active session |
|
|
106
128
|
| `doctor` | Diagnose endpoint/auth/session setup |
|
|
129
|
+
| `audit on|off|status` | Enable, disable, or inspect local audit mode for the attached tab |
|
|
107
130
|
|
|
108
131
|
#### Cloud Start Options
|
|
109
132
|
|
|
@@ -137,6 +160,8 @@ thinkrun forward
|
|
|
137
160
|
|
|
138
161
|
Use `--mode local` or `--mode cloud` to override persisted context for a single command.
|
|
139
162
|
|
|
163
|
+
`thinkrun attach <tabId> --audit` enables audit mode immediately for that attached local tab.
|
|
164
|
+
|
|
140
165
|
### Interaction
|
|
141
166
|
|
|
142
167
|
| Command | Description |
|
package/dist/bin/thinkrun.js
CHANGED
|
@@ -12,6 +12,7 @@ import { createConfigCommand } from '../src/commands/config.js';
|
|
|
12
12
|
import { createCloudCommand } from '../src/commands/cloud.js';
|
|
13
13
|
import { createCacheCommand } from '../src/commands/cache.js';
|
|
14
14
|
import { createDoctorCommand } from '../src/commands/doctor.js';
|
|
15
|
+
import { createAuditCommand } from '../src/commands/audit.js';
|
|
15
16
|
import { createResetConnectionCommand } from '../src/commands/reset-connection.js';
|
|
16
17
|
import { createInstallCommand } from '../src/commands/install.js';
|
|
17
18
|
import { createSessionDebugCommand } from '../src/commands/session-debug.js';
|
|
@@ -58,6 +59,7 @@ program.addCommand(createConfigCommand());
|
|
|
58
59
|
program.addCommand(createCloudCommand());
|
|
59
60
|
program.addCommand(createCacheCommand());
|
|
60
61
|
program.addCommand(createDoctorCommand());
|
|
62
|
+
program.addCommand(createAuditCommand());
|
|
61
63
|
program.addCommand(createResetConnectionCommand());
|
|
62
64
|
program.addCommand(createInstallCommand());
|
|
63
65
|
program.addCommand(createSessionDebugCommand());
|
package/dist/bin/thinkrun.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"thinkrun.js","sourceRoot":"","sources":["../../bin/thinkrun.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"thinkrun.js","sourceRoot":"","sources":["../../bin/thinkrun.ts"],"names":[],"mappings":"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"}
|
|
@@ -14,6 +14,7 @@ export declare class LocalAdapter implements BrowserAdapter {
|
|
|
14
14
|
private defaultTimeout;
|
|
15
15
|
private validatedTabCache;
|
|
16
16
|
private syncedNetworkRequestMarkers;
|
|
17
|
+
private auditScreenshotChains;
|
|
17
18
|
private readonly TAB_CACHE_TTL_MS;
|
|
18
19
|
/** Injected fetch function — allows unit tests to intercept all HTTP calls. */
|
|
19
20
|
private readonly fetchFn;
|
|
@@ -36,6 +37,13 @@ export declare class LocalAdapter implements BrowserAdapter {
|
|
|
36
37
|
private syncAction;
|
|
37
38
|
private getNetworkRequestSyncKey;
|
|
38
39
|
private getNetworkRequestId;
|
|
40
|
+
private getScreenshotMimeType;
|
|
41
|
+
private buildAuditScreenshotCaption;
|
|
42
|
+
private runSerializedAuditScreenshotCapture;
|
|
43
|
+
private captureAuditScreenshot;
|
|
44
|
+
private triggerAuditScreenshot;
|
|
45
|
+
private createAuditActionId;
|
|
46
|
+
private buildAuditCaptureDetails;
|
|
39
47
|
private getNetworkRequestMarker;
|
|
40
48
|
private getNetworkRequestTimestamp;
|
|
41
49
|
private findNetworkRequestMarkerIndex;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"local.d.ts","sourceRoot":"","sources":["../../../src/adapters/local.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,KAAK,EACV,OAAO,EACP,cAAc,EACd,YAAY,EACZ,eAAe,EACf,YAAY,EACZ,cAAc,EACd,WAAW,EACX,iBAAiB,EACjB,cAAc,EACd,WAAW,EACX,YAAY,EACZ,aAAa,EACb,aAAa,EACd,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"local.d.ts","sourceRoot":"","sources":["../../../src/adapters/local.ts"],"names":[],"mappings":"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"}
|
|
@@ -9,9 +9,10 @@ import { join } from 'path';
|
|
|
9
9
|
import { randomUUID } from 'crypto';
|
|
10
10
|
import { ApiError, SessionError } from '../errors.js';
|
|
11
11
|
import { config } from '../config/store.js';
|
|
12
|
+
import { resolveTabAuditState } from '@thinkrun/shared/audit-state';
|
|
12
13
|
import { readBridgePort, DEFAULT_BRIDGE_PORT, BRIDGE_HEALTH_PROBE_TIMEOUT_MS, BRIDGE_REQUEST_TIMEOUT_MS, unwrapEvaluatePayload, } from '../utils.js';
|
|
13
14
|
import { clearLocalSessionContext, getLocalSessionContext, setLocalSessionContext } from '../session/context.js';
|
|
14
|
-
import { initCliSession, syncBrowserAction, syncScreenshotAction, closeCliSession, readCliSessionId, readCliNetworkCursor, writeCliNetworkCursor, } from '../session/cli-session-sync.js';
|
|
15
|
+
import { initCliSession, syncBrowserAction, syncScreenshotAction, closeCliSession, readCliSessionId, readCliNetworkCursor, readCliAuditScreenshotState, writeCliNetworkCursor, writeCliAuditScreenshotState, unrefAbortSignal, } from '../session/cli-session-sync.js';
|
|
15
16
|
import { acquireLock, getLockedBy, getWorkingLocation, releaseWorkingLocation, setWorkingLocation, updateWorkingLocationControlSession } from '../working-location.js';
|
|
16
17
|
import { resolveAgentId } from '../session/agent-identity.js';
|
|
17
18
|
import { localCommandRequiresTabError } from '../session/errors.js';
|
|
@@ -22,12 +23,19 @@ import { captureFingerprint, compareFingerprints } from '../obstacle-recovery/st
|
|
|
22
23
|
import { classifyElementFailure } from '../obstacle-recovery/obstacle-classifier.js';
|
|
23
24
|
import { getLocalCommandRetryProfileFromPath, } from './local-command-retry.js';
|
|
24
25
|
import { LOCAL_BRIDGE_TYPED_TRANSPORT_RECOVERY_ATTEMPTS, LOCAL_BRIDGE_TYPED_EXTENSION_REVALIDATION_DELAYS_MS, LOCAL_BRIDGE_TYPED_RECENT_DISCONNECT_GRACE_MS, } from '../local-bridge-timing.js';
|
|
26
|
+
import { redactSensitiveResult } from '@thinkrun/shared/sensitive-result-redaction';
|
|
25
27
|
/** Tunable post-action settle delay (ms). React batches setState updates
|
|
26
28
|
* (~16ms); 50ms gives margin for async DOM mutations to settle. */
|
|
27
29
|
const POST_ACTION_SETTLE_MS = 50;
|
|
28
30
|
const FINGERPRINT_EVALUATE_TIMEOUT_MS = 2500;
|
|
29
31
|
const MAX_NETWORK_REQUESTS_PER_SYNC = 200;
|
|
30
32
|
const FINAL_NETWORK_FLUSH_TIMEOUT_MS = 5_000;
|
|
33
|
+
const AUDIT_SCREENSHOT_TIMEOUT_MS = 8_000;
|
|
34
|
+
const AUDIT_SCREENSHOT_SESSION_CEILING = 500;
|
|
35
|
+
const AUDIT_SCREENSHOT_RECENT_KEY_LIMIT = 64;
|
|
36
|
+
// Leave 1KB headroom under the backend's 10KB result cap so metadata wrapping
|
|
37
|
+
// and transport encoding cannot push an otherwise-valid payload over the limit.
|
|
38
|
+
const MAX_SYNC_RESULT_JSON_LENGTH = 9_000;
|
|
31
39
|
/**
|
|
32
40
|
* Actionable hints keyed by native host error codes.
|
|
33
41
|
* These are surfaced in structured error output (--json mode) and TTY tips.
|
|
@@ -58,11 +66,89 @@ export function getNativeCodeHint(code) {
|
|
|
58
66
|
return undefined;
|
|
59
67
|
return NATIVE_CODE_HINTS[code];
|
|
60
68
|
}
|
|
69
|
+
function sanitizeAndTruncateSyncResult(value) {
|
|
70
|
+
return truncateSyncResult(redactSensitiveResult(value));
|
|
71
|
+
}
|
|
72
|
+
function truncateSyncResult(value) {
|
|
73
|
+
if (value === undefined)
|
|
74
|
+
return undefined;
|
|
75
|
+
if (typeof value === 'string') {
|
|
76
|
+
if (JSON.stringify(value).length <= MAX_SYNC_RESULT_JSON_LENGTH)
|
|
77
|
+
return value;
|
|
78
|
+
const suffix = '... [truncated]';
|
|
79
|
+
let low = 0;
|
|
80
|
+
let high = value.length;
|
|
81
|
+
let best = suffix;
|
|
82
|
+
while (low <= high) {
|
|
83
|
+
const mid = Math.floor((low + high) / 2);
|
|
84
|
+
const candidate = `${value.slice(0, mid)}${suffix}`;
|
|
85
|
+
if (JSON.stringify(candidate).length <= MAX_SYNC_RESULT_JSON_LENGTH) {
|
|
86
|
+
best = candidate;
|
|
87
|
+
low = mid + 1;
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
high = mid - 1;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return best;
|
|
94
|
+
}
|
|
95
|
+
try {
|
|
96
|
+
const serialized = JSON.stringify(value);
|
|
97
|
+
if (serialized.length <= MAX_SYNC_RESULT_JSON_LENGTH)
|
|
98
|
+
return value;
|
|
99
|
+
if (value && typeof value === 'object' && !Array.isArray(value)) {
|
|
100
|
+
const next = {};
|
|
101
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
102
|
+
next[key] = truncateSyncResult(entry);
|
|
103
|
+
if (JSON.stringify(next).length > MAX_SYNC_RESULT_JSON_LENGTH) {
|
|
104
|
+
next[key] = '[truncated]';
|
|
105
|
+
if (JSON.stringify(next).length > MAX_SYNC_RESULT_JSON_LENGTH) {
|
|
106
|
+
delete next[key];
|
|
107
|
+
break;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
while (Object.keys(next).length > 0 && JSON.stringify(next).length > MAX_SYNC_RESULT_JSON_LENGTH) {
|
|
112
|
+
const lastKey = Object.keys(next).pop();
|
|
113
|
+
if (!lastKey)
|
|
114
|
+
break;
|
|
115
|
+
delete next[lastKey];
|
|
116
|
+
}
|
|
117
|
+
if (JSON.stringify(next).length <= MAX_SYNC_RESULT_JSON_LENGTH)
|
|
118
|
+
return next;
|
|
119
|
+
return truncateSyncResult(serialized);
|
|
120
|
+
}
|
|
121
|
+
if (Array.isArray(value)) {
|
|
122
|
+
const next = [];
|
|
123
|
+
for (const entry of value) {
|
|
124
|
+
next.push(truncateSyncResult(entry));
|
|
125
|
+
if (JSON.stringify(next).length > MAX_SYNC_RESULT_JSON_LENGTH) {
|
|
126
|
+
next[next.length - 1] = '[truncated]';
|
|
127
|
+
if (JSON.stringify(next).length > MAX_SYNC_RESULT_JSON_LENGTH) {
|
|
128
|
+
next.pop();
|
|
129
|
+
break;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
while (next.length > 0 && JSON.stringify(next).length > MAX_SYNC_RESULT_JSON_LENGTH) {
|
|
134
|
+
next.pop();
|
|
135
|
+
}
|
|
136
|
+
if (JSON.stringify(next).length <= MAX_SYNC_RESULT_JSON_LENGTH)
|
|
137
|
+
return next;
|
|
138
|
+
return truncateSyncResult(serialized);
|
|
139
|
+
}
|
|
140
|
+
return '[truncated]';
|
|
141
|
+
}
|
|
142
|
+
catch {
|
|
143
|
+
return '[unserializable result omitted]';
|
|
144
|
+
}
|
|
145
|
+
}
|
|
61
146
|
export class LocalAdapter {
|
|
62
147
|
baseUrl;
|
|
63
148
|
defaultTimeout = 60000;
|
|
64
149
|
validatedTabCache = new Map();
|
|
65
150
|
syncedNetworkRequestMarkers = new Map();
|
|
151
|
+
auditScreenshotChains = new Map();
|
|
66
152
|
TAB_CACHE_TTL_MS = 60_000;
|
|
67
153
|
/** Injected fetch function — allows unit tests to intercept all HTTP calls. */
|
|
68
154
|
fetchFn;
|
|
@@ -117,6 +203,102 @@ export class LocalAdapter {
|
|
|
117
203
|
? request.id
|
|
118
204
|
: undefined;
|
|
119
205
|
}
|
|
206
|
+
getScreenshotMimeType(format) {
|
|
207
|
+
return format === 'jpeg' ? 'image/jpeg'
|
|
208
|
+
: format === 'webp' ? 'image/webp'
|
|
209
|
+
: 'image/png';
|
|
210
|
+
}
|
|
211
|
+
buildAuditScreenshotCaption(type, details) {
|
|
212
|
+
const subject = typeof details['selector'] === 'string' ? details['selector']
|
|
213
|
+
: typeof details['url'] === 'string' ? details['url']
|
|
214
|
+
: typeof details['key'] === 'string' ? details['key']
|
|
215
|
+
: 'page state';
|
|
216
|
+
return `Audit after ${type}: ${subject}`.slice(0, 240);
|
|
217
|
+
}
|
|
218
|
+
async runSerializedAuditScreenshotCapture(key, task) {
|
|
219
|
+
const prior = this.auditScreenshotChains.get(key) ?? Promise.resolve();
|
|
220
|
+
const current = prior.catch(() => { }).then(task);
|
|
221
|
+
this.auditScreenshotChains.set(key, current);
|
|
222
|
+
try {
|
|
223
|
+
await current;
|
|
224
|
+
}
|
|
225
|
+
finally {
|
|
226
|
+
if (this.auditScreenshotChains.get(key) === current) {
|
|
227
|
+
this.auditScreenshotChains.delete(key);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
async captureAuditScreenshot(tabId, type, details) {
|
|
232
|
+
const auditState = resolveTabAuditState({ tabId });
|
|
233
|
+
if (!auditState.enabled)
|
|
234
|
+
return;
|
|
235
|
+
const persistedSessionId = readCliSessionId(tabId);
|
|
236
|
+
if (!persistedSessionId)
|
|
237
|
+
return;
|
|
238
|
+
const captureKey = `${tabId}:${persistedSessionId}`;
|
|
239
|
+
await this.runSerializedAuditScreenshotCapture(captureKey, async () => {
|
|
240
|
+
const dedupKey = typeof details['__auditActionId'] === 'string'
|
|
241
|
+
? `${type}:${details['__auditActionId']}`
|
|
242
|
+
: undefined;
|
|
243
|
+
const persistedAuditState = readCliAuditScreenshotState(tabId, persistedSessionId) ?? { count: 0, recentKeys: [] };
|
|
244
|
+
if (dedupKey && persistedAuditState.recentKeys.includes(dedupKey))
|
|
245
|
+
return;
|
|
246
|
+
if (persistedAuditState.count >= AUDIT_SCREENSHOT_SESSION_CEILING) {
|
|
247
|
+
console.warn(`[thinkrun] audit screenshot ceiling reached for session ${persistedSessionId}; dropping additional audit frames`);
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
const sessionId = this.tabOverride ? undefined : this.getAgentSessionId();
|
|
251
|
+
const headers = { 'Content-Type': 'application/json' };
|
|
252
|
+
if (sessionId)
|
|
253
|
+
headers['x-session-id'] = sessionId;
|
|
254
|
+
try {
|
|
255
|
+
const response = await this.fetchFn(`${this.baseUrl}/sessions/${tabId}/screenshot`, {
|
|
256
|
+
method: 'POST',
|
|
257
|
+
headers,
|
|
258
|
+
body: JSON.stringify({ type: 'png' }),
|
|
259
|
+
signal: unrefAbortSignal(AUDIT_SCREENSHOT_TIMEOUT_MS),
|
|
260
|
+
});
|
|
261
|
+
const json = await response.json();
|
|
262
|
+
if (!response.ok || json?.success === false)
|
|
263
|
+
return;
|
|
264
|
+
const screenshot = json?.data && typeof json.data === 'object'
|
|
265
|
+
? json.data.screenshot
|
|
266
|
+
: json?.data;
|
|
267
|
+
if (typeof screenshot !== 'string' || screenshot.length === 0)
|
|
268
|
+
return;
|
|
269
|
+
const delivered = await syncScreenshotAction(persistedSessionId, screenshot, this.getScreenshotMimeType('png'), this.buildAuditScreenshotCaption(type, details), typeof details['__auditTimestamp'] === 'string' ? details['__auditTimestamp'] : undefined, this.fetchFn);
|
|
270
|
+
if (!delivered)
|
|
271
|
+
return;
|
|
272
|
+
writeCliAuditScreenshotState(tabId, persistedSessionId, {
|
|
273
|
+
count: persistedAuditState.count + 1,
|
|
274
|
+
recentKeys: dedupKey
|
|
275
|
+
? [...persistedAuditState.recentKeys, dedupKey].slice(-AUDIT_SCREENSHOT_RECENT_KEY_LIMIT)
|
|
276
|
+
: persistedAuditState.recentKeys,
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
catch {
|
|
280
|
+
// Fire-and-forget audit capture must never break the primary action path.
|
|
281
|
+
}
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
triggerAuditScreenshot(tabId, type, details) {
|
|
285
|
+
this.captureAuditScreenshot(tabId, type, details).catch(() => {
|
|
286
|
+
// Explicit swallow so callers never observe audit capture failures.
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
createAuditActionId(type) {
|
|
290
|
+
return `${type}:${randomUUID()}`;
|
|
291
|
+
}
|
|
292
|
+
buildAuditCaptureDetails(type, actionId, details) {
|
|
293
|
+
const captureDetails = {
|
|
294
|
+
...details,
|
|
295
|
+
// Post-action capture timestamp used to order deferred audit screenshots.
|
|
296
|
+
__auditTimestamp: new Date().toISOString(),
|
|
297
|
+
};
|
|
298
|
+
if (!actionId)
|
|
299
|
+
return captureDetails;
|
|
300
|
+
return { ...captureDetails, __auditActionId: actionId };
|
|
301
|
+
}
|
|
120
302
|
getNetworkRequestMarker(request) {
|
|
121
303
|
const method = typeof request.method === 'string' ? request.method : undefined;
|
|
122
304
|
const url = typeof request.url === 'string' ? request.url : undefined;
|
|
@@ -711,7 +893,7 @@ export class LocalAdapter {
|
|
|
711
893
|
apiErr.retryHint = json.retryHint;
|
|
712
894
|
throw apiErr;
|
|
713
895
|
}
|
|
714
|
-
return json;
|
|
896
|
+
return { ...json, __thinkrunRequestId: requestId };
|
|
715
897
|
}
|
|
716
898
|
catch (error) {
|
|
717
899
|
this.logDiagnostics('bridge_request_error', {
|
|
@@ -823,6 +1005,7 @@ export class LocalAdapter {
|
|
|
823
1005
|
// --- Navigation ---
|
|
824
1006
|
async navigate(url, options = {}) {
|
|
825
1007
|
const tabId = await this.getActiveTabId();
|
|
1008
|
+
const auditActionId = this.createAuditActionId('navigate');
|
|
826
1009
|
try {
|
|
827
1010
|
const response = await this.request(`/sessions/${tabId}/navigate`, {
|
|
828
1011
|
method: 'POST',
|
|
@@ -837,7 +1020,9 @@ export class LocalAdapter {
|
|
|
837
1020
|
const syncedUrl = typeof response.data?.url === 'string' && response.data.url.length > 0
|
|
838
1021
|
? response.data.url
|
|
839
1022
|
: url;
|
|
840
|
-
|
|
1023
|
+
const syncDetails = { url: syncedUrl };
|
|
1024
|
+
this.syncAction(tabId, 'navigate', syncDetails);
|
|
1025
|
+
this.triggerAuditScreenshot(tabId, 'navigate', this.buildAuditCaptureDetails('navigate', auditActionId, syncDetails));
|
|
841
1026
|
}
|
|
842
1027
|
return { success: response.success, data: response.data };
|
|
843
1028
|
}
|
|
@@ -860,16 +1045,24 @@ export class LocalAdapter {
|
|
|
860
1045
|
}
|
|
861
1046
|
async goBack() {
|
|
862
1047
|
const tabId = await this.getActiveTabId();
|
|
1048
|
+
const auditActionId = this.createAuditActionId('go-back');
|
|
863
1049
|
const response = await this.request(`/sessions/${tabId}/go-back`, { method: 'POST' });
|
|
864
|
-
if (response.success)
|
|
865
|
-
|
|
1050
|
+
if (response.success) {
|
|
1051
|
+
const syncDetails = {};
|
|
1052
|
+
this.syncAction(tabId, 'go-back', syncDetails);
|
|
1053
|
+
this.triggerAuditScreenshot(tabId, 'go-back', this.buildAuditCaptureDetails('go-back', auditActionId, syncDetails));
|
|
1054
|
+
}
|
|
866
1055
|
return { success: response.success, data: response.data };
|
|
867
1056
|
}
|
|
868
1057
|
async goForward() {
|
|
869
1058
|
const tabId = await this.getActiveTabId();
|
|
1059
|
+
const auditActionId = this.createAuditActionId('go-forward');
|
|
870
1060
|
const response = await this.request(`/sessions/${tabId}/go-forward`, { method: 'POST' });
|
|
871
|
-
if (response.success)
|
|
872
|
-
|
|
1061
|
+
if (response.success) {
|
|
1062
|
+
const syncDetails = {};
|
|
1063
|
+
this.syncAction(tabId, 'go-forward', syncDetails);
|
|
1064
|
+
this.triggerAuditScreenshot(tabId, 'go-forward', this.buildAuditCaptureDetails('go-forward', auditActionId, syncDetails));
|
|
1065
|
+
}
|
|
873
1066
|
return { success: response.success, data: response.data };
|
|
874
1067
|
}
|
|
875
1068
|
// --- Fingerprint + obstacle helpers ─────────────────────────────────────
|
|
@@ -924,6 +1117,7 @@ export class LocalAdapter {
|
|
|
924
1117
|
// --- Interaction ---
|
|
925
1118
|
async click(selector, options = {}) {
|
|
926
1119
|
const tabId = await this.getActiveTabId();
|
|
1120
|
+
const auditActionId = this.createAuditActionId('click');
|
|
927
1121
|
// Capture pre-action fingerprint (best-effort)
|
|
928
1122
|
const pre = await this.tryCaptureFP(selector);
|
|
929
1123
|
let response;
|
|
@@ -966,12 +1160,16 @@ export class LocalAdapter {
|
|
|
966
1160
|
}
|
|
967
1161
|
catch { /* fingerprint failure — do not break normal flow */ }
|
|
968
1162
|
}
|
|
969
|
-
if (response.success)
|
|
970
|
-
|
|
1163
|
+
if (response.success) {
|
|
1164
|
+
const syncDetails = { selector };
|
|
1165
|
+
this.syncAction(tabId, 'click', syncDetails);
|
|
1166
|
+
this.triggerAuditScreenshot(tabId, 'click', this.buildAuditCaptureDetails('click', auditActionId, syncDetails));
|
|
1167
|
+
}
|
|
971
1168
|
return { success: response.success };
|
|
972
1169
|
}
|
|
973
1170
|
async clickAt(x, y, options = {}) {
|
|
974
1171
|
const tabId = await this.getActiveTabId();
|
|
1172
|
+
const auditActionId = this.createAuditActionId('click_at');
|
|
975
1173
|
// Coordinate clicks are an escape hatch when semantic targeting has already
|
|
976
1174
|
// failed, so there is no stable selector to fingerprint pre/post here.
|
|
977
1175
|
const response = await this.request(`/sessions/${tabId}/click-at`, {
|
|
@@ -984,12 +1182,16 @@ export class LocalAdapter {
|
|
|
984
1182
|
timeout: options.timeout ?? 15000,
|
|
985
1183
|
}),
|
|
986
1184
|
});
|
|
987
|
-
if (response.success)
|
|
988
|
-
|
|
1185
|
+
if (response.success) {
|
|
1186
|
+
const syncDetails = { x, y, coordinateSpace: 'viewport' };
|
|
1187
|
+
this.syncAction(tabId, 'click_at', syncDetails);
|
|
1188
|
+
this.triggerAuditScreenshot(tabId, 'click_at', this.buildAuditCaptureDetails('click_at', auditActionId, syncDetails));
|
|
1189
|
+
}
|
|
989
1190
|
return { success: response.success, data: response.data };
|
|
990
1191
|
}
|
|
991
1192
|
async type(selector, text, options = {}) {
|
|
992
1193
|
const tabId = await this.getActiveTabId();
|
|
1194
|
+
const auditActionId = this.createAuditActionId('type');
|
|
993
1195
|
const pre = await this.tryCaptureFP(selector);
|
|
994
1196
|
let response;
|
|
995
1197
|
try {
|
|
@@ -1023,12 +1225,16 @@ export class LocalAdapter {
|
|
|
1023
1225
|
}
|
|
1024
1226
|
catch { /* fingerprint failure — do not break normal flow */ }
|
|
1025
1227
|
}
|
|
1026
|
-
if (response.success)
|
|
1027
|
-
|
|
1228
|
+
if (response.success) {
|
|
1229
|
+
const syncDetails = { selector };
|
|
1230
|
+
this.syncAction(tabId, 'type', syncDetails);
|
|
1231
|
+
this.triggerAuditScreenshot(tabId, 'type', this.buildAuditCaptureDetails('type', auditActionId, syncDetails));
|
|
1232
|
+
}
|
|
1028
1233
|
return { success: response.success };
|
|
1029
1234
|
}
|
|
1030
1235
|
async fill(selector, value) {
|
|
1031
1236
|
const tabId = await this.getActiveTabId();
|
|
1237
|
+
const auditActionId = this.createAuditActionId('fill');
|
|
1032
1238
|
const pre = await this.tryCaptureFP(selector);
|
|
1033
1239
|
let response;
|
|
1034
1240
|
try {
|
|
@@ -1062,18 +1268,25 @@ export class LocalAdapter {
|
|
|
1062
1268
|
}
|
|
1063
1269
|
catch { /* fingerprint failure — do not break normal flow */ }
|
|
1064
1270
|
}
|
|
1065
|
-
if (response.success)
|
|
1066
|
-
|
|
1271
|
+
if (response.success) {
|
|
1272
|
+
const syncDetails = { selector };
|
|
1273
|
+
this.syncAction(tabId, 'fill', syncDetails);
|
|
1274
|
+
this.triggerAuditScreenshot(tabId, 'fill', this.buildAuditCaptureDetails('fill', auditActionId, syncDetails));
|
|
1275
|
+
}
|
|
1067
1276
|
return { success: response.success };
|
|
1068
1277
|
}
|
|
1069
1278
|
async press(key) {
|
|
1070
1279
|
const tabId = await this.getActiveTabId();
|
|
1280
|
+
const auditActionId = this.createAuditActionId('press');
|
|
1071
1281
|
const response = await this.request(`/sessions/${tabId}/press`, {
|
|
1072
1282
|
method: 'POST',
|
|
1073
1283
|
body: JSON.stringify({ key }),
|
|
1074
1284
|
});
|
|
1075
|
-
if (response.success)
|
|
1076
|
-
|
|
1285
|
+
if (response.success) {
|
|
1286
|
+
const syncDetails = { key };
|
|
1287
|
+
this.syncAction(tabId, 'press', syncDetails);
|
|
1288
|
+
this.triggerAuditScreenshot(tabId, 'press', this.buildAuditCaptureDetails('press', auditActionId, syncDetails));
|
|
1289
|
+
}
|
|
1077
1290
|
return { success: response.success };
|
|
1078
1291
|
}
|
|
1079
1292
|
async scroll(options) {
|
|
@@ -1081,6 +1294,7 @@ export class LocalAdapter {
|
|
|
1081
1294
|
// Selector-based: scroll element into view via evaluate, but sync as 'scroll'
|
|
1082
1295
|
// (not 'evaluate') so the activity feed shows the user-facing action type.
|
|
1083
1296
|
if (options.selector) {
|
|
1297
|
+
const auditActionId = this.createAuditActionId('scroll');
|
|
1084
1298
|
const resp = await this.request(`/sessions/${tabId}/evaluate`, {
|
|
1085
1299
|
method: 'POST',
|
|
1086
1300
|
body: JSON.stringify({
|
|
@@ -1088,8 +1302,11 @@ export class LocalAdapter {
|
|
|
1088
1302
|
args: [],
|
|
1089
1303
|
}),
|
|
1090
1304
|
});
|
|
1091
|
-
if (resp.success)
|
|
1092
|
-
|
|
1305
|
+
if (resp.success) {
|
|
1306
|
+
const syncDetails = { selector: options.selector };
|
|
1307
|
+
this.syncAction(tabId, 'scroll', syncDetails);
|
|
1308
|
+
this.triggerAuditScreenshot(tabId, 'scroll', this.buildAuditCaptureDetails('scroll', auditActionId, syncDetails));
|
|
1309
|
+
}
|
|
1093
1310
|
return { success: resp.success, data: resp.data };
|
|
1094
1311
|
}
|
|
1095
1312
|
// Horizontal scroll is not supported by the native host's handleScroll (which only
|
|
@@ -1101,23 +1318,31 @@ export class LocalAdapter {
|
|
|
1101
1318
|
// Translate y offset → {direction, amount} as expected by native host handleScroll
|
|
1102
1319
|
const direction = (options.y !== undefined && options.y < 0) ? 'up' : 'down';
|
|
1103
1320
|
const amount = options.y !== undefined ? Math.abs(options.y) : 500;
|
|
1321
|
+
const auditActionId = this.createAuditActionId('scroll');
|
|
1104
1322
|
const response = await this.request(`/sessions/${tabId}/scroll`, {
|
|
1105
1323
|
method: 'POST',
|
|
1106
1324
|
body: JSON.stringify({ direction, amount }),
|
|
1107
1325
|
});
|
|
1108
|
-
if (response.success)
|
|
1109
|
-
|
|
1326
|
+
if (response.success) {
|
|
1327
|
+
const syncDetails = { direction, amount };
|
|
1328
|
+
this.syncAction(tabId, 'scroll', syncDetails);
|
|
1329
|
+
this.triggerAuditScreenshot(tabId, 'scroll', this.buildAuditCaptureDetails('scroll', auditActionId, syncDetails));
|
|
1330
|
+
}
|
|
1110
1331
|
return { success: response.success };
|
|
1111
1332
|
}
|
|
1112
1333
|
async hover(selector) {
|
|
1113
1334
|
const tabId = await this.getActiveTabId();
|
|
1335
|
+
const auditActionId = this.createAuditActionId('hover');
|
|
1114
1336
|
try {
|
|
1115
1337
|
const response = await this.request(`/sessions/${tabId}/hover`, {
|
|
1116
1338
|
method: 'POST',
|
|
1117
1339
|
body: JSON.stringify({ selector }),
|
|
1118
1340
|
});
|
|
1119
|
-
if (response.success)
|
|
1120
|
-
|
|
1341
|
+
if (response.success) {
|
|
1342
|
+
const syncDetails = { selector };
|
|
1343
|
+
this.syncAction(tabId, 'hover', syncDetails);
|
|
1344
|
+
this.triggerAuditScreenshot(tabId, 'hover', this.buildAuditCaptureDetails('hover', auditActionId, syncDetails));
|
|
1345
|
+
}
|
|
1121
1346
|
return { success: response.success };
|
|
1122
1347
|
}
|
|
1123
1348
|
catch (err) {
|
|
@@ -1129,6 +1354,7 @@ export class LocalAdapter {
|
|
|
1129
1354
|
}
|
|
1130
1355
|
async select(selector, value) {
|
|
1131
1356
|
const tabId = await this.getActiveTabId();
|
|
1357
|
+
const auditActionId = this.createAuditActionId('select');
|
|
1132
1358
|
const pre = await this.tryCaptureFP(selector);
|
|
1133
1359
|
let response;
|
|
1134
1360
|
try {
|
|
@@ -1181,8 +1407,11 @@ export class LocalAdapter {
|
|
|
1181
1407
|
}
|
|
1182
1408
|
catch { /* fingerprint failure — do not break normal flow */ }
|
|
1183
1409
|
}
|
|
1184
|
-
if (response.success)
|
|
1185
|
-
|
|
1410
|
+
if (response.success) {
|
|
1411
|
+
const syncDetails = { selector };
|
|
1412
|
+
this.syncAction(tabId, 'select', syncDetails);
|
|
1413
|
+
this.triggerAuditScreenshot(tabId, 'select', this.buildAuditCaptureDetails('select', auditActionId, syncDetails));
|
|
1414
|
+
}
|
|
1186
1415
|
return { success: response.success };
|
|
1187
1416
|
}
|
|
1188
1417
|
// --- Waiting ---
|
|
@@ -1245,9 +1474,7 @@ export class LocalAdapter {
|
|
|
1245
1474
|
const tempPath = join(tmpdir(), `thinkrun-${ts}-${randomUUID().slice(0, 8)}.png`);
|
|
1246
1475
|
writeFileSync(tempPath, Buffer.from(b64, 'base64'));
|
|
1247
1476
|
// Derive MIME type once — used for both the artifact upload and the sync action.
|
|
1248
|
-
const mimeType = options.format
|
|
1249
|
-
: options.format === 'webp' ? 'image/webp'
|
|
1250
|
-
: 'image/png';
|
|
1477
|
+
const mimeType = this.getScreenshotMimeType(options.format);
|
|
1251
1478
|
// If this local tab has a registered cloud session (from startSession()), sync
|
|
1252
1479
|
// the screenshot as an action in the activity feed. Fire-and-forget — never
|
|
1253
1480
|
// blocks the caller.
|
|
@@ -1263,7 +1490,7 @@ export class LocalAdapter {
|
|
|
1263
1490
|
if (!caption) {
|
|
1264
1491
|
throw new Error('Local screenshots synced to ThinkRun require --caption <text>');
|
|
1265
1492
|
}
|
|
1266
|
-
syncScreenshotAction(persistedSessionId, b64, mimeType, caption, this.fetchFn);
|
|
1493
|
+
syncScreenshotAction(persistedSessionId, b64, mimeType, caption, undefined, this.fetchFn);
|
|
1267
1494
|
}
|
|
1268
1495
|
}
|
|
1269
1496
|
// If API key is configured, upload to cloud artifact storage so the screenshot
|
|
@@ -1323,8 +1550,9 @@ export class LocalAdapter {
|
|
|
1323
1550
|
multiple: options.all,
|
|
1324
1551
|
}),
|
|
1325
1552
|
});
|
|
1326
|
-
if (response.success)
|
|
1327
|
-
this.syncAction(tabId, 'extract', { selector: selector || 'page' });
|
|
1553
|
+
if (response.success) {
|
|
1554
|
+
this.syncAction(tabId, 'extract', { selector: selector || 'page' }, { result: sanitizeAndTruncateSyncResult(response.data) });
|
|
1555
|
+
}
|
|
1328
1556
|
return { success: response.success, data: response.data };
|
|
1329
1557
|
}
|
|
1330
1558
|
async evaluate(script, args = [], evalOpts) {
|
|
@@ -1336,7 +1564,7 @@ export class LocalAdapter {
|
|
|
1336
1564
|
timeoutMs: Math.min(timeoutMs + 15_000, 615_000),
|
|
1337
1565
|
});
|
|
1338
1566
|
if (response.success)
|
|
1339
|
-
this.syncAction(tabId, 'evaluate', {}, { result: response.data });
|
|
1567
|
+
this.syncAction(tabId, 'evaluate', {}, { result: sanitizeAndTruncateSyncResult(response.data) });
|
|
1340
1568
|
return { success: response.success, data: response.data };
|
|
1341
1569
|
}
|
|
1342
1570
|
async getUrl() {
|