free-computer-use 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 (135) hide show
  1. package/.env.example +31 -0
  2. package/CHANGELOG.md +19 -0
  3. package/CONTRIBUTING.md +66 -0
  4. package/LICENSE +21 -0
  5. package/README.md +140 -0
  6. package/SECURITY.md +133 -0
  7. package/artifacts/benchmark-public.json +797 -0
  8. package/assets/readme/hero.svg +53 -0
  9. package/assets/readme/incident-demo.gif +0 -0
  10. package/assets/readme/incident-evidence.json +52 -0
  11. package/dist/actions/compiler.d.ts +5 -0
  12. package/dist/actions/compiler.js +16 -0
  13. package/dist/actions/compiler.js.map +1 -0
  14. package/dist/actions/executor.d.ts +38 -0
  15. package/dist/actions/executor.js +305 -0
  16. package/dist/actions/executor.js.map +1 -0
  17. package/dist/actions/policy.d.ts +4 -0
  18. package/dist/actions/policy.js +18 -0
  19. package/dist/actions/policy.js.map +1 -0
  20. package/dist/actions/schema.d.ts +4149 -0
  21. package/dist/actions/schema.js +59 -0
  22. package/dist/actions/schema.js.map +1 -0
  23. package/dist/adapters/generic.d.ts +14 -0
  24. package/dist/adapters/generic.js +33 -0
  25. package/dist/adapters/generic.js.map +1 -0
  26. package/dist/agent/Agent.d.ts +69 -0
  27. package/dist/agent/Agent.js +375 -0
  28. package/dist/agent/Agent.js.map +1 -0
  29. package/dist/agent/Control.d.ts +23 -0
  30. package/dist/agent/Control.js +51 -0
  31. package/dist/agent/Control.js.map +1 -0
  32. package/dist/agent/TokenBudget.d.ts +52 -0
  33. package/dist/agent/TokenBudget.js +47 -0
  34. package/dist/agent/TokenBudget.js.map +1 -0
  35. package/dist/agent/goalCriteria.d.ts +2 -0
  36. package/dist/agent/goalCriteria.js +13 -0
  37. package/dist/agent/goalCriteria.js.map +1 -0
  38. package/dist/browser/Browser.d.ts +72 -0
  39. package/dist/browser/Browser.js +378 -0
  40. package/dist/browser/Browser.js.map +1 -0
  41. package/dist/browser/DomExtractor.d.ts +6 -0
  42. package/dist/browser/DomExtractor.js +134 -0
  43. package/dist/browser/DomExtractor.js.map +1 -0
  44. package/dist/browser/Interaction.d.ts +43 -0
  45. package/dist/browser/Interaction.js +225 -0
  46. package/dist/browser/Interaction.js.map +1 -0
  47. package/dist/browser/NetworkGuardProxy.d.ts +31 -0
  48. package/dist/browser/NetworkGuardProxy.js +331 -0
  49. package/dist/browser/NetworkGuardProxy.js.map +1 -0
  50. package/dist/browser/Observer.d.ts +12 -0
  51. package/dist/browser/Observer.js +31 -0
  52. package/dist/browser/Observer.js.map +1 -0
  53. package/dist/browser/PageCompressor.d.ts +47 -0
  54. package/dist/browser/PageCompressor.js +62 -0
  55. package/dist/browser/PageCompressor.js.map +1 -0
  56. package/dist/browser/SecurityBoundaryError.d.ts +3 -0
  57. package/dist/browser/SecurityBoundaryError.js +4 -0
  58. package/dist/browser/SecurityBoundaryError.js.map +1 -0
  59. package/dist/browser/SelectorEngine.d.ts +18 -0
  60. package/dist/browser/SelectorEngine.js +72 -0
  61. package/dist/browser/SelectorEngine.js.map +1 -0
  62. package/dist/browser/types.d.ts +38 -0
  63. package/dist/browser/types.js +2 -0
  64. package/dist/browser/types.js.map +1 -0
  65. package/dist/cli/index.d.ts +2 -0
  66. package/dist/cli/index.js +284 -0
  67. package/dist/cli/index.js.map +1 -0
  68. package/dist/config.d.ts +11 -0
  69. package/dist/config.js +77 -0
  70. package/dist/config.js.map +1 -0
  71. package/dist/history/TraceStore.d.ts +29 -0
  72. package/dist/history/TraceStore.js +53 -0
  73. package/dist/history/TraceStore.js.map +1 -0
  74. package/dist/index.d.ts +18 -0
  75. package/dist/index.js +16 -0
  76. package/dist/index.js.map +1 -0
  77. package/dist/llm/ClaudeSubscriptionProvider.d.ts +26 -0
  78. package/dist/llm/ClaudeSubscriptionProvider.js +182 -0
  79. package/dist/llm/ClaudeSubscriptionProvider.js.map +1 -0
  80. package/dist/llm/CodexSubscriptionProvider.d.ts +26 -0
  81. package/dist/llm/CodexSubscriptionProvider.js +168 -0
  82. package/dist/llm/CodexSubscriptionProvider.js.map +1 -0
  83. package/dist/llm/FlashProvider.d.ts +27 -0
  84. package/dist/llm/FlashProvider.js +103 -0
  85. package/dist/llm/FlashProvider.js.map +1 -0
  86. package/dist/llm/LLMProvider.d.ts +37 -0
  87. package/dist/llm/LLMProvider.js +2 -0
  88. package/dist/llm/LLMProvider.js.map +1 -0
  89. package/dist/llm/cliEnvironment.d.ts +5 -0
  90. package/dist/llm/cliEnvironment.js +21 -0
  91. package/dist/llm/cliEnvironment.js.map +1 -0
  92. package/dist/llm/prompts.d.ts +4 -0
  93. package/dist/llm/prompts.js +12 -0
  94. package/dist/llm/prompts.js.map +1 -0
  95. package/dist/llm/structuredOutput.d.ts +3 -0
  96. package/dist/llm/structuredOutput.js +58 -0
  97. package/dist/llm/structuredOutput.js.map +1 -0
  98. package/dist/mcp/index.d.ts +13 -0
  99. package/dist/mcp/index.js +243 -0
  100. package/dist/mcp/index.js.map +1 -0
  101. package/dist/profile/ProfileStore.d.ts +7 -0
  102. package/dist/profile/ProfileStore.js +52 -0
  103. package/dist/profile/ProfileStore.js.map +1 -0
  104. package/dist/profile/VariableResolver.d.ts +15 -0
  105. package/dist/profile/VariableResolver.js +50 -0
  106. package/dist/profile/VariableResolver.js.map +1 -0
  107. package/dist/server/index.d.ts +14 -0
  108. package/dist/server/index.js +239 -0
  109. package/dist/server/index.js.map +1 -0
  110. package/dist/ui/app.js +132 -0
  111. package/dist/ui/index.html +29 -0
  112. package/dist/ui/logo.svg +5 -0
  113. package/dist/ui/results.js +59 -0
  114. package/dist/ui/style.css +33 -0
  115. package/dist/verification/Verifier.d.ts +72 -0
  116. package/dist/verification/Verifier.js +87 -0
  117. package/dist/verification/Verifier.js.map +1 -0
  118. package/dist/workflows/WorkflowEngine.d.ts +23 -0
  119. package/dist/workflows/WorkflowEngine.js +52 -0
  120. package/dist/workflows/WorkflowEngine.js.map +1 -0
  121. package/docs/ADOPTION.md +61 -0
  122. package/docs/ARCHITECTURE.md +65 -0
  123. package/docs/BENCHMARKS.md +64 -0
  124. package/docs/IMPLEMENTATION.md +93 -0
  125. package/docs/LOCAL_DATA.md +98 -0
  126. package/docs/LOCAL_VALIDATION.md +87 -0
  127. package/docs/MCP.md +81 -0
  128. package/docs/PROVIDERS.md +150 -0
  129. package/docs/RELEASE_CHECKLIST.md +37 -0
  130. package/docs/REQUIREMENTS.md +39 -0
  131. package/docs/SUPPORT_MATRIX.md +193 -0
  132. package/docs/THREAT_MODEL.md +108 -0
  133. package/docs/USEFUL_EXAMPLES.md +151 -0
  134. package/docs/brand-mark.svg +12 -0
  135. package/package.json +90 -0
@@ -0,0 +1,53 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="1200" height="430" viewBox="0 0 1200 430" role="img" aria-labelledby="title description">
2
+ <title id="title">FreeComputerUse — a browser agent you can see and control</title>
3
+ <desc id="description">Choose a model to plan a browser task. Approve the website. Playwright acts locally, verifies the result and can replay a compatible workflow without model calls.</desc>
4
+ <defs>
5
+ <pattern id="grid" width="38" height="38" patternUnits="userSpaceOnUse"><path d="M38 0H0V38" fill="none" stroke="#ffffff09"/></pattern>
6
+ <linearGradient id="wash" x1="0" y1="0" x2="1" y2="1"><stop stop-color="#18251f"/><stop offset="1" stop-color="#101a24"/></linearGradient>
7
+ <clipPath id="corners"><rect width="1200" height="430" rx="18"/></clipPath>
8
+ </defs>
9
+ <g clip-path="url(#corners)">
10
+ <rect width="1200" height="430" fill="url(#wash)"/>
11
+ <rect x="690" width="510" height="430" fill="url(#grid)"/>
12
+ <path d="M690 0V430" stroke="#ffffff16"/>
13
+ <g transform="translate(42 29) scale(.7)">
14
+ <rect x="1" y="1" width="62" height="62" rx="19" fill="#101712"/>
15
+ <rect x="9" y="10" width="46" height="44" rx="7" fill="#18231a" stroke="#eaf0e4" stroke-width="3"/>
16
+ <path d="M12 21h40" stroke="#c9ed72" stroke-width="7"/>
17
+ <circle cx="17" cy="16" r="1.6" fill="#101712"/><circle cx="22.5" cy="16" r="1.6" fill="#101712"/><circle cx="28" cy="16" r="1.6" fill="#101712"/>
18
+ <path d="M16 29h7M16 35h6" stroke="#9aaa91" stroke-linecap="round" stroke-width="2.5"/>
19
+ <path d="M25 25v25l7.4-7.1 6.2 12.2 5.4-2.8-6.2-12.2 11-.4z" fill="#c9ed72" stroke="#18231a" stroke-linejoin="round" stroke-width="2.4"/>
20
+ </g>
21
+ <text x="94" y="67" fill="#eff4eb" font-family="Manrope,Arial,sans-serif" font-size="23" font-weight="700" letter-spacing="-.6">FreeComputerUse</text>
22
+ <text x="48" y="132" fill="#aabbb0" font-family="monospace" font-size="11" letter-spacing="2.5">LOCAL-FIRST BROWSER AUTOMATION</text>
23
+ <text x="44" y="203" fill="#f5f5ec" font-family="Manrope,Arial,sans-serif" font-size="53" font-weight="700" letter-spacing="-2.3">Give the browser</text>
24
+ <text x="43" y="262" fill="#c8f169" font-family="Georgia,serif" font-size="54" font-style="italic" letter-spacing="-1.4">the whole task.</text>
25
+ <text x="48" y="314" fill="#c2cec4" font-family="Manrope,Arial,sans-serif" font-size="16">Choose your model. Approve the site. Watch each action.</text>
26
+ <g transform="translate(48 354)" font-family="monospace" font-size="10" letter-spacing=".7">
27
+ <rect width="142" height="32" rx="16" fill="#293d31" stroke="#718d52"/><text x="17" y="21" fill="#def1bc">PLAYWRIGHT · LOCAL</text>
28
+ <rect x="154" width="155" height="32" rx="16" fill="#202f3f" stroke="#476482"/><text x="171" y="21" fill="#c5dcf5">MODEL-AGNOSTIC</text>
29
+ <rect x="321" width="171" height="32" rx="16" fill="#293d31" stroke="#718d52"/><text x="338" y="21" fill="#def1bc">REPEAT · ZERO CALLS</text>
30
+ </g>
31
+ <g transform="translate(738 43)" font-family="Manrope,Arial,sans-serif">
32
+ <rect width="412" height="340" rx="11" fill="#f4f3e9" stroke="#ffffff33"/>
33
+ <path d="M0 43H412" stroke="#d9ded2"/>
34
+ <circle cx="20" cy="22" r="4" fill="#d76250"/><circle cx="35" cy="22" r="4" fill="#d9b857"/><circle cx="50" cy="22" r="4" fill="#75a66b"/>
35
+ <text x="70" y="26" fill="#5f7167" font-family="monospace" font-size="10">local session / invoices</text>
36
+ <rect x="269" y="12" width="126" height="21" rx="10" fill="#e2efcf"/><circle cx="281" cy="22" r="3" fill="#518751"/><text x="290" y="26" fill="#416b43" font-family="monospace" font-size="8">SITE APPROVED</text>
37
+ <text x="21" y="71" fill="#75857a" font-family="monospace" font-size="9" letter-spacing="1.4">TASK / OVERDUE INVOICE</text>
38
+ <text x="20" y="96" fill="#1c2b25" font-size="18" font-weight="700">Find and verify INV-2609-04</text>
39
+ <rect x="18" y="115" width="376" height="53" rx="6" fill="#fff" stroke="#dce1d7"/>
40
+ <circle cx="42" cy="141" r="12" fill="#253d33"/><text x="38.5" y="145" fill="#d8f28f" font-family="monospace" font-size="10">01</text>
41
+ <text x="65" y="137" fill="#213229" font-size="12" font-weight="700">Observe the page</text><text x="65" y="154" fill="#75857a" font-family="monospace" font-size="9">DOM + accessible controls</text>
42
+ <rect x="18" y="178" width="376" height="53" rx="6" fill="#fff" stroke="#dce1d7"/>
43
+ <circle cx="42" cy="204" r="12" fill="#253d33"/><text x="38.5" y="208" fill="#d8f28f" font-family="monospace" font-size="10">02</text>
44
+ <text x="65" y="200" fill="#213229" font-size="12" font-weight="700">Plan a safe batch</text><text x="65" y="217" fill="#75857a" font-family="monospace" font-size="9">OpenAI · Claude · Grok · more</text>
45
+ <rect x="18" y="241" width="376" height="53" rx="6" fill="#fff" stroke="#dce1d7"/>
46
+ <circle cx="42" cy="267" r="12" fill="#253d33"/><text x="38.5" y="271" fill="#d8f28f" font-family="monospace" font-size="10">03</text>
47
+ <text x="65" y="263" fill="#213229" font-size="12" font-weight="700">Execute and verify</text><text x="65" y="280" fill="#75857a" font-family="monospace" font-size="9">Visible actions · checked result</text>
48
+ <rect x="18" y="307" width="376" height="20" rx="4" fill="#dff0bb"/><text x="29" y="321" fill="#34553b" font-family="monospace" font-size="9">COMPATIBLE REPEAT</text><text x="366" y="323" text-anchor="end" fill="#34553b" font-size="17" font-weight="700">0 CALLS</text>
49
+ <path d="M401 267c22-3 22-41 1-44" fill="none" stroke="#c8f169" stroke-width="2"/><path d="M397 220l8 2-4 7" fill="none" stroke="#c8f169" stroke-width="2"/>
50
+ </g>
51
+ <path d="M1139 348c-2-.8-3.6.7-2.8 2.7l8.1 20.5c.9 2.2 4 2 4.7-.4l2.4-8.1 8.1-2.4c2.3-.7 2.5-3.8.3-4.7Z" fill="#3264f6" stroke="#fff" stroke-width="2.2" stroke-linejoin="round"/>
52
+ </g>
53
+ </svg>
Binary file
@@ -0,0 +1,52 @@
1
+ {
2
+ "task": "INC-204 synthetic incident investigation",
3
+ "recording": "one continuous, unsped dashboard run",
4
+ "start": "https://othmaneblial.github.io/FreeComputerUse/lab/workspace.html?view=incident",
5
+ "goal": "Investigate synthetic incident INC-204. Filter the alert queue to API Gateway, High severity, and Last 24 hours. Open the incident, inspect its timeline, request metrics, deployment comparison, and runbook. Use the evidence you find to complete the incident brief: affected endpoint, before/after 429 rates, relevant deployment, configuration change, and the appropriate review decision. Save the brief locally and download it. Do not roll back a service, contact customers, or claim the cause is proven.",
6
+ "status": "completed",
7
+ "provider": "deepseek-flash",
8
+ "metrics": {
9
+ "durationMs": 74591,
10
+ "browserActions": 21,
11
+ "failedActions": 1,
12
+ "llmCalls": 10,
13
+ "inputTokens": 30584,
14
+ "outputTokens": 1469,
15
+ "estimatedCostUSD": 0.006497424,
16
+ "actionsPerLLMCall": 2.1,
17
+ "tokensPerAction": 1526.3333333333333,
18
+ "repairs": 4,
19
+ "workflowCacheHits": 0,
20
+ "pageCacheEntries": 16,
21
+ "planBatches": 5,
22
+ "compressionReduction": 0.24349064279902355,
23
+ "selectorSuccessRate": 1,
24
+ "usageEstimated": false,
25
+ "provider": "deepseek-flash",
26
+ "mode": "normal",
27
+ "approvedSites": [
28
+ "https://othmaneblial.github.io"
29
+ ]
30
+ },
31
+ "visibleCursorSamples": 241,
32
+ "approved": [
33
+ "Practice site access",
34
+ "Synthetic brief save"
35
+ ],
36
+ "pages": [
37
+ "/FreeComputerUse/lab/workspace.html",
38
+ "/FreeComputerUse/lab/incident-detail.html",
39
+ "/FreeComputerUse/lab/incident-metrics.html",
40
+ "/FreeComputerUse/lab/incident-deployments.html",
41
+ "/FreeComputerUse/lab/incident-runbook.html",
42
+ "/FreeComputerUse/lab/incident-brief.html"
43
+ ],
44
+ "downloadedBrief": "INC-204-incident-brief.txt",
45
+ "checks": [
46
+ "brief content",
47
+ "six distinct page visits",
48
+ "visible agent cursor",
49
+ "normal-mode site approval"
50
+ ],
51
+ "disclaimer": "Synthetic practice workspace. No production rollback or customer message."
52
+ }
@@ -0,0 +1,5 @@
1
+ import type { Locator } from 'playwright';
2
+ import { type Action } from './schema.js';
3
+ export declare class ActionCompiler {
4
+ normalize(action: Action, locator?: Locator): Promise<Action>;
5
+ }
@@ -0,0 +1,16 @@
1
+ import { ActionSchema } from './schema.js';
2
+ export class ActionCompiler {
3
+ async normalize(action, locator) {
4
+ if (action.type === 'click' && locator) {
5
+ const download = await locator.evaluate(el => el.matches('a[download]') ? el.getAttribute('download') : null);
6
+ if (download !== null)
7
+ return ActionSchema.parse({ ...action, type: 'download', filename: download || undefined });
8
+ }
9
+ // The DOM, not a model's guessed control kind, determines the operation.
10
+ if (action.type === 'fill' && locator && await locator.evaluate(el => el.tagName === 'SELECT')) {
11
+ return ActionSchema.parse({ ...action, type: 'select' });
12
+ }
13
+ return action;
14
+ }
15
+ }
16
+ //# sourceMappingURL=compiler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compiler.js","sourceRoot":"","sources":["../../src/actions/compiler.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAc,MAAM,aAAa,CAAC;AACvD,MAAM,OAAO,cAAc;IACzB,KAAK,CAAC,SAAS,CAAC,MAAa,EAAC,OAAgB;QAC5C,IAAG,MAAM,CAAC,IAAI,KAAG,OAAO,IAAE,OAAO,EAAC,CAAC;YACjC,MAAM,QAAQ,GAAC,MAAM,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAA,EAAE,CAAA,EAAE,CAAC,OAAO,CAAC,aAAa,CAAC,CAAA,CAAC,CAAA,EAAE,CAAC,YAAY,CAAC,UAAU,CAAC,CAAA,CAAC,CAAA,IAAI,CAAC,CAAC;YACtG,IAAG,QAAQ,KAAG,IAAI;gBAAC,OAAO,YAAY,CAAC,KAAK,CAAC,EAAC,GAAG,MAAM,EAAC,IAAI,EAAC,UAAU,EAAC,QAAQ,EAAC,QAAQ,IAAE,SAAS,EAAC,CAAC,CAAC;QACzG,CAAC;QACD,yEAAyE;QACzE,IAAG,MAAM,CAAC,IAAI,KAAG,MAAM,IAAE,OAAO,IAAE,MAAM,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAA,EAAE,CAAA,EAAE,CAAC,OAAO,KAAG,QAAQ,CAAC,EAAC,CAAC;YACnF,OAAO,YAAY,CAAC,KAAK,CAAC,EAAC,GAAG,MAAM,EAAC,IAAI,EAAC,QAAQ,EAAC,CAAC,CAAC;QACvD,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;CACF"}
@@ -0,0 +1,38 @@
1
+ import { type Action, type Condition } from './schema.js';
2
+ import { type ConfirmationPolicy } from './policy.js';
3
+ import type { Browser } from '../browser/Browser.js';
4
+ import type { Observer } from '../browser/Observer.js';
5
+ import type { VariableResolver } from '../profile/VariableResolver.js';
6
+ import type { Control } from '../agent/Control.js';
7
+ import { Verifier } from '../verification/Verifier.js';
8
+ import { ActionCompiler } from './compiler.js';
9
+ export interface ActionResult {
10
+ action: Action;
11
+ startedAt: number;
12
+ durationMs: number;
13
+ success: boolean;
14
+ strategy?: string;
15
+ data?: unknown;
16
+ error?: string;
17
+ uncertain?: boolean;
18
+ }
19
+ export declare class Executor {
20
+ readonly browser: Browser;
21
+ readonly observer: Observer;
22
+ readonly variables: VariableResolver;
23
+ readonly control: Control;
24
+ readonly options: {
25
+ confirmation?: ConfirmationPolicy;
26
+ downloadDir?: string;
27
+ };
28
+ readonly compiler: ActionCompiler;
29
+ readonly verifier: Verifier;
30
+ constructor(browser: Browser, observer: Observer, variables: VariableResolver, control: Control, options?: {
31
+ confirmation?: ConfirmationPolicy;
32
+ downloadDir?: string;
33
+ });
34
+ semantic(action: Action): Action;
35
+ semanticCondition(condition: Condition): Condition;
36
+ private storeDownload;
37
+ run(input: Action): Promise<ActionResult>;
38
+ }
@@ -0,0 +1,305 @@
1
+ import { chmod, lstat, mkdir, stat } from 'node:fs/promises';
2
+ import { randomUUID } from 'node:crypto';
3
+ import { basename, resolve } from 'node:path';
4
+ import { ActionSchema } from './schema.js';
5
+ import { sensitiveReason } from './policy.js';
6
+ import { Verifier } from '../verification/Verifier.js';
7
+ import { ActionCompiler } from './compiler.js';
8
+ export class Executor {
9
+ browser;
10
+ observer;
11
+ variables;
12
+ control;
13
+ options;
14
+ compiler = new ActionCompiler();
15
+ verifier;
16
+ constructor(browser, observer, variables, control, options = {}) {
17
+ this.browser = browser;
18
+ this.observer = observer;
19
+ this.variables = variables;
20
+ this.control = control;
21
+ this.options = options;
22
+ this.verifier = new Verifier(browser, observer, variables);
23
+ }
24
+ semantic(action) {
25
+ const result = { ...action };
26
+ if ('target' in result && typeof result.target === 'string')
27
+ result.target = this.observer.selectors.descriptor(result.target);
28
+ if (result.verify)
29
+ result.verify = result.verify.map(c => this.semanticCondition(c));
30
+ if (result.type === 'wait')
31
+ result.condition = this.semanticCondition(result.condition);
32
+ return result;
33
+ }
34
+ semanticCondition(condition) {
35
+ return 'target' in condition && typeof condition.target === 'string' ? { ...condition, target: this.observer.selectors.descriptor(condition.target) } : condition;
36
+ }
37
+ async storeDownload(download, requestedName) {
38
+ const folder = resolve(this.options.downloadDir ?? '.fcu/downloads');
39
+ await mkdir(folder, { recursive: true, mode: 0o700 });
40
+ const info = await lstat(folder);
41
+ if (!info.isDirectory() || info.isSymbolicLink())
42
+ throw new Error('Download folder must be a real local directory');
43
+ await chmod(folder, 0o700);
44
+ const filename = [...basename((requestedName ?? download.suggestedFilename()).replaceAll('\\', '/')).normalize('NFC')
45
+ .replace(/[\u0000-\u001f\u007f<>:"|?*]/g, '_').replace(/[. ]+$/g, '')].slice(0, 180).join('');
46
+ if (!filename || filename === '.' || filename === '..')
47
+ throw new Error('Invalid download filename');
48
+ const path = resolve(folder, `${randomUUID()}-${filename}`);
49
+ await download.saveAs(path);
50
+ if (await download.failure())
51
+ throw new Error('Browser download failed');
52
+ await chmod(path, 0o600);
53
+ this.browser.downloads.push({ path, filename });
54
+ return { path, filename };
55
+ }
56
+ async run(input) {
57
+ let action = ActionSchema.parse(input);
58
+ const startedAt = Date.now();
59
+ let strategy, executed = false, receiptAction = action;
60
+ let assertApproved, disposeApproved;
61
+ try {
62
+ await this.control.checkpoint();
63
+ let locator;
64
+ if ('target' in action && action.target) {
65
+ const selected = await this.observer.selectors.resolve(this.browser.page, action.target, action.timeoutMs, action.type === 'extract');
66
+ locator = selected.locator;
67
+ strategy = selected.strategy;
68
+ }
69
+ action = await this.compiler.normalize(action, locator);
70
+ receiptAction = this.semantic(action);
71
+ const reason = await sensitiveReason(action, locator);
72
+ const policy = this.options.confirmation ?? 'sensitive';
73
+ if (policy === 'always' || policy === 'sensitive' && reason) {
74
+ const approvedPage = this.browser.page, approvedURL = approvedPage.url();
75
+ const approvedElement = await locator?.elementHandle();
76
+ disposeApproved = async () => { await approvedElement?.dispose(); };
77
+ const fingerprint = locator ? await locator.evaluate(el => JSON.stringify({ tag: el.tagName, text: el.textContent, aria: el.getAttribute('aria-label'), type: el.getAttribute('type'), href: el.getAttribute('href'), form: el.form?.action, method: el.form?.method })) : undefined;
78
+ assertApproved = async () => {
79
+ if (this.browser.page !== approvedPage || approvedPage.url() !== approvedURL)
80
+ throw new Error('Browser page changed while awaiting approval; review a new plan');
81
+ if (locator && approvedElement) {
82
+ const same = await locator.evaluate((el, approved) => el === approved && el.isConnected, approvedElement);
83
+ const current = await locator.evaluate(el => JSON.stringify({ tag: el.tagName, text: el.textContent, aria: el.getAttribute('aria-label'), type: el.getAttribute('type'), href: el.getAttribute('href'), form: el.form?.action, method: el.form?.method }));
84
+ if (!same || current !== fingerprint)
85
+ throw new Error('Approved target changed while awaiting approval; review a new action');
86
+ }
87
+ };
88
+ await this.control.confirm(reason ?? 'All-actions confirmation policy', this.variables.redact(JSON.stringify(receiptAction)));
89
+ await assertApproved();
90
+ }
91
+ await this.control.checkpoint();
92
+ const page = this.browser.page;
93
+ const timeout = action.timeoutMs ?? 4000;
94
+ let data;
95
+ const interaction = this.browser.interaction, interactionOptions = { timeout, checkpoint: () => this.control.checkpoint(), beforeEffect: assertApproved };
96
+ const value = 'value' in action ? this.variables.resolve(action.value) : '';
97
+ if (locator && ['click', 'press', 'submit'].includes(action.type)) {
98
+ const info = await locator.evaluate((el, type) => {
99
+ const f = el instanceof HTMLFormElement ? el : el.form;
100
+ const submitting = type === 'submit' || type === 'press' || el.matches('button:not([type=button]):not([type=reset]),input[type=submit]');
101
+ return f && submitting && f.checkValidity() ? { actionURL: f.action, method: f.method.toUpperCase(), id: f.id, label: f.getAttribute('aria-label') ?? '', unique: document.forms.length === 1 } : null;
102
+ }, action.type);
103
+ if (info && ('target' in receiptAction) && receiptAction.target)
104
+ this.browser.formReceipts.push({ ...info, target: this.observer.selectors.descriptor(receiptAction.target), time: Date.now() });
105
+ }
106
+ executed = true;
107
+ switch (action.type) {
108
+ case 'navigate':
109
+ if (action.url.includes('{{profile.') || action.url.includes('{{files.'))
110
+ throw new Error('Local vault values cannot be embedded in navigation URLs');
111
+ await this.browser.navigate(action.url);
112
+ break;
113
+ case 'openTab':
114
+ if (action.url.includes('{{profile.') || action.url.includes('{{files.'))
115
+ throw new Error('Local vault values cannot be embedded in navigation URLs');
116
+ await this.browser.openTab(action.url);
117
+ break;
118
+ case 'closeTab':
119
+ await this.browser.closeTab();
120
+ break;
121
+ case 'switchTab':
122
+ await this.browser.switchTab(action.index, timeout);
123
+ break;
124
+ case 'back':
125
+ await page.goBack({ waitUntil: 'domcontentloaded' });
126
+ break;
127
+ case 'forward':
128
+ await page.goForward({ waitUntil: 'domcontentloaded' });
129
+ break;
130
+ case 'reload':
131
+ await page.reload({ waitUntil: 'domcontentloaded' });
132
+ break;
133
+ case 'click': {
134
+ const downloadIntent = await locator.evaluate(el => /^\s*(download|export)\b/i.test(el.getAttribute('aria-label') || el.textContent || el.getAttribute('value') || ''));
135
+ const downloadEvent = downloadIntent ? page.waitForEvent('download', { timeout }).catch(() => undefined) : Promise.resolve(undefined);
136
+ await interaction.perform(locator, 'click', async () => {
137
+ const newTab = await locator.evaluate(el => el.matches('a[target="_blank"]'));
138
+ if (newTab) {
139
+ const both = await Promise.allSettled([page.waitForEvent('popup', { timeout }), locator.click({ timeout })]);
140
+ if (both[0].status === 'rejected')
141
+ throw both[0].reason;
142
+ if (both[1].status === 'rejected')
143
+ throw both[1].reason;
144
+ await both[0].value.waitForLoadState('domcontentloaded', { timeout });
145
+ this.browser.page = both[0].value;
146
+ }
147
+ else
148
+ await locator.click({ timeout });
149
+ }, interactionOptions);
150
+ const observed = await downloadEvent;
151
+ if (observed) {
152
+ data = await this.storeDownload(observed);
153
+ receiptAction = this.semantic(ActionSchema.parse({ ...action, type: 'download' }));
154
+ }
155
+ break;
156
+ }
157
+ case 'doubleClick':
158
+ await interaction.perform(locator, 'doubleClick', () => locator.dblclick({ timeout }), interactionOptions);
159
+ break;
160
+ case 'hover':
161
+ await interaction.perform(locator, 'hover', () => locator.hover({ timeout }), interactionOptions);
162
+ break;
163
+ case 'fill':
164
+ await interaction.enter(locator, value, true, interactionOptions);
165
+ if (await locator.inputValue() !== value)
166
+ throw new Error('Fill postcondition failed');
167
+ break;
168
+ case 'type':
169
+ await interaction.enter(locator, value, false, interactionOptions);
170
+ break;
171
+ case 'select': {
172
+ const options = await locator.evaluate(el => [...el.options].map(o => ({ label: o.label, value: o.value })));
173
+ const option = options.find(o => o.value === value) || options.find(o => o.label === value);
174
+ if (!option)
175
+ throw new Error('Select option not found');
176
+ await interaction.perform(locator, 'select', () => locator.selectOption(option.value, { timeout }), interactionOptions);
177
+ break;
178
+ }
179
+ case 'check':
180
+ await interaction.perform(locator, 'check', () => locator.check({ timeout }), interactionOptions);
181
+ if (!await locator.isChecked())
182
+ throw new Error('Check postcondition failed');
183
+ break;
184
+ case 'uncheck':
185
+ await interaction.perform(locator, 'uncheck', () => locator.uncheck({ timeout }), interactionOptions);
186
+ if (await locator.isChecked())
187
+ throw new Error('Uncheck postcondition failed');
188
+ break;
189
+ case 'press':
190
+ await interaction.perform(locator, 'press', () => locator.press(value, { timeout }), interactionOptions);
191
+ break;
192
+ case 'scroll':
193
+ if (locator)
194
+ await interaction.perform(locator, 'scroll', () => locator.scrollIntoViewIfNeeded({ timeout }), interactionOptions);
195
+ else
196
+ await interaction.scroll(action.pixels * (action.direction === 'up' ? -1 : 1), interactionOptions);
197
+ break;
198
+ case 'upload': {
199
+ const file = this.variables.file(action.file);
200
+ if (!(await stat(file)).isFile())
201
+ throw new Error('Upload alias is not a regular file');
202
+ // Hidden native file controls have no pointer target.
203
+ if (await locator.isVisible())
204
+ await interaction.perform(locator, 'upload', () => locator.setInputFiles(file, { timeout }), interactionOptions);
205
+ else {
206
+ await assertApproved?.();
207
+ await locator.setInputFiles(file, { timeout });
208
+ }
209
+ break;
210
+ }
211
+ case 'download': {
212
+ const both = await interaction.perform(locator, 'click', () => Promise.allSettled([page.waitForEvent('download', { timeout }), locator.click({ timeout })]), interactionOptions);
213
+ if (both[0].status === 'rejected')
214
+ throw both[0].reason;
215
+ if (both[1].status === 'rejected')
216
+ throw both[1].reason;
217
+ data = await this.storeDownload(both[0].value, action.filename);
218
+ break;
219
+ }
220
+ case 'wait': {
221
+ const verification = await this.verifier.check([action.condition], timeout, startedAt);
222
+ if (!verification.success)
223
+ throw new Error('Wait condition failed');
224
+ break;
225
+ }
226
+ case 'submit': {
227
+ const form = locator;
228
+ await interaction.perform(form, 'submit', () => form.evaluate(el => {
229
+ const f = el instanceof HTMLFormElement ? el : el.form;
230
+ if (!f)
231
+ throw new Error('Target is not a form or form control');
232
+ if (!f.reportValidity())
233
+ throw new Error('Form validation failed');
234
+ f.addEventListener('submit', () => f.setAttribute('data-fcu-submitted', 'true'), { once: true });
235
+ f.requestSubmit();
236
+ }), interactionOptions);
237
+ break;
238
+ }
239
+ case 'extract': {
240
+ interaction.cue('extract');
241
+ const root = locator ?? page.locator('body');
242
+ if (action.format === 'table')
243
+ data = await root.locator('tr').filter({ visible: true }).evaluateAll(rows => rows.map(row => [...row.querySelectorAll('th,td')].map(cell => cell.textContent?.trim() ?? '')));
244
+ else if (action.format === 'links')
245
+ data = await root.evaluateAll(els => els.flatMap(el => [...(el.matches('a[href]') ? [el] : el.querySelectorAll('a[href]'))].filter(a => a.getClientRects().length > 0).map(a => ({ text: a.textContent?.trim(), url: a.href }))));
246
+ else if (action.format === 'records') {
247
+ if (!action.fields || !Object.keys(action.fields).length || Object.keys(action.fields).length > 20)
248
+ throw new Error('Records extraction requires 1..20 controlled CSS fields');
249
+ data = await root.filter({ visible: true }).evaluateAll((els, fields) => els.flatMap(el => el.matches('table,tbody') ? [...el.querySelectorAll('tr')].filter(row => row.querySelector('td')) : [el]).map(el => Object.fromEntries(Object.entries(fields).map(([key, field]) => {
250
+ let node = el.querySelector(field.css);
251
+ let value = '';
252
+ // Resolve tabular fields from actual headers, rather than guessed cell indices.
253
+ if (el.tagName === 'TR' && field.attribute === 'text') {
254
+ const headers = [...(el.closest('table')?.querySelectorAll('thead th,tr:first-child th') ?? [])];
255
+ const [normalize] = [(s) => (s ?? '').toLowerCase().replace(/[^a-z]/g, '')];
256
+ const wanted = normalize(key), indices = headers.map((h, i) => normalize(h.textContent ?? '') === wanted ? i : -1).filter(i => i >= 0);
257
+ const cells = [...el.querySelectorAll(':scope > td')];
258
+ if (indices.length === 1 && cells.length >= headers.length)
259
+ node = cells[indices[0] + cells.length - headers.length] ?? node;
260
+ }
261
+ if (node) {
262
+ if (field.attribute === 'text')
263
+ value = node.innerText?.trim() ?? node.textContent?.trim() ?? '';
264
+ else if (field.attribute === 'href')
265
+ value = node.href ?? '';
266
+ else if (field.attribute === 'src')
267
+ value = node.src ?? '';
268
+ else if (field.attribute === 'value')
269
+ value = node.matches('input[type=password],input[autocomplete=cc-number],input[autocomplete=cc-csc]') ? '[sensitive value omitted]' : node.value ?? '';
270
+ else
271
+ value = node.getAttribute(field.attribute) ?? '';
272
+ }
273
+ return [key, value];
274
+ }))), action.fields);
275
+ }
276
+ else
277
+ data = (await root.filter({ visible: true }).allInnerTexts()).join('\n').slice(0, 100000);
278
+ if (Array.isArray(data)) {
279
+ const match = action.match;
280
+ if (match)
281
+ data = data.filter(item => JSON.stringify(item).toLowerCase().includes(match.toLowerCase()));
282
+ if (action.limit)
283
+ data = data.slice(0, action.limit);
284
+ }
285
+ this.browser.extractions.push({ key: action.key, value: data });
286
+ data = { [action.key]: data };
287
+ break;
288
+ }
289
+ }
290
+ if (action.verify?.length) {
291
+ const checked = await this.verifier.check(action.verify, timeout, startedAt);
292
+ if (!checked.success)
293
+ throw new Error(`Action verification failed: ${JSON.stringify(checked.failed)}`);
294
+ }
295
+ return { action: receiptAction, startedAt, durationMs: Date.now() - startedAt, success: true, strategy, data };
296
+ }
297
+ catch (error) {
298
+ return { action: receiptAction, startedAt, durationMs: Date.now() - startedAt, success: false, strategy, error: this.variables.redact(error instanceof Error ? error.message : 'Browser action failed'), uncertain: executed && ['click', 'doubleClick', 'press', 'submit', 'download'].includes(action.type) };
299
+ }
300
+ finally {
301
+ await disposeApproved?.();
302
+ }
303
+ }
304
+ }
305
+ //# sourceMappingURL=executor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"executor.js","sourceRoot":"","sources":["../../src/actions/executor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { Action } from './schema.js';
2
+ import type { Locator } from 'playwright';
3
+ export type ConfirmationPolicy = 'sensitive' | 'always' | 'never';
4
+ export declare function sensitiveReason(action: Action, locator?: Locator): Promise<string | undefined>;
@@ -0,0 +1,18 @@
1
+ export async function sensitiveReason(action, locator) {
2
+ if (action.sensitive || action.type === 'submit')
3
+ return 'Explicit submission or sensitive action';
4
+ if (!['click', 'doubleClick', 'press', 'check', 'uncheck'].includes(action.type) || !locator)
5
+ return;
6
+ const facts = await locator.evaluate(el => ({
7
+ text: (el.getAttribute('aria-label') || el.textContent || el.getAttribute('value') || '').trim(),
8
+ type: el.getAttribute('type'), tag: el.tagName.toLowerCase(),
9
+ submit: !!el.form && (el.tagName === 'BUTTON' ? el.getAttribute('type') !== 'button' : el.getAttribute('type') === 'submit'),
10
+ }));
11
+ if (/\b(submit|purchase|buy|pay|checkout|delete|remove|send|confirm|transfer|publish|unsubscribe|register|create account|accept terms)\b/i.test(facts.text))
12
+ return `Potentially irreversible control: ${facts.text.slice(0, 80)}`;
13
+ if (action.type === 'press' && action.value === 'Enter' && facts.type !== 'search')
14
+ return 'Enter may submit a form';
15
+ if (facts.submit && !/\b(search|find flights|find tickets|filter|continue|next|review|apply|sign in|log in)\b/i.test(facts.text))
16
+ return 'Form submission';
17
+ }
18
+ //# sourceMappingURL=policy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policy.js","sourceRoot":"","sources":["../../src/actions/policy.ts"],"names":[],"mappings":"AAGA,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,MAAa,EAAC,OAAgB;IAClE,IAAG,MAAM,CAAC,SAAS,IAAE,MAAM,CAAC,IAAI,KAAG,QAAQ;QAAC,OAAO,yCAAyC,CAAC;IAC7F,IAAG,CAAC,CAAC,OAAO,EAAC,aAAa,EAAC,OAAO,EAAC,OAAO,EAAC,SAAS,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,IAAE,CAAC,OAAO;QAAC,OAAO;IAC7F,MAAM,KAAK,GAAC,MAAM,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAA,EAAE,CAAA,CAAC;QACtC,IAAI,EAAC,CAAC,EAAE,CAAC,YAAY,CAAC,YAAY,CAAC,IAAE,EAAE,CAAC,WAAW,IAAE,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC,IAAE,EAAE,CAAC,CAAC,IAAI,EAAE;QACzF,IAAI,EAAC,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC,EAAC,GAAG,EAAC,EAAE,CAAC,OAAO,CAAC,WAAW,EAAE;QACzD,MAAM,EAAC,CAAC,CAAE,EAAuB,CAAC,IAAI,IAAI,CAAC,EAAE,CAAC,OAAO,KAAG,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC,KAAG,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC,KAAG,QAAQ,CAAC;KAC5I,CAAC,CAAC,CAAC;IACJ,IAAG,sIAAsI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;QAAC,OAAO,qCAAqC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAC,EAAE,CAAC,EAAE,CAAC;IAChO,IAAG,MAAM,CAAC,IAAI,KAAG,OAAO,IAAE,MAAM,CAAC,KAAK,KAAG,OAAO,IAAE,KAAK,CAAC,IAAI,KAAG,QAAQ;QAAC,OAAO,yBAAyB,CAAC;IACzG,IAAG,KAAK,CAAC,MAAM,IAAE,CAAC,0FAA0F,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;QAAC,OAAO,iBAAiB,CAAC;AACzJ,CAAC"}