@4ier/neo 0.4.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.
@@ -0,0 +1,4 @@
1
+ (function(){"use strict";const M="__neo_capture_request",q=100*1024;function W(o,a=q){return o.length<=a?o:`${o.slice(0,a)}
2
+ [truncated ${o.length-a} bytes]`}function P(o,a=q){if(o==null)return o;if(typeof o=="string")return W(o,a);if(typeof o=="object")try{const c=JSON.stringify(o);return c&&c.length>a?W(c,a):o}catch{return W(String(o),a)}return W(String(o),a)}const $=/\.(?:js|css|png|jpe?g|gif|webp|ico|svg|woff2?|eot|ttf|otf|map)(?:[?#].*)?$/i,G=["google-analytics","googletagmanager","googlesyndication","doubleclick","sentry.io","hotjar.com","mixpanel.com","segment.com","segment.io","amplitude.com","fullstory.com","intercom.io","crisp.chat","hubspot.com","clarity.ms","newrelic.com","datadoghq.com","bugsnag.com","logrocket.io","heapanalytics.com","posthog.com","connect.facebook.net","bat.bing.com","mc.yandex.ru","splunkcloud.com","adora-cdn.com","transcend-cdn.com","w3-reporting","proxsee.pscp.tv","video.twimg.com","abs.twimg.com","pbs.twimg.com","googlevideo.com","ytimg.com","cdn.jsdelivr.net","cdnjs.cloudflare.com","unpkg.com","fonts.googleapis.com","fonts.gstatic.com","analytics.google.com","stats.g.doubleclick.net","pagead2.googlesyndication.com","adservice.google.com","static.cloudflareinsights.com","rum.browser-intake-datadoghq.com","app.launchdarkly.com","events.launchdarkly.com","api.statsig.com","featuregates.org","hdslb.com","bilivideo.com","bilivideo.cn","biliapi.net","data.bilibili.com","cm.bilibili.com","a-cdn.anthropic.com","a-cdn.claude.ai","statsig.anthropic.com","api.honeycomb.io"],j=new Set(["chrome-extension:","moz-extension:","safari-extension:","data:","blob:"]);function X(o,a={},c){try{const i=new URL(o,c||"http://localhost"),m=i.href.toLowerCase(),T=i.pathname.toLowerCase(),b=i.hostname.toLowerCase();if(j.has(i.protocol)||$.test(T))return!0;const H=`${m} ${b} ${JSON.stringify(a).toLowerCase()}`;return G.some(p=>H.includes(p))}catch{return!0}}function z(o,a,c){try{const i=new URL(a,c||"http://localhost");return`${o} ${i.pathname}`}catch{return`${o} ${a}`}}function g(o,a=q){return o.length<=a?o:`${o.slice(0,a)}
3
+ [truncated ${o.length-a} bytes]`}function I(o,a){const c=g(o);if((a||"").toLowerCase().includes("application/json")||o.startsWith("{")&&o.endsWith("}")||o.startsWith("[")&&o.endsWith("]"))try{return JSON.parse(o)}catch{return c}return c}function J(o){const a={};for(const c of o.split(`\r
4
+ `)){const i=c.indexOf(":");i<=0||(a[c.slice(0,i).trim()]=c.slice(i+1).trim())}return a}function D(o){try{return new URL(o).hostname}catch{return"unknown"}}function Y(o,a){try{return new URL(o,a).toString()}catch{return String(o)}}function K(o){if(o.id)return`#${o.id}`;const a=o.tagName.toLowerCase(),c=o.className&&typeof o.className=="string"?"."+o.className.trim().split(/\s+/).slice(0,2).join("."):"";return a+c}function F(o){return(o||"").trim().slice(0,50)||void 0}const O=new Map,k=6e4,V=3;function Q(o,a){const c=z(o,a,location.href),i=Date.now(),m=O.get(c);if(!m||i-m.lastTime>k){if(O.set(c,{count:1,lastTime:i}),O.size>200)for(const[T,b]of O)i-b.lastTime>k*2&&O.delete(T);return!1}return m.count++,m.lastTime=i,m.count>V}if(!window.__neoInterceptorInstalled){let o=function(e){return K({id:e.id,tagName:e.tagName,className:e.className})},a=function(e){return F(e.textContent)},c=function(){if(!S)return;if(Date.now()-S.timestamp>ee){S=null;return}return{...S,event:S.event}},i=function(){return typeof crypto<"u"&&typeof crypto.randomUUID=="function"?crypto.randomUUID():`neo-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,10)}`},m=function(e){return Y(e,location.href)},T=function(e,t={}){return X(e,t,location.href)},b=function(e){const t={};if(!e)return t;const n=e instanceof Headers?e.entries():Object.entries(e);for(const[s,u]of n)t[s]=u;return t},H=function(e){if(e!=null){if(typeof e=="string")return g(e);if(e instanceof URLSearchParams)return g(e.toString());if(e instanceof FormData){const t={};return e.forEach((n,s)=>{t[s]=String(n)}),t}if(e instanceof Blob)return`[Blob ${e.size} bytes]`;if(e instanceof ArrayBuffer)try{return g(new TextDecoder().decode(new Uint8Array(e)))}catch{return"[arraybuffer body]"}if(ArrayBuffer.isView(e))try{return g(new TextDecoder().decode(e))}catch{return"[typed array body]"}if(typeof e=="object")try{return P(e)}catch{return"[unserializable body]"}return g(String(e))}},p=function(e){if(!Q(e.method,e.url))try{window.postMessage({type:M,payload:e},"*")}catch{}},Z=function(e){const t=e.getResponseHeader("content-type")||void 0;let n="";try{(e.responseType===""||e.responseType==="text"||e.responseType==="json")&&(n=typeof e.responseText=="string"?e.responseText:"")}catch{n=""}return{statusText:e.status,headers:J(e.getAllResponseHeaders()),body:n?I(n,t):void 0}},A=function(e){return typeof e=="string"?g(e):e instanceof Blob?`[Blob ${e.size} bytes]`:e instanceof ArrayBuffer?`[ArrayBuffer ${e.byteLength} bytes]`:ArrayBuffer.isView(e)?`[TypedArray ${e.byteLength} bytes]`:String(e)},U=function(e){if(e.startsWith("{")&&e.endsWith("}")||e.startsWith("[")&&e.endsWith("]"))try{return JSON.parse(e)}catch{}return e},v=function(e){const t=Date.now();return t-e.msgWindowStart>se&&(e.msgCount=0,e.msgWindowStart=t),e.msgCount++,e.msgCount>ae};window.__neoInterceptorInstalled=!0;let S=null;const ee=2e3;document.addEventListener("click",e=>{const t=e.target;!t||!t.tagName||(S={event:"click",selector:o(t),text:a(t),timestamp:Date.now()})},!0),document.addEventListener("submit",e=>{const t=e.target;t&&(S={event:"submit",selector:o(t),text:void 0,timestamp:Date.now()})},!0);const B=window.fetch.bind(window),N=XMLHttpRequest.prototype,x=N.open,te=N.send,oe=N.setRequestHeader,R="__neo_meta";async function ne(e){if(e instanceof Blob)try{const t=await e.text();return I(t,e.type)}catch{return"[unreadable blob]"}return H(e)}window.fetch=async(...e)=>{const t=e[1],n=e[0],s=Date.now(),u=performance.now(),r=m(n instanceof Request?n.url:n),y=(typeof n!="string"&&!(n instanceof URL)&&(t!=null&&t.method)?t.method:n instanceof Request?n.method:(t==null?void 0:t.method)||"GET").toUpperCase(),f=b(n instanceof Request?n.headers:t==null?void 0:t.headers),l=Object.keys(f).length?f:t!=null&&t.headers?b(t.headers):{};if(T(r,l))return B(n,t);const h=await ne(n instanceof Request?await n.clone().text():t==null?void 0:t.body);try{const d=await B(n,t),w=Math.max(0,Math.round(performance.now()-u));let C;try{const ie=await d.clone().text();C=I(ie,d.headers.get("content-type")||void 0)}catch{C="[unreadable response body]"}const L={id:i(),timestamp:s,domain:D(r),url:r,method:y,requestHeaders:l,requestBody:h,responseStatus:d.status,responseHeaders:b(d.headers),responseBody:C,duration:w,trigger:c(),tabId:-1,tabUrl:location.href,source:"fetch"};return p(L),d}catch(d){const w=Math.max(0,Math.round(performance.now()-u)),C=d instanceof Error?d.message:String(d),L={id:i(),timestamp:s,domain:D(r),url:r,method:y,requestHeaders:l,requestBody:h,responseStatus:0,responseHeaders:{},responseBody:g(C),duration:w,trigger:c(),tabId:-1,tabUrl:location.href,source:"fetch"};throw p(L),d}},x.call,N.open=function(t,n,...s){const u={method:(t==null?void 0:t.toUpperCase())||"GET",url:m(n),headers:{},body:void 0,startedAt:0,startPerf:0,skipped:!1,finished:!1};return this[R]=u,x.apply(this,[t,n,...s])},N.setRequestHeader=function(t,n){const s=this[R];return s&&(s.headers[t]=n),oe.call(this,t,n)},N.send=function(t){const s=this[R]||{method:"GET",url:m(""),headers:{},body:void 0,startedAt:0,startPerf:0,skipped:!1,finished:!1};s.body=H(t),s.startedAt=Date.now(),s.startPerf=performance.now(),s.skipped=T(s.url,s.headers),s.finished=!1,this[R]=s;const u=async()=>{const r=this[R];if(!r||r.finished||r.skipped)return;r.finished=!0;const{statusText:y,headers:f,body:l}=Z(this),h=Math.max(0,Math.round(performance.now()-r.startPerf)),d={id:i(),timestamp:r.startedAt,domain:D(r.url),url:r.url,method:r.method,requestHeaders:r.headers,requestBody:r.body,responseStatus:y,responseHeaders:f,responseBody:l,duration:h,trigger:c(),tabId:-1,tabUrl:location.href,source:"xhr"};p(d)};return this.addEventListener("loadend",()=>{u()}),this.addEventListener("error",()=>{u()}),this.addEventListener("abort",()=>{u()}),te.call(this,t)};const E=window.WebSocket,re="__neo_ws_meta",se=1e4,ae=20;window.WebSocket=function(t,n){const s=n!==void 0?new E(t,n):new E(t),u=typeof t=="string"?t:t.toString(),r={url:u,domain:D(u.replace(/^ws(s)?:\/\//,"http$1://")),connectedAt:Date.now(),msgCount:0,msgWindowStart:Date.now()};s[re]=r,s.addEventListener("open",()=>{const f={id:i(),timestamp:Date.now(),domain:r.domain,url:r.url,method:"WS_OPEN",requestHeaders:{},requestBody:n?{protocols:Array.isArray(n)?n:[n]}:void 0,responseStatus:101,responseHeaders:{},responseBody:void 0,duration:Date.now()-r.connectedAt,tabId:-1,tabUrl:location.href,source:"websocket"};p(f)}),s.addEventListener("message",f=>{if(v(r))return;const l=A(f.data),h={id:i(),timestamp:Date.now(),domain:r.domain,url:r.url,method:"WS_RECV",requestHeaders:{},requestBody:void 0,responseStatus:200,responseHeaders:{},responseBody:U(l),duration:0,tabId:-1,tabUrl:location.href,source:"websocket"};p(h)}),s.addEventListener("close",f=>{const l={id:i(),timestamp:Date.now(),domain:r.domain,url:r.url,method:"WS_CLOSE",requestHeaders:{},requestBody:void 0,responseStatus:f.code,responseHeaders:{},responseBody:f.reason||void 0,duration:Date.now()-r.connectedAt,tabId:-1,tabUrl:location.href,source:"websocket"};p(l)}),s.addEventListener("error",()=>{const f={id:i(),timestamp:Date.now(),domain:r.domain,url:r.url,method:"WS_ERROR",requestHeaders:{},requestBody:void 0,responseStatus:0,responseHeaders:{},responseBody:"[WebSocket error]",duration:Date.now()-r.connectedAt,tabId:-1,tabUrl:location.href,source:"websocket"};p(f)});const y=s.send.bind(s);return s.send=function(l){if(!v(r)){const h=A(l),d={id:i(),timestamp:Date.now(),domain:r.domain,url:r.url,method:"WS_SEND",requestHeaders:{},requestBody:U(h),responseStatus:0,responseHeaders:{},responseBody:void 0,duration:0,tabId:-1,tabUrl:location.href,source:"websocket"};p(d)}return y(l)},s},window.WebSocket.prototype=E.prototype,Object.defineProperties(window.WebSocket,{CONNECTING:{value:E.CONNECTING},OPEN:{value:E.OPEN},CLOSING:{value:E.CLOSING},CLOSED:{value:E.CLOSED}});const _=window.EventSource;_&&(window.EventSource=function(t,n){const s=typeof t=="string"?t:t.toString(),u=n?new _(t,n):new _(t),r=D(s),y=Date.now();let f=0;const l=30;return u.addEventListener("open",()=>{p({id:i(),timestamp:Date.now(),domain:r,url:s,method:"SSE_OPEN",requestHeaders:{},requestBody:n!=null&&n.withCredentials?{withCredentials:!0}:void 0,responseStatus:200,responseHeaders:{},responseBody:void 0,duration:Date.now()-y,tabId:-1,tabUrl:location.href,source:"eventsource"})}),u.addEventListener("message",h=>{if(f++,f>l)return;const d=typeof h.data=="string"?h.data:String(h.data);let w=d;if(d.startsWith("{")||d.startsWith("["))try{w=JSON.parse(d)}catch{}p({id:i(),timestamp:Date.now(),domain:r,url:s,method:"SSE_MSG",requestHeaders:{},requestBody:void 0,responseStatus:200,responseHeaders:{},responseBody:typeof w=="string"?g(w):w,duration:Date.now()-y,tabId:-1,tabUrl:location.href,source:"eventsource"})}),u.addEventListener("error",()=>{p({id:i(),timestamp:Date.now(),domain:r,url:s,method:"SSE_ERROR",requestHeaders:{},requestBody:void 0,responseStatus:0,responseHeaders:{},responseBody:"[EventSource error]",duration:Date.now()-y,tabId:-1,tabUrl:location.href,source:"eventsource"})}),u},window.EventSource.prototype=_.prototype,Object.defineProperties(window.EventSource,{CONNECTING:{value:_.CONNECTING},OPEN:{value:_.OPEN},CLOSED:{value:_.CLOSED}}))}})();
@@ -0,0 +1,51 @@
1
+ {
2
+ "manifest_version": 3,
3
+ "name": "Neo",
4
+ "version": "0.4.0",
5
+ "description": "Neo: capture fetch/XHR/WebSocket/SSE traffic with DOM trigger tracking, generate API schemas, execute from CLI.",
6
+ "permissions": [
7
+ "tabs"
8
+ ],
9
+ "host_permissions": [
10
+ "<all_urls>"
11
+ ],
12
+ "background": {
13
+ "service_worker": "background.js"
14
+ },
15
+ "action": {
16
+ "default_title": "Neo"
17
+ },
18
+ "content_scripts": [
19
+ {
20
+ "matches": [
21
+ "<all_urls>"
22
+ ],
23
+ "js": [
24
+ "inject.js"
25
+ ],
26
+ "run_at": "document_start",
27
+ "all_frames": true,
28
+ "world": "MAIN"
29
+ },
30
+ {
31
+ "matches": [
32
+ "<all_urls>"
33
+ ],
34
+ "js": [
35
+ "content.js"
36
+ ],
37
+ "run_at": "document_start",
38
+ "all_frames": true
39
+ }
40
+ ],
41
+ "web_accessible_resources": [
42
+ {
43
+ "resources": [
44
+ "inject.js"
45
+ ],
46
+ "matches": [
47
+ "<all_urls>"
48
+ ]
49
+ }
50
+ ]
51
+ }
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "@4ier/neo",
3
+ "version": "0.4.0",
4
+ "description": "Turn any website into an AI-callable API. Passive traffic capture, API schema generation, and execution.",
5
+ "type": "module",
6
+ "scripts": {
7
+ "build": "NEO_ENTRY=background vite build && NEO_ENTRY=content vite build && NEO_ENTRY=inject vite build",
8
+ "test": "node tools/neo.test.cjs"
9
+ },
10
+ "bin": {
11
+ "neo": "tools/neo.cjs"
12
+ },
13
+ "files": [
14
+ "tools/neo.cjs",
15
+ "extension-dist/background.js",
16
+ "extension-dist/content.js",
17
+ "extension-dist/inject.js",
18
+ "extension-dist/manifest.json"
19
+ ],
20
+ "keywords": [
21
+ "browser",
22
+ "api",
23
+ "chrome",
24
+ "cdp",
25
+ "automation",
26
+ "web-scraping",
27
+ "ai-agent",
28
+ "openclaw"
29
+ ],
30
+ "repository": {
31
+ "type": "git",
32
+ "url": "https://github.com/4ier/neo.git"
33
+ },
34
+ "license": "MIT",
35
+ "author": "4ier",
36
+ "dependencies": {
37
+ "ws": "^8.19.0"
38
+ },
39
+ "devDependencies": {
40
+ "@types/chrome": "^0.0.303",
41
+ "@types/node": "^22.10.5",
42
+ "dexie": "^4.0.11",
43
+ "typescript": "^5.8.2",
44
+ "vite": "^6.0.0"
45
+ }
46
+ }