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.
- package/.env.example +31 -0
- package/CHANGELOG.md +19 -0
- package/CONTRIBUTING.md +66 -0
- package/LICENSE +21 -0
- package/README.md +140 -0
- package/SECURITY.md +133 -0
- package/artifacts/benchmark-public.json +797 -0
- package/assets/readme/hero.svg +53 -0
- package/assets/readme/incident-demo.gif +0 -0
- package/assets/readme/incident-evidence.json +52 -0
- package/dist/actions/compiler.d.ts +5 -0
- package/dist/actions/compiler.js +16 -0
- package/dist/actions/compiler.js.map +1 -0
- package/dist/actions/executor.d.ts +38 -0
- package/dist/actions/executor.js +305 -0
- package/dist/actions/executor.js.map +1 -0
- package/dist/actions/policy.d.ts +4 -0
- package/dist/actions/policy.js +18 -0
- package/dist/actions/policy.js.map +1 -0
- package/dist/actions/schema.d.ts +4149 -0
- package/dist/actions/schema.js +59 -0
- package/dist/actions/schema.js.map +1 -0
- package/dist/adapters/generic.d.ts +14 -0
- package/dist/adapters/generic.js +33 -0
- package/dist/adapters/generic.js.map +1 -0
- package/dist/agent/Agent.d.ts +69 -0
- package/dist/agent/Agent.js +375 -0
- package/dist/agent/Agent.js.map +1 -0
- package/dist/agent/Control.d.ts +23 -0
- package/dist/agent/Control.js +51 -0
- package/dist/agent/Control.js.map +1 -0
- package/dist/agent/TokenBudget.d.ts +52 -0
- package/dist/agent/TokenBudget.js +47 -0
- package/dist/agent/TokenBudget.js.map +1 -0
- package/dist/agent/goalCriteria.d.ts +2 -0
- package/dist/agent/goalCriteria.js +13 -0
- package/dist/agent/goalCriteria.js.map +1 -0
- package/dist/browser/Browser.d.ts +72 -0
- package/dist/browser/Browser.js +378 -0
- package/dist/browser/Browser.js.map +1 -0
- package/dist/browser/DomExtractor.d.ts +6 -0
- package/dist/browser/DomExtractor.js +134 -0
- package/dist/browser/DomExtractor.js.map +1 -0
- package/dist/browser/Interaction.d.ts +43 -0
- package/dist/browser/Interaction.js +225 -0
- package/dist/browser/Interaction.js.map +1 -0
- package/dist/browser/NetworkGuardProxy.d.ts +31 -0
- package/dist/browser/NetworkGuardProxy.js +331 -0
- package/dist/browser/NetworkGuardProxy.js.map +1 -0
- package/dist/browser/Observer.d.ts +12 -0
- package/dist/browser/Observer.js +31 -0
- package/dist/browser/Observer.js.map +1 -0
- package/dist/browser/PageCompressor.d.ts +47 -0
- package/dist/browser/PageCompressor.js +62 -0
- package/dist/browser/PageCompressor.js.map +1 -0
- package/dist/browser/SecurityBoundaryError.d.ts +3 -0
- package/dist/browser/SecurityBoundaryError.js +4 -0
- package/dist/browser/SecurityBoundaryError.js.map +1 -0
- package/dist/browser/SelectorEngine.d.ts +18 -0
- package/dist/browser/SelectorEngine.js +72 -0
- package/dist/browser/SelectorEngine.js.map +1 -0
- package/dist/browser/types.d.ts +38 -0
- package/dist/browser/types.js +2 -0
- package/dist/browser/types.js.map +1 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +284 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/config.d.ts +11 -0
- package/dist/config.js +77 -0
- package/dist/config.js.map +1 -0
- package/dist/history/TraceStore.d.ts +29 -0
- package/dist/history/TraceStore.js +53 -0
- package/dist/history/TraceStore.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/llm/ClaudeSubscriptionProvider.d.ts +26 -0
- package/dist/llm/ClaudeSubscriptionProvider.js +182 -0
- package/dist/llm/ClaudeSubscriptionProvider.js.map +1 -0
- package/dist/llm/CodexSubscriptionProvider.d.ts +26 -0
- package/dist/llm/CodexSubscriptionProvider.js +168 -0
- package/dist/llm/CodexSubscriptionProvider.js.map +1 -0
- package/dist/llm/FlashProvider.d.ts +27 -0
- package/dist/llm/FlashProvider.js +103 -0
- package/dist/llm/FlashProvider.js.map +1 -0
- package/dist/llm/LLMProvider.d.ts +37 -0
- package/dist/llm/LLMProvider.js +2 -0
- package/dist/llm/LLMProvider.js.map +1 -0
- package/dist/llm/cliEnvironment.d.ts +5 -0
- package/dist/llm/cliEnvironment.js +21 -0
- package/dist/llm/cliEnvironment.js.map +1 -0
- package/dist/llm/prompts.d.ts +4 -0
- package/dist/llm/prompts.js +12 -0
- package/dist/llm/prompts.js.map +1 -0
- package/dist/llm/structuredOutput.d.ts +3 -0
- package/dist/llm/structuredOutput.js +58 -0
- package/dist/llm/structuredOutput.js.map +1 -0
- package/dist/mcp/index.d.ts +13 -0
- package/dist/mcp/index.js +243 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/profile/ProfileStore.d.ts +7 -0
- package/dist/profile/ProfileStore.js +52 -0
- package/dist/profile/ProfileStore.js.map +1 -0
- package/dist/profile/VariableResolver.d.ts +15 -0
- package/dist/profile/VariableResolver.js +50 -0
- package/dist/profile/VariableResolver.js.map +1 -0
- package/dist/server/index.d.ts +14 -0
- package/dist/server/index.js +239 -0
- package/dist/server/index.js.map +1 -0
- package/dist/ui/app.js +132 -0
- package/dist/ui/index.html +29 -0
- package/dist/ui/logo.svg +5 -0
- package/dist/ui/results.js +59 -0
- package/dist/ui/style.css +33 -0
- package/dist/verification/Verifier.d.ts +72 -0
- package/dist/verification/Verifier.js +87 -0
- package/dist/verification/Verifier.js.map +1 -0
- package/dist/workflows/WorkflowEngine.d.ts +23 -0
- package/dist/workflows/WorkflowEngine.js +52 -0
- package/dist/workflows/WorkflowEngine.js.map +1 -0
- package/docs/ADOPTION.md +61 -0
- package/docs/ARCHITECTURE.md +65 -0
- package/docs/BENCHMARKS.md +64 -0
- package/docs/IMPLEMENTATION.md +93 -0
- package/docs/LOCAL_DATA.md +98 -0
- package/docs/LOCAL_VALIDATION.md +87 -0
- package/docs/MCP.md +81 -0
- package/docs/PROVIDERS.md +150 -0
- package/docs/RELEASE_CHECKLIST.md +37 -0
- package/docs/REQUIREMENTS.md +39 -0
- package/docs/SUPPORT_MATRIX.md +193 -0
- package/docs/THREAT_MODEL.md +108 -0
- package/docs/USEFUL_EXAMPLES.md +151 -0
- package/docs/brand-mark.svg +12 -0
- package/package.json +90 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
@font-face{font-family:Workspace;src:local("Avenir Next")}@font-face{font-family:Editorial;src:local("Georgia")}*{box-sizing:border-box}html{background:#f4f3ee;color:#252d29;font-family:Workspace,"Segoe UI",sans-serif;font-size:14px}body{margin:0}button,input,textarea,select{font:inherit}button,a,input,textarea,select{outline-offset:4px}button{cursor:pointer;border:1px solid #d9ddd3;background:transparent;border-radius:5px;padding:9px 13px;color:inherit;transition:background .15s}button:hover:enabled{background:#e6eadf}button:disabled{opacity:.4;cursor:default}button:focus-visible,input:focus-visible,textarea:focus-visible,select:focus-visible{outline:2px solid #456a3d}header{height:82px;padding:0 28px;display:flex;align-items:center;justify-content:space-between;border-bottom:1px solid #d9ddd3;background:#fcfcf7}.brand{display:flex;gap:12px;align-items:center;text-decoration:none;color:inherit;font-weight:700;font-size:18px;letter-spacing:-.5px}.brandmark{height:44px;width:44px;display:block;flex:none}.edition{display:block;font:9px monospace;letter-spacing:1.6px;margin-top:4px;color:#52634a}.header-tools{display:flex;gap:24px;align-items:center}.local-badge{color:#52634a;font-size:12px}.local-badge i,.control-bar i{display:inline-block;width:6px;height:6px;border-radius:50%;background:#679752;margin-right:7px}.quiet{border:0;padding:8px 0}.quiet span{margin-left:10px}.workspace{display:grid;grid-template-columns:minmax(260px,310px) minmax(400px,1fr) 278px;min-height:calc(100vh - 82px)}.task-panel{padding:28px 26px 20px;border-right:1px solid #d9ddd3;display:flex;flex-direction:column}.panel-label,.micro,.section-title,.eyebrow{font-family:monospace;font-size:10px;letter-spacing:1.4px;color:#52634a}.panel-label{margin-bottom:26px}h1{font-size:27px;line-height:1.3;letter-spacing:-.9px;margin:0 0 15px;font-weight:500}h1 em{font-family:Editorial,serif;font-weight:400;color:#627656}.intro{line-height:1.65;color:#52634a;font-size:12px;margin:0 0 24px}label{display:block;font-size:11px;font-weight:600;margin:17px 0 8px}input,textarea,select{background:#fcfcf8;border:1px solid #d9ddd3;border-radius:5px;padding:11px;width:100%;color:#344030}textarea{resize:vertical;line-height:1.6}input::placeholder,textarea::placeholder{color:#52634a;font-size:12px}.options{margin:18px 0;color:#52634a;font-size:11px}.options summary{cursor:pointer;list-style:none;display:flex;justify-content:space-between}.check{display:flex;align-items:center;gap:8px}.check input{width:14px;accent-color:#456a3d}.primary{background:#d5ee79;border:1px solid #bcd962;font-weight:600;padding:12px 15px;display:flex;justify-content:space-between;align-items:center;color:#2b4024}.primary:hover:enabled{background:#c8e466}#run{width:100%;margin:22px 0 6px}.notice{font-size:12px;color:#526343;line-height:1.5;min-height:18px}.notice.error{color:#aa442f}.recent{border-top:1px solid #d9ddd3;margin-top:28px;padding-top:21px}.section-title{display:flex;align-items:center;justify-content:space-between;margin-bottom:15px}.section-title>span{letter-spacing:0;background:#e8eadf;padding:2px 6px;border-radius:3px}.section-title button{font-family:Workspace,sans-serif;letter-spacing:0;font-size:10px;padding:3px 7px}.empty-list{color:#52634a;font-size:11px;padding:10px 0}.history-item{border:0;border-bottom:1px solid #e0e3d8;text-align:left;padding:11px 0;width:100%;display:block;border-radius:0}.history-item strong{font-size:11px;font-weight:500;display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.history-item small{color:#52634a;font-size:9px;display:block;margin-top:5px}.history-item small b{font-weight:500;color:#52634a}.workflow-button{display:flex;justify-content:space-between;margin:15px 0;font-size:11px;color:#60724f}.task-footer{margin-top:auto;padding-top:30px;font:italic 15px Editorial,serif;line-height:1.6;color:#52634a}.task-footer strong{color:#53654b;font-weight:400}.browser-panel{padding:24px;min-width:0;background:#eeeee6}.browser-toolbar{background:#fafaf5;display:flex;align-items:center;gap:14px;padding:13px;border:1px solid #d8dcd0;border-radius:8px 8px 0 0}.traffic{display:flex;gap:5px}.traffic i{width:7px;height:7px;background:#c3c8bb;border-radius:50%}.traffic i:first-child{background:#cda997}.page-url{flex:1;font-family:monospace;font-size:10px;color:#52634a;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;background:#efefe7;padding:7px;border-radius:3px}.preview-tag{font:9px monospace;letter-spacing:1px;color:#52634a}.browser-stage{position:relative;min-height:365px;aspect-ratio:16/10;display:grid;place-items:center;background:#fcfcf7;border:1px solid #d8dcd0;border-top:0;overflow:hidden}.browser-empty{padding:28px;text-align:center;animation:arrive .5s both}.empty-symbol{width:48px;height:48px;font-size:30px;color:#4b6540;background:#e8eedc;margin:0 auto 25px;border-radius:50%;display:grid;place-items:center}.eyebrow{font-size:9px;color:#52634a}h2{font-weight:500;letter-spacing:-.6px}.browser-empty h2{font:34px/1.18 Editorial,serif;letter-spacing:-1px;margin:18px 0}.browser-empty p{font-size:12px;line-height:1.7;color:#52634a}.method{display:flex;justify-content:center;gap:12px;align-items:center;margin-top:24px;font:10px monospace;color:#52634a}.method b{color:#52634a;font-weight:400}#preview{display:block;width:100%;max-height:100%;object-fit:contain;cursor:default}#preview[hidden]{display:none}#preview.manual{cursor:crosshair}.control-bar{display:flex;justify-content:space-between;align-items:center;gap:8px;padding:13px 0;border-bottom:1px solid #d7dccf;font-size:10px;color:#52634a}.control-bar div{display:flex;gap:5px}.control-bar button{font-size:10px;padding:7px 9px;background:#f8f9f0}.danger{color:#8a3b35}.manual-tools{padding:12px;background:#e5ecd7;border-radius:5px;margin-top:10px}.manual-tools label{margin:0 0 10px}.manual-tools>div{display:flex;gap:7px}.manual-tools button{white-space:nowrap;font-size:11px}.manual-tools input{min-width:50px}.approval{padding:18px;background:#f4f7d3;border:1px solid #d5dbaa;margin-top:14px;border-radius:7px}.approval h3{margin:8px 0;font-size:18px;font-weight:500}.approval p{font-size:12px}.approval pre{font-size:10px;white-space:pre-wrap;overflow-wrap:anywhere;color:#52634a}.approval-actions{display:flex;gap:8px}.approval-actions button{font-size:11px}.activity{margin-top:24px}.activity ol{list-style:none;padding:0;margin:0;max-height:260px;overflow:auto;scrollbar-width:thin}.activity li{display:flex;align-items:flex-start;gap:12px;padding:10px 0;border-bottom:1px solid #dfe2d7;font-size:11px;color:#52634a}.activity li .phase{font:9px monospace;width:55px;flex-shrink:0;margin-top:2px;color:#52634a}.activity li .phase.EXECUTE{color:#52634a}.activity li .phase.ERROR{color:#8a3b35}.activity li .time{margin-left:auto;color:#52634a;font:9px monospace;white-space:nowrap}.stream-empty{font-family:monospace;color:#52634a!important}.state-panel{padding:28px 23px;background:#fcfcf7;border-left:1px solid #d9ddd3}.state-panel .panel-label{margin-bottom:23px}.state-title{display:flex;align-items:center;justify-content:space-between}.state-title h2{margin:0;font-size:18px}.status{background:#edf0e3;color:#52634a;font:9px monospace;letter-spacing:.5px;border-radius:3px;padding:5px 7px}.status.active{background:#e4eeb6;color:#52634a}.loop{display:flex;flex-wrap:wrap;gap:6px;margin:20px 0 26px}.loop span{font:9px monospace;border:1px solid #e3e7da;padding:5px;color:#52634a;border-radius:3px}.loop span.current{border-color:#a8c36e;color:#47612e;background:#f1f6df}.model-block{border-top:1px solid #dce1d3;border-bottom:1px solid #dce1d3;padding:19px 0}.model-block strong{display:block;margin-top:9px;font-size:14px;font-weight:500}.model-block p,.dom-stat p,.budget p{font-size:10px;line-height:1.5;color:#52634a;margin:6px 0 0}.metrics{margin-top:12px}.metrics>div{display:flex;justify-content:space-between;align-items:center;border-bottom:1px solid #e7eadf;padding:11px 0}.metrics span{font-size:11px;color:#52634a}.metrics strong{font:20px monospace;letter-spacing:-1px;color:#4a6237}.metrics .cost{border-bottom:0;padding-top:16px}.metrics .cost strong{font-size:22px}.budget{margin:20px 0 28px}.budget .section-title{margin-bottom:10px}.meter{height:4px;background:#eaeee0;border-radius:3px;overflow:hidden}.meter i{display:block;height:100%;width:0;background:#aacd61;transition:width .3s}.plan-section ol{padding-left:16px;font-size:11px;line-height:1.7;color:#52634a}.plan-section li{margin-bottom:8px}.dom-stat{border-top:1px solid #dce1d3;padding-top:19px;margin-top:25px}.dom-stat strong{display:block;font:26px Editorial,serif;margin-top:9px;color:#52634a}.warnings{font-size:11px;color:#795021;line-height:1.6;margin-top:15px}.privacy{font-size:9px;line-height:1.7;color:#52634a;border-top:1px solid #e4e9d9;padding-top:17px;margin-top:24px}dialog{border:1px solid #cdd6bb;border-radius:10px;width:min(640px,94vw);padding:28px;color:#34472c;background:#fcfdf5;box-shadow:0 30px 100px #20351333}dialog::backdrop{background:#22331966;backdrop-filter:blur(3px)}.dialog-heading{display:flex;align-items:center;justify-content:space-between}.dialog-heading h2{margin:0}.dialog-heading button{border:0;font-size:22px}dialog p{color:#52634a;font-size:12px;line-height:1.7}dialog textarea{font:11px/1.6 monospace;min-height:150px}dialog .primary{margin-top:17px}.hint{font-size:10px!important}.workflow-row{padding:16px 0;border-top:1px solid #dde5d0;font-size:12px;overflow-wrap:anywhere}.workflow-row small{display:block;color:#52634a;margin-top:7px}[hidden]{display:none!important}@keyframes arrive{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}@media(min-width:1600px){.workspace{grid-template-columns:340px 1fr 300px}.browser-panel{padding:32px}.browser-stage{max-height:650px}.task-panel{padding:32px}.state-panel{padding:32px}}@media(max-width:1120px){.workspace{grid-template-columns:260px minmax(350px,1fr)}.state-panel{grid-column:1/-1;display:grid;grid-template-columns:repeat(3,1fr);gap:20px;border-left:0;border-top:1px solid #d9ddd3}.state-panel>.panel-label,.state-panel>.privacy{display:none}.state-title{grid-column:1}.loop{grid-column:2/4;margin:0}.model-block{grid-column:1;padding:14px 0}.metrics{grid-column:2;grid-row:2/4;margin:0}.budget{grid-column:3;margin:0}.plan-section{grid-column:3}.dom-stat{grid-column:1;grid-row:3;margin:0}.warnings{grid-column:1/-1}}@media(max-width:650px){header{height:70px;padding:0 16px}.brand{font-size:15px}.header-tools{gap:12px}.local-badge{display:none}.header-tools button{font-size:11px}.workspace{display:flex;flex-direction:column}.task-panel{padding:23px;border-right:0}h1{font-size:27px}.task-panel .panel-label{margin-bottom:15px}.intro{margin-bottom:8px}.task-footer{display:none}.recent{margin-top:20px}#history{max-height:125px;overflow:auto}.browser-panel{padding:16px}.browser-stage{min-height:300px;aspect-ratio:auto}.browser-empty h2{font-size:30px}.browser-empty{padding:22px}.method{gap:8px}.control-bar{flex-wrap:wrap;gap:12px}.manual-tools>div{flex-wrap:wrap}.state-panel{padding:23px;display:grid;grid-template-columns:1fr 1fr}.state-title{grid-column:1/-1}.loop{grid-column:1/-1;grid-row:2}.model-block{grid-column:1;grid-row:3}.metrics{grid-column:2;grid-row:3/6}.budget{grid-column:1;grid-row:4}.plan-section{grid-column:1/-1;grid-row:6}.dom-stat{grid-column:1;grid-row:5}.activity li .time{display:none}}@media(prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
|
2
|
+
|
|
3
|
+
.page-scroll{display:flex;gap:3px;flex:none}.page-scroll button{padding:4px 8px;font-size:14px}
|
|
4
|
+
#result-dialog{width:min(840px,94vw);padding:28px;background:#f8f9f3}
|
|
5
|
+
#result-dialog .dialog-heading h2{font:30px Editorial,serif;margin:7px 0 0;color:#263e34}
|
|
6
|
+
.result-tools{display:flex;gap:8px;margin:20px 0}.result-tools button{font-size:11px;background:#fff}
|
|
7
|
+
#result-panel{margin:0;padding:0;border:0;background:transparent;max-height:62dvh;overflow:auto;scrollbar-width:thin}
|
|
8
|
+
.result-overview{display:flex;align-items:center;justify-content:space-between;gap:10px;margin:0 0 14px}
|
|
9
|
+
.result-status{font:10px monospace;text-transform:uppercase;letter-spacing:1px;border-radius:20px;padding:7px 10px;background:#e7efdf;color:#3d643a}
|
|
10
|
+
.result-status.partial{background:#fff0d8;color:#795021}.result-count{font-size:11px;color:#52634a}
|
|
11
|
+
.result-caveat{padding:13px 16px;border-left:3px solid #d7a35e;background:#fff3df;border-radius:0 6px 6px 0;color:#795021!important;font-size:12px!important}
|
|
12
|
+
.result-card{margin:12px 0;padding:21px;background:#fff;border:1px solid #dce3d7;border-radius:10px}
|
|
13
|
+
.result-card h3{font:10px monospace;text-transform:uppercase;letter-spacing:1.2px;color:#52634a;margin:0 0 20px}
|
|
14
|
+
.result-facts{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:20px 32px;margin:0}
|
|
15
|
+
.result-facts dt{font-size:11px;color:#52634a}.result-facts dd{margin:5px 0 0;font-size:17px;color:#2b4236;font-weight:600;overflow-wrap:anywhere}
|
|
16
|
+
.result-prose{font-size:13px;line-height:1.8;white-space:pre-wrap;overflow-wrap:anywhere;color:#3a5040}
|
|
17
|
+
.result-source{margin-top:22px;padding-top:13px;border-top:1px solid #edf0e9;font-size:11px;color:#52634a}.result-source summary{cursor:pointer}.result-source .result-prose{margin-top:16px;font-size:12px}
|
|
18
|
+
.result-supporting{font-size:11px;color:#52634a}.result-supporting summary{cursor:pointer}.result-supporting .result-prose{margin-top:16px}
|
|
19
|
+
#agent-cursor.preparing::before{content:"";position:absolute;left:-8px;top:-8px;width:18px;height:18px;border:1px solid #567bcb88;background:#a9c6ff22;border-radius:50%;animation:preparing-cursor 1.6s ease-in-out infinite;z-index:-1}
|
|
20
|
+
#pointer-layer #agent-cursor{left:-2px;top:-2px;filter:drop-shadow(0 2px 3px #1452a855)}
|
|
21
|
+
@keyframes preparing-cursor{0%,100%{opacity:.35}50%{opacity:.9}}
|
|
22
|
+
.result-table-wrap{overflow:auto}.result-table{width:100%;border-collapse:collapse;white-space:normal;font-size:12px}
|
|
23
|
+
.result-table th{text-align:left;font-size:10px;color:#52634a;font-weight:500;background:#f6f8f1;padding:12px}
|
|
24
|
+
.result-table td{padding:14px 12px;border-bottom:1px solid #e9eee4;color:#324d3a;min-width:100px;max-width:320px;overflow-wrap:anywhere}.result-table tbody tr:last-child td{border-bottom:0}
|
|
25
|
+
.result-links{list-style:none;margin:0;padding:0}.result-links li{padding:12px 0;border-bottom:1px solid #edf0e9}.result-links a{color:#345e99;font-size:13px}.result-links small{display:block;font-size:10px;overflow-wrap:anywhere;color:#52634a;margin-top:5px}
|
|
26
|
+
.result-file{display:flex;gap:12px;align-items:center;flex-wrap:wrap;padding:12px 0}.file-icon{width:32px;height:38px;display:grid;place-items:center;border:1px solid #d9e1d2;border-radius:4px;color:#4c6c40;background:#f4f8ed;font-size:20px}.result-file strong{font-weight:500;font-size:12px;overflow-wrap:anywhere;min-width:0}.file-save{margin-left:auto;color:#375d44;font-size:11px;border:1px solid #d4dfca;border-radius:5px;padding:8px 10px;text-decoration:none}
|
|
27
|
+
.result-empty{font-size:12px;color:#52634a}.result-list{font-size:13px;line-height:1.8}
|
|
28
|
+
@media(max-width:650px){#result-dialog{padding:18px}.result-card{padding:16px}.result-facts{gap:18px}.result-facts dd{font-size:15px}.result-count{font-size:10px}.file-save{margin-left:44px}.browser-toolbar .preview-tag{display:none}}
|
|
29
|
+
|
|
30
|
+
#preview{height:100%;min-height:0}#pointer-layer{position:absolute;inset:0;pointer-events:none;overflow:hidden}#agent-cursor{position:absolute;left:-1px;top:-1px;will-change:transform;filter:drop-shadow(0 1px 2px #183c3444);transition:transform 35ms linear}#agent-cursor svg{display:block}#agent-cursor.typing{filter:drop-shadow(0 0 3px #507bec66)}#click-ring{position:absolute;width:28px;height:28px;margin:-14px;border:1.5px solid #537be6;background:#87a5ff22;border-radius:50%;opacity:0}#click-ring.pulse{animation:click-pulse .55s ease-out}.interaction-line{display:flex;align-items:center;gap:7px;padding:12px 0 0;color:#526343;font-size:11px;min-width:0}.interaction-dot{height:5px;width:5px;background:#8eab53;border-radius:50%;flex-shrink:0}.interaction-note{margin-left:auto;color:#52634a;font:9px monospace;white-space:nowrap}@keyframes click-pulse{0%{opacity:1;scale:.4}100%{opacity:0;scale:1.6}}@media(max-width:650px){.interaction-note{display:none}}@media(prefers-reduced-motion:reduce){#click-ring.pulse{animation:none;opacity:.7}}
|
|
31
|
+
#fullscreen{font-size:10px;padding:6px 8px;white-space:nowrap}.mobile-view-switch{display:none}.run-options{border:0;padding:0;display:flex;justify-content:space-between;width:100%;font-size:11px;color:#52634a;margin-top:18px}.permission-note{font-size:10px;color:#52634a;line-height:1.5;margin:10px 0 0}.workspace-links{border-top:1px solid #d9ddd3;margin-top:22px;padding-top:8px}.workspace-links button{width:100%;margin:10px 0}.workspace{height:calc(100dvh - 82px);min-height:0}.task-panel,.state-panel{min-height:0;overflow:auto}.browser-panel{display:flex;flex-direction:column;min-height:0;padding:20px}.browser-toolbar,.interaction-line,.control-bar,.approval,.manual-tools{flex:none}.browser-stage{flex:1;aspect-ratio:auto;min-height:120px;max-height:none}#preview{position:absolute;inset:0;width:100%;height:100%;max-height:none}.browser-empty{padding:16px}.control-bar{flex-wrap:wrap;gap:10px}.control-bar>div{flex-wrap:wrap}.approval{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:14px;margin-top:10px}.approval h3{font-size:14px;margin:4px 0}.approval p{font-size:11px;margin:4px 0;overflow-wrap:anywhere;max-width:60ch}.approval-actions{flex:none;align-items:center}.approval-actions .primary{padding:10px 12px}.approval-details{position:relative;flex:none;font-size:10px;color:#52634a}.approval-details summary{cursor:pointer}.approval-details pre{position:absolute;bottom:100%;right:0;width:min(430px,75vw);max-height:250px;overflow:auto;padding:15px;background:#fcfdf5;border:1px solid #c6d09e;border-radius:6px;box-shadow:0 8px 30px #20351322;z-index:5}.stream-dialog{width:min(850px,94vw)}.stream-dialog .activity{margin-top:16px}.stream-dialog .activity ol{max-height:55dvh}.results{margin:15px 0 0}.results pre{max-height:60dvh;overflow:auto;white-space:pre-wrap;overflow-wrap:anywhere;font:11px/1.7 monospace}.browser-panel:fullscreen,.browser-panel.expanded{width:100vw;height:100dvh;padding:20px;background:#eeeee6;display:flex}.browser-panel.expanded{position:fixed;inset:0;z-index:200}.browser-panel:fullscreen .browser-stage,.browser-panel.expanded .browser-stage{max-height:none}.task-footer{padding-top:14px}body{height:100dvh;overflow:hidden}dialog{max-height:90dvh;overflow:auto}@media(min-width:651px) and (max-width:1120px){.workspace{grid-template-columns:240px minmax(0,1fr) 220px}.state-panel{grid-column:auto;display:block;padding:22px 18px;border-left:1px solid #d9ddd3;border-top:0}.state-panel>.panel-label,.state-panel>.privacy{display:block}.state-panel .loop{margin:16px 0}.state-panel .metrics{margin-top:12px}.state-panel .budget{margin:18px 0}.state-panel .dom-stat{margin-top:20px}.task-panel{padding:22px 18px}.browser-panel{padding:16px}.approval{flex-wrap:wrap;gap:8px}.approval>div:first-child{width:100%}.browser-empty h2{font-size:28px}.browser-empty .eyebrow{font-size:8px}.interaction-note{display:none}}@media(max-height:800px){.task-panel{padding-top:18px}.task-panel .panel-label{margin-bottom:16px}.task-panel h1{font-size:24px;margin-bottom:10px}.task-panel .intro{margin-bottom:10px}.task-panel label{margin-top:12px}.task-panel textarea{height:110px}.workspace-links{margin-top:12px}.task-footer{display:none}.state-panel{padding-top:18px}.state-panel .loop{margin:12px 0 16px}.state-panel .model-block{padding:12px 0}.state-panel .metrics>div{padding:9px 0}.state-panel .budget{margin:16px 0}}@media(max-width:650px){.mobile-view-switch{display:flex;height:40px;align-items:center;justify-content:center;gap:8px;background:#fcfcf7;border-bottom:1px solid #d9ddd3}.mobile-view-switch button{font-size:11px;padding:6px 16px;border:0}.mobile-view-switch button[aria-pressed=true]{background:#e9efda;color:#3d582f}.workspace{height:calc(100dvh - 110px)}.workspace>.task-panel,.workspace>.browser-panel,.workspace>.state-panel{height:100%;width:100%;flex:none}.workspace>.state-panel{display:block;overflow:auto}.workspace>.browser-panel{display:flex}.workspace>.task-panel{overflow:auto}body:not([data-mobile-view=browser]) .workspace>.browser-panel{display:none}body:not([data-mobile-view=stats]) .workspace>.state-panel{display:none}body[data-mobile-view=browser] .workspace>.task-panel,body[data-mobile-view=stats] .workspace>.task-panel{display:none}.browser-panel{padding:12px}.browser-stage{min-height:100px}.browser-empty h2{font-size:28px}.browser-empty .method{margin-top:12px}.empty-symbol{margin-bottom:14px}.browser-toolbar{gap:8px;padding:10px}.traffic{display:none}#fullscreen span{display:none}#fullscreen{font-size:18px}.control-bar{font-size:10px;gap:8px}.control-bar button{padding:7px}.approval{flex-wrap:wrap;gap:10px}.approval>div:first-child{width:100%}.approval-details{margin-right:auto}.approval-details pre{right:auto;left:0}.workspace-links button{margin:8px 0}.browser-panel:fullscreen,.browser-panel.expanded{padding:12px}.manual-tools{padding:10px}.state-panel .state-title{margin-bottom:18px}.state-panel .model-block{margin-top:16px}}
|
|
32
|
+
.site-permissions{border-top:1px solid #d9ddd3;margin-top:20px;padding-top:16px}.site-permissions h3{font-size:14px;margin:0 0 6px}.site-permissions p{font-size:11px;line-height:1.55;color:#687467;margin:0 0 12px}.site-permissions ul{list-style:none;padding:0;margin:0;display:grid;gap:8px}.site-permissions li{display:flex;align-items:center;justify-content:space-between;gap:12px;min-width:0;padding:8px 10px;border:1px solid #d9ddd3;border-radius:8px;font-size:12px}.site-permissions li span{min-width:0;overflow-wrap:anywhere}.site-permissions li.empty{color:#687467}.site-permissions li button{flex:none;padding:6px 10px;color:#8a3b35;border-color:#d9b3af;background:#fff9f8}
|
|
33
|
+
.status.blocked{background:#f7dfdc;color:#8a3b35}.phase.BLOCKED{background:#f7dfdc;color:#8a3b35}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import type { Condition } from '../actions/schema.js';
|
|
2
|
+
import type { Browser } from '../browser/Browser.js';
|
|
3
|
+
import type { Observer } from '../browser/Observer.js';
|
|
4
|
+
import type { VariableResolver } from '../profile/VariableResolver.js';
|
|
5
|
+
export declare class Verifier {
|
|
6
|
+
readonly browser: Browser;
|
|
7
|
+
readonly observer: Observer;
|
|
8
|
+
readonly variables: VariableResolver;
|
|
9
|
+
constructor(browser: Browser, observer: Observer, variables: VariableResolver);
|
|
10
|
+
one(condition: Condition, since?: number): Promise<boolean>;
|
|
11
|
+
check(conditions: Condition[], timeoutMs?: number, since?: number): Promise<{
|
|
12
|
+
success: boolean;
|
|
13
|
+
failed: ({
|
|
14
|
+
type: "input_value_equals";
|
|
15
|
+
target: string | {
|
|
16
|
+
role?: string | undefined;
|
|
17
|
+
name?: string | undefined;
|
|
18
|
+
label?: string | undefined;
|
|
19
|
+
placeholder?: string | undefined;
|
|
20
|
+
testId?: string | undefined;
|
|
21
|
+
id?: string | undefined;
|
|
22
|
+
attributeName?: string | undefined;
|
|
23
|
+
text?: string | undefined;
|
|
24
|
+
css?: string | undefined;
|
|
25
|
+
frame?: number | undefined;
|
|
26
|
+
};
|
|
27
|
+
value: string;
|
|
28
|
+
} | {
|
|
29
|
+
type: "extraction_created";
|
|
30
|
+
key?: string | undefined;
|
|
31
|
+
} | {
|
|
32
|
+
type: "extraction_contains";
|
|
33
|
+
key?: string | undefined;
|
|
34
|
+
value: string;
|
|
35
|
+
} | {
|
|
36
|
+
type: "tab_count";
|
|
37
|
+
count: number;
|
|
38
|
+
} | {
|
|
39
|
+
type: "extraction_count";
|
|
40
|
+
key?: string | undefined;
|
|
41
|
+
min: number;
|
|
42
|
+
max?: number | undefined;
|
|
43
|
+
} | {
|
|
44
|
+
type: "checkbox_checked" | "element_exists" | "element_not_visible" | "element_visible" | "form_submitted";
|
|
45
|
+
target: string | {
|
|
46
|
+
role?: string | undefined;
|
|
47
|
+
name?: string | undefined;
|
|
48
|
+
label?: string | undefined;
|
|
49
|
+
placeholder?: string | undefined;
|
|
50
|
+
testId?: string | undefined;
|
|
51
|
+
id?: string | undefined;
|
|
52
|
+
attributeName?: string | undefined;
|
|
53
|
+
text?: string | undefined;
|
|
54
|
+
css?: string | undefined;
|
|
55
|
+
frame?: number | undefined;
|
|
56
|
+
};
|
|
57
|
+
} | {
|
|
58
|
+
type: "text_disappeared" | "text_exists" | "title_changed" | "url_contains" | "url_equals";
|
|
59
|
+
value: string;
|
|
60
|
+
} | {
|
|
61
|
+
type: "network_response";
|
|
62
|
+
value: string;
|
|
63
|
+
status?: number | undefined;
|
|
64
|
+
} | {
|
|
65
|
+
type: "download_created";
|
|
66
|
+
value?: string | undefined;
|
|
67
|
+
} | {
|
|
68
|
+
type: "page_changed";
|
|
69
|
+
value: string;
|
|
70
|
+
})[];
|
|
71
|
+
}>;
|
|
72
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
export class Verifier {
|
|
2
|
+
browser;
|
|
3
|
+
observer;
|
|
4
|
+
variables;
|
|
5
|
+
constructor(browser, observer, variables) {
|
|
6
|
+
this.browser = browser;
|
|
7
|
+
this.observer = observer;
|
|
8
|
+
this.variables = variables;
|
|
9
|
+
}
|
|
10
|
+
async one(condition, since = 0) {
|
|
11
|
+
const page = this.browser.page;
|
|
12
|
+
if (condition.type === 'form_submitted') {
|
|
13
|
+
const target = this.observer.selectors.descriptor(condition.target);
|
|
14
|
+
return this.browser.formReceipts.some(f => {
|
|
15
|
+
const matches = JSON.stringify(f.target) === JSON.stringify(target) || (f.id && (target.id === f.id || target.css === `#${f.id}` || target.css === `form#${f.id}`)) || (f.label && (target.label === f.label || target.role === 'form' && target.name === f.label)) || (f.unique && target.css === 'form');
|
|
16
|
+
const action = new URL(f.actionURL);
|
|
17
|
+
return matches && f.time >= since && this.browser.responses.some(r => { const url = new URL(r.url); return r.time >= f.time && r.status >= 200 && r.status < 400 && r.method === f.method && r.resource === 'document' && url.origin === action.origin && url.pathname === action.pathname; });
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
if ('target' in condition) {
|
|
21
|
+
let locator;
|
|
22
|
+
try {
|
|
23
|
+
locator = (await this.observer.selectors.resolve(page, condition.target, 100)).locator;
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
return condition.type === 'element_not_visible';
|
|
27
|
+
}
|
|
28
|
+
switch (condition.type) {
|
|
29
|
+
case 'element_exists': return await locator.count() > 0;
|
|
30
|
+
case 'element_visible': return locator.isVisible();
|
|
31
|
+
case 'element_not_visible': return !(await locator.isVisible());
|
|
32
|
+
case 'input_value_equals': return await locator.inputValue() === this.variables.resolve(condition.value);
|
|
33
|
+
case 'checkbox_checked': return locator.isChecked();
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
switch (condition.type) {
|
|
37
|
+
case 'extraction_created': return this.browser.extractions.some(e => !condition.key || e.key === condition.key);
|
|
38
|
+
case 'extraction_contains': return this.browser.extractions.some(e => (!condition.key || e.key === condition.key) && JSON.stringify(e.value).includes(this.variables.resolve(condition.value)));
|
|
39
|
+
case 'tab_count': return this.browser.context.pages().length === condition.count;
|
|
40
|
+
case 'extraction_count': {
|
|
41
|
+
const values = this.browser.extractions.filter(e => !condition.key || e.key === condition.key).flatMap(e => Array.isArray(e.value) ? e.value : []);
|
|
42
|
+
const size = new Set(values.map(v => JSON.stringify(v))).size;
|
|
43
|
+
return size >= condition.min && (condition.max === undefined || size <= condition.max);
|
|
44
|
+
}
|
|
45
|
+
case 'url_equals': return page.url() === this.variables.resolve(condition.value);
|
|
46
|
+
case 'url_contains': return page.url().includes(this.variables.resolve(condition.value));
|
|
47
|
+
case 'title_changed': return await page.title() !== condition.value;
|
|
48
|
+
case 'text_exists':
|
|
49
|
+
for (const frame of page.frames())
|
|
50
|
+
if (await frame.getByText(this.variables.resolve(condition.value), { exact: false }).filter({ visible: true }).count() > 0)
|
|
51
|
+
return true;
|
|
52
|
+
return false;
|
|
53
|
+
case 'text_disappeared':
|
|
54
|
+
for (const frame of page.frames())
|
|
55
|
+
if (await frame.getByText(this.variables.resolve(condition.value), { exact: false }).filter({ visible: true }).count() > 0)
|
|
56
|
+
return false;
|
|
57
|
+
return true;
|
|
58
|
+
case 'download_created': return this.browser.downloads.some(d => !condition.value || d.filename === condition.value);
|
|
59
|
+
case 'network_response': return this.browser.responses.some(r => r.time >= since && r.url.includes(condition.value) && (!condition.status || r.status === condition.status));
|
|
60
|
+
case 'page_changed': return (await this.observer.inspect(page)).hash !== condition.value;
|
|
61
|
+
}
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
async check(conditions, timeoutMs = 3000, since = 0) {
|
|
65
|
+
const deadline = Date.now() + timeoutMs;
|
|
66
|
+
let failed = [];
|
|
67
|
+
do {
|
|
68
|
+
if (this.browser.page.isClosed())
|
|
69
|
+
return { success: false, failed: conditions };
|
|
70
|
+
failed = [];
|
|
71
|
+
for (const condition of conditions) {
|
|
72
|
+
try {
|
|
73
|
+
if (!await this.one(condition, since))
|
|
74
|
+
failed.push(condition);
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
failed.push(condition);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
if (!failed.length)
|
|
81
|
+
return { success: true, failed };
|
|
82
|
+
await this.browser.page.waitForTimeout(60);
|
|
83
|
+
} while (Date.now() < deadline);
|
|
84
|
+
return { success: false, failed };
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=Verifier.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Verifier.js","sourceRoot":"","sources":["../../src/verification/Verifier.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type Plan } from '../actions/schema.js';
|
|
2
|
+
import type { PageState } from '../browser/types.js';
|
|
3
|
+
import type { TraceStore, Trace } from '../history/TraceStore.js';
|
|
4
|
+
export declare const normalizeIntent: (goal: string) => string;
|
|
5
|
+
export declare const structureHash: (state: PageState) => string;
|
|
6
|
+
export interface Workflow {
|
|
7
|
+
id: string;
|
|
8
|
+
origin: string;
|
|
9
|
+
path: string;
|
|
10
|
+
intent: string;
|
|
11
|
+
structure: string;
|
|
12
|
+
plan: Plan;
|
|
13
|
+
learnedFrom: string;
|
|
14
|
+
createdAt: number;
|
|
15
|
+
}
|
|
16
|
+
export declare class WorkflowEngine {
|
|
17
|
+
readonly store: TraceStore;
|
|
18
|
+
constructor(store: TraceStore);
|
|
19
|
+
match(goal: string, state: PageState): Workflow | undefined;
|
|
20
|
+
learn(trace: Trace, initial: PageState): Workflow | undefined;
|
|
21
|
+
list(): Record<string, import("node:sqlite").SQLOutputValue>[];
|
|
22
|
+
get(id: string): Workflow | undefined;
|
|
23
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { PlanSchema } from '../actions/schema.js';
|
|
3
|
+
export const normalizeIntent = (goal) => goal.toLowerCase().replace(/\s+/g, ' ').trim();
|
|
4
|
+
export const structureHash = (state) => createHash('sha256').update(JSON.stringify(state.elements.map(e => [e.role, e.name, e.type, e.required]))).digest('hex').slice(0, 20);
|
|
5
|
+
export class WorkflowEngine {
|
|
6
|
+
store;
|
|
7
|
+
constructor(store) {
|
|
8
|
+
this.store = store;
|
|
9
|
+
}
|
|
10
|
+
match(goal, state) {
|
|
11
|
+
const url = new URL(state.url);
|
|
12
|
+
const intent = normalizeIntent(goal), structure = structureHash(state);
|
|
13
|
+
const rows = this.store.db.prepare('SELECT workflow FROM workflows WHERE domain=? AND intent=? AND structure=?').all(url.origin, intent, structure);
|
|
14
|
+
for (const row of rows) {
|
|
15
|
+
const workflow = JSON.parse(row.workflow);
|
|
16
|
+
if (workflow.path === url.pathname) {
|
|
17
|
+
PlanSchema.parse(workflow.plan);
|
|
18
|
+
this.store.db.prepare('UPDATE workflows SET hits=hits+1 WHERE id=?').run(workflow.id);
|
|
19
|
+
return workflow;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
learn(trace, initial) {
|
|
25
|
+
if (trace.status !== 'completed' || !trace.actions.length)
|
|
26
|
+
return;
|
|
27
|
+
const actions = trace.actions.filter(result => result.success).map(result => result.action);
|
|
28
|
+
const completion = [...new Map(trace.completion.map(c => [JSON.stringify(c), c])).values()];
|
|
29
|
+
if (actions.length > 80 || completion.length > 12)
|
|
30
|
+
return;
|
|
31
|
+
if (actions.some(action => containsRef(action)))
|
|
32
|
+
return; // Only portable semantic workflows.
|
|
33
|
+
const url = new URL(initial.url), intent = normalizeIntent(trace.goal), structure = structureHash(initial);
|
|
34
|
+
const id = createHash('sha256').update([url.origin, url.pathname, intent, structure].join('\n')).digest('hex').slice(0, 16);
|
|
35
|
+
const plan = PlanSchema.parse({ goal: trace.goal, steps: trace.plans.flatMap(p => p.steps).slice(0, 12), actions, completion, continue: false });
|
|
36
|
+
const workflow = { id, origin: url.origin, path: url.pathname, intent, structure, plan, learnedFrom: trace.id, createdAt: Date.now() };
|
|
37
|
+
this.store.db.prepare('INSERT OR REPLACE INTO workflows(id,domain,intent,structure,workflow,hits) VALUES(?,?,?,?,?,COALESCE((SELECT hits FROM workflows WHERE id=?),0))').run(id, url.origin, intent, structure, JSON.stringify(workflow), id);
|
|
38
|
+
return workflow;
|
|
39
|
+
}
|
|
40
|
+
list() { return this.store.db.prepare('SELECT id,domain,intent,hits FROM workflows ORDER BY hits DESC').all(); }
|
|
41
|
+
get(id) { const row = this.store.db.prepare('SELECT workflow FROM workflows WHERE id=?').get(id); return row ? JSON.parse(row.workflow) : undefined; }
|
|
42
|
+
}
|
|
43
|
+
function containsRef(action) {
|
|
44
|
+
if ('target' in action && typeof action.target === 'string')
|
|
45
|
+
return true;
|
|
46
|
+
if ('condition' in action && containsRef(action.condition))
|
|
47
|
+
return true;
|
|
48
|
+
if ('verify' in action && action.verify?.some(containsRef))
|
|
49
|
+
return true;
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=WorkflowEngine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WorkflowEngine.js","sourceRoot":"","sources":["../../src/workflows/WorkflowEngine.ts"],"names":[],"mappings":"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"}
|
package/docs/ADOPTION.md
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# Adoption tracking
|
|
2
|
+
|
|
3
|
+
This project does not collect hidden product telemetry. Adoption is reviewed from
|
|
4
|
+
public repository and registry data, plus task reports that users choose to
|
|
5
|
+
share. Local browser interaction events only drive the dashboard visualization;
|
|
6
|
+
they are not an installation or usage counter.
|
|
7
|
+
|
|
8
|
+
## Public baseline — 24 September 2026
|
|
9
|
+
|
|
10
|
+
| Signal | Observed value | Source |
|
|
11
|
+
| --- | ---: | --- |
|
|
12
|
+
| GitHub stars | 5 | Public repository metadata |
|
|
13
|
+
| GitHub forks | 1 | Public repository metadata |
|
|
14
|
+
| Watchers | 0 | Public repository metadata |
|
|
15
|
+
| Listed contributors | 1 | Public contributors endpoint |
|
|
16
|
+
| Open issues / pull requests | 0 / 0 | Public GitHub API |
|
|
17
|
+
| Discussions | Disabled | Public repository metadata |
|
|
18
|
+
| GitHub releases / asset downloads | 0 / not applicable | Public releases endpoint |
|
|
19
|
+
| npm `free-computer-use@0.1.0` | Not published (registry returned 404) | npm registry query |
|
|
20
|
+
| Installations / community task reproductions | Installations not measured; no public reproductions documented | No installation telemetry; public issue list is empty and Discussions are disabled |
|
|
21
|
+
|
|
22
|
+
This is a dated baseline, not a growth claim. GitHub stars and forks are
|
|
23
|
+
secondary signals; they do not show that an installation or browser task
|
|
24
|
+
worked. No public issue or discussion currently records a user reproduction.
|
|
25
|
+
|
|
26
|
+
## Monthly review
|
|
27
|
+
|
|
28
|
+
Review these public signals on or after the 24th of each month, after a public
|
|
29
|
+
release exists:
|
|
30
|
+
|
|
31
|
+
1. Record stars, forks, listed contributors, open issues and pull requests.
|
|
32
|
+
2. Sum download counts for published GitHub Release assets. Record npm registry
|
|
33
|
+
downloads only after the package is published.
|
|
34
|
+
3. Review public bug reports for installation, provider, security, documentation
|
|
35
|
+
and workflow blockers. Link each confirmed problem to a roadmap acceptance
|
|
36
|
+
criterion and an issue; close the loop with a reproduced fix or a documented
|
|
37
|
+
limitation.
|
|
38
|
+
4. Record user-reported task reproductions only when the user chooses to share
|
|
39
|
+
them. Ask before quoting or publishing private feedback.
|
|
40
|
+
|
|
41
|
+
Do not infer installation counts from stars, add background analytics, or use
|
|
42
|
+
owner-only GitHub traffic reports as public adoption data. Keep reviews manual;
|
|
43
|
+
the repository's current policy does not allow GitHub Actions validation.
|
|
44
|
+
|
|
45
|
+
## Collection commands
|
|
46
|
+
|
|
47
|
+
These read public metadata and do not change the repository:
|
|
48
|
+
|
|
49
|
+
```sh
|
|
50
|
+
gh api repos/OthmaneBlial/FreeComputerUse --jq '{stars: .stargazers_count, forks: .forks_count, watchers: .subscribers_count, discussions: .has_discussions}'
|
|
51
|
+
gh api 'repos/OthmaneBlial/FreeComputerUse/issues?state=open&per_page=100' --jq '[.[] | select(has("pull_request") | not)] | length'
|
|
52
|
+
gh api 'repos/OthmaneBlial/FreeComputerUse/pulls?state=open&per_page=100' --jq 'length'
|
|
53
|
+
gh api 'repos/OthmaneBlial/FreeComputerUse/contributors?per_page=100' --jq 'length'
|
|
54
|
+
gh api 'repos/OthmaneBlial/FreeComputerUse/releases?per_page=100' --jq '[.[] | .assets[].download_count] | add // 0'
|
|
55
|
+
npm view free-computer-use@0.1.0 version
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
An npm 404 means no public version was found; it is not a zero-download
|
|
59
|
+
measurement. Do not query or publish private analytics to fill gaps.
|
|
60
|
+
|
|
61
|
+
**Next review:** 24 October 2026, or after the first public release if later.
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# Architecture
|
|
2
|
+
|
|
3
|
+
FreeComputerUse is a local Node.js process. The model proposes bounded browser
|
|
4
|
+
actions; the local policy and executor decide whether and how those actions run.
|
|
5
|
+
There is no hosted application server or background cloud sync in this design.
|
|
6
|
+
|
|
7
|
+
```mermaid
|
|
8
|
+
flowchart LR
|
|
9
|
+
CLI[CLI] --> CONFIG[Config]
|
|
10
|
+
UI[Local dashboard] --> API[Loopback HTTP API]
|
|
11
|
+
API --> AGENT[Agent]
|
|
12
|
+
CLI --> AGENT
|
|
13
|
+
AGENT --> OBS[DOM observer and compressor]
|
|
14
|
+
OBS --> PROVIDER[API provider or local CLI]
|
|
15
|
+
PROVIDER --> SCHEMA[Validated action plan]
|
|
16
|
+
SCHEMA --> POLICY[Origin and action policy]
|
|
17
|
+
POLICY --> EXEC[Playwright executor]
|
|
18
|
+
EXEC --> BROWSER[Local browser]
|
|
19
|
+
BROWSER --> VERIFY[Result verifier]
|
|
20
|
+
AGENT --> STORE[Local SQLite traces and workflows]
|
|
21
|
+
API --> PROFILE[Local profile vault]
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Request path
|
|
25
|
+
|
|
26
|
+
1. `src/cli/index.ts` loads environment configuration and starts a task, the
|
|
27
|
+
local dashboard, or a diagnostic. `src/config.ts` resolves provider settings,
|
|
28
|
+
token limits and the dedicated local data directory.
|
|
29
|
+
2. `src/agent/Agent.ts` coordinates observation, planning, execution, repair,
|
|
30
|
+
independent completion checks and trace updates. `Control` carries approval,
|
|
31
|
+
pause, resume and stop signals.
|
|
32
|
+
3. `Observer`, `DomExtractor` and `PageCompressor` collect a bounded DOM-based
|
|
33
|
+
page description. `LLMProvider` adapters return a structured plan; Zod
|
|
34
|
+
schemas validate it before `Executor` can act.
|
|
35
|
+
4. `policy.ts` applies site-origin and sensitive-action rules. `Browser.ts`
|
|
36
|
+
attaches Chromium request guards, and `NetworkGuardProxy.ts` checks proxied
|
|
37
|
+
HTTP(S)/WebSocket destinations. `Executor` performs the fixed action set;
|
|
38
|
+
it does not evaluate model-supplied JavaScript or shell commands.
|
|
39
|
+
5. `Verifier` checks task-specific completion evidence. `WorkflowEngine` stores
|
|
40
|
+
compatible learned workflows and replays them without another model request,
|
|
41
|
+
while retaining the regular permission checks.
|
|
42
|
+
|
|
43
|
+
## Local surfaces and data
|
|
44
|
+
|
|
45
|
+
- `src/server/index.ts` serves the dashboard only on loopback and checks its
|
|
46
|
+
session cookie, Host, Origin and CSRF token. `src/ui/` contains the browser UI.
|
|
47
|
+
- `ProfileStore` stores explicitly configured aliases; `TraceStore` stores run
|
|
48
|
+
history and learned workflows in SQLite. Browser profiles and downloads use
|
|
49
|
+
the same configured data directory. Details, retention and deletion are in
|
|
50
|
+
[Local data](LOCAL_DATA.md).
|
|
51
|
+
- API mode sends the page context needed to plan to the selected provider.
|
|
52
|
+
Subscription modes invoke the corresponding local provider CLI. Provider
|
|
53
|
+
routes and evidence are in [Providers](PROVIDERS.md) and the
|
|
54
|
+
[support matrix](SUPPORT_MATRIX.md).
|
|
55
|
+
- `lab/` is a set of deterministic local practice pages. `docs/` is the GitHub
|
|
56
|
+
Pages source and contains the public landing page and lab copy. It is not the
|
|
57
|
+
agent runtime.
|
|
58
|
+
|
|
59
|
+
## Change boundaries
|
|
60
|
+
|
|
61
|
+
Changes to a trust boundary need negative tests plus a matching allowed-path
|
|
62
|
+
test. Changes to a provider need contract tests and updated support evidence.
|
|
63
|
+
Changes to local storage need import-failure, permission and cleanup checks.
|
|
64
|
+
Run `npm run check` for types and `npm run validate` for the complete local
|
|
65
|
+
gate; the validation policy intentionally does not use GitHub Actions.
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# Measured validation
|
|
2
|
+
|
|
3
|
+
Provider-by-provider implementation, automated-test and live-evidence status is
|
|
4
|
+
tracked in the [support matrix](SUPPORT_MATRIX.md). This report records the
|
|
5
|
+
specific dated trials below; it does not establish general provider or website
|
|
6
|
+
compatibility.
|
|
7
|
+
|
|
8
|
+
Public suite measured 2026-09-18T16:52:19.246Z using real deepseek-flash, Node v25.9.0, Playwright 1.63.0.
|
|
9
|
+
|
|
10
|
+
14/14 public tasks passed their independent result checks. 14/14 compatible learned repeats passed with no provider installed and zero model calls. First runs used 30 successful browser actions, 18 model calls and 31,654 total tokens. Configured-price estimate: $0.006109 for those first runs.
|
|
11
|
+
|
|
12
|
+
| Scenario | Correctness | Actions | Calls | Tokens | Execution repairs | Learned repeat |
|
|
13
|
+
| --- | --- | ---: | ---: | ---: | ---: | --- |
|
|
14
|
+
| Product comparison / Books to Scrape | Pass | 1 | 1 | 3772 | 0 | Pass / 0 |
|
|
15
|
+
| Travel search / BlazeDemo | Pass | 4 | 1 | 1687 | 0 | Pass / 0 |
|
|
16
|
+
| Dashboard tables / The Internet | Pass | 1 | 1 | 2054 | 0 | Pass / 0 |
|
|
17
|
+
| Dropdown setting / The Internet | Pass | 1 | 1 | 1435 | 0 | Pass / 0 |
|
|
18
|
+
| Dynamic loading / The Internet | Pass | 3 | 1 | 1482 | 0 | Pass / 0 |
|
|
19
|
+
| Structured research / Quotes to Scrape | Pass | 1 | 1 | 2201 | 0 | Pass / 0 |
|
|
20
|
+
| Invoice download / public Northstar lab | Pass | 1 | 1 | 1470 | 0 | Pass / 0 |
|
|
21
|
+
| Revenue extraction / public Northstar lab | Pass | 1 | 1 | 1573 | 0 | Pass / 0 |
|
|
22
|
+
| Local preferences / public Northstar lab | Pass | 3 | 1 | 1657 | 0 | Pass / 0 |
|
|
23
|
+
| Persistent session / public Northstar lab | Pass | 1 | 1 | 1510 | 0 | Pass / 0 |
|
|
24
|
+
| Dynamic modal / public Northstar lab | Pass | 4 | 2 | 3123 | 0 | Pass / 0 |
|
|
25
|
+
| Embedded form / public Northstar lab | Pass | 3 | 1 | 1686 | 0 | Pass / 0 |
|
|
26
|
+
| Multiple tabs / public Northstar lab | Pass | 5 | 3 | 4936 | 1 | Pass / 0 |
|
|
27
|
+
| DOM repair / public Northstar lab | Pass | 1 | 2 | 3068 | 1 | Pass / 0 |
|
|
28
|
+
|
|
29
|
+
## Local integration suite
|
|
30
|
+
|
|
31
|
+
Measured 2026-09-18T16:52:23.922Z: 6/6 tasks and 6/6 provider-free learned repeats passed. First runs used 31 actions, 10 model calls and 16,392 tokens. Cases include synthetic search, contact form, travel wizard, product filtering, a multi-page application with upload/approval, and changed-control recovery.
|
|
32
|
+
|
|
33
|
+
## Method and limitations
|
|
34
|
+
|
|
35
|
+
Every scenario requires deterministic final conditions plus an independent oracle for extracted data, field values, saved settings, file bytes or browser/session outcome. Runtime completion alone is not accepted as task correctness. A repeat uses the same goal and compatible starting page; no general site-transfer claim is made. Website approvals remain enabled and are explicitly handled by the harness for its selected sandbox origin.
|
|
36
|
+
|
|
37
|
+
External sites are read-only scraping/automation sandboxes. Forms, settings, session login and injected DOM changes use our own synthetic lab. No messages to people, purchases, real accounts or real account changes occur. The session case manually seeds a fake session, then checks persistent cookies and localStorage after browser restart without logging in again.
|
|
38
|
+
|
|
39
|
+
One measured trial per case. Individual failures during development led to fixes for table row extraction, downloads, popup timing, schema correction and the demo cookie's expiry; these results describe the final trial, not all development attempts or a general success rate. The live JSON reports remain the source of truth. Execution repair counts do not include provider schema-correction calls; those calls are included in total calls/tokens.
|
|
40
|
+
|
|
41
|
+
Costs use configured peak rates ($0.30/M uncached input, $0.006/M cached input, $1.20/M output), verified against the [provider pricing page](https://api-docs.deepseek.com/quick_start/pricing/) on 2026-09-18. These are conservative estimates, not billing receipts; off-peak charges can be lower. Context reduction varies by site. Decorative CSS intentionally enlarged the original local/static fixtures used for the earlier measurements above; the redesigned public lab now uses shared styling. No screenshot-agent baseline, benchmark savings percentage or universal success rate was measured.
|
|
42
|
+
|
|
43
|
+
## Complex styled workflows and real-world research
|
|
44
|
+
|
|
45
|
+
The new lab has six complex browser-only practice cases. Three use separate HTML
|
|
46
|
+
documents: product details/comparison, journey results/itinerary, invoice details.
|
|
47
|
+
Local execution tests supply validated action plans, check independent data/state/
|
|
48
|
+
download oracles, and repeat all six without a provider. This validates execution
|
|
49
|
+
and reuse, not model planning.
|
|
50
|
+
|
|
51
|
+
Real Flash trials are in [the complex report](../artifacts/benchmark-complex-live.json)
|
|
52
|
+
and the dated subset reports beside it. Outcomes vary across trials; failures from
|
|
53
|
+
strict schema validation, guessed controls, intermediate criteria and budget
|
|
54
|
+
limits remain recorded. Do not substitute an earlier pass for a later failure.
|
|
55
|
+
All listed cases have independent correctness checks; a runtime completion alone
|
|
56
|
+
does not establish correctness.
|
|
57
|
+
|
|
58
|
+
[Real-world trials](../artifacts/benchmark-real-world.json) run the full sourced
|
|
59
|
+
GitHub and GOV.UK goals without supplied plans. GOV.UK completed and repeated
|
|
60
|
+
without a provider. The GitHub audit remained unsuccessful in the recorded trial,
|
|
61
|
+
including a repeated extraction loop. Other researched website goals are source
|
|
62
|
+
checks, not completed-agent evidence. See [the examples guide](USEFUL_EXAMPLES.md).
|
|
63
|
+
|
|
64
|
+
Reproduce with npm run benchmark -- --live and npm run benchmark:public. Both opt into API spend. Public selection: npm run benchmark:public -- --only=travel. Reports: [public](../artifacts/benchmark-public.json), [local](../artifacts/benchmark-live.json), [earlier demo measurements](../artifacts/demo-measurements.json).
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# Implementation notes
|
|
2
|
+
|
|
3
|
+
The eight MVP milestones are implemented: browser runtime, Flash integration,
|
|
4
|
+
verification/repair, metrics/diffs, workflow/replay, CLI, local UI, and validation.
|
|
5
|
+
The workspace and repository retain the name FreeComputerUse.
|
|
6
|
+
|
|
7
|
+
## Runtime decisions
|
|
8
|
+
|
|
9
|
+
The model produces strictly validated JSON actions, never code. The runtime owns
|
|
10
|
+
selectors, local variables, browser state, permission gates and final verification.
|
|
11
|
+
Known narrow tasks use local strategies; compatible learned tasks reuse semantic
|
|
12
|
+
actions. New page content needs another batch; ordinary clicks do not.
|
|
13
|
+
|
|
14
|
+
`Agent` asks permission for each new origin. The exported low-level `Browser`
|
|
15
|
+
blocks network requests by default; library callers must pass `allowedOrigins`
|
|
16
|
+
or explicitly choose `allowExternal`. Chromium DevTools Protocol interception
|
|
17
|
+
attaches to each page target before its first navigation and checks redirect
|
|
18
|
+
hops. Redirected documents use the same approval callback. A synthetic local
|
|
19
|
+
test on Chrome 154 confirms the first fast redirect from a new popup is checked
|
|
20
|
+
before the target server receives it. Browser HTTP(S) and WebSocket traffic also
|
|
21
|
+
uses a loopback-only proxy, which connects to the vetted address it resolved;
|
|
22
|
+
synthetic DNS-rebinding and plain WebSocket tests pass on system Chrome 154.
|
|
23
|
+
Chrome-originated approved WSS returns a frame through the proxy, while an
|
|
24
|
+
unapproved WSS origin is blocked before the target receives a TCP connection.
|
|
25
|
+
The test ignores errors from its generated local certificate. A separate
|
|
26
|
+
opt-in WSS smoke on 24 September 2026 connected to Postman Echo with Chrome's
|
|
27
|
+
normal TLS validation and received its fixed synthetic payload; this proves one
|
|
28
|
+
endpoint/runtime only. Other browser builds, network-specific NAT64 and
|
|
29
|
+
non-HTTP egress remain open in Phase 2.2 of `ROADMAP.md`.
|
|
30
|
+
Closing the active page stops its run and cancels a pending site approval. The
|
|
31
|
+
browser context stays open; the next task starts in a fresh tab. Closing a tab
|
|
32
|
+
through an action first switches the active page to the remaining tab.
|
|
33
|
+
|
|
34
|
+
Semantic references are stable for each live document and frame. Selector ranking
|
|
35
|
+
prefers role/name, label, placeholder, test ID, ID/name, text, CSS and observed DOM
|
|
36
|
+
path. Multiple matches fail for mutations. Extraction permits collections.
|
|
37
|
+
|
|
38
|
+
Plans and repairs have separate strict schemas. Repair preserves the successful
|
|
39
|
+
prefix and pending compatible actions. Invalid provider JSON gets at most one
|
|
40
|
+
schema correction, counted as another call. Execution repair, action/state loops,
|
|
41
|
+
navigation loops, step count and provider token admissions are bounded separately.
|
|
42
|
+
User-owned final criteria cannot be removed by model repair. Completion proves
|
|
43
|
+
those checks, not arbitrary semantic correctness; benchmark oracles also inspect
|
|
44
|
+
actual data and browser outcomes.
|
|
45
|
+
|
|
46
|
+
## Data and reuse
|
|
47
|
+
|
|
48
|
+
The profile sends alias names instead of values. Runtime resolution is local;
|
|
49
|
+
known values are redacted from serialized prompts/traces. SQLite stores private
|
|
50
|
+
run metadata, plans, actions, timing, provider usage and compatible workflows.
|
|
51
|
+
Successful actions are converted to semantic descriptors. Matching uses exact
|
|
52
|
+
origin/path, normalized intent and an initial control fingerprint. Changed tasks
|
|
53
|
+
or incompatible structures are not assumed to be the same workflow.
|
|
54
|
+
|
|
55
|
+
Replay disables the provider even if one is configured. It stops on failure.
|
|
56
|
+
Site and sensitive-action approvals still apply. Persistent browser contexts retain
|
|
57
|
+
localStorage and unexpired persistent cookies; session-only cookies can expire on
|
|
58
|
+
browser shutdown according to site policy. The public lab uses synthetic persistent
|
|
59
|
+
cookies to validate a restart without another simulated login.
|
|
60
|
+
|
|
61
|
+
## Progressive context and visual boundary
|
|
62
|
+
|
|
63
|
+
Observation exposes overview/controls/regions and bounded visible text/tables.
|
|
64
|
+
Batch transitions and repairs can use DOM diffs. Repeated failures escalate to
|
|
65
|
+
accessibility and a sanitized component HTML fragment. The UI preview and explicit
|
|
66
|
+
CLI screenshot are local. Images are not sent to the provider. Vision control,
|
|
67
|
+
canvas execution, multi-model routing and named external site adapters are planned.
|
|
68
|
+
|
|
69
|
+
The dashboard executes mouse movement over multiple real Playwright mouse events,
|
|
70
|
+
types short text progressively, and scrolls in increments. Trusted pointer telemetry
|
|
71
|
+
travels over the authenticated event stream; a cursor and click ring are drawn in
|
|
72
|
+
the dashboard, without injecting code into websites or including typed values.
|
|
73
|
+
Preview requests are serialized and refresh continuously while a task runs.
|
|
74
|
+
Cursor projection accounts for image scaling, letterboxing and iframe coordinates;
|
|
75
|
+
document IDs hide stale cursors on navigation. Approval guards are checked again
|
|
76
|
+
after movement, and pause/stop checkpoints interrupt movement and typing. Native
|
|
77
|
+
input types, passwords and long text retain direct entry. CLI/benchmark execution
|
|
78
|
+
keeps its original pace unless visual interaction is explicitly enabled.
|
|
79
|
+
|
|
80
|
+
## Evidence
|
|
81
|
+
|
|
82
|
+
`npm test` runs actual Chromium against deterministic local pages. Real provider
|
|
83
|
+
measurements are stored in `artifacts/demo-measurements.json`,
|
|
84
|
+
`artifacts/benchmark-live.json` and `artifacts/benchmark-public.json`. Scripted
|
|
85
|
+
fixture-provider runs are explicitly distinguished from model performance.
|
|
86
|
+
Public tasks use scraping/automation sandboxes and our browser-only simulation
|
|
87
|
+
lab; no real people, messages, payments or account mutations are involved.
|
|
88
|
+
See `README.md` and `SECURITY.md` for scope, installation and security limitations.
|
|
89
|
+
|
|
90
|
+
Provider implementation, mock-test coverage, dated live evidence and unverified
|
|
91
|
+
routes are listed separately in the [support matrix](SUPPORT_MATRIX.md). The
|
|
92
|
+
DeepSeek benchmark is a historical single-trial measurement, not proof that all
|
|
93
|
+
OpenAI-compatible endpoints work.
|