lobster-cli 0.1.0 → 0.3.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 (45) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +148 -268
  3. package/dist/agent/core.js +63 -0
  4. package/dist/agent/core.js.map +1 -1
  5. package/dist/agent/index.js +63 -0
  6. package/dist/agent/index.js.map +1 -1
  7. package/dist/browser/chrome-attach.js +102 -0
  8. package/dist/browser/chrome-attach.js.map +1 -0
  9. package/dist/browser/dom/compact-snapshot.js +162 -0
  10. package/dist/browser/dom/compact-snapshot.js.map +1 -0
  11. package/dist/browser/dom/index.js +160 -0
  12. package/dist/browser/dom/index.js.map +1 -1
  13. package/dist/browser/index.js +1201 -70
  14. package/dist/browser/index.js.map +1 -1
  15. package/dist/browser/manager.js +443 -11
  16. package/dist/browser/manager.js.map +1 -1
  17. package/dist/browser/page-adapter.js +370 -1
  18. package/dist/browser/page-adapter.js.map +1 -1
  19. package/dist/browser/profiles.js +238 -0
  20. package/dist/browser/profiles.js.map +1 -0
  21. package/dist/browser/semantic-find.js +152 -0
  22. package/dist/browser/semantic-find.js.map +1 -0
  23. package/dist/browser/stealth.js +187 -0
  24. package/dist/browser/stealth.js.map +1 -0
  25. package/dist/config/index.js +8 -1
  26. package/dist/config/index.js.map +1 -1
  27. package/dist/config/schema.js +8 -1
  28. package/dist/config/schema.js.map +1 -1
  29. package/dist/doc/index.js +31715 -0
  30. package/dist/doc/index.js.map +1 -0
  31. package/dist/domain-guard.js +103 -0
  32. package/dist/domain-guard.js.map +1 -0
  33. package/dist/index.js +32914 -262
  34. package/dist/index.js.map +1 -1
  35. package/dist/lib.js +1488 -241
  36. package/dist/lib.js.map +1 -1
  37. package/dist/llm/client.js +63 -0
  38. package/dist/llm/client.js.map +1 -1
  39. package/dist/llm/index.js +63 -0
  40. package/dist/llm/index.js.map +1 -1
  41. package/dist/llm/openai-client.js +63 -0
  42. package/dist/llm/openai-client.js.map +1 -1
  43. package/dist/router/index.js +925 -61
  44. package/dist/router/index.js.map +1 -1
  45. package/package.json +16 -2
@@ -0,0 +1,103 @@
1
+ // src/domain-guard.ts
2
+ var DEFAULT_BLOCK_MESSAGE = "This domain is not allowed by the current configuration.";
3
+ var DomainGuard = class {
4
+ allow;
5
+ block;
6
+ message;
7
+ matchSubs;
8
+ constructor(config = {}) {
9
+ this.allow = (config.allowDomains || []).map((d) => d.toLowerCase().replace(/^www\./, ""));
10
+ this.block = (config.blockDomains || []).map((d) => d.toLowerCase().replace(/^www\./, ""));
11
+ this.message = config.blockMessage || DEFAULT_BLOCK_MESSAGE;
12
+ this.matchSubs = config.matchSubdomains ?? true;
13
+ }
14
+ /**
15
+ * Check if a URL is allowed. Returns true if allowed, throws if blocked.
16
+ */
17
+ check(url) {
18
+ if (this.allow.length === 0 && this.block.length === 0) return true;
19
+ const domain = this.extractDomain(url);
20
+ if (!domain) return true;
21
+ if (this.allow.length > 0) {
22
+ if (!this.matches(domain, this.allow)) {
23
+ throw new DomainBlockedError(domain, this.message);
24
+ }
25
+ return true;
26
+ }
27
+ if (this.block.length > 0) {
28
+ if (this.matches(domain, this.block)) {
29
+ throw new DomainBlockedError(domain, this.message);
30
+ }
31
+ return true;
32
+ }
33
+ return true;
34
+ }
35
+ /**
36
+ * Check without throwing — returns { allowed, domain, message }.
37
+ */
38
+ test(url) {
39
+ const domain = this.extractDomain(url);
40
+ if (!domain) return { allowed: true, domain: "" };
41
+ try {
42
+ this.check(url);
43
+ return { allowed: true, domain };
44
+ } catch (err) {
45
+ if (err instanceof DomainBlockedError) {
46
+ return { allowed: false, domain, message: err.message };
47
+ }
48
+ return { allowed: true, domain };
49
+ }
50
+ }
51
+ /**
52
+ * Check if domain matches any pattern in the list.
53
+ */
54
+ matches(domain, patterns) {
55
+ for (const pattern of patterns) {
56
+ if (domain === pattern) return true;
57
+ if (this.matchSubs && domain.endsWith("." + pattern)) return true;
58
+ }
59
+ return false;
60
+ }
61
+ /**
62
+ * Extract domain from URL, stripping www. prefix.
63
+ */
64
+ extractDomain(url) {
65
+ try {
66
+ const parsed = new URL(url.startsWith("http") ? url : "https://" + url);
67
+ return parsed.hostname.toLowerCase().replace(/^www\./, "");
68
+ } catch {
69
+ return "";
70
+ }
71
+ }
72
+ /**
73
+ * Whether any restrictions are active.
74
+ */
75
+ get isRestricted() {
76
+ return this.allow.length > 0 || this.block.length > 0;
77
+ }
78
+ /**
79
+ * Get list of allowed domains (empty = all allowed).
80
+ */
81
+ get allowedDomains() {
82
+ return [...this.allow];
83
+ }
84
+ /**
85
+ * Get list of blocked domains.
86
+ */
87
+ get blockedDomains() {
88
+ return [...this.block];
89
+ }
90
+ };
91
+ var DomainBlockedError = class extends Error {
92
+ domain;
93
+ constructor(domain, message) {
94
+ super(message);
95
+ this.name = "DomainBlockedError";
96
+ this.domain = domain;
97
+ }
98
+ };
99
+ export {
100
+ DomainBlockedError,
101
+ DomainGuard
102
+ };
103
+ //# sourceMappingURL=domain-guard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/domain-guard.ts"],"sourcesContent":["/**\n * Domain Guard — restrict which websites LobsterCLI can operate on.\n *\n * Three modes:\n * - No config: works on all websites (default)\n * - allowDomains: whitelist — ONLY these sites work\n * - blockDomains: blacklist — everything EXCEPT these sites works\n *\n * Usage (library):\n * import { DomainGuard } from 'lobster-cli'\n * const guard = new DomainGuard({ allowDomains: ['bloomberg.com', 'yahoo.com'] })\n * guard.check('https://bloomberg.com/markets') // → ok\n * guard.check('https://reddit.com') // → throws\n *\n * Usage (config):\n * lobster config set domains.allow \"bloomberg.com,yahoo.com\"\n * lobster config set domains.blockMessage \"This tool only works on finance sites.\"\n */\n\nexport interface DomainGuardConfig {\n /** Whitelist — only these domains are allowed. Empty = allow all. */\n allowDomains?: string[];\n /** Blacklist — these domains are blocked. Ignored if allowDomains is set. */\n blockDomains?: string[];\n /** Custom message shown when a domain is blocked. */\n blockMessage?: string;\n /** Allow subdomains to match (e.g., \"yahoo.com\" matches \"finance.yahoo.com\"). Default: true */\n matchSubdomains?: boolean;\n}\n\nconst DEFAULT_BLOCK_MESSAGE = 'This domain is not allowed by the current configuration.';\n\nexport class DomainGuard {\n private allow: string[];\n private block: string[];\n private message: string;\n private matchSubs: boolean;\n\n constructor(config: DomainGuardConfig = {}) {\n this.allow = (config.allowDomains || []).map(d => d.toLowerCase().replace(/^www\\./, ''));\n this.block = (config.blockDomains || []).map(d => d.toLowerCase().replace(/^www\\./, ''));\n this.message = config.blockMessage || DEFAULT_BLOCK_MESSAGE;\n this.matchSubs = config.matchSubdomains ?? true;\n }\n\n /**\n * Check if a URL is allowed. Returns true if allowed, throws if blocked.\n */\n check(url: string): true {\n // No restrictions configured — allow everything\n if (this.allow.length === 0 && this.block.length === 0) return true;\n\n const domain = this.extractDomain(url);\n if (!domain) return true; // Can't parse = allow (for local files, etc.)\n\n // Whitelist mode: only allowed domains pass\n if (this.allow.length > 0) {\n if (!this.matches(domain, this.allow)) {\n throw new DomainBlockedError(domain, this.message);\n }\n return true;\n }\n\n // Blacklist mode: blocked domains fail\n if (this.block.length > 0) {\n if (this.matches(domain, this.block)) {\n throw new DomainBlockedError(domain, this.message);\n }\n return true;\n }\n\n return true;\n }\n\n /**\n * Check without throwing — returns { allowed, domain, message }.\n */\n test(url: string): { allowed: boolean; domain: string; message?: string } {\n const domain = this.extractDomain(url);\n if (!domain) return { allowed: true, domain: '' };\n\n try {\n this.check(url);\n return { allowed: true, domain };\n } catch (err) {\n if (err instanceof DomainBlockedError) {\n return { allowed: false, domain, message: err.message };\n }\n return { allowed: true, domain };\n }\n }\n\n /**\n * Check if domain matches any pattern in the list.\n */\n private matches(domain: string, patterns: string[]): boolean {\n for (const pattern of patterns) {\n if (domain === pattern) return true;\n if (this.matchSubs && domain.endsWith('.' + pattern)) return true;\n }\n return false;\n }\n\n /**\n * Extract domain from URL, stripping www. prefix.\n */\n private extractDomain(url: string): string {\n try {\n const parsed = new URL(url.startsWith('http') ? url : 'https://' + url);\n return parsed.hostname.toLowerCase().replace(/^www\\./, '');\n } catch {\n return '';\n }\n }\n\n /**\n * Whether any restrictions are active.\n */\n get isRestricted(): boolean {\n return this.allow.length > 0 || this.block.length > 0;\n }\n\n /**\n * Get list of allowed domains (empty = all allowed).\n */\n get allowedDomains(): string[] {\n return [...this.allow];\n }\n\n /**\n * Get list of blocked domains.\n */\n get blockedDomains(): string[] {\n return [...this.block];\n }\n}\n\nexport class DomainBlockedError extends Error {\n public readonly domain: string;\n\n constructor(domain: string, message: string) {\n super(message);\n this.name = 'DomainBlockedError';\n this.domain = domain;\n }\n}\n"],"mappings":";AA8BA,IAAM,wBAAwB;AAEvB,IAAM,cAAN,MAAkB;AAAA,EACf;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAER,YAAY,SAA4B,CAAC,GAAG;AAC1C,SAAK,SAAS,OAAO,gBAAgB,CAAC,GAAG,IAAI,OAAK,EAAE,YAAY,EAAE,QAAQ,UAAU,EAAE,CAAC;AACvF,SAAK,SAAS,OAAO,gBAAgB,CAAC,GAAG,IAAI,OAAK,EAAE,YAAY,EAAE,QAAQ,UAAU,EAAE,CAAC;AACvF,SAAK,UAAU,OAAO,gBAAgB;AACtC,SAAK,YAAY,OAAO,mBAAmB;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,KAAmB;AAEvB,QAAI,KAAK,MAAM,WAAW,KAAK,KAAK,MAAM,WAAW,EAAG,QAAO;AAE/D,UAAM,SAAS,KAAK,cAAc,GAAG;AACrC,QAAI,CAAC,OAAQ,QAAO;AAGpB,QAAI,KAAK,MAAM,SAAS,GAAG;AACzB,UAAI,CAAC,KAAK,QAAQ,QAAQ,KAAK,KAAK,GAAG;AACrC,cAAM,IAAI,mBAAmB,QAAQ,KAAK,OAAO;AAAA,MACnD;AACA,aAAO;AAAA,IACT;AAGA,QAAI,KAAK,MAAM,SAAS,GAAG;AACzB,UAAI,KAAK,QAAQ,QAAQ,KAAK,KAAK,GAAG;AACpC,cAAM,IAAI,mBAAmB,QAAQ,KAAK,OAAO;AAAA,MACnD;AACA,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,KAAK,KAAqE;AACxE,UAAM,SAAS,KAAK,cAAc,GAAG;AACrC,QAAI,CAAC,OAAQ,QAAO,EAAE,SAAS,MAAM,QAAQ,GAAG;AAEhD,QAAI;AACF,WAAK,MAAM,GAAG;AACd,aAAO,EAAE,SAAS,MAAM,OAAO;AAAA,IACjC,SAAS,KAAK;AACZ,UAAI,eAAe,oBAAoB;AACrC,eAAO,EAAE,SAAS,OAAO,QAAQ,SAAS,IAAI,QAAQ;AAAA,MACxD;AACA,aAAO,EAAE,SAAS,MAAM,OAAO;AAAA,IACjC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,QAAQ,QAAgB,UAA6B;AAC3D,eAAW,WAAW,UAAU;AAC9B,UAAI,WAAW,QAAS,QAAO;AAC/B,UAAI,KAAK,aAAa,OAAO,SAAS,MAAM,OAAO,EAAG,QAAO;AAAA,IAC/D;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKQ,cAAc,KAAqB;AACzC,QAAI;AACF,YAAM,SAAS,IAAI,IAAI,IAAI,WAAW,MAAM,IAAI,MAAM,aAAa,GAAG;AACtE,aAAO,OAAO,SAAS,YAAY,EAAE,QAAQ,UAAU,EAAE;AAAA,IAC3D,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,eAAwB;AAC1B,WAAO,KAAK,MAAM,SAAS,KAAK,KAAK,MAAM,SAAS;AAAA,EACtD;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,iBAA2B;AAC7B,WAAO,CAAC,GAAG,KAAK,KAAK;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,iBAA2B;AAC7B,WAAO,CAAC,GAAG,KAAK,KAAK;AAAA,EACvB;AACF;AAEO,IAAM,qBAAN,cAAiC,MAAM;AAAA,EAC5B;AAAA,EAEhB,YAAY,QAAgB,SAAiB;AAC3C,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,SAAS;AAAA,EAChB;AACF;","names":[]}