autokap 1.0.7 → 1.0.10
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/assets/cursors/macos.svg +4 -0
- package/assets/cursors/windows.svg +15 -0
- package/assets/skill/OPCODE-REFERENCE.md +635 -0
- package/assets/skill/README.md +39 -0
- package/assets/skill/SKILL.md +454 -468
- package/assets/skill/STUDIO-SKILL.md +476 -0
- package/assets/skill/references/examples.md +104 -0
- package/assets/skill/references/interactive-demo.md +225 -0
- package/assets/skill/references/mock-data.md +178 -0
- package/dist/action-verifier.d.ts +29 -0
- package/dist/action-verifier.js +133 -0
- package/dist/agent-action-recovery.d.ts +45 -0
- package/dist/agent-action-recovery.js +370 -0
- package/dist/agent-message-utils.d.ts +21 -0
- package/dist/agent-message-utils.js +77 -0
- package/dist/agent-url-utils.d.ts +30 -0
- package/dist/agent-url-utils.js +138 -0
- package/dist/agent.d.ts +92 -8
- package/dist/agent.js +2936 -781
- package/dist/ak-tree.d.ts +39 -0
- package/dist/ak-tree.js +368 -0
- package/dist/alt-text.d.ts +26 -0
- package/dist/alt-text.js +55 -0
- package/dist/auth-capture.d.ts +17 -0
- package/dist/auth-capture.js +197 -0
- package/dist/benchmark.d.ts +59 -0
- package/dist/benchmark.js +135 -0
- package/dist/billing-operation-logging.d.ts +3 -1
- package/dist/billing-operation-logging.js +4 -0
- package/dist/browser-bar.d.ts +14 -6
- package/dist/browser-bar.js +145 -8
- package/dist/browser-pool.d.ts +7 -0
- package/dist/browser-pool.js +15 -5
- package/dist/browser-utils.d.ts +31 -0
- package/dist/browser-utils.js +97 -0
- package/dist/browser.d.ts +61 -11
- package/dist/browser.js +1513 -59
- package/dist/capture-alt-text.js +2 -1
- package/dist/capture-encryption.d.ts +3 -1
- package/dist/capture-encryption.js +21 -6
- package/dist/capture-language-preflight.js +14 -0
- package/dist/capture-llm-page-identity.js +22 -10
- package/dist/capture-page-identity.d.ts +5 -7
- package/dist/capture-page-identity.js +211 -78
- package/dist/capture-preset-credentials.d.ts +50 -0
- package/dist/capture-preset-credentials.js +127 -0
- package/dist/capture-request-plan.d.ts +2 -2
- package/dist/capture-request-plan.js +64 -16
- package/dist/capture-run-optimizer.js +48 -33
- package/dist/capture-selector-memory.d.ts +5 -0
- package/dist/capture-selector-memory.js +18 -0
- package/dist/capture-strategy.d.ts +36 -0
- package/dist/capture-strategy.js +96 -0
- package/dist/capture-studio-sync.d.ts +1 -0
- package/dist/capture-studio-sync.js +9 -3
- package/dist/capture-surface-contract.d.ts +36 -0
- package/dist/capture-surface-contract.js +299 -0
- package/dist/capture-transition-engine.d.ts +28 -0
- package/dist/capture-transition-engine.js +292 -0
- package/dist/capture-variant-state.d.ts +2 -0
- package/dist/capture-variant-state.js +26 -0
- package/dist/capture-verification.d.ts +35 -0
- package/dist/capture-verification.js +95 -0
- package/dist/capture-viewport-lock.d.ts +48 -0
- package/dist/capture-viewport-lock.js +74 -0
- package/dist/circuit-breaker.d.ts +42 -0
- package/dist/circuit-breaker.js +119 -0
- package/dist/cli-config.d.ts +9 -1
- package/dist/cli-config.js +112 -7
- package/dist/cli-contract.d.ts +19 -0
- package/dist/cli-contract.js +173 -0
- package/dist/cli-runner-local.d.ts +12 -0
- package/dist/cli-runner-local.js +115 -0
- package/dist/cli-runner.d.ts +34 -0
- package/dist/cli-runner.js +580 -0
- package/dist/cli-utils.d.ts +0 -1
- package/dist/cli-utils.js +2 -5
- package/dist/cli.js +1011 -267
- package/dist/clip-begin-frame-recorder.d.ts +44 -0
- package/dist/clip-begin-frame-recorder.js +250 -0
- package/dist/clip-capture-backend.d.ts +25 -0
- package/dist/clip-capture-backend.js +189 -0
- package/dist/clip-capture-loop.d.ts +61 -0
- package/dist/clip-capture-loop.js +111 -0
- package/dist/clip-frame-recorder.d.ts +63 -0
- package/dist/clip-frame-recorder.js +305 -0
- package/dist/clip-orchestrator.js +9 -2
- package/dist/clip-postprocess.d.ts +31 -2
- package/dist/clip-postprocess.js +194 -68
- package/dist/clip-runtime.d.ts +18 -0
- package/dist/clip-runtime.js +67 -0
- package/dist/clip-scale.d.ts +10 -0
- package/dist/clip-scale.js +21 -0
- package/dist/clip-screencast-recorder.d.ts +42 -0
- package/dist/clip-screencast-recorder.js +242 -0
- package/dist/clip-sidecar.d.ts +54 -0
- package/dist/clip-sidecar.js +208 -0
- package/dist/cookie-dismiss.d.ts +2 -0
- package/dist/cookie-dismiss.js +48 -13
- package/dist/cost-logging.d.ts +8 -0
- package/dist/cost-logging.js +160 -46
- package/dist/cost-resolution-monitor.d.ts +16 -0
- package/dist/cost-resolution-monitor.js +34 -0
- package/dist/credential-templates.js +2 -2
- package/dist/cursor-overlay-script.d.ts +6 -0
- package/dist/cursor-overlay-script.js +169 -0
- package/dist/dom-css-purger.d.ts +65 -0
- package/dist/dom-css-purger.js +333 -0
- package/dist/dom-font-inliner.d.ts +45 -0
- package/dist/dom-font-inliner.js +148 -0
- package/dist/dom-patch-resolver.d.ts +52 -0
- package/dist/dom-patch-resolver.js +242 -0
- package/dist/dom-serializer.d.ts +82 -0
- package/dist/dom-serializer.js +378 -0
- package/dist/element-capture.d.ts +1 -41
- package/dist/element-capture.js +202 -446
- package/dist/env-validation.d.ts +5 -0
- package/dist/env-validation.js +63 -0
- package/dist/execution-schema.d.ts +4753 -0
- package/dist/execution-schema.js +563 -0
- package/dist/execution-types.d.ts +936 -0
- package/dist/execution-types.js +66 -0
- package/dist/fonts-loader.d.ts +14 -0
- package/dist/fonts-loader.js +55 -0
- package/dist/hybrid-navigator.js +12 -12
- package/dist/index.d.ts +11 -6
- package/dist/index.js +11 -4
- package/dist/legacy/agent-action-recovery.d.ts +45 -0
- package/dist/legacy/agent-action-recovery.js +370 -0
- package/dist/legacy/agent-message-utils.d.ts +21 -0
- package/dist/legacy/agent-message-utils.js +77 -0
- package/dist/legacy/agent-url-utils.d.ts +30 -0
- package/dist/legacy/agent-url-utils.js +138 -0
- package/dist/legacy/agent.d.ts +226 -0
- package/dist/legacy/agent.js +6666 -0
- package/dist/legacy/clip-orchestrator.d.ts +148 -0
- package/dist/legacy/clip-orchestrator.js +957 -0
- package/dist/legacy/credential-templates.d.ts +5 -0
- package/dist/legacy/credential-templates.js +60 -0
- package/dist/legacy/hybrid-navigator.d.ts +138 -0
- package/dist/legacy/hybrid-navigator.js +468 -0
- package/dist/legacy/llm-usage.d.ts +17 -0
- package/dist/legacy/llm-usage.js +45 -0
- package/dist/legacy/prompt-cache.d.ts +10 -0
- package/dist/legacy/prompt-cache.js +24 -0
- package/dist/legacy/prompts.d.ts +175 -0
- package/dist/legacy/prompts.js +1038 -0
- package/dist/legacy/tools.d.ts +4 -0
- package/dist/legacy/tools.js +216 -0
- package/dist/legacy/video-agent.d.ts +143 -0
- package/dist/legacy/video-agent.js +4788 -0
- package/dist/legacy/video-observation.d.ts +36 -0
- package/dist/legacy/video-observation.js +192 -0
- package/dist/legacy/video-planner.d.ts +12 -0
- package/dist/legacy/video-planner.js +501 -0
- package/dist/legacy/video-prompts.d.ts +37 -0
- package/dist/legacy/video-prompts.js +569 -0
- package/dist/legacy/video-tools.d.ts +3 -0
- package/dist/legacy/video-tools.js +59 -0
- package/dist/legacy/video-variant-state.d.ts +29 -0
- package/dist/legacy/video-variant-state.js +80 -0
- package/dist/legacy/vision-model.d.ts +17 -0
- package/dist/legacy/vision-model.js +74 -0
- package/dist/llm-healer.d.ts +55 -0
- package/dist/llm-healer.js +213 -0
- package/dist/llm-provider.d.ts +29 -0
- package/dist/llm-provider.js +83 -0
- package/dist/logger.d.ts +6 -2
- package/dist/logger.js +15 -1
- package/dist/mockup-html.js +35 -25
- package/dist/mockup.d.ts +95 -2
- package/dist/mockup.js +427 -166
- package/dist/mouse-animation.d.ts +2 -2
- package/dist/mouse-animation.js +34 -20
- package/dist/opcode-actions.d.ts +42 -0
- package/dist/opcode-actions.js +524 -0
- package/dist/opcode-runner.d.ts +51 -0
- package/dist/opcode-runner.js +779 -0
- package/dist/openrouter-client.d.ts +40 -0
- package/dist/openrouter-client.js +16 -0
- package/dist/overlay-engine.d.ts +24 -0
- package/dist/overlay-engine.js +176 -0
- package/dist/postcondition.d.ts +16 -0
- package/dist/postcondition.js +269 -0
- package/dist/program-patcher.d.ts +25 -0
- package/dist/program-patcher.js +44 -0
- package/dist/program-signing.d.ts +1094 -0
- package/dist/program-signing.js +140 -0
- package/dist/prompts.d.ts +13 -5
- package/dist/prompts.js +224 -351
- package/dist/provider-config.d.ts +17 -0
- package/dist/provider-config.js +42 -0
- package/dist/recovery-chain.d.ts +37 -0
- package/dist/recovery-chain.js +374 -0
- package/dist/remote-browser.d.ts +28 -4
- package/dist/remote-browser.js +60 -5
- package/dist/safari-browser-bar.d.ts +15 -0
- package/dist/safari-browser-bar.js +95 -0
- package/dist/safari-toolbar-asset.d.ts +15 -0
- package/dist/safari-toolbar-asset.js +12 -0
- package/dist/security.d.ts +2 -1
- package/dist/security.js +49 -10
- package/dist/selector-resolver.d.ts +34 -0
- package/dist/selector-resolver.js +181 -0
- package/dist/semantic-resolver.d.ts +35 -0
- package/dist/semantic-resolver.js +161 -0
- package/dist/server-capture-runtime.d.ts +5 -3
- package/dist/server-capture-runtime.js +42 -95
- package/dist/server-credit-usage.d.ts +2 -2
- package/dist/server-project-webhooks.d.ts +15 -1
- package/dist/server-project-webhooks.js +34 -8
- package/dist/server-screenshot-watermark.js +27 -5
- package/dist/session-profile.js +164 -1
- package/dist/sf-pro-symbols.d.ts +1 -0
- package/dist/sf-pro-symbols.js +55 -0
- package/dist/skill-packaging.d.ts +28 -0
- package/dist/skill-packaging.js +169 -0
- package/dist/smart-wait.d.ts +27 -0
- package/dist/smart-wait.js +81 -0
- package/dist/status-bar-render.d.ts +20 -0
- package/dist/status-bar-render.js +410 -0
- package/dist/status-bar.d.ts +9 -0
- package/dist/status-bar.js +298 -14
- package/dist/svg-browser-bar.d.ts +33 -0
- package/dist/svg-browser-bar.js +206 -0
- package/dist/svg-status-bar.d.ts +36 -0
- package/dist/svg-status-bar.js +597 -0
- package/dist/svg-text.d.ts +61 -0
- package/dist/svg-text.js +118 -0
- package/dist/tools.js +89 -451
- package/dist/types.d.ts +248 -7
- package/dist/types.js +23 -1
- package/dist/v2/action-verifier.d.ts +29 -0
- package/dist/v2/action-verifier.js +133 -0
- package/dist/v2/alt-text.d.ts +26 -0
- package/dist/v2/alt-text.js +55 -0
- package/dist/v2/benchmark.d.ts +59 -0
- package/dist/v2/benchmark.js +135 -0
- package/dist/v2/capture-strategy.d.ts +30 -0
- package/dist/v2/capture-strategy.js +67 -0
- package/dist/v2/capture-verification.d.ts +35 -0
- package/dist/v2/capture-verification.js +95 -0
- package/dist/v2/circuit-breaker.d.ts +42 -0
- package/dist/v2/circuit-breaker.js +119 -0
- package/dist/v2/cli-runner-local.d.ts +11 -0
- package/dist/v2/cli-runner-local.js +91 -0
- package/dist/v2/cli-runner.d.ts +34 -0
- package/dist/v2/cli-runner.js +300 -0
- package/dist/v2/compiler-prompts.d.ts +27 -0
- package/dist/v2/compiler-prompts.js +123 -0
- package/dist/v2/compiler.d.ts +37 -0
- package/dist/v2/compiler.js +147 -0
- package/dist/v2/explorer.d.ts +41 -0
- package/dist/v2/explorer.js +56 -0
- package/dist/v2/index.d.ts +37 -0
- package/dist/v2/index.js +31 -0
- package/dist/v2/llm-healer.d.ts +62 -0
- package/dist/v2/llm-healer.js +166 -0
- package/dist/v2/llm-provider.d.ts +29 -0
- package/dist/v2/llm-provider.js +80 -0
- package/dist/v2/opcode-runner.d.ts +47 -0
- package/dist/v2/opcode-runner.js +634 -0
- package/dist/v2/overlay-engine.d.ts +24 -0
- package/dist/v2/overlay-engine.js +150 -0
- package/dist/v2/postcondition.d.ts +16 -0
- package/dist/v2/postcondition.js +249 -0
- package/dist/v2/program-patcher.d.ts +25 -0
- package/dist/v2/program-patcher.js +44 -0
- package/dist/v2/recovery-chain.d.ts +30 -0
- package/dist/v2/recovery-chain.js +368 -0
- package/dist/v2/schema.d.ts +2580 -0
- package/dist/v2/schema.js +295 -0
- package/dist/v2/selector-resolver.d.ts +34 -0
- package/dist/v2/selector-resolver.js +181 -0
- package/dist/v2/semantic-resolver.d.ts +35 -0
- package/dist/v2/semantic-resolver.js +161 -0
- package/dist/v2/smart-wait.d.ts +27 -0
- package/dist/v2/smart-wait.js +81 -0
- package/dist/v2/types.d.ts +444 -0
- package/dist/v2/types.js +19 -0
- package/dist/v2/web-playwright-local.d.ts +69 -0
- package/dist/v2/web-playwright-local.js +392 -0
- package/dist/version.d.ts +1 -0
- package/dist/version.js +5 -0
- package/dist/video-agent.js +18 -13
- package/dist/video-planner.js +2 -1
- package/dist/video-prompts.js +3 -3
- package/dist/web-playwright-local.d.ts +156 -0
- package/dist/web-playwright-local.js +989 -0
- package/dist/ws-auth.js +4 -1
- package/dist/ws-broadcast.d.ts +34 -0
- package/dist/ws-broadcast.js +85 -0
- package/dist/ws-connection-limits.d.ts +12 -0
- package/dist/ws-connection-limits.js +44 -0
- package/dist/ws-handler-utils.d.ts +32 -0
- package/dist/ws-handler-utils.js +139 -0
- package/dist/ws-handler.js +294 -164
- package/dist/ws-metrics-server.d.ts +9 -0
- package/dist/ws-metrics-server.js +31 -0
- package/dist/ws-server.js +41 -1
- package/package.json +62 -35
package/dist/cost-logging.js
CHANGED
|
@@ -1,49 +1,88 @@
|
|
|
1
|
+
function isFiniteInteger(value) {
|
|
2
|
+
return typeof value === 'number' && Number.isInteger(value);
|
|
3
|
+
}
|
|
4
|
+
function normalizeUsageForCostLog(step, index) {
|
|
5
|
+
const normalizedStepNumber = isFiniteInteger(step.stepNumber) && step.stepNumber >= 0
|
|
6
|
+
? step.stepNumber
|
|
7
|
+
: index + 1;
|
|
8
|
+
const normalizedStepType = typeof step.stepType === 'string' && step.stepType.trim().length > 0
|
|
9
|
+
? step.stepType
|
|
10
|
+
: 'agent_iteration';
|
|
11
|
+
const normalizedModelRequested = typeof step.modelRequested === 'string' && step.modelRequested.trim().length > 0
|
|
12
|
+
? step.modelRequested
|
|
13
|
+
: step.modelUsed ?? 'unknown';
|
|
14
|
+
const normalizedImagesInPrompt = typeof step.imagesInPrompt === 'number' && Number.isFinite(step.imagesInPrompt)
|
|
15
|
+
? step.imagesInPrompt
|
|
16
|
+
: 0;
|
|
17
|
+
if (normalizedStepNumber !== step.stepNumber
|
|
18
|
+
|| normalizedStepType !== step.stepType
|
|
19
|
+
|| normalizedModelRequested !== step.modelRequested
|
|
20
|
+
|| normalizedImagesInPrompt !== step.imagesInPrompt) {
|
|
21
|
+
console.warn('Normalizing invalid cost log usage entry:', JSON.stringify({
|
|
22
|
+
stepNumber: step.stepNumber ?? null,
|
|
23
|
+
stepType: step.stepType ?? null,
|
|
24
|
+
modelRequested: step.modelRequested ?? null,
|
|
25
|
+
modelUsed: step.modelUsed ?? null,
|
|
26
|
+
fallbackStepNumber: normalizedStepNumber,
|
|
27
|
+
}));
|
|
28
|
+
}
|
|
29
|
+
return {
|
|
30
|
+
...step,
|
|
31
|
+
stepNumber: normalizedStepNumber,
|
|
32
|
+
stepType: normalizedStepType,
|
|
33
|
+
modelRequested: normalizedModelRequested,
|
|
34
|
+
imagesInPrompt: normalizedImagesInPrompt,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
1
37
|
export async function insertCostLogs(supabase, ctx, steps) {
|
|
2
38
|
if (steps.length === 0)
|
|
3
39
|
return [];
|
|
4
|
-
const rows = steps.map((
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
40
|
+
const rows = steps.map((rawStep, index) => {
|
|
41
|
+
const step = normalizeUsageForCostLog(rawStep, index);
|
|
42
|
+
return {
|
|
43
|
+
id: crypto.randomUUID(),
|
|
44
|
+
run_id: ctx.runId,
|
|
45
|
+
user_id: ctx.userId,
|
|
46
|
+
project_id: ctx.projectId ?? null,
|
|
47
|
+
preset_id: ctx.presetId ?? null,
|
|
48
|
+
capture_id: ctx.captureId ?? null,
|
|
49
|
+
step_number: step.stepNumber,
|
|
50
|
+
step_type: step.stepType,
|
|
51
|
+
model_requested: step.modelRequested,
|
|
52
|
+
model_used: step.modelUsed,
|
|
53
|
+
generation_id: step.generationId,
|
|
54
|
+
prompt_tokens: step.promptTokens,
|
|
55
|
+
completion_tokens: step.completionTokens,
|
|
56
|
+
total_tokens: step.totalTokens,
|
|
57
|
+
cost_resolved: false,
|
|
58
|
+
images_in_prompt: step.imagesInPrompt,
|
|
59
|
+
lang: ctx.lang ?? null,
|
|
60
|
+
theme: ctx.theme ?? null,
|
|
61
|
+
capture_type: ctx.captureType ?? null,
|
|
62
|
+
element_name: ctx.elementName ?? null,
|
|
63
|
+
target_id: ctx.targetId ?? null,
|
|
64
|
+
viewport_width: ctx.viewportWidth ?? null,
|
|
65
|
+
viewport_height: ctx.viewportHeight ?? null,
|
|
66
|
+
system_prompt_chars: step.systemPromptChars ?? null,
|
|
67
|
+
tool_schema_chars: step.toolSchemaChars ?? null,
|
|
68
|
+
user_payload_chars: step.userPayloadChars ?? null,
|
|
69
|
+
accessibility_chars: step.accessibilityChars ?? null,
|
|
70
|
+
interactive_element_count: step.interactiveElementCount ?? null,
|
|
71
|
+
action_history_count: step.actionHistoryCount ?? null,
|
|
72
|
+
elements_chars: step.elementsChars ?? null,
|
|
73
|
+
session_summary_chars: step.sessionSummaryChars ?? null,
|
|
74
|
+
selector_memory_chars: step.selectorMemoryChars ?? null,
|
|
75
|
+
agent_context_chars: step.agentContextChars ?? null,
|
|
76
|
+
profile_validation_status: step.profileValidationStatus ?? null,
|
|
77
|
+
session_profile_source: step.sessionProfileSource ?? null,
|
|
78
|
+
repair_path_used: step.repairPathUsed ?? null,
|
|
79
|
+
evaluator_used: step.evaluatorUsed ?? false,
|
|
80
|
+
cache_read_tokens: step.cacheReadTokens ?? null,
|
|
81
|
+
cache_write_tokens: step.cacheWriteTokens ?? null,
|
|
82
|
+
session_profile_reused: step.sessionProfileReused ?? false,
|
|
83
|
+
action_replay_used: step.actionReplayUsed ?? false,
|
|
84
|
+
};
|
|
85
|
+
});
|
|
47
86
|
try {
|
|
48
87
|
const { error } = await supabase.from('cost_logs').insert(rows);
|
|
49
88
|
if (error) {
|
|
@@ -79,9 +118,21 @@ export async function updateCostLogCaptureContext(supabase, costLogIds, params)
|
|
|
79
118
|
}
|
|
80
119
|
}
|
|
81
120
|
async function resolveCost(updateClient, generationId, costLogId, apiKey) {
|
|
82
|
-
const delays = [10_000, 20_000, 40_000];
|
|
121
|
+
const delays = [10_000, 20_000, 40_000, 80_000, 160_000];
|
|
83
122
|
for (let attempt = 0; attempt < delays.length; attempt += 1) {
|
|
84
123
|
await new Promise((resolve) => setTimeout(resolve, delays[attempt]));
|
|
124
|
+
// Track resolution attempt (best-effort)
|
|
125
|
+
try {
|
|
126
|
+
await updateClient
|
|
127
|
+
.from('cost_logs')
|
|
128
|
+
.update({
|
|
129
|
+
resolution_attempts: attempt + 1,
|
|
130
|
+
last_resolution_attempt_at: new Date().toISOString(),
|
|
131
|
+
cost_resolution_status: 'pending',
|
|
132
|
+
})
|
|
133
|
+
.eq('id', costLogId);
|
|
134
|
+
}
|
|
135
|
+
catch { /* best-effort tracking */ }
|
|
85
136
|
try {
|
|
86
137
|
const response = await fetch(`https://openrouter.ai/api/v1/generation?id=${generationId}`, { headers: { Authorization: `Bearer ${apiKey}` } });
|
|
87
138
|
if (response.status === 404 && attempt < delays.length - 1) {
|
|
@@ -89,13 +140,19 @@ async function resolveCost(updateClient, generationId, costLogId, apiKey) {
|
|
|
89
140
|
}
|
|
90
141
|
if (!response.ok) {
|
|
91
142
|
console.error(`OpenRouter generation lookup failed (${generationId}): HTTP ${response.status}`);
|
|
92
|
-
|
|
143
|
+
if (attempt === delays.length - 1) {
|
|
144
|
+
await markCostResolutionFailed(updateClient, costLogId, `HTTP ${response.status}`);
|
|
145
|
+
}
|
|
146
|
+
continue;
|
|
93
147
|
}
|
|
94
148
|
const generation = await response.json();
|
|
95
149
|
const totalCost = generation.data?.total_cost ?? null;
|
|
96
150
|
if (totalCost == null) {
|
|
97
151
|
console.warn(`OpenRouter returned no total_cost for generation ${generationId}`);
|
|
98
|
-
|
|
152
|
+
if (attempt === delays.length - 1) {
|
|
153
|
+
await markCostResolutionFailed(updateClient, costLogId, 'no total_cost in response');
|
|
154
|
+
}
|
|
155
|
+
continue;
|
|
99
156
|
}
|
|
100
157
|
const { error } = await updateClient
|
|
101
158
|
.from('cost_logs')
|
|
@@ -103,6 +160,7 @@ async function resolveCost(updateClient, generationId, costLogId, apiKey) {
|
|
|
103
160
|
cost_usd: totalCost,
|
|
104
161
|
cost_resolved: true,
|
|
105
162
|
resolved_at: new Date().toISOString(),
|
|
163
|
+
cost_resolution_status: 'resolved',
|
|
106
164
|
})
|
|
107
165
|
.eq('id', costLogId);
|
|
108
166
|
if (error) {
|
|
@@ -113,10 +171,66 @@ async function resolveCost(updateClient, generationId, costLogId, apiKey) {
|
|
|
113
171
|
catch (error) {
|
|
114
172
|
if (attempt === delays.length - 1) {
|
|
115
173
|
console.error(`Cost resolution failed for ${generationId}:`, error.message);
|
|
174
|
+
await markCostResolutionFailed(updateClient, costLogId, error.message);
|
|
116
175
|
}
|
|
117
176
|
}
|
|
118
177
|
}
|
|
119
178
|
}
|
|
179
|
+
async function markCostResolutionFailed(updateClient, costLogId, reason) {
|
|
180
|
+
try {
|
|
181
|
+
await updateClient
|
|
182
|
+
.from('cost_logs')
|
|
183
|
+
.update({ cost_resolution_status: 'failed' })
|
|
184
|
+
.eq('id', costLogId);
|
|
185
|
+
console.error(`Cost resolution marked as failed for ${costLogId}: ${reason}`);
|
|
186
|
+
}
|
|
187
|
+
catch {
|
|
188
|
+
// best-effort — don't fail the caller
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Retry resolution for previously failed cost logs.
|
|
193
|
+
* Designed to be called by a reconciliation cron job.
|
|
194
|
+
*/
|
|
195
|
+
export async function reconcileUnresolvedCosts(supabase, apiKey) {
|
|
196
|
+
const sevenDaysAgo = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString();
|
|
197
|
+
const { data: failedLogs, error } = await supabase
|
|
198
|
+
.from('cost_logs')
|
|
199
|
+
.select('id, generation_id')
|
|
200
|
+
.eq('cost_resolution_status', 'failed')
|
|
201
|
+
.gt('created_at', sevenDaysAgo)
|
|
202
|
+
.not('generation_id', 'is', null)
|
|
203
|
+
.limit(100);
|
|
204
|
+
if (error || !failedLogs?.length) {
|
|
205
|
+
return { retried: 0, resolved: 0 };
|
|
206
|
+
}
|
|
207
|
+
let resolved = 0;
|
|
208
|
+
for (const log of failedLogs) {
|
|
209
|
+
try {
|
|
210
|
+
const response = await fetch(`https://openrouter.ai/api/v1/generation?id=${log.generation_id}`, { headers: { Authorization: `Bearer ${apiKey}` } });
|
|
211
|
+
if (!response.ok)
|
|
212
|
+
continue;
|
|
213
|
+
const generation = await response.json();
|
|
214
|
+
const totalCost = generation.data?.total_cost ?? null;
|
|
215
|
+
if (totalCost == null)
|
|
216
|
+
continue;
|
|
217
|
+
await supabase
|
|
218
|
+
.from('cost_logs')
|
|
219
|
+
.update({
|
|
220
|
+
cost_usd: totalCost,
|
|
221
|
+
cost_resolved: true,
|
|
222
|
+
resolved_at: new Date().toISOString(),
|
|
223
|
+
cost_resolution_status: 'resolved',
|
|
224
|
+
})
|
|
225
|
+
.eq('id', log.id);
|
|
226
|
+
resolved += 1;
|
|
227
|
+
}
|
|
228
|
+
catch {
|
|
229
|
+
// skip this entry, will be retried next run
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
return { retried: failedLogs.length, resolved };
|
|
233
|
+
}
|
|
120
234
|
export function resolveAllCosts(supabase, entries, apiKey, serviceClient) {
|
|
121
235
|
const toResolve = entries.filter((entry) => entry.generationId != null);
|
|
122
236
|
if (toResolve.length === 0) {
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cost resolution monitoring — exposes metrics for alerting
|
|
3
|
+
* when the failure rate of OpenRouter cost lookups exceeds thresholds.
|
|
4
|
+
*/
|
|
5
|
+
import type { SupabaseClient } from '@supabase/supabase-js';
|
|
6
|
+
export interface CostResolutionStats {
|
|
7
|
+
/** Number of cost logs with status 'failed' in the last hour. */
|
|
8
|
+
failedLastHour: number;
|
|
9
|
+
/** Total cost logs created in the last hour. */
|
|
10
|
+
totalLastHour: number;
|
|
11
|
+
/** Failure rate as a percentage (0-100). */
|
|
12
|
+
failureRate: number;
|
|
13
|
+
/** Number of cost logs still pending (older than 5 minutes). */
|
|
14
|
+
stalePending: number;
|
|
15
|
+
}
|
|
16
|
+
export declare function getCostResolutionStats(supabase: SupabaseClient): Promise<CostResolutionStats>;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cost resolution monitoring — exposes metrics for alerting
|
|
3
|
+
* when the failure rate of OpenRouter cost lookups exceeds thresholds.
|
|
4
|
+
*/
|
|
5
|
+
export async function getCostResolutionStats(supabase) {
|
|
6
|
+
const oneHourAgo = new Date(Date.now() - 60 * 60 * 1000).toISOString();
|
|
7
|
+
const fiveMinutesAgo = new Date(Date.now() - 5 * 60 * 1000).toISOString();
|
|
8
|
+
const [failedResult, totalResult, staleResult] = await Promise.all([
|
|
9
|
+
supabase
|
|
10
|
+
.from('cost_logs')
|
|
11
|
+
.select('*', { count: 'exact', head: true })
|
|
12
|
+
.eq('cost_resolution_status', 'failed')
|
|
13
|
+
.gt('created_at', oneHourAgo),
|
|
14
|
+
supabase
|
|
15
|
+
.from('cost_logs')
|
|
16
|
+
.select('*', { count: 'exact', head: true })
|
|
17
|
+
.gt('created_at', oneHourAgo)
|
|
18
|
+
.not('generation_id', 'is', null),
|
|
19
|
+
supabase
|
|
20
|
+
.from('cost_logs')
|
|
21
|
+
.select('*', { count: 'exact', head: true })
|
|
22
|
+
.eq('cost_resolution_status', 'pending')
|
|
23
|
+
.lt('created_at', fiveMinutesAgo)
|
|
24
|
+
.not('generation_id', 'is', null),
|
|
25
|
+
]);
|
|
26
|
+
const failedLastHour = failedResult.count ?? 0;
|
|
27
|
+
const totalLastHour = totalResult.count ?? 0;
|
|
28
|
+
const stalePending = staleResult.count ?? 0;
|
|
29
|
+
const failureRate = totalLastHour > 0
|
|
30
|
+
? Math.round((failedLastHour / totalLastHour) * 10000) / 100
|
|
31
|
+
: 0;
|
|
32
|
+
return { failedLastHour, totalLastHour, failureRate, stalePending };
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=cost-resolution-monitor.js.map
|
|
@@ -47,9 +47,9 @@ export function resolveActionCredentialArgs(action, args, credentials) {
|
|
|
47
47
|
if (!credentials)
|
|
48
48
|
return args;
|
|
49
49
|
const resolved = { ...args };
|
|
50
|
-
if (action === "type_text" && typeof resolved.text === "string") {
|
|
50
|
+
if ((action === "type_text" || action === "type") && typeof resolved.text === "string") {
|
|
51
51
|
resolved.text = resolveCredentialTemplates(resolved.text, credentials);
|
|
52
|
-
ensureNoCredentialTemplate(
|
|
52
|
+
ensureNoCredentialTemplate(`${action}.text`, resolved.text);
|
|
53
53
|
}
|
|
54
54
|
if (action === "navigate_to" && typeof resolved.url === "string") {
|
|
55
55
|
resolved.url = resolveCredentialTemplates(resolved.url, credentials);
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { VideoCursorTheme } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* JavaScript injected via `context.addInitScript()` to show a visible animated
|
|
4
|
+
* cursor in Playwright video recordings (the native OS cursor is invisible).
|
|
5
|
+
*/
|
|
6
|
+
export declare function buildCursorOverlayScript(theme?: VideoCursorTheme): string;
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
// SVG files are the single source of truth — edit web/public/cursors/*.svg directly.
|
|
5
|
+
function loadCursorSvg(name) {
|
|
6
|
+
const currentDir = path.dirname(fileURLToPath(import.meta.url));
|
|
7
|
+
const candidatePaths = [
|
|
8
|
+
// From dist/ → ../web/public/cursors/
|
|
9
|
+
path.resolve(currentDir, '../web/public/cursors', `${name}.svg`),
|
|
10
|
+
// From package/dist/ → ../../web/public/cursors/
|
|
11
|
+
path.resolve(currentDir, '../../web/public/cursors', `${name}.svg`),
|
|
12
|
+
// Bundled alongside dist in package/assets/cursors/
|
|
13
|
+
path.resolve(currentDir, '../assets/cursors', `${name}.svg`),
|
|
14
|
+
// Fallback: same directory
|
|
15
|
+
path.resolve(currentDir, './web/public/cursors', `${name}.svg`),
|
|
16
|
+
];
|
|
17
|
+
for (const candidatePath of candidatePaths) {
|
|
18
|
+
if (fs.existsSync(candidatePath)) {
|
|
19
|
+
return fs.readFileSync(candidatePath, 'utf-8').trim();
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
throw new Error(`Cursor asset "${name}.svg" not found. Looked in: ${candidatePaths.join(', ')}`);
|
|
23
|
+
}
|
|
24
|
+
const CURSOR_THEME_SVGS = {};
|
|
25
|
+
function getCursorThemeSvg(theme) {
|
|
26
|
+
if (!CURSOR_THEME_SVGS[theme]) {
|
|
27
|
+
CURSOR_THEME_SVGS[theme] = loadCursorSvg(theme);
|
|
28
|
+
}
|
|
29
|
+
return CURSOR_THEME_SVGS[theme];
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* JavaScript injected via `context.addInitScript()` to show a visible animated
|
|
33
|
+
* cursor in Playwright video recordings (the native OS cursor is invisible).
|
|
34
|
+
*/
|
|
35
|
+
export function buildCursorOverlayScript(theme = 'minimal') {
|
|
36
|
+
const cursorSvg = theme === 'minimal' ? null : getCursorThemeSvg(theme);
|
|
37
|
+
return `
|
|
38
|
+
(function() {
|
|
39
|
+
function injectCursor() {
|
|
40
|
+
if (document.getElementById('__ak_cursor__')) return;
|
|
41
|
+
const cursorTheme = ${JSON.stringify(theme)};
|
|
42
|
+
const cursorSvg = ${JSON.stringify(cursorSvg)};
|
|
43
|
+
|
|
44
|
+
const style = document.createElement('style');
|
|
45
|
+
style.textContent = [
|
|
46
|
+
'*, *::before, *::after { cursor: none !important; }',
|
|
47
|
+
'#__ak_cursor__ { mix-blend-mode: normal; }',
|
|
48
|
+
'#__ak_cursor__ svg { width: 100%; height: 100%; display: block; overflow: visible; }',
|
|
49
|
+
'#__ak_cursor__[data-theme="macos"], #__ak_cursor__[data-theme="windows"] { width: 28px !important; height: 28px !important; background: transparent !important; border: 0 !important; border-radius: 0 !important; box-shadow: none !important; }',
|
|
50
|
+
'#__ak_cursor__.__ak_pressed { transform: translate(-50%, -50%) scale(0.72) !important; box-shadow: 0 0 0 8px rgba(37, 99, 235, 0.18), 0 4px 18px rgba(0,0,0,0.28) !important; background: rgba(255,255,255,0.98) !important; border-color: rgba(30,41,59,0.92) !important; }',
|
|
51
|
+
'#__ak_cursor__[data-theme="macos"].__ak_pressed, #__ak_cursor__[data-theme="windows"].__ak_pressed { background: transparent !important; border-color: transparent !important; box-shadow: none !important; filter: drop-shadow(0 0 0 rgba(37, 99, 235, 0)) drop-shadow(0 0 0 rgba(37, 99, 235, 0)) !important; }',
|
|
52
|
+
'#__ak_cursor__[data-theme="macos"].__ak_pressed svg, #__ak_cursor__[data-theme="windows"].__ak_pressed svg { filter: drop-shadow(0 0 0.5px rgba(255,255,255,0.9)) drop-shadow(0 0 10px rgba(37, 99, 235, 0.45)); }',
|
|
53
|
+
'#__ak_cursor_click_pulse__ { position: fixed; width: 20px; height: 20px; border-radius: 9999px; pointer-events: none; z-index: 2147483646; border: 3px solid rgba(37, 99, 235, 0.75); box-shadow: 0 0 0 1px rgba(255,255,255,0.45) inset; transform: translate(-50%, -50%) scale(0.55); opacity: 0; }',
|
|
54
|
+
'#__ak_cursor_click_pulse__.__ak_active { animation: __ak_cursor_pulse__ 340ms cubic-bezier(0.16, 1, 0.3, 1) forwards; }',
|
|
55
|
+
'@keyframes __ak_cursor_pulse__ { 0% { opacity: 0.95; transform: translate(-50%, -50%) scale(0.55); } 100% { opacity: 0; transform: translate(-50%, -50%) scale(2.6); } }',
|
|
56
|
+
].join('\\n');
|
|
57
|
+
document.head.appendChild(style);
|
|
58
|
+
|
|
59
|
+
const cursor = document.createElement('div');
|
|
60
|
+
cursor.id = '__ak_cursor__';
|
|
61
|
+
cursor.dataset.theme = cursorTheme;
|
|
62
|
+
cursor.style.cssText = [
|
|
63
|
+
'position: fixed',
|
|
64
|
+
'top: -100px',
|
|
65
|
+
'left: -100px',
|
|
66
|
+
'width: 20px',
|
|
67
|
+
'height: 20px',
|
|
68
|
+
'background: rgba(255, 255, 255, 0.95)',
|
|
69
|
+
'border: 2.5px solid rgba(0, 0, 0, 0.8)',
|
|
70
|
+
'border-radius: 50%',
|
|
71
|
+
'pointer-events: none',
|
|
72
|
+
'z-index: 2147483647',
|
|
73
|
+
'transform: translate(-50%, -50%)',
|
|
74
|
+
'box-shadow: 0 2px 8px rgba(0,0,0,0.4)',
|
|
75
|
+
'transition: transform 0.09s ease, box-shadow 0.12s ease, background 0.12s ease, border-color 0.12s ease',
|
|
76
|
+
'will-change: left, top',
|
|
77
|
+
].join(';');
|
|
78
|
+
if (cursorSvg) cursor.innerHTML = cursorSvg;
|
|
79
|
+
|
|
80
|
+
const pulse = document.createElement('div');
|
|
81
|
+
pulse.id = '__ak_cursor_click_pulse__';
|
|
82
|
+
|
|
83
|
+
document.body.appendChild(cursor);
|
|
84
|
+
document.body.appendChild(pulse);
|
|
85
|
+
|
|
86
|
+
let pulseResetTimer = null;
|
|
87
|
+
|
|
88
|
+
function setCursorPosition(x, y) {
|
|
89
|
+
cursor.style.left = x + 'px';
|
|
90
|
+
cursor.style.top = y + 'px';
|
|
91
|
+
pulse.style.left = x + 'px';
|
|
92
|
+
pulse.style.top = y + 'px';
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function triggerPulse() {
|
|
96
|
+
pulse.classList.remove('__ak_active');
|
|
97
|
+
void pulse.offsetWidth;
|
|
98
|
+
pulse.classList.add('__ak_active');
|
|
99
|
+
if (pulseResetTimer) clearTimeout(pulseResetTimer);
|
|
100
|
+
pulseResetTimer = setTimeout(function() {
|
|
101
|
+
pulse.classList.remove('__ak_active');
|
|
102
|
+
}, 380);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// CDP mouse events (page.mouse.move) don't fire DOM mousemove events in
|
|
106
|
+
// Playwright video recording. Expose global helpers so the runner can
|
|
107
|
+
// position the cursor directly via page.evaluate().
|
|
108
|
+
window.__akMoveCursor = function(x, y) { setCursorPosition(x, y); };
|
|
109
|
+
window.__akPressCursor = function() { cursor.classList.add('__ak_pressed'); };
|
|
110
|
+
window.__akReleaseCursor = function() { cursor.classList.remove('__ak_pressed'); };
|
|
111
|
+
window.__akClickPulse = function(x, y) {
|
|
112
|
+
setCursorPosition(x, y);
|
|
113
|
+
triggerPulse();
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
// Keep DOM event listeners as fallback for real mouse events (headed mode)
|
|
117
|
+
document.addEventListener('mousemove', function(e) {
|
|
118
|
+
setCursorPosition(e.clientX, e.clientY);
|
|
119
|
+
}, { passive: true });
|
|
120
|
+
|
|
121
|
+
window.addEventListener('mousedown', function(e) {
|
|
122
|
+
setCursorPosition(e.clientX, e.clientY);
|
|
123
|
+
cursor.classList.add('__ak_pressed');
|
|
124
|
+
triggerPulse();
|
|
125
|
+
}, true);
|
|
126
|
+
window.addEventListener('mouseup', function(e) {
|
|
127
|
+
setCursorPosition(e.clientX, e.clientY);
|
|
128
|
+
cursor.classList.remove('__ak_pressed');
|
|
129
|
+
}, true);
|
|
130
|
+
window.addEventListener('click', function(e) {
|
|
131
|
+
setCursorPosition(e.clientX, e.clientY);
|
|
132
|
+
triggerPulse();
|
|
133
|
+
}, true);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Inject immediately and re-inject if a framework (React, Next.js, etc.)
|
|
137
|
+
// replaces the body during hydration and removes our cursor element.
|
|
138
|
+
function ensureCursor() {
|
|
139
|
+
if (!document.getElementById('__ak_cursor__')) {
|
|
140
|
+
if (document.body) injectCursor();
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if (document.readyState === 'loading') {
|
|
145
|
+
document.addEventListener('DOMContentLoaded', ensureCursor);
|
|
146
|
+
} else {
|
|
147
|
+
ensureCursor();
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Re-inject when frameworks replace body content during hydration.
|
|
151
|
+
var observer = new MutationObserver(function() {
|
|
152
|
+
if (document.body && !document.getElementById('__ak_cursor__')) {
|
|
153
|
+
injectCursor();
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
function startObserving() {
|
|
157
|
+
if (document.body) {
|
|
158
|
+
observer.observe(document.body, { childList: true });
|
|
159
|
+
} else {
|
|
160
|
+
document.addEventListener('DOMContentLoaded', function() {
|
|
161
|
+
observer.observe(document.body, { childList: true });
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
startObserving();
|
|
166
|
+
})();
|
|
167
|
+
`;
|
|
168
|
+
}
|
|
169
|
+
//# sourceMappingURL=cursor-overlay-script.js.map
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DOM CSS Purger — AUT-121 Interactive Demos, Phase 3
|
|
3
|
+
*
|
|
4
|
+
* Walks captured HTML, collects every tag/class/id present in the DOM, then
|
|
5
|
+
* walks each inline `<style>` block and drops CSS rules whose selectors
|
|
6
|
+
* never match any element. Designed to shrink captured DOMs by 60-80% per
|
|
7
|
+
* the Linear estimate.
|
|
8
|
+
*
|
|
9
|
+
* Conservative on purpose — better to keep a few unused bytes than break a
|
|
10
|
+
* captured layout. Specifically, the purger PRESERVES:
|
|
11
|
+
* - All at-rules: @media, @supports, @keyframes, @font-face, @import,
|
|
12
|
+
* @charset, @namespace, @page (passed through unchanged for the rules
|
|
13
|
+
* inside @media/@supports, recursively pruned)
|
|
14
|
+
* - Selectors that only contain pseudo-classes (`:hover`, `:focus`, etc.)
|
|
15
|
+
* since they may match elements only in interactive states
|
|
16
|
+
* - Universal selector `*`
|
|
17
|
+
* - Attribute selectors (parsed but not validated against the DOM —
|
|
18
|
+
* `[data-state]` would require a DOM walk to verify, kept for safety)
|
|
19
|
+
*
|
|
20
|
+
* For Phase 3 minimum viable, only inline `<style>` blocks are purged.
|
|
21
|
+
* External `<link rel="stylesheet">` files would require server-side
|
|
22
|
+
* fetching of the asset bytes — that's left to a follow-up.
|
|
23
|
+
*
|
|
24
|
+
* No regex CSS parser is perfect, but the trade-off is:
|
|
25
|
+
* - dependency-free (we already pay for parse5 in dom-serializer)
|
|
26
|
+
* - small footprint (~150 LOC)
|
|
27
|
+
* - good enough for the 95% of CSS that captures produce
|
|
28
|
+
*
|
|
29
|
+
* Worst case: a malformed CSS block is left untouched.
|
|
30
|
+
*/
|
|
31
|
+
export interface PurgeStats {
|
|
32
|
+
/** Number of `<style>` blocks processed */
|
|
33
|
+
blocks: number;
|
|
34
|
+
/** Bytes of CSS before purging */
|
|
35
|
+
preBytes: number;
|
|
36
|
+
/** Bytes of CSS after purging */
|
|
37
|
+
postBytes: number;
|
|
38
|
+
/** Number of rules removed */
|
|
39
|
+
rulesRemoved: number;
|
|
40
|
+
}
|
|
41
|
+
export interface PurgeResult {
|
|
42
|
+
html: string;
|
|
43
|
+
stats: PurgeStats;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Walk an HTML document, find every `<style>` block, and purge each one
|
|
47
|
+
* against the set of tags/classes/ids actually present in the document.
|
|
48
|
+
*/
|
|
49
|
+
export declare function purgeInlineStyleBlocks(html: string): PurgeResult;
|
|
50
|
+
interface DomPresence {
|
|
51
|
+
tags: Set<string>;
|
|
52
|
+
classes: Set<string>;
|
|
53
|
+
ids: Set<string>;
|
|
54
|
+
}
|
|
55
|
+
interface PurgedCss {
|
|
56
|
+
css: string;
|
|
57
|
+
removed: number;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Tokenize CSS into a flat sequence of `at-rule` / `rule` blocks and walk
|
|
61
|
+
* each rule to decide whether to keep it. At-rules are preserved verbatim
|
|
62
|
+
* — `@media`/`@supports` bodies are recursively purged.
|
|
63
|
+
*/
|
|
64
|
+
export declare function purgeCss(input: string, presence: DomPresence): PurgedCss;
|
|
65
|
+
export {};
|