@nuanu-ai/agentbrowse 0.2.46 → 0.2.48
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 +69 -10
- package/dist/agentpay-gateway.d.ts +9 -0
- package/dist/agentpay-gateway.d.ts.map +1 -1
- package/dist/agentpay-gateway.js +30 -0
- package/dist/agentpay-stagehand-llm.d.ts.map +1 -1
- package/dist/agentpay-stagehand-llm.js +9 -1
- package/dist/command-api-tracing.d.ts +19 -0
- package/dist/command-api-tracing.d.ts.map +1 -0
- package/dist/command-api-tracing.js +137 -0
- package/dist/commands/act.d.ts.map +1 -1
- package/dist/commands/act.js +822 -670
- package/dist/commands/act.test-harness.d.ts +6 -0
- package/dist/commands/act.test-harness.d.ts.map +1 -1
- package/dist/commands/act.test-harness.js +44 -1
- package/dist/commands/action-acceptance.d.ts.map +1 -1
- package/dist/commands/action-acceptance.js +115 -0
- package/dist/commands/captcha-solve.d.ts.map +1 -1
- package/dist/commands/captcha-solve.js +83 -16
- package/dist/commands/click-action-executor.d.ts +0 -1
- package/dist/commands/click-action-executor.d.ts.map +1 -1
- package/dist/commands/click-action-executor.js +31 -77
- package/dist/commands/close.d.ts +3 -3
- package/dist/commands/close.d.ts.map +1 -1
- package/dist/commands/close.js +178 -0
- package/dist/commands/descriptor-validation.d.ts.map +1 -1
- package/dist/commands/descriptor-validation.js +75 -57
- package/dist/commands/end-session.d.ts +25 -0
- package/dist/commands/end-session.d.ts.map +1 -0
- package/dist/commands/end-session.js +161 -0
- package/dist/commands/extract-stagehand-executor.js +1 -1
- package/dist/commands/extract.d.ts.map +1 -1
- package/dist/commands/extract.js +339 -202
- package/dist/commands/fill-secret.d.ts +3 -3
- package/dist/commands/fill-secret.d.ts.map +1 -1
- package/dist/commands/fill-secret.js +419 -234
- package/dist/commands/get-secrets-catalog.d.ts.map +1 -1
- package/dist/commands/get-secrets-catalog.js +66 -5
- package/dist/commands/interaction-kernel.d.ts +46 -0
- package/dist/commands/interaction-kernel.d.ts.map +1 -0
- package/dist/commands/interaction-kernel.js +215 -0
- package/dist/commands/launch.d.ts +0 -2
- package/dist/commands/launch.d.ts.map +1 -1
- package/dist/commands/launch.js +109 -17
- package/dist/commands/navigate.d.ts.map +1 -1
- package/dist/commands/navigate.js +188 -45
- package/dist/commands/observe-accessibility.d.ts.map +1 -1
- package/dist/commands/observe-accessibility.js +50 -39
- package/dist/commands/observe-dom-label-contract.d.ts.map +1 -1
- package/dist/commands/observe-dom-label-contract.js +5 -0
- package/dist/commands/observe-inventory.d.ts +13 -0
- package/dist/commands/observe-inventory.d.ts.map +1 -1
- package/dist/commands/observe-inventory.js +320 -65
- package/dist/commands/observe-persistence.d.ts.map +1 -1
- package/dist/commands/observe-persistence.js +3 -0
- package/dist/commands/observe-projection.d.ts +1 -0
- package/dist/commands/observe-projection.d.ts.map +1 -1
- package/dist/commands/observe-projection.js +7 -2
- package/dist/commands/observe-protected.d.ts +1 -0
- package/dist/commands/observe-protected.d.ts.map +1 -1
- package/dist/commands/observe-protected.js +9 -4
- package/dist/commands/observe-semantics.d.ts.map +1 -1
- package/dist/commands/observe-semantics.js +5 -2
- package/dist/commands/observe-stagehand.d.ts +1 -0
- package/dist/commands/observe-stagehand.d.ts.map +1 -1
- package/dist/commands/observe-stagehand.js +2 -0
- package/dist/commands/observe.d.ts +2 -0
- package/dist/commands/observe.d.ts.map +1 -1
- package/dist/commands/observe.js +387 -203
- package/dist/commands/observe.test-harness.d.ts +8 -0
- package/dist/commands/observe.test-harness.d.ts.map +1 -1
- package/dist/commands/observe.test-harness.js +48 -1
- package/dist/commands/poll-secret.d.ts +6 -0
- package/dist/commands/poll-secret.d.ts.map +1 -0
- package/dist/commands/poll-secret.js +159 -0
- package/dist/commands/request-secret.d.ts +6 -0
- package/dist/commands/request-secret.d.ts.map +1 -0
- package/dist/commands/request-secret.js +284 -0
- package/dist/commands/screenshot.d.ts.map +1 -1
- package/dist/commands/screenshot.js +172 -7
- package/dist/commands/select-action-executor.d.ts.map +1 -1
- package/dist/commands/semantic-observe.d.ts +4 -0
- package/dist/commands/semantic-observe.d.ts.map +1 -1
- package/dist/commands/semantic-observe.js +388 -17
- package/dist/commands/start-session.d.ts +31 -0
- package/dist/commands/start-session.d.ts.map +1 -0
- package/dist/commands/start-session.js +347 -0
- package/dist/commands/status.d.ts +2 -1
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +166 -144
- package/dist/control-semantics.d.ts +1 -0
- package/dist/control-semantics.d.ts.map +1 -1
- package/dist/control-semantics.js +51 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +144 -45
- package/dist/otel-exporter.d.ts +58 -0
- package/dist/otel-exporter.d.ts.map +1 -0
- package/dist/otel-exporter.js +263 -0
- package/dist/otel-projector.d.ts +75 -0
- package/dist/otel-projector.d.ts.map +1 -0
- package/dist/otel-projector.js +409 -0
- package/dist/owned-browser.d.ts +1 -1
- package/dist/owned-browser.d.ts.map +1 -1
- package/dist/owned-browser.js +13 -1
- package/dist/owned-process.d.ts +2 -0
- package/dist/owned-process.d.ts.map +1 -1
- package/dist/owned-process.js +7 -3
- package/dist/playwright-runtime.d.ts +1 -1
- package/dist/playwright-runtime.d.ts.map +1 -1
- package/dist/playwright-runtime.js +8 -8
- package/dist/run-observability.d.ts +25 -0
- package/dist/run-observability.d.ts.map +1 -0
- package/dist/run-observability.js +115 -0
- package/dist/run-store.d.ts +274 -0
- package/dist/run-store.d.ts.map +1 -0
- package/dist/run-store.js +631 -0
- package/dist/runtime-metrics.d.ts +27 -0
- package/dist/runtime-metrics.d.ts.map +1 -0
- package/dist/runtime-metrics.js +66 -0
- package/dist/runtime-page-state.d.ts +11 -0
- package/dist/runtime-page-state.d.ts.map +1 -0
- package/dist/runtime-page-state.js +62 -0
- package/dist/runtime-protected-state.d.ts +16 -0
- package/dist/runtime-protected-state.d.ts.map +1 -0
- package/dist/runtime-protected-state.js +157 -0
- package/dist/runtime-state.d.ts +10 -44
- package/dist/runtime-state.d.ts.map +1 -1
- package/dist/runtime-state.js +57 -222
- package/dist/secrets/backend.d.ts +65 -16
- package/dist/secrets/backend.d.ts.map +1 -1
- package/dist/secrets/backend.js +135 -95
- package/dist/secrets/catalog-sync.d.ts.map +1 -1
- package/dist/secrets/catalog-sync.js +4 -1
- package/dist/secrets/form-matcher.d.ts +5 -5
- package/dist/secrets/form-matcher.d.ts.map +1 -1
- package/dist/secrets/form-matcher.js +292 -164
- package/dist/secrets/intent-output.d.ts +6 -10
- package/dist/secrets/intent-output.d.ts.map +1 -1
- package/dist/secrets/intent-output.js +4 -58
- package/dist/secrets/mock-agentpay-cabinet.d.ts +38 -27
- package/dist/secrets/mock-agentpay-cabinet.d.ts.map +1 -1
- package/dist/secrets/mock-agentpay-cabinet.js +177 -111
- package/dist/secrets/protected-artifact-guard.d.ts +2 -2
- package/dist/secrets/protected-artifact-guard.d.ts.map +1 -1
- package/dist/secrets/protected-artifact-guard.js +2 -2
- package/dist/secrets/protected-bindings.d.ts +1 -1
- package/dist/secrets/protected-bindings.d.ts.map +1 -1
- package/dist/secrets/protected-bindings.js +6 -0
- package/dist/secrets/protected-field-semantics.d.ts +9 -0
- package/dist/secrets/protected-field-semantics.d.ts.map +1 -0
- package/dist/secrets/protected-field-semantics.js +154 -0
- package/dist/secrets/protected-field-values.d.ts.map +1 -1
- package/dist/secrets/protected-field-values.js +3 -3
- package/dist/secrets/protected-fill.d.ts +1 -1
- package/dist/secrets/protected-fill.d.ts.map +1 -1
- package/dist/secrets/protected-fill.js +45 -149
- package/dist/secrets/protected-value-adapters.d.ts +2 -1
- package/dist/secrets/protected-value-adapters.d.ts.map +1 -1
- package/dist/secrets/protected-value-adapters.js +80 -1
- package/dist/secrets/request-output.d.ts +11 -0
- package/dist/secrets/request-output.d.ts.map +1 -0
- package/dist/secrets/request-output.js +75 -0
- package/dist/secrets/types.d.ts +15 -9
- package/dist/secrets/types.d.ts.map +1 -1
- package/dist/secrets/types.js +3 -0
- package/dist/session-event-exporter.d.ts +36 -0
- package/dist/session-event-exporter.d.ts.map +1 -0
- package/dist/session-event-exporter.js +428 -0
- package/dist/session.d.ts +16 -7
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +150 -23
- package/dist/sessions-backend.d.ts +354 -0
- package/dist/sessions-backend.d.ts.map +1 -0
- package/dist/sessions-backend.js +126 -0
- package/dist/solver/browser-launcher.d.ts +1 -1
- package/dist/solver/browser-launcher.d.ts.map +1 -1
- package/dist/solver/browser-launcher.js +39 -13
- package/dist/solver/captcha-solver.d.ts.map +1 -1
- package/dist/solver/captcha-solver.js +8 -1
- package/dist/solver/types.d.ts +1 -0
- package/dist/solver/types.d.ts.map +1 -1
- package/dist/workflow-session-completion.d.ts +33 -0
- package/dist/workflow-session-completion.d.ts.map +1 -0
- package/dist/workflow-session-completion.js +156 -0
- package/package.json +9 -1
- package/dist/commands/create-intent.d.ts +0 -6
- package/dist/commands/create-intent.d.ts.map +0 -1
- package/dist/commands/create-intent.js +0 -75
- package/dist/commands/poll-intent.d.ts +0 -6
- package/dist/commands/poll-intent.d.ts.map +0 -1
- package/dist/commands/poll-intent.js +0 -57
package/dist/index.js
CHANGED
|
@@ -7,7 +7,7 @@ import { preflightAgentpayGateway } from './agentpay-gateway.js';
|
|
|
7
7
|
import { browseCommand, browseCommandName } from './command-name.js';
|
|
8
8
|
import { assertSemanticObserveRuntimeSupport } from './commands/semantic-observe-lexical.js';
|
|
9
9
|
import { loadSession } from './session.js';
|
|
10
|
-
import { outputError, outputJSON, fatal, info } from './output.js';
|
|
10
|
+
import { outputContractFailure, outputError, outputJSON, fatal, info } from './output.js';
|
|
11
11
|
import { applyDemoProxyBootstrap } from './solver/config.js';
|
|
12
12
|
function usageText() {
|
|
13
13
|
return `Usage: ${browseCommandName()} <command> [args] [options]
|
|
@@ -15,14 +15,17 @@ function usageText() {
|
|
|
15
15
|
Commands:
|
|
16
16
|
init <apiKey> [--api-url <url>] Configure AgentPay gateway access for AgentBrowse
|
|
17
17
|
launch [url] [options] Launch browser, optionally navigate to URL
|
|
18
|
+
start-session [name] [--merchant-name <name>]
|
|
19
|
+
Start workflow session and telemetry on the current browser
|
|
20
|
+
end-session Complete the active workflow session without closing the browser
|
|
18
21
|
solve-captcha [--timeout <s>] Wait for captcha and solve it on current page
|
|
19
22
|
navigate <url> Navigate current tab to URL
|
|
20
23
|
get-secrets-catalog [url] Refresh stored-secret metadata for a URL or current page
|
|
21
|
-
|
|
22
|
-
Create or reuse
|
|
23
|
-
poll-
|
|
24
|
-
fill-secret <fillRef> <
|
|
25
|
-
|
|
24
|
+
request-secret <fillRef> <storedSecretRef> --merchant-name <name>
|
|
25
|
+
Create or reuse a session-bound secret request for one fill target
|
|
26
|
+
poll-secret <requestId> Poll one secret request state without blocking
|
|
27
|
+
fill-secret <fillRef> <requestId>
|
|
28
|
+
Claim an approved secret request and fill protected fields
|
|
26
29
|
act <targetRef> <action> [value] Perform action on a previously observed target
|
|
27
30
|
extract '<schema-json>' [scopeRef] Extract structured data from the page or a stored scope
|
|
28
31
|
observe ["<goal>"] Discover available targets/elements
|
|
@@ -40,6 +43,7 @@ Options:
|
|
|
40
43
|
--headless Launch browser in headless mode
|
|
41
44
|
--path <file> Output path for screenshot
|
|
42
45
|
--timeout <seconds> Timeout for solve-captcha command (default: 90)
|
|
46
|
+
--merchant-name <name> Merchant/vendor name for start-session or request-secret
|
|
43
47
|
--help Show this help message
|
|
44
48
|
|
|
45
49
|
Environment:
|
|
@@ -48,11 +52,13 @@ Environment:
|
|
|
48
52
|
}
|
|
49
53
|
const KNOWN_COMMANDS = new Set([
|
|
50
54
|
'launch',
|
|
55
|
+
'start-session',
|
|
56
|
+
'end-session',
|
|
51
57
|
'init',
|
|
52
58
|
'navigate',
|
|
53
59
|
'get-secrets-catalog',
|
|
54
|
-
'
|
|
55
|
-
'poll-
|
|
60
|
+
'request-secret',
|
|
61
|
+
'poll-secret',
|
|
56
62
|
'fill-secret',
|
|
57
63
|
'solve-captcha',
|
|
58
64
|
'act',
|
|
@@ -201,19 +207,96 @@ function parseInitArgs(args) {
|
|
|
201
207
|
apiUrl,
|
|
202
208
|
};
|
|
203
209
|
}
|
|
210
|
+
function parseStartSessionArgs(args) {
|
|
211
|
+
const nameParts = [];
|
|
212
|
+
let merchantName;
|
|
213
|
+
for (let i = 0; i < args.length; i++) {
|
|
214
|
+
const arg = args[i];
|
|
215
|
+
if (arg === '--merchant-name') {
|
|
216
|
+
const value = args[i + 1];
|
|
217
|
+
if (!value || value.startsWith('--')) {
|
|
218
|
+
outputError(`Usage: ${browseCommand('start-session', '[name]', '[--merchant-name <name>]')}`);
|
|
219
|
+
}
|
|
220
|
+
merchantName = value;
|
|
221
|
+
i += 1;
|
|
222
|
+
continue;
|
|
223
|
+
}
|
|
224
|
+
if (arg.startsWith('--')) {
|
|
225
|
+
outputError(`Usage: ${browseCommand('start-session', '[name]', '[--merchant-name <name>]')}`);
|
|
226
|
+
}
|
|
227
|
+
nameParts.push(arg);
|
|
228
|
+
}
|
|
229
|
+
return {
|
|
230
|
+
name: nameParts.join(' ').trim() || undefined,
|
|
231
|
+
merchantName,
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
function parseRequestSecretArgs(args) {
|
|
235
|
+
const positionals = [];
|
|
236
|
+
let merchantName;
|
|
237
|
+
for (let i = 0; i < args.length; i++) {
|
|
238
|
+
const arg = args[i];
|
|
239
|
+
if (arg === '--merchant-name') {
|
|
240
|
+
const value = args[i + 1];
|
|
241
|
+
if (!value || value.startsWith('--')) {
|
|
242
|
+
outputError(`Usage: ${browseCommand('request-secret', '<fillRef>', '<storedSecretRef>', '--merchant-name <name>')}`);
|
|
243
|
+
}
|
|
244
|
+
merchantName = value.trim();
|
|
245
|
+
i += 1;
|
|
246
|
+
continue;
|
|
247
|
+
}
|
|
248
|
+
if (arg.startsWith('--')) {
|
|
249
|
+
outputError(`Usage: ${browseCommand('request-secret', '<fillRef>', '<storedSecretRef>', '--merchant-name <name>')}`);
|
|
250
|
+
}
|
|
251
|
+
positionals.push(arg);
|
|
252
|
+
}
|
|
253
|
+
if (merchantName !== undefined && merchantName.length === 0) {
|
|
254
|
+
outputError('Invalid --merchant-name value. Expected a non-empty string.');
|
|
255
|
+
}
|
|
256
|
+
if (positionals.length !== 2) {
|
|
257
|
+
outputError(`Usage: ${browseCommand('request-secret', '<fillRef>', '<storedSecretRef>', '--merchant-name <name>')}`);
|
|
258
|
+
}
|
|
259
|
+
if (!merchantName) {
|
|
260
|
+
outputError(`The \`request-secret\` command requires \`--merchant-name <name>\` so the operator sees which vendor requested the secret.`);
|
|
261
|
+
}
|
|
262
|
+
return {
|
|
263
|
+
fillRef: positionals[0],
|
|
264
|
+
storedSecretRef: positionals[1],
|
|
265
|
+
merchantName,
|
|
266
|
+
};
|
|
267
|
+
}
|
|
204
268
|
/** Require an active browser session. */
|
|
205
|
-
function
|
|
269
|
+
function requireBrowserSessionRecord(command) {
|
|
206
270
|
const session = loadSession();
|
|
207
|
-
if (session)
|
|
271
|
+
if (session) {
|
|
208
272
|
return session;
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
273
|
+
}
|
|
274
|
+
return outputContractFailure({
|
|
275
|
+
error: 'workflow_session_required',
|
|
276
|
+
outcomeType: 'blocked',
|
|
277
|
+
message: `The \`${command}\` command requires an active product workflow session.`,
|
|
278
|
+
reason: `No persisted browser session was found. Run \`${browseCommandName()} launch [url]\` first, then \`${browseCommandName()} start-session\`.`,
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
function requireProductSessionRecord(command) {
|
|
282
|
+
const session = requireBrowserSessionRecord(command);
|
|
283
|
+
if (session.intentSessionId && session.activeRunId) {
|
|
284
|
+
return session;
|
|
285
|
+
}
|
|
286
|
+
if (!session.intentSessionId) {
|
|
287
|
+
return outputContractFailure({
|
|
288
|
+
error: 'workflow_session_required',
|
|
289
|
+
outcomeType: 'blocked',
|
|
290
|
+
message: `The \`${command}\` command requires an active product workflow session.`,
|
|
291
|
+
reason: `A browser session is loaded, but no product workflow session is active for it. Run \`${browseCommandName()} start-session\` first.`,
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
return outputContractFailure({
|
|
295
|
+
error: 'workflow_session_required',
|
|
296
|
+
outcomeType: 'blocked',
|
|
297
|
+
message: `The \`${command}\` command requires an active product workflow session.`,
|
|
298
|
+
reason: `The current product workflow session is missing its local run binding. Run \`${browseCommandName()} start-session\` again to re-bind the current browser session.`,
|
|
299
|
+
});
|
|
217
300
|
}
|
|
218
301
|
async function main(argv = process.argv) {
|
|
219
302
|
applyDemoProxyBootstrap();
|
|
@@ -257,60 +340,74 @@ async function main(argv = process.argv) {
|
|
|
257
340
|
proxy: launchArgs.proxy,
|
|
258
341
|
noProxy: launchArgs.noProxy,
|
|
259
342
|
});
|
|
260
|
-
const updateNotice = await
|
|
343
|
+
const updateNotice = await Promise.race([
|
|
344
|
+
updateNoticePromise,
|
|
345
|
+
new Promise((resolve) => {
|
|
346
|
+
queueMicrotask(() => resolve(null));
|
|
347
|
+
}),
|
|
348
|
+
]);
|
|
261
349
|
if (updateNotice) {
|
|
262
350
|
info(updateNotice.message);
|
|
263
351
|
}
|
|
264
352
|
outputJSON(launchResult);
|
|
265
353
|
break;
|
|
266
354
|
}
|
|
355
|
+
case 'start-session': {
|
|
356
|
+
const startSessionArgs = parseStartSessionArgs(args);
|
|
357
|
+
const { startSession } = await import('./commands/start-session.js');
|
|
358
|
+
outputJSON(await startSession(startSessionArgs.name, {
|
|
359
|
+
merchantName: startSessionArgs.merchantName,
|
|
360
|
+
}));
|
|
361
|
+
break;
|
|
362
|
+
}
|
|
363
|
+
case 'end-session': {
|
|
364
|
+
const { endSession } = await import('./commands/end-session.js');
|
|
365
|
+
outputJSON(await endSession(requireProductSessionRecord(command)));
|
|
366
|
+
break;
|
|
367
|
+
}
|
|
267
368
|
case 'navigate': {
|
|
268
369
|
const url = getPositional(args);
|
|
269
370
|
if (!url)
|
|
270
371
|
outputError(`Usage: ${browseCommand('navigate', '<url>')}`);
|
|
271
372
|
const { navigate } = await import('./commands/navigate.js');
|
|
272
|
-
await navigate(
|
|
373
|
+
await navigate(requireProductSessionRecord(command), url);
|
|
273
374
|
break;
|
|
274
375
|
}
|
|
275
376
|
case 'get-secrets-catalog': {
|
|
276
377
|
const url = getPositional(args);
|
|
277
378
|
const { getSecretsCatalog } = await import('./commands/get-secrets-catalog.js');
|
|
278
|
-
await getSecretsCatalog(
|
|
379
|
+
await getSecretsCatalog(requireProductSessionRecord(command), url);
|
|
279
380
|
break;
|
|
280
381
|
}
|
|
281
|
-
case '
|
|
282
|
-
const
|
|
283
|
-
const
|
|
284
|
-
|
|
285
|
-
outputError(`Usage: ${browseCommand('create-intent', '<fillRef>', '<storedSecretRef>')}`);
|
|
286
|
-
}
|
|
287
|
-
const { createIntent } = await import('./commands/create-intent.js');
|
|
288
|
-
await createIntent(requireSessionRecord(), fillRef, storedSecretRef);
|
|
382
|
+
case 'request-secret': {
|
|
383
|
+
const requestSecretArgs = parseRequestSecretArgs(args);
|
|
384
|
+
const { requestSecret } = await import('./commands/request-secret.js');
|
|
385
|
+
await requestSecret(requireProductSessionRecord(command), requestSecretArgs.fillRef, requestSecretArgs.storedSecretRef, requestSecretArgs.merchantName);
|
|
289
386
|
break;
|
|
290
387
|
}
|
|
291
|
-
case 'poll-
|
|
292
|
-
const
|
|
293
|
-
if (!
|
|
294
|
-
outputError(`Usage: ${browseCommand('poll-
|
|
388
|
+
case 'poll-secret': {
|
|
389
|
+
const requestId = getPositional(args);
|
|
390
|
+
if (!requestId) {
|
|
391
|
+
outputError(`Usage: ${browseCommand('poll-secret', '<requestId>')}`);
|
|
295
392
|
}
|
|
296
|
-
const {
|
|
297
|
-
await
|
|
393
|
+
const { pollSecret } = await import('./commands/poll-secret.js');
|
|
394
|
+
await pollSecret(requireProductSessionRecord(command), requestId);
|
|
298
395
|
break;
|
|
299
396
|
}
|
|
300
397
|
case 'fill-secret': {
|
|
301
398
|
const positionals = getPositionals(args);
|
|
302
|
-
const [fillRef,
|
|
303
|
-
if (!fillRef || !
|
|
304
|
-
outputError(`Usage: ${browseCommand('fill-secret', '<fillRef>', '<
|
|
399
|
+
const [fillRef, requestId] = positionals;
|
|
400
|
+
if (!fillRef || !requestId) {
|
|
401
|
+
outputError(`Usage: ${browseCommand('fill-secret', '<fillRef>', '<requestId>')}`);
|
|
305
402
|
}
|
|
306
403
|
const { fillSecret } = await import('./commands/fill-secret.js');
|
|
307
|
-
await fillSecret(
|
|
404
|
+
await fillSecret(requireProductSessionRecord(command), fillRef, requestId);
|
|
308
405
|
break;
|
|
309
406
|
}
|
|
310
407
|
case 'solve-captcha': {
|
|
311
408
|
const timeout = parseCaptchaTimeout(args);
|
|
312
409
|
const { captchaSolve } = await import('./commands/captcha-solve.js');
|
|
313
|
-
await captchaSolve(
|
|
410
|
+
await captchaSolve(requireProductSessionRecord(command), timeout);
|
|
314
411
|
break;
|
|
315
412
|
}
|
|
316
413
|
case 'act': {
|
|
@@ -323,7 +420,8 @@ async function main(argv = process.argv) {
|
|
|
323
420
|
if (!isBrowseAction(action)) {
|
|
324
421
|
outputError(`Unsupported act action: ${action}. Expected one of: click, fill, type, select, press.`);
|
|
325
422
|
}
|
|
326
|
-
|
|
423
|
+
const session = requireProductSessionRecord(command);
|
|
424
|
+
await act(session, targetRef, action, valueParts.length > 0 ? valueParts.join(' ') : undefined);
|
|
327
425
|
break;
|
|
328
426
|
}
|
|
329
427
|
case 'extract': {
|
|
@@ -333,13 +431,13 @@ async function main(argv = process.argv) {
|
|
|
333
431
|
outputError(`Usage: ${browseCommand('extract', "'<schema-json>'", '[scopeRef]')}`);
|
|
334
432
|
}
|
|
335
433
|
const { extract } = await import('./commands/extract.js');
|
|
336
|
-
await extract(
|
|
434
|
+
await extract(requireProductSessionRecord(command), schemaJson, scopeRef);
|
|
337
435
|
break;
|
|
338
436
|
}
|
|
339
437
|
case 'observe': {
|
|
340
438
|
const instruction = getPositional(args);
|
|
341
439
|
const { observe } = await import('./commands/observe.js');
|
|
342
|
-
await observe(
|
|
440
|
+
await observe(requireProductSessionRecord(command), instruction);
|
|
343
441
|
break;
|
|
344
442
|
}
|
|
345
443
|
case 'screenshot': {
|
|
@@ -349,12 +447,13 @@ async function main(argv = process.argv) {
|
|
|
349
447
|
}
|
|
350
448
|
const filePath = getFlag(args, '--path');
|
|
351
449
|
const { screenshot } = await import('./commands/screenshot.js');
|
|
352
|
-
await screenshot(
|
|
450
|
+
await screenshot(requireProductSessionRecord(command), filePath);
|
|
353
451
|
break;
|
|
354
452
|
}
|
|
355
453
|
case 'status': {
|
|
454
|
+
requireProductSessionRecord(command);
|
|
356
455
|
const { status } = await import('./commands/status.js');
|
|
357
|
-
await status();
|
|
456
|
+
outputJSON(await status());
|
|
358
457
|
break;
|
|
359
458
|
}
|
|
360
459
|
case 'close': {
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { type OtlpTraceRequest } from './otel-projector.js';
|
|
2
|
+
export type OtlpHttpJsonExporterConfig = {
|
|
3
|
+
tracesEndpoint: string;
|
|
4
|
+
headers: Record<string, string>;
|
|
5
|
+
timeoutMs: number;
|
|
6
|
+
protocol: 'http/json';
|
|
7
|
+
};
|
|
8
|
+
export type ExportStepTraceResult = {
|
|
9
|
+
attempted: false;
|
|
10
|
+
reason: 'config_missing' | 'run_missing' | 'step_missing' | 'unsupported_protocol';
|
|
11
|
+
} | {
|
|
12
|
+
attempted: true;
|
|
13
|
+
success: true;
|
|
14
|
+
status: number;
|
|
15
|
+
payload: OtlpTraceRequest;
|
|
16
|
+
} | {
|
|
17
|
+
attempted: true;
|
|
18
|
+
success: false;
|
|
19
|
+
status?: number;
|
|
20
|
+
reason: string;
|
|
21
|
+
payload: OtlpTraceRequest;
|
|
22
|
+
};
|
|
23
|
+
export type ExportRunRootTraceResult = {
|
|
24
|
+
attempted: false;
|
|
25
|
+
reason: 'config_missing' | 'run_missing';
|
|
26
|
+
} | {
|
|
27
|
+
attempted: true;
|
|
28
|
+
success: true;
|
|
29
|
+
status: number;
|
|
30
|
+
payload: OtlpTraceRequest;
|
|
31
|
+
} | {
|
|
32
|
+
attempted: true;
|
|
33
|
+
success: false;
|
|
34
|
+
status?: number;
|
|
35
|
+
reason: string;
|
|
36
|
+
payload: OtlpTraceRequest;
|
|
37
|
+
};
|
|
38
|
+
export declare function loadOtlpHttpJsonExporterConfig(env?: NodeJS.ProcessEnv): OtlpHttpJsonExporterConfig | null;
|
|
39
|
+
export declare function exportRunStepToOtlpHttpJson(params?: {
|
|
40
|
+
runId: string;
|
|
41
|
+
stepId: string;
|
|
42
|
+
config?: OtlpHttpJsonExporterConfig | null;
|
|
43
|
+
fetchImpl?: typeof fetch;
|
|
44
|
+
}): Promise<ExportStepTraceResult>;
|
|
45
|
+
export declare function buildRunStepOtlpTraceRequest(runId: string, stepId: string): OtlpTraceRequest | null;
|
|
46
|
+
export declare function exportRunRootToOtlpHttpJson(params?: {
|
|
47
|
+
runId: string;
|
|
48
|
+
config?: OtlpHttpJsonExporterConfig | null;
|
|
49
|
+
fetchImpl?: typeof fetch;
|
|
50
|
+
}): Promise<ExportRunRootTraceResult>;
|
|
51
|
+
export declare function buildRunRootOtlpTraceRequest(runId: string): OtlpTraceRequest | null;
|
|
52
|
+
export declare function exportRunStepToOtlpHttpJsonBestEffort(runId: string | undefined, stepId: string | undefined, options?: {
|
|
53
|
+
fetchImpl?: typeof fetch;
|
|
54
|
+
}): Promise<ExportStepTraceResult>;
|
|
55
|
+
export declare function exportRunRootToOtlpHttpJsonBestEffort(runId: string | undefined, options?: {
|
|
56
|
+
fetchImpl?: typeof fetch;
|
|
57
|
+
}): Promise<ExportRunRootTraceResult>;
|
|
58
|
+
//# sourceMappingURL=otel-exporter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"otel-exporter.d.ts","sourceRoot":"","sources":["../src/otel-exporter.ts"],"names":[],"mappings":"AAQA,OAAO,EAGL,KAAK,gBAAgB,EACtB,MAAM,qBAAqB,CAAC;AAS7B,MAAM,MAAM,0BAA0B,GAAG;IACvC,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,WAAW,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAC7B;IACE,SAAS,EAAE,KAAK,CAAC;IACjB,MAAM,EAAE,gBAAgB,GAAG,aAAa,GAAG,cAAc,GAAG,sBAAsB,CAAC;CACpF,GACD;IACE,SAAS,EAAE,IAAI,CAAC;IAChB,OAAO,EAAE,IAAI,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,gBAAgB,CAAC;CAC3B,GACD;IACE,SAAS,EAAE,IAAI,CAAC;IAChB,OAAO,EAAE,KAAK,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,gBAAgB,CAAC;CAC3B,CAAC;AAEN,MAAM,MAAM,wBAAwB,GAChC;IACE,SAAS,EAAE,KAAK,CAAC;IACjB,MAAM,EAAE,gBAAgB,GAAG,aAAa,CAAC;CAC1C,GACD;IACE,SAAS,EAAE,IAAI,CAAC;IAChB,OAAO,EAAE,IAAI,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,gBAAgB,CAAC;CAC3B,GACD;IACE,SAAS,EAAE,IAAI,CAAC;IAChB,OAAO,EAAE,KAAK,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,gBAAgB,CAAC;CAC3B,CAAC;AA4DN,wBAAgB,8BAA8B,CAC5C,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,0BAA0B,GAAG,IAAI,CAsCnC;AAED,wBAAsB,2BAA2B,CAC/C,MAAM,GAAE;IACN,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,0BAA0B,GAAG,IAAI,CAAC;IAC3C,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CAI1B,GACA,OAAO,CAAC,qBAAqB,CAAC,CAgFhC;AAED,wBAAgB,4BAA4B,CAC1C,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,GACb,gBAAgB,GAAG,IAAI,CAyBzB;AAED,wBAAsB,2BAA2B,CAC/C,MAAM,GAAE;IACN,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,0BAA0B,GAAG,IAAI,CAAC;IAC3C,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CAG1B,GACA,OAAO,CAAC,wBAAwB,CAAC,CAkDnC;AAED,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI,CAOnF;AAED,wBAAsB,qCAAqC,CACzD,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,OAAO,GAAE;IACP,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CACrB,GACL,OAAO,CAAC,qBAAqB,CAAC,CAUhC;AAED,wBAAsB,qCAAqC,CACzD,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,OAAO,GAAE;IACP,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CACrB,GACL,OAAO,CAAC,wBAAwB,CAAC,CASnC"}
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
import { listRunEventRecordsForStep, loadArtifactManifest, loadBrowserStateSnapshot, loadRunRecord, loadStepRecord, setRunIngestState, } from './run-store.js';
|
|
2
|
+
import { projectRunRootToOtlpTraceRequest, projectStepToOtlpTraceRequest, } from './otel-projector.js';
|
|
3
|
+
import { exportRunStepViaSessionEvent } from './session-event-exporter.js';
|
|
4
|
+
import { buildAgentpayTelemetryTracesUrl, tryResolveAgentpayGatewayConfig, } from './agentpay-gateway.js';
|
|
5
|
+
const DEFAULT_HTTP_TIMEOUT_MS = 5_000;
|
|
6
|
+
function trimEnv(value) {
|
|
7
|
+
const trimmed = value?.trim();
|
|
8
|
+
return trimmed ? trimmed : undefined;
|
|
9
|
+
}
|
|
10
|
+
function parseHeaderList(value) {
|
|
11
|
+
if (!value) {
|
|
12
|
+
return {};
|
|
13
|
+
}
|
|
14
|
+
const headers = {};
|
|
15
|
+
for (const chunk of value.split(',')) {
|
|
16
|
+
const separatorIndex = chunk.indexOf('=');
|
|
17
|
+
if (separatorIndex === -1) {
|
|
18
|
+
continue;
|
|
19
|
+
}
|
|
20
|
+
const key = chunk.slice(0, separatorIndex).trim();
|
|
21
|
+
const headerValue = chunk.slice(separatorIndex + 1).trim();
|
|
22
|
+
if (!key || !headerValue) {
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
headers[key] = headerValue;
|
|
26
|
+
}
|
|
27
|
+
return headers;
|
|
28
|
+
}
|
|
29
|
+
function parseTimeoutMs(value) {
|
|
30
|
+
const parsed = value ? Number(value) : NaN;
|
|
31
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : DEFAULT_HTTP_TIMEOUT_MS;
|
|
32
|
+
}
|
|
33
|
+
function buildTracesEndpoint(base) {
|
|
34
|
+
return `${base.replace(/\/+$/, '')}/v1/traces`;
|
|
35
|
+
}
|
|
36
|
+
async function postOtlpTraceRequest(params) {
|
|
37
|
+
const controller = new AbortController();
|
|
38
|
+
const timeout = setTimeout(() => controller.abort(), params.config.timeoutMs);
|
|
39
|
+
try {
|
|
40
|
+
return await params.fetchImpl(params.config.tracesEndpoint, {
|
|
41
|
+
method: 'POST',
|
|
42
|
+
headers: {
|
|
43
|
+
'content-type': 'application/json',
|
|
44
|
+
...params.config.headers,
|
|
45
|
+
},
|
|
46
|
+
body: JSON.stringify(params.payload),
|
|
47
|
+
signal: controller.signal,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
finally {
|
|
51
|
+
clearTimeout(timeout);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
export function loadOtlpHttpJsonExporterConfig(env = process.env) {
|
|
55
|
+
const protocol = trimEnv(env.OTEL_EXPORTER_OTLP_TRACES_PROTOCOL) ??
|
|
56
|
+
trimEnv(env.OTEL_EXPORTER_OTLP_PROTOCOL) ??
|
|
57
|
+
'http/json';
|
|
58
|
+
if (protocol !== 'http/json') {
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
const tracesEndpoint = trimEnv(env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT);
|
|
62
|
+
const baseEndpoint = trimEnv(env.OTEL_EXPORTER_OTLP_ENDPOINT);
|
|
63
|
+
const gateway = tryResolveAgentpayGatewayConfig();
|
|
64
|
+
const resolvedEndpoint = tracesEndpoint ??
|
|
65
|
+
(baseEndpoint ? buildTracesEndpoint(baseEndpoint) : null) ??
|
|
66
|
+
(gateway ? buildAgentpayTelemetryTracesUrl(gateway.apiUrl) : null);
|
|
67
|
+
if (!resolvedEndpoint) {
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
const timeoutMs = parseTimeoutMs(trimEnv(env.OTEL_EXPORTER_OTLP_TRACES_TIMEOUT) ??
|
|
71
|
+
trimEnv(env.OTEL_EXPORTER_OTLP_TIMEOUT));
|
|
72
|
+
const headers = {
|
|
73
|
+
...parseHeaderList(trimEnv(env.OTEL_EXPORTER_OTLP_HEADERS)),
|
|
74
|
+
...parseHeaderList(trimEnv(env.OTEL_EXPORTER_OTLP_TRACES_HEADERS)),
|
|
75
|
+
};
|
|
76
|
+
if (!headers.authorization && gateway) {
|
|
77
|
+
headers.authorization = `Bearer ${gateway.apiKey}`;
|
|
78
|
+
}
|
|
79
|
+
return {
|
|
80
|
+
tracesEndpoint: resolvedEndpoint,
|
|
81
|
+
headers,
|
|
82
|
+
timeoutMs,
|
|
83
|
+
protocol: 'http/json',
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
export async function exportRunStepToOtlpHttpJson(params = {
|
|
87
|
+
runId: '',
|
|
88
|
+
stepId: '',
|
|
89
|
+
}) {
|
|
90
|
+
const run = loadRunRecord(params.runId);
|
|
91
|
+
if (!run) {
|
|
92
|
+
return { attempted: false, reason: 'run_missing' };
|
|
93
|
+
}
|
|
94
|
+
const step = loadStepRecord(params.runId, params.stepId);
|
|
95
|
+
if (!step) {
|
|
96
|
+
return { attempted: false, reason: 'step_missing' };
|
|
97
|
+
}
|
|
98
|
+
const payload = buildRunStepOtlpTraceRequest(params.runId, params.stepId);
|
|
99
|
+
if (!payload) {
|
|
100
|
+
return { attempted: false, reason: 'step_missing' };
|
|
101
|
+
}
|
|
102
|
+
const fetchImpl = params.fetchImpl ?? fetch;
|
|
103
|
+
const sessionEventResult = await exportRunStepViaSessionEvent({
|
|
104
|
+
runId: params.runId,
|
|
105
|
+
stepId: params.stepId,
|
|
106
|
+
telemetryPayload: payload,
|
|
107
|
+
fetchImpl,
|
|
108
|
+
});
|
|
109
|
+
if (sessionEventResult.attempted) {
|
|
110
|
+
if (sessionEventResult.success) {
|
|
111
|
+
return {
|
|
112
|
+
attempted: true,
|
|
113
|
+
success: true,
|
|
114
|
+
status: sessionEventResult.status,
|
|
115
|
+
payload,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
return {
|
|
119
|
+
attempted: true,
|
|
120
|
+
success: false,
|
|
121
|
+
...(sessionEventResult.status !== undefined ? { status: sessionEventResult.status } : {}),
|
|
122
|
+
reason: sessionEventResult.reason,
|
|
123
|
+
payload,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
const config = params.config ?? loadOtlpHttpJsonExporterConfig();
|
|
127
|
+
if (!config) {
|
|
128
|
+
return { attempted: false, reason: 'config_missing' };
|
|
129
|
+
}
|
|
130
|
+
try {
|
|
131
|
+
const response = await postOtlpTraceRequest({
|
|
132
|
+
payload,
|
|
133
|
+
config,
|
|
134
|
+
fetchImpl,
|
|
135
|
+
});
|
|
136
|
+
if (!response.ok) {
|
|
137
|
+
setRunIngestState(params.runId, 'export_failed');
|
|
138
|
+
return {
|
|
139
|
+
attempted: true,
|
|
140
|
+
success: false,
|
|
141
|
+
status: response.status,
|
|
142
|
+
reason: `otlp_http_status_${response.status}`,
|
|
143
|
+
payload,
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
setRunIngestState(params.runId, 'exported');
|
|
147
|
+
return {
|
|
148
|
+
attempted: true,
|
|
149
|
+
success: true,
|
|
150
|
+
status: response.status,
|
|
151
|
+
payload,
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
catch (error) {
|
|
155
|
+
setRunIngestState(params.runId, 'export_failed');
|
|
156
|
+
return {
|
|
157
|
+
attempted: true,
|
|
158
|
+
success: false,
|
|
159
|
+
reason: error instanceof Error ? error.message : String(error),
|
|
160
|
+
payload,
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
export function buildRunStepOtlpTraceRequest(runId, stepId) {
|
|
165
|
+
const run = loadRunRecord(runId);
|
|
166
|
+
if (!run) {
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
const step = loadStepRecord(runId, stepId);
|
|
170
|
+
if (!step) {
|
|
171
|
+
return null;
|
|
172
|
+
}
|
|
173
|
+
return projectStepToOtlpTraceRequest({
|
|
174
|
+
run,
|
|
175
|
+
step,
|
|
176
|
+
events: listRunEventRecordsForStep(runId, stepId),
|
|
177
|
+
beforeSnapshot: step.beforeSnapshotId
|
|
178
|
+
? loadBrowserStateSnapshot(runId, step.beforeSnapshotId)
|
|
179
|
+
: null,
|
|
180
|
+
afterSnapshot: step.afterSnapshotId
|
|
181
|
+
? loadBrowserStateSnapshot(runId, step.afterSnapshotId)
|
|
182
|
+
: null,
|
|
183
|
+
artifactManifest: step.artifactManifestId
|
|
184
|
+
? loadArtifactManifest(runId, step.artifactManifestId)
|
|
185
|
+
: null,
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
export async function exportRunRootToOtlpHttpJson(params = {
|
|
189
|
+
runId: '',
|
|
190
|
+
}) {
|
|
191
|
+
const config = params.config ?? loadOtlpHttpJsonExporterConfig();
|
|
192
|
+
if (!config) {
|
|
193
|
+
return { attempted: false, reason: 'config_missing' };
|
|
194
|
+
}
|
|
195
|
+
const run = loadRunRecord(params.runId);
|
|
196
|
+
if (!run) {
|
|
197
|
+
return { attempted: false, reason: 'run_missing' };
|
|
198
|
+
}
|
|
199
|
+
const payload = buildRunRootOtlpTraceRequest(params.runId);
|
|
200
|
+
if (!payload) {
|
|
201
|
+
return { attempted: false, reason: 'run_missing' };
|
|
202
|
+
}
|
|
203
|
+
const fetchImpl = params.fetchImpl ?? fetch;
|
|
204
|
+
try {
|
|
205
|
+
const response = await postOtlpTraceRequest({
|
|
206
|
+
payload,
|
|
207
|
+
config,
|
|
208
|
+
fetchImpl,
|
|
209
|
+
});
|
|
210
|
+
if (!response.ok) {
|
|
211
|
+
setRunIngestState(params.runId, 'export_failed');
|
|
212
|
+
return {
|
|
213
|
+
attempted: true,
|
|
214
|
+
success: false,
|
|
215
|
+
status: response.status,
|
|
216
|
+
reason: `otlp_http_status_${response.status}`,
|
|
217
|
+
payload,
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
setRunIngestState(params.runId, 'exported');
|
|
221
|
+
return {
|
|
222
|
+
attempted: true,
|
|
223
|
+
success: true,
|
|
224
|
+
status: response.status,
|
|
225
|
+
payload,
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
catch (error) {
|
|
229
|
+
setRunIngestState(params.runId, 'export_failed');
|
|
230
|
+
return {
|
|
231
|
+
attempted: true,
|
|
232
|
+
success: false,
|
|
233
|
+
reason: error instanceof Error ? error.message : String(error),
|
|
234
|
+
payload,
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
export function buildRunRootOtlpTraceRequest(runId) {
|
|
239
|
+
const run = loadRunRecord(runId);
|
|
240
|
+
if (!run) {
|
|
241
|
+
return null;
|
|
242
|
+
}
|
|
243
|
+
return projectRunRootToOtlpTraceRequest({ run });
|
|
244
|
+
}
|
|
245
|
+
export async function exportRunStepToOtlpHttpJsonBestEffort(runId, stepId, options = {}) {
|
|
246
|
+
if (!runId || !stepId) {
|
|
247
|
+
return { attempted: false, reason: 'step_missing' };
|
|
248
|
+
}
|
|
249
|
+
return exportRunStepToOtlpHttpJson({
|
|
250
|
+
runId,
|
|
251
|
+
stepId,
|
|
252
|
+
fetchImpl: options.fetchImpl,
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
export async function exportRunRootToOtlpHttpJsonBestEffort(runId, options = {}) {
|
|
256
|
+
if (!runId) {
|
|
257
|
+
return { attempted: false, reason: 'run_missing' };
|
|
258
|
+
}
|
|
259
|
+
return exportRunRootToOtlpHttpJson({
|
|
260
|
+
runId,
|
|
261
|
+
fetchImpl: options.fetchImpl,
|
|
262
|
+
});
|
|
263
|
+
}
|