@mercuryo-ai/magicpay-cli 0.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 (144) hide show
  1. package/README.md +56 -0
  2. package/dist/agentbrowse-assistive.d.ts +2 -0
  3. package/dist/agentbrowse-assistive.d.ts.map +1 -0
  4. package/dist/agentbrowse-assistive.js +66 -0
  5. package/dist/assistive-llm-client.d.ts +13 -0
  6. package/dist/assistive-llm-client.d.ts.map +1 -0
  7. package/dist/assistive-llm-client.js +152 -0
  8. package/dist/browser-bridge/act.d.ts +5 -0
  9. package/dist/browser-bridge/act.d.ts.map +1 -0
  10. package/dist/browser-bridge/act.js +8 -0
  11. package/dist/browser-bridge/observe.d.ts +5 -0
  12. package/dist/browser-bridge/observe.d.ts.map +1 -0
  13. package/dist/browser-bridge/observe.js +53 -0
  14. package/dist/browser-home.d.ts +7 -0
  15. package/dist/browser-home.d.ts.map +1 -0
  16. package/dist/browser-home.js +34 -0
  17. package/dist/commands/act.d.ts +5 -0
  18. package/dist/commands/act.d.ts.map +1 -0
  19. package/dist/commands/act.js +8 -0
  20. package/dist/commands/attach.d.ts +4 -0
  21. package/dist/commands/attach.d.ts.map +1 -0
  22. package/dist/commands/attach.js +10 -0
  23. package/dist/commands/browser-status.d.ts +5 -0
  24. package/dist/commands/browser-status.d.ts.map +1 -0
  25. package/dist/commands/browser-status.js +5 -0
  26. package/dist/commands/close.d.ts +4 -0
  27. package/dist/commands/close.d.ts.map +1 -0
  28. package/dist/commands/close.js +11 -0
  29. package/dist/commands/end-session.d.ts +22 -0
  30. package/dist/commands/end-session.d.ts.map +1 -0
  31. package/dist/commands/end-session.js +104 -0
  32. package/dist/commands/extract.d.ts +4 -0
  33. package/dist/commands/extract.d.ts.map +1 -0
  34. package/dist/commands/extract.js +14 -0
  35. package/dist/commands/fill-secret.d.ts +10 -0
  36. package/dist/commands/fill-secret.d.ts.map +1 -0
  37. package/dist/commands/fill-secret.js +483 -0
  38. package/dist/commands/find-form.d.ts +57 -0
  39. package/dist/commands/find-form.d.ts.map +1 -0
  40. package/dist/commands/find-form.js +138 -0
  41. package/dist/commands/get-secrets-catalog.d.ts +13 -0
  42. package/dist/commands/get-secrets-catalog.d.ts.map +1 -0
  43. package/dist/commands/get-secrets-catalog.js +103 -0
  44. package/dist/commands/init.d.ts +10 -0
  45. package/dist/commands/init.d.ts.map +1 -0
  46. package/dist/commands/init.js +28 -0
  47. package/dist/commands/launch.d.ts +4 -0
  48. package/dist/commands/launch.d.ts.map +1 -0
  49. package/dist/commands/launch.js +10 -0
  50. package/dist/commands/mock-approve-secret.d.ts +21 -0
  51. package/dist/commands/mock-approve-secret.d.ts.map +1 -0
  52. package/dist/commands/mock-approve-secret.js +69 -0
  53. package/dist/commands/mock-deny-secret.d.ts +21 -0
  54. package/dist/commands/mock-deny-secret.d.ts.map +1 -0
  55. package/dist/commands/mock-deny-secret.js +69 -0
  56. package/dist/commands/navigate.d.ts +4 -0
  57. package/dist/commands/navigate.d.ts.map +1 -0
  58. package/dist/commands/navigate.js +9 -0
  59. package/dist/commands/observe.d.ts +5 -0
  60. package/dist/commands/observe.d.ts.map +1 -0
  61. package/dist/commands/observe.js +53 -0
  62. package/dist/commands/poll-secret.d.ts +13 -0
  63. package/dist/commands/poll-secret.d.ts.map +1 -0
  64. package/dist/commands/poll-secret.js +87 -0
  65. package/dist/commands/request-secret.d.ts +15 -0
  66. package/dist/commands/request-secret.d.ts.map +1 -0
  67. package/dist/commands/request-secret.js +235 -0
  68. package/dist/commands/screenshot.d.ts +4 -0
  69. package/dist/commands/screenshot.d.ts.map +1 -0
  70. package/dist/commands/screenshot.js +11 -0
  71. package/dist/commands/solve-captcha.d.ts +19 -0
  72. package/dist/commands/solve-captcha.d.ts.map +1 -0
  73. package/dist/commands/solve-captcha.js +63 -0
  74. package/dist/commands/start-session.d.ts +28 -0
  75. package/dist/commands/start-session.d.ts.map +1 -0
  76. package/dist/commands/start-session.js +298 -0
  77. package/dist/commands/status.d.ts +27 -0
  78. package/dist/commands/status.d.ts.map +1 -0
  79. package/dist/commands/status.js +51 -0
  80. package/dist/commands/submit-form.d.ts +36 -0
  81. package/dist/commands/submit-form.d.ts.map +1 -0
  82. package/dist/commands/submit-form.js +242 -0
  83. package/dist/config.d.ts +2 -0
  84. package/dist/config.d.ts.map +1 -0
  85. package/dist/config.js +1 -0
  86. package/dist/fillable-form-state.d.ts +5 -0
  87. package/dist/fillable-form-state.d.ts.map +1 -0
  88. package/dist/fillable-form-state.js +22 -0
  89. package/dist/gateway.d.ts +10 -0
  90. package/dist/gateway.d.ts.map +1 -0
  91. package/dist/gateway.js +49 -0
  92. package/dist/generated/build-config.d.ts +2 -0
  93. package/dist/generated/build-config.d.ts.map +1 -0
  94. package/dist/generated/build-config.js +2 -0
  95. package/dist/index.d.ts +4 -0
  96. package/dist/index.d.ts.map +1 -0
  97. package/dist/index.js +398 -0
  98. package/dist/mock-secret-cabinet.d.ts +37 -0
  99. package/dist/mock-secret-cabinet.d.ts.map +1 -0
  100. package/dist/mock-secret-cabinet.js +321 -0
  101. package/dist/mock-secret-store.d.ts +12 -0
  102. package/dist/mock-secret-store.d.ts.map +1 -0
  103. package/dist/mock-secret-store.js +108 -0
  104. package/dist/mock-stored-secrets.json +180 -0
  105. package/dist/otel-exporter.d.ts +58 -0
  106. package/dist/otel-exporter.d.ts.map +1 -0
  107. package/dist/otel-exporter.js +241 -0
  108. package/dist/otel-projector.d.ts +59 -0
  109. package/dist/otel-projector.d.ts.map +1 -0
  110. package/dist/otel-projector.js +325 -0
  111. package/dist/output.d.ts +10 -0
  112. package/dist/output.d.ts.map +1 -0
  113. package/dist/output.js +29 -0
  114. package/dist/package-version.d.ts +2 -0
  115. package/dist/package-version.d.ts.map +1 -0
  116. package/dist/package-version.js +14 -0
  117. package/dist/protected-exposure.d.ts +4 -0
  118. package/dist/protected-exposure.d.ts.map +1 -0
  119. package/dist/protected-exposure.js +17 -0
  120. package/dist/request-output.d.ts +4 -0
  121. package/dist/request-output.d.ts.map +1 -0
  122. package/dist/request-output.js +27 -0
  123. package/dist/run-store.d.ts +130 -0
  124. package/dist/run-store.d.ts.map +1 -0
  125. package/dist/run-store.js +245 -0
  126. package/dist/secret-backend.d.ts +28 -0
  127. package/dist/secret-backend.d.ts.map +1 -0
  128. package/dist/secret-backend.js +335 -0
  129. package/dist/secret-state.d.ts +7 -0
  130. package/dist/secret-state.d.ts.map +1 -0
  131. package/dist/secret-state.js +26 -0
  132. package/dist/session-backend.d.ts +34 -0
  133. package/dist/session-backend.d.ts.map +1 -0
  134. package/dist/session-backend.js +36 -0
  135. package/dist/update-check.d.ts +13 -0
  136. package/dist/update-check.d.ts.map +1 -0
  137. package/dist/update-check.js +175 -0
  138. package/dist/workflow-session-completion.d.ts +32 -0
  139. package/dist/workflow-session-completion.d.ts.map +1 -0
  140. package/dist/workflow-session-completion.js +149 -0
  141. package/dist/workflow-state.d.ts +2 -0
  142. package/dist/workflow-state.d.ts.map +1 -0
  143. package/dist/workflow-state.js +1 -0
  144. package/package.json +67 -0
@@ -0,0 +1,241 @@
1
+ import { buildMagicPayTelemetryTracesUrl, tryResolveMagicPayGatewayConfig, } from './gateway.js';
2
+ import { projectRunRootToOtlpTraceRequest, projectStepToOtlpTraceRequest } from './otel-projector.js';
3
+ import { loadRunRecord, loadStepRecord, setRunIngestState } from './run-store.js';
4
+ const DEFAULT_HTTP_TIMEOUT_MS = 5_000;
5
+ const DISABLE_TELEMETRY_ENV = 'MAGICPAY_DISABLE_TELEMETRY';
6
+ function trimEnv(value) {
7
+ const trimmed = value?.trim();
8
+ return trimmed ? trimmed : undefined;
9
+ }
10
+ function telemetryDisabled(env) {
11
+ const value = trimEnv(env[DISABLE_TELEMETRY_ENV]);
12
+ if (!value) {
13
+ return false;
14
+ }
15
+ const normalized = value.toLowerCase();
16
+ return normalized === '1' || normalized === 'true' || normalized === 'yes' || normalized === 'on';
17
+ }
18
+ function parseHeaderList(value) {
19
+ if (!value) {
20
+ return {};
21
+ }
22
+ const headers = {};
23
+ for (const chunk of value.split(',')) {
24
+ const separatorIndex = chunk.indexOf('=');
25
+ if (separatorIndex === -1) {
26
+ continue;
27
+ }
28
+ const key = chunk.slice(0, separatorIndex).trim();
29
+ const headerValue = chunk.slice(separatorIndex + 1).trim();
30
+ if (!key || !headerValue) {
31
+ continue;
32
+ }
33
+ headers[key] = headerValue;
34
+ }
35
+ return headers;
36
+ }
37
+ function parseTimeoutMs(value) {
38
+ const parsed = value ? Number(value) : Number.NaN;
39
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : DEFAULT_HTTP_TIMEOUT_MS;
40
+ }
41
+ function buildTracesEndpoint(base) {
42
+ return `${base.replace(/\/+$/, '')}/v1/traces`;
43
+ }
44
+ async function postOtlpTraceRequest(params) {
45
+ const controller = new AbortController();
46
+ const timeout = setTimeout(() => controller.abort(), params.config.timeoutMs);
47
+ try {
48
+ return await params.fetchImpl(params.config.tracesEndpoint, {
49
+ method: 'POST',
50
+ headers: {
51
+ 'content-type': 'application/json',
52
+ ...params.config.headers,
53
+ },
54
+ body: JSON.stringify(params.payload),
55
+ signal: controller.signal,
56
+ });
57
+ }
58
+ finally {
59
+ clearTimeout(timeout);
60
+ }
61
+ }
62
+ export function loadOtlpHttpJsonExporterConfig(env = process.env) {
63
+ if (telemetryDisabled(env)) {
64
+ return null;
65
+ }
66
+ const protocol = trimEnv(env.OTEL_EXPORTER_OTLP_TRACES_PROTOCOL) ??
67
+ trimEnv(env.OTEL_EXPORTER_OTLP_PROTOCOL) ??
68
+ 'http/json';
69
+ if (protocol !== 'http/json') {
70
+ return null;
71
+ }
72
+ const tracesEndpoint = trimEnv(env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT);
73
+ const baseEndpoint = trimEnv(env.OTEL_EXPORTER_OTLP_ENDPOINT);
74
+ const gateway = tryResolveMagicPayGatewayConfig();
75
+ const resolvedEndpoint = tracesEndpoint ??
76
+ (baseEndpoint ? buildTracesEndpoint(baseEndpoint) : null) ??
77
+ (gateway ? buildMagicPayTelemetryTracesUrl(gateway.apiUrl) : null);
78
+ if (!resolvedEndpoint) {
79
+ return null;
80
+ }
81
+ const timeoutMs = parseTimeoutMs(trimEnv(env.OTEL_EXPORTER_OTLP_TRACES_TIMEOUT) ??
82
+ trimEnv(env.OTEL_EXPORTER_OTLP_TIMEOUT));
83
+ const headers = {
84
+ ...parseHeaderList(trimEnv(env.OTEL_EXPORTER_OTLP_HEADERS)),
85
+ ...parseHeaderList(trimEnv(env.OTEL_EXPORTER_OTLP_TRACES_HEADERS)),
86
+ };
87
+ if (!headers.authorization && gateway) {
88
+ headers.authorization = `Bearer ${gateway.apiKey}`;
89
+ }
90
+ return {
91
+ tracesEndpoint: resolvedEndpoint,
92
+ headers,
93
+ timeoutMs,
94
+ protocol: 'http/json',
95
+ };
96
+ }
97
+ export function buildRunStepOtlpTraceRequest(runId, stepId) {
98
+ const run = loadRunRecord(runId);
99
+ if (!run) {
100
+ return null;
101
+ }
102
+ const step = loadStepRecord(runId, stepId);
103
+ if (!step) {
104
+ return null;
105
+ }
106
+ return projectStepToOtlpTraceRequest({
107
+ run,
108
+ step,
109
+ });
110
+ }
111
+ export async function exportRunStepToOtlpHttpJson(params = {
112
+ runId: '',
113
+ stepId: '',
114
+ }) {
115
+ const run = loadRunRecord(params.runId);
116
+ if (!run) {
117
+ return { attempted: false, reason: 'run_missing' };
118
+ }
119
+ const step = loadStepRecord(params.runId, params.stepId);
120
+ if (!step) {
121
+ return { attempted: false, reason: 'step_missing' };
122
+ }
123
+ const payload = buildRunStepOtlpTraceRequest(params.runId, params.stepId);
124
+ if (!payload) {
125
+ return { attempted: false, reason: 'step_missing' };
126
+ }
127
+ const fetchImpl = params.fetchImpl ?? fetch;
128
+ const config = params.config ?? loadOtlpHttpJsonExporterConfig();
129
+ if (!config) {
130
+ return { attempted: false, reason: 'config_missing' };
131
+ }
132
+ try {
133
+ const response = await postOtlpTraceRequest({
134
+ payload,
135
+ config,
136
+ fetchImpl,
137
+ });
138
+ if (!response.ok) {
139
+ setRunIngestState(params.runId, 'export_failed');
140
+ return {
141
+ attempted: true,
142
+ success: false,
143
+ status: response.status,
144
+ reason: `otlp_http_status_${response.status}`,
145
+ payload,
146
+ };
147
+ }
148
+ setRunIngestState(params.runId, 'exported');
149
+ return {
150
+ attempted: true,
151
+ success: true,
152
+ status: response.status,
153
+ payload,
154
+ };
155
+ }
156
+ catch (error) {
157
+ setRunIngestState(params.runId, 'export_failed');
158
+ return {
159
+ attempted: true,
160
+ success: false,
161
+ reason: error instanceof Error ? error.message : String(error),
162
+ payload,
163
+ };
164
+ }
165
+ }
166
+ export function buildRunRootOtlpTraceRequest(runId) {
167
+ const run = loadRunRecord(runId);
168
+ if (!run) {
169
+ return null;
170
+ }
171
+ return projectRunRootToOtlpTraceRequest({ run });
172
+ }
173
+ export async function exportRunRootToOtlpHttpJson(params = {
174
+ runId: '',
175
+ }) {
176
+ const config = params.config ?? loadOtlpHttpJsonExporterConfig();
177
+ if (!config) {
178
+ return { attempted: false, reason: 'config_missing' };
179
+ }
180
+ const run = loadRunRecord(params.runId);
181
+ if (!run) {
182
+ return { attempted: false, reason: 'run_missing' };
183
+ }
184
+ const payload = buildRunRootOtlpTraceRequest(params.runId);
185
+ if (!payload) {
186
+ return { attempted: false, reason: 'run_missing' };
187
+ }
188
+ const fetchImpl = params.fetchImpl ?? fetch;
189
+ try {
190
+ const response = await postOtlpTraceRequest({
191
+ payload,
192
+ config,
193
+ fetchImpl,
194
+ });
195
+ if (!response.ok) {
196
+ setRunIngestState(params.runId, 'export_failed');
197
+ return {
198
+ attempted: true,
199
+ success: false,
200
+ status: response.status,
201
+ reason: `otlp_http_status_${response.status}`,
202
+ payload,
203
+ };
204
+ }
205
+ setRunIngestState(params.runId, 'exported');
206
+ return {
207
+ attempted: true,
208
+ success: true,
209
+ status: response.status,
210
+ payload,
211
+ };
212
+ }
213
+ catch (error) {
214
+ setRunIngestState(params.runId, 'export_failed');
215
+ return {
216
+ attempted: true,
217
+ success: false,
218
+ reason: error instanceof Error ? error.message : String(error),
219
+ payload,
220
+ };
221
+ }
222
+ }
223
+ export async function exportRunStepToOtlpHttpJsonBestEffort(runId, stepId, options = {}) {
224
+ if (!runId || !stepId) {
225
+ return { attempted: false, reason: 'step_missing' };
226
+ }
227
+ return exportRunStepToOtlpHttpJson({
228
+ runId,
229
+ stepId,
230
+ fetchImpl: options.fetchImpl,
231
+ });
232
+ }
233
+ export async function exportRunRootToOtlpHttpJsonBestEffort(runId, options = {}) {
234
+ if (!runId) {
235
+ return { attempted: false, reason: 'run_missing' };
236
+ }
237
+ return exportRunRootToOtlpHttpJson({
238
+ runId,
239
+ fetchImpl: options.fetchImpl,
240
+ });
241
+ }
@@ -0,0 +1,59 @@
1
+ import type { RunRecord, StepRecord } from './run-store.js';
2
+ type OtlpAnyValue = {
3
+ stringValue: string;
4
+ } | {
5
+ boolValue: boolean;
6
+ } | {
7
+ intValue: string;
8
+ } | {
9
+ doubleValue: number;
10
+ } | {
11
+ arrayValue: {
12
+ values: OtlpAnyValue[];
13
+ };
14
+ } | {
15
+ kvlistValue: {
16
+ values: OtlpKeyValue[];
17
+ };
18
+ };
19
+ type OtlpKeyValue = {
20
+ key: string;
21
+ value: OtlpAnyValue;
22
+ };
23
+ type OtlpSpan = {
24
+ traceId: string;
25
+ spanId: string;
26
+ parentSpanId?: string;
27
+ name: string;
28
+ kind: number;
29
+ startTimeUnixNano: string;
30
+ endTimeUnixNano: string;
31
+ attributes?: OtlpKeyValue[];
32
+ status?: {
33
+ code: number;
34
+ message?: string;
35
+ };
36
+ };
37
+ export type OtlpTraceRequest = {
38
+ resourceSpans: Array<{
39
+ resource: {
40
+ attributes: OtlpKeyValue[];
41
+ };
42
+ scopeSpans: Array<{
43
+ scope: {
44
+ name: string;
45
+ };
46
+ spans: OtlpSpan[];
47
+ }>;
48
+ }>;
49
+ };
50
+ export declare function sanitizeUrlForTelemetry(url: string): string;
51
+ export declare function projectStepToOtlpTraceRequest(params: {
52
+ run: RunRecord;
53
+ step: StepRecord;
54
+ }): OtlpTraceRequest;
55
+ export declare function projectRunRootToOtlpTraceRequest(params: {
56
+ run: RunRecord;
57
+ }): OtlpTraceRequest;
58
+ export {};
59
+ //# sourceMappingURL=otel-projector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"otel-projector.d.ts","sourceRoot":"","sources":["../src/otel-projector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAuB,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAEjF,KAAK,YAAY,GACb;IAAE,WAAW,EAAE,MAAM,CAAA;CAAE,GACvB;IAAE,SAAS,EAAE,OAAO,CAAA;CAAE,GACtB;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,GACpB;IAAE,WAAW,EAAE,MAAM,CAAA;CAAE,GACvB;IAAE,UAAU,EAAE;QAAE,MAAM,EAAE,YAAY,EAAE,CAAA;KAAE,CAAA;CAAE,GAC1C;IAAE,WAAW,EAAE;QAAE,MAAM,EAAE,YAAY,EAAE,CAAA;KAAE,CAAA;CAAE,CAAC;AAEhD,KAAK,YAAY,GAAG;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,YAAY,CAAC;CACrB,CAAC;AAEF,KAAK,QAAQ,GAAG;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,iBAAiB,EAAE,MAAM,CAAC;IAC1B,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,YAAY,EAAE,CAAC;IAC5B,MAAM,CAAC,EAAE;QACP,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,aAAa,EAAE,KAAK,CAAC;QACnB,QAAQ,EAAE;YACR,UAAU,EAAE,YAAY,EAAE,CAAC;SAC5B,CAAC;QACF,UAAU,EAAE,KAAK,CAAC;YAChB,KAAK,EAAE;gBACL,IAAI,EAAE,MAAM,CAAC;aACd,CAAC;YACF,KAAK,EAAE,QAAQ,EAAE,CAAC;SACnB,CAAC,CAAC;KACJ,CAAC,CAAC;CACJ,CAAC;AAwBF,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAW3D;AAgQD,wBAAgB,6BAA6B,CAAC,MAAM,EAAE;IACpD,GAAG,EAAE,SAAS,CAAC;IACf,IAAI,EAAE,UAAU,CAAC;CAClB,GAAG,gBAAgB,CA0CnB;AAED,wBAAgB,gCAAgC,CAAC,MAAM,EAAE;IAAE,GAAG,EAAE,SAAS,CAAA;CAAE,GAAG,gBAAgB,CA2C7F"}
@@ -0,0 +1,325 @@
1
+ const INTERNAL_SPAN_KIND = 1;
2
+ const CLIENT_SPAN_KIND = 3;
3
+ const STATUS_CODE_UNSET = 0;
4
+ const STATUS_CODE_OK = 1;
5
+ const STATUS_CODE_ERROR = 2;
6
+ const MAX_ATTRIBUTE_STRING_LENGTH = 256;
7
+ const MAX_REASON_LENGTH = 512;
8
+ const SENSITIVE_KEY_PATTERN = /(secret|token|password|authorization|cookie|api[-_]?key|raw[-_]?value|raw[-_]?values|resolved[-_]?values|protected[-_]?values)/i;
9
+ function isoToUnixNano(value, fallback) {
10
+ const source = value ?? fallback;
11
+ const millis = new Date(source).getTime();
12
+ const safeMillis = Number.isFinite(millis) ? millis : new Date(fallback).getTime();
13
+ return `${Math.max(0, safeMillis) * 1_000_000}`;
14
+ }
15
+ function truncateString(value, maxLength = MAX_ATTRIBUTE_STRING_LENGTH) {
16
+ return value.length <= maxLength ? value : `${value.slice(0, maxLength)}...`;
17
+ }
18
+ export function sanitizeUrlForTelemetry(url) {
19
+ try {
20
+ const parsed = new URL(url);
21
+ parsed.username = '';
22
+ parsed.password = '';
23
+ parsed.search = '';
24
+ parsed.hash = '';
25
+ return parsed.toString();
26
+ }
27
+ catch {
28
+ return truncateString(url);
29
+ }
30
+ }
31
+ function isSensitiveKey(key) {
32
+ return SENSITIVE_KEY_PATTERN.test(key);
33
+ }
34
+ function normalizePrimitiveForTelemetry(key, value) {
35
+ if (value === null || value === undefined) {
36
+ return undefined;
37
+ }
38
+ if (isSensitiveKey(key)) {
39
+ return '[redacted]';
40
+ }
41
+ if (typeof value === 'string') {
42
+ if (key.toLowerCase().includes('url')) {
43
+ return sanitizeUrlForTelemetry(value);
44
+ }
45
+ if (key.toLowerCase().includes('reason')) {
46
+ return truncateString(value, MAX_REASON_LENGTH);
47
+ }
48
+ if (key.toLowerCase().includes('message')) {
49
+ return truncateString(value, MAX_ATTRIBUTE_STRING_LENGTH);
50
+ }
51
+ return truncateString(value);
52
+ }
53
+ if (typeof value === 'boolean' || typeof value === 'number') {
54
+ return value;
55
+ }
56
+ return undefined;
57
+ }
58
+ function flattenTelemetryAttributes(prefix, value, target) {
59
+ if (value === null || value === undefined) {
60
+ return;
61
+ }
62
+ if (Array.isArray(value)) {
63
+ if (value.length === 0) {
64
+ return;
65
+ }
66
+ const normalized = value
67
+ .map((entry, index) => normalizePrimitiveForTelemetry(`${prefix}[${index}]`, entry))
68
+ .filter((entry) => entry !== undefined);
69
+ if (normalized.length > 0) {
70
+ target[prefix] = normalized;
71
+ }
72
+ return;
73
+ }
74
+ if (typeof value === 'object') {
75
+ for (const [key, nested] of Object.entries(value)) {
76
+ const nextPrefix = prefix.length > 0 ? `${prefix}.${key}` : key;
77
+ flattenTelemetryAttributes(nextPrefix, nested, target);
78
+ }
79
+ return;
80
+ }
81
+ const normalized = normalizePrimitiveForTelemetry(prefix, value);
82
+ if (normalized !== undefined) {
83
+ target[prefix] = normalized;
84
+ }
85
+ }
86
+ function toAnyValue(value) {
87
+ if (typeof value === 'string') {
88
+ return { stringValue: value };
89
+ }
90
+ if (typeof value === 'boolean') {
91
+ return { boolValue: value };
92
+ }
93
+ if (typeof value === 'number') {
94
+ if (Number.isInteger(value)) {
95
+ return { intValue: String(value) };
96
+ }
97
+ return { doubleValue: value };
98
+ }
99
+ if (Array.isArray(value)) {
100
+ const values = value.map(toAnyValue).filter((entry) => entry !== null);
101
+ return { arrayValue: { values } };
102
+ }
103
+ if (value && typeof value === 'object') {
104
+ const values = Object.entries(value)
105
+ .map(([key, nested]) => {
106
+ const nestedValue = toAnyValue(nested);
107
+ return nestedValue ? { key, value: nestedValue } : null;
108
+ })
109
+ .filter((entry) => entry !== null);
110
+ return { kvlistValue: { values } };
111
+ }
112
+ return null;
113
+ }
114
+ function toKeyValues(values) {
115
+ return Object.entries(values)
116
+ .map(([key, value]) => {
117
+ const anyValue = toAnyValue(value);
118
+ return anyValue ? { key, value: anyValue } : null;
119
+ })
120
+ .filter((entry) => entry !== null);
121
+ }
122
+ function getPrimaryRunSiteHost(run) {
123
+ return run.hostHints?.find((entry) => typeof entry === 'string' && entry.length > 0);
124
+ }
125
+ function buildResourceAttributes(run) {
126
+ const siteHost = getPrimaryRunSiteHost(run);
127
+ const values = {
128
+ 'service.name': run.resource.serviceName,
129
+ 'service.version': run.resource.serviceVersion,
130
+ 'service.instance.id': run.resource.serviceInstanceId,
131
+ 'telemetry.sdk.language': run.resource.telemetrySdkLanguage,
132
+ 'agentbrowse.session.id': run.sessionId,
133
+ 'agentbrowse.run.id': run.runId,
134
+ 'agentbrowse.run.source': run.source,
135
+ 'agentbrowse.run.entry_command': run.entryCommand,
136
+ 'agentbrowse.run.display_name': run.displayName,
137
+ 'agentbrowse.run.profile': run.profile,
138
+ 'agentbrowse.run.site_host': siteHost,
139
+ 'agentbrowse.run.started_at': run.startedAt,
140
+ 'agentbrowse.run.ended_at': run.endedAt,
141
+ 'agentbrowse.run.status': run.status,
142
+ 'agentbrowse.run.protected': run.protectedRun,
143
+ 'agentbrowse.run.final_outcome_type': run.finalOutcome?.outcomeType,
144
+ 'agentbrowse.run.final_message': run.finalOutcome?.message,
145
+ 'agentbrowse.run.final_reason': run.finalOutcome?.reason,
146
+ };
147
+ if (run.hostHints && run.hostHints.length > 0) {
148
+ values['agentbrowse.run.host_hints'] = run.hostHints.map((host) => truncateString(host));
149
+ }
150
+ return toKeyValues(values);
151
+ }
152
+ function buildStepAttributes(run, step) {
153
+ const values = {
154
+ 'agentbrowse.run.id': run.runId,
155
+ 'agentbrowse.session.id': run.sessionId,
156
+ 'agentbrowse.step.id': step.stepId,
157
+ 'agentbrowse.step.ordinal': step.ordinal,
158
+ 'agentbrowse.step.command': step.command,
159
+ 'agentbrowse.step.protected': step.protectedStep,
160
+ 'agentbrowse.step.page_ref': step.refs?.pageRef,
161
+ 'agentbrowse.step.target_ref': step.refs?.targetRef,
162
+ 'agentbrowse.step.surface_ref': step.refs?.surfaceRef,
163
+ 'agentbrowse.step.fill_ref': step.refs?.fillRef,
164
+ 'agentbrowse.step.request_id': step.refs?.requestId,
165
+ 'agentbrowse.step.success': step.outputSummary?.success,
166
+ 'agentbrowse.step.outcome_type': step.outputSummary?.outcomeType,
167
+ 'agentbrowse.step.message': step.outputSummary?.message,
168
+ 'agentbrowse.step.reason': step.outputSummary?.reason,
169
+ 'agentbrowse.step.event_count': step.eventIds.length,
170
+ 'agentbrowse.step.child_span_count': step.childSpans.length,
171
+ 'agentbrowse.trace.propagation_mode': run.traceContext.propagationMode,
172
+ };
173
+ const flattenedInput = {};
174
+ flattenTelemetryAttributes('agentbrowse.step.input', step.input, flattenedInput);
175
+ Object.assign(values, flattenedInput);
176
+ return toKeyValues(values);
177
+ }
178
+ function buildRunRootSpanName(run) {
179
+ const siteHost = getPrimaryRunSiteHost(run);
180
+ const displayName = typeof run.displayName === 'string' && run.displayName.trim().length > 0
181
+ ? run.displayName.trim()
182
+ : undefined;
183
+ if (siteHost && displayName) {
184
+ return truncateString(`${siteHost} - ${displayName}`);
185
+ }
186
+ if (displayName) {
187
+ return truncateString(displayName);
188
+ }
189
+ if (siteHost) {
190
+ return truncateString(siteHost);
191
+ }
192
+ if (run.entryCommand) {
193
+ return `magicpay.${truncateString(run.entryCommand)}`;
194
+ }
195
+ return 'magicpay.run';
196
+ }
197
+ function buildRunRootSpanAttributes(run) {
198
+ const siteHost = getPrimaryRunSiteHost(run);
199
+ const values = {
200
+ 'agentbrowse.run.id': run.runId,
201
+ 'agentbrowse.session.id': run.sessionId,
202
+ 'agentbrowse.run.entry_command': run.entryCommand,
203
+ 'agentbrowse.run.display_name': run.displayName,
204
+ 'agentbrowse.run.site_host': siteHost,
205
+ 'agentbrowse.run.status': run.status,
206
+ 'agentbrowse.run.protected': run.protectedRun,
207
+ 'agentbrowse.run.step_count': run.stepIds.length,
208
+ 'agentbrowse.run.final_outcome_type': run.finalOutcome?.outcomeType,
209
+ 'agentbrowse.run.final_message': run.finalOutcome?.message,
210
+ 'agentbrowse.run.final_reason': run.finalOutcome?.reason,
211
+ };
212
+ if (run.hostHints && run.hostHints.length > 0) {
213
+ values['agentbrowse.run.host_hints'] = run.hostHints.map((host) => truncateString(host));
214
+ }
215
+ return toKeyValues(values);
216
+ }
217
+ function buildStepStatus(step) {
218
+ const code = step.otel.statusCode === 'ok'
219
+ ? STATUS_CODE_OK
220
+ : step.otel.statusCode === 'error'
221
+ ? STATUS_CODE_ERROR
222
+ : STATUS_CODE_UNSET;
223
+ return {
224
+ code,
225
+ ...(step.otel.statusMessage ? { message: truncateString(step.otel.statusMessage) } : {}),
226
+ };
227
+ }
228
+ function buildChildSpanStatus(childSpan) {
229
+ const code = childSpan.statusCode === 'ok'
230
+ ? STATUS_CODE_OK
231
+ : childSpan.statusCode === 'error'
232
+ ? STATUS_CODE_ERROR
233
+ : STATUS_CODE_UNSET;
234
+ return {
235
+ code,
236
+ ...(childSpan.statusMessage ? { message: truncateString(childSpan.statusMessage) } : {}),
237
+ };
238
+ }
239
+ function buildChildSpanAttributes(childSpan) {
240
+ const flattened = {};
241
+ flattenTelemetryAttributes('', childSpan.attributes, flattened);
242
+ return toKeyValues(flattened);
243
+ }
244
+ export function projectStepToOtlpTraceRequest(params) {
245
+ const stepSpan = {
246
+ traceId: params.step.otel.traceId,
247
+ spanId: params.step.otel.spanId,
248
+ ...(params.step.otel.parentSpanId ? { parentSpanId: params.step.otel.parentSpanId } : {}),
249
+ name: params.step.otel.spanName,
250
+ kind: INTERNAL_SPAN_KIND,
251
+ startTimeUnixNano: isoToUnixNano(params.step.startedAt, params.run.startedAt),
252
+ endTimeUnixNano: isoToUnixNano(params.step.endedAt, params.step.startedAt),
253
+ attributes: buildStepAttributes(params.run, params.step),
254
+ status: buildStepStatus(params.step),
255
+ };
256
+ const childSpans = params.step.childSpans.map((childSpan) => ({
257
+ traceId: params.step.otel.traceId,
258
+ spanId: childSpan.spanId,
259
+ parentSpanId: childSpan.parentSpanId,
260
+ name: childSpan.name,
261
+ kind: CLIENT_SPAN_KIND,
262
+ startTimeUnixNano: isoToUnixNano(childSpan.startedAt, params.step.startedAt),
263
+ endTimeUnixNano: isoToUnixNano(childSpan.endedAt, childSpan.startedAt),
264
+ attributes: buildChildSpanAttributes(childSpan),
265
+ status: buildChildSpanStatus(childSpan),
266
+ }));
267
+ return {
268
+ resourceSpans: [
269
+ {
270
+ resource: {
271
+ attributes: buildResourceAttributes(params.run),
272
+ },
273
+ scopeSpans: [
274
+ {
275
+ scope: {
276
+ name: params.step.otel.instrumentationScope,
277
+ },
278
+ spans: [stepSpan, ...childSpans],
279
+ },
280
+ ],
281
+ },
282
+ ],
283
+ };
284
+ }
285
+ export function projectRunRootToOtlpTraceRequest(params) {
286
+ const statusCode = params.run.finalOutcome?.success === true || params.run.status === 'completed'
287
+ ? STATUS_CODE_OK
288
+ : params.run.finalOutcome?.success === false ||
289
+ params.run.status === 'failed' ||
290
+ params.run.status === 'aborted'
291
+ ? STATUS_CODE_ERROR
292
+ : STATUS_CODE_UNSET;
293
+ const span = {
294
+ traceId: params.run.traceContext.traceId,
295
+ spanId: params.run.traceContext.rootSpanId,
296
+ name: buildRunRootSpanName(params.run),
297
+ kind: INTERNAL_SPAN_KIND,
298
+ startTimeUnixNano: isoToUnixNano(params.run.startedAt, params.run.startedAt),
299
+ endTimeUnixNano: isoToUnixNano(params.run.endedAt, params.run.startedAt),
300
+ attributes: buildRunRootSpanAttributes(params.run),
301
+ status: {
302
+ code: statusCode,
303
+ ...(params.run.finalOutcome?.reason
304
+ ? { message: truncateString(params.run.finalOutcome.reason) }
305
+ : {}),
306
+ },
307
+ };
308
+ return {
309
+ resourceSpans: [
310
+ {
311
+ resource: {
312
+ attributes: buildResourceAttributes(params.run),
313
+ },
314
+ scopeSpans: [
315
+ {
316
+ scope: {
317
+ name: 'magicpay.local-run-store',
318
+ },
319
+ spans: [span],
320
+ },
321
+ ],
322
+ },
323
+ ],
324
+ };
325
+ }
@@ -0,0 +1,10 @@
1
+ export interface CliResult {
2
+ success: boolean;
3
+ error?: string;
4
+ }
5
+ export declare function outputJSON<T extends CliResult>(result: T): never;
6
+ export declare function outputError(error: string): never;
7
+ export declare function writeInfo(message: string): void;
8
+ export declare function info(message: string): never;
9
+ export declare function fatal(message: string): never;
10
+ //# sourceMappingURL=output.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAWD,wBAAgB,UAAU,CAAC,CAAC,SAAS,SAAS,EAAE,MAAM,EAAE,CAAC,GAAG,KAAK,CAMhE;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,CAEhD;AAED,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAE/C;AAED,wBAAgB,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,KAAK,CAG3C;AAED,wBAAgB,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,KAAK,CAG5C"}
package/dist/output.js ADDED
@@ -0,0 +1,29 @@
1
+ const DEFAULT_COMMAND_NAME = 'magicpay';
2
+ function serializeResult(result) {
3
+ return `${JSON.stringify(result, null, 2)}\n`;
4
+ }
5
+ function commandName() {
6
+ const normalized = process.env.MAGICPAY_COMMAND?.trim();
7
+ return normalized && normalized.length > 0 ? normalized : DEFAULT_COMMAND_NAME;
8
+ }
9
+ export function outputJSON(result) {
10
+ const normalizedResult = result.success
11
+ ? result
12
+ : { ...result, error: result.error ?? 'Unknown error' };
13
+ process.stdout.write(serializeResult(normalizedResult));
14
+ process.exit(result.success ? 0 : 1);
15
+ }
16
+ export function outputError(error) {
17
+ outputJSON({ success: false, error });
18
+ }
19
+ export function writeInfo(message) {
20
+ process.stderr.write(`${message}\n`);
21
+ }
22
+ export function info(message) {
23
+ process.stdout.write(`${message}\n`);
24
+ process.exit(0);
25
+ }
26
+ export function fatal(message) {
27
+ process.stderr.write(`[${commandName()}] Fatal: ${message}\n`);
28
+ process.exit(1);
29
+ }
@@ -0,0 +1,2 @@
1
+ export declare function readCurrentPackageVersion(): string;
2
+ //# sourceMappingURL=package-version.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"package-version.d.ts","sourceRoot":"","sources":["../src/package-version.ts"],"names":[],"mappings":"AAMA,wBAAgB,yBAAyB,IAAI,MAAM,CAYlD"}
@@ -0,0 +1,14 @@
1
+ import { readFileSync } from 'node:fs';
2
+ const PACKAGE_JSON_URL = new URL('../package.json', import.meta.url);
3
+ let cachedPackageVersion = null;
4
+ export function readCurrentPackageVersion() {
5
+ if (cachedPackageVersion) {
6
+ return cachedPackageVersion;
7
+ }
8
+ const raw = JSON.parse(readFileSync(PACKAGE_JSON_URL, 'utf-8'));
9
+ if (!raw.version || typeof raw.version !== 'string') {
10
+ throw new Error('Package version is missing from package.json.');
11
+ }
12
+ cachedPackageVersion = raw.version;
13
+ return cachedPackageVersion;
14
+ }