orangeslice 1.4.0 → 1.4.2

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/dist/b2b.d.ts CHANGED
@@ -18,7 +18,7 @@ export interface QueryResult<T = Record<string, unknown>> {
18
18
  * @example
19
19
  * const companies = await b2b.sql<Company[]>("SELECT * FROM linkedin_company WHERE domain = 'stripe.com'");
20
20
  */
21
- export declare function sql<T = Record<string, unknown>[]>(query: string): Promise<T>;
21
+ export declare function sql<T = Record<string, unknown>[]>(sqlQuery: string): Promise<T>;
22
22
  /**
23
23
  * Execute a SQL query and get full result with metadata
24
24
  */
package/dist/b2b.js CHANGED
@@ -14,6 +14,30 @@ let config = {
14
14
  // Create queue and rate limiter with defaults
15
15
  let queue = (0, queue_1.createQueue)(config.concurrency);
16
16
  let rateLimiter = (0, queue_1.createRateLimiter)(config.minDelayMs);
17
+ /**
18
+ * Helper to make POST request, handling redirects manually
19
+ * (Node.js fetch has issues with POST body on redirects)
20
+ */
21
+ async function fetchWithRedirect(url, body) {
22
+ let response = await fetch(url, {
23
+ method: "POST",
24
+ headers: { "Content-Type": "application/json" },
25
+ body,
26
+ redirect: "manual",
27
+ });
28
+ // Handle redirect manually - re-POST to the new location
29
+ if (response.status >= 300 && response.status < 400) {
30
+ const location = response.headers.get("location");
31
+ if (location) {
32
+ response = await fetch(location, {
33
+ method: "POST",
34
+ headers: { "Content-Type": "application/json" },
35
+ body,
36
+ });
37
+ }
38
+ }
39
+ return response;
40
+ }
17
41
  /**
18
42
  * Configure the B2B client
19
43
  */
@@ -36,14 +60,11 @@ function configure(options) {
36
60
  * @example
37
61
  * const companies = await b2b.sql<Company[]>("SELECT * FROM linkedin_company WHERE domain = 'stripe.com'");
38
62
  */
39
- async function sql(query) {
63
+ async function sql(sqlQuery) {
40
64
  return queue(async () => {
41
65
  return rateLimiter(async () => {
42
- const response = await fetch(config.proxyUrl, {
43
- method: "POST",
44
- headers: { "Content-Type": "application/json" },
45
- body: JSON.stringify({ sql: query }),
46
- });
66
+ const body = JSON.stringify({ sql: sqlQuery });
67
+ const response = await fetchWithRedirect(config.proxyUrl, body);
47
68
  if (!response.ok) {
48
69
  throw new Error(`B2B SQL request failed: ${response.status} ${response.statusText}`);
49
70
  }
@@ -61,11 +82,8 @@ async function sql(query) {
61
82
  async function query(sqlQuery) {
62
83
  return queue(async () => {
63
84
  return rateLimiter(async () => {
64
- const response = await fetch(config.proxyUrl, {
65
- method: "POST",
66
- headers: { "Content-Type": "application/json" },
67
- body: JSON.stringify({ sql: sqlQuery }),
68
- });
85
+ const body = JSON.stringify({ sql: sqlQuery });
86
+ const response = await fetchWithRedirect(config.proxyUrl, body);
69
87
  if (!response.ok) {
70
88
  throw new Error(`B2B SQL request failed: ${response.status} ${response.statusText}`);
71
89
  }
package/dist/cli.js CHANGED
@@ -39,10 +39,18 @@ const path = __importStar(require("path"));
39
39
  const child_process_1 = require("child_process");
40
40
  const DOCS_DIR = path.join(__dirname, "..", "docs");
41
41
  const TARGET_DIR = path.join(process.cwd(), "orangeslice-docs");
42
+ const AGENTS_MD = path.join(DOCS_DIR, "AGENTS.md");
43
+ const ROOT_AGENTS_MD = path.join(process.cwd(), "AGENTS.md");
42
44
  async function main() {
43
- console.log("\n orangeslice - setting up B2B client for AI agents...\n");
44
- // 1. Copy docs
45
- console.log("1. Copying B2B documentation...");
45
+ console.log("\n🍊 orangeslice - setting up sales agent for AI...\n");
46
+ // 1. Copy AGENTS.md to project root (for auto-detection by Claude Code, etc.)
47
+ console.log("1. Installing AGENTS.md at project root...");
48
+ if (fs.existsSync(AGENTS_MD)) {
49
+ fs.copyFileSync(AGENTS_MD, ROOT_AGENTS_MD);
50
+ console.log(" ✓ AGENTS.md → ./AGENTS.md (auto-detected by AI agents)\n");
51
+ }
52
+ // 2. Copy full docs to orangeslice-docs/
53
+ console.log("2. Copying detailed documentation...");
46
54
  if (!fs.existsSync(TARGET_DIR)) {
47
55
  fs.mkdirSync(TARGET_DIR, { recursive: true });
48
56
  }
@@ -51,30 +59,22 @@ async function main() {
51
59
  const src = path.join(DOCS_DIR, file);
52
60
  const dest = path.join(TARGET_DIR, file);
53
61
  fs.copyFileSync(src, dest);
54
- console.log(` ${file}`);
55
62
  }
56
- console.log(` Copied ${files.length} docs to ./orangeslice-docs/\n`);
57
- // 2. Install package
58
- console.log("2. Installing orangeslice package...");
63
+ console.log(` ${files.length} docs ./orangeslice-docs/\n`);
64
+ // 3. Install package
65
+ console.log("3. Installing orangeslice package...");
59
66
  try {
60
67
  (0, child_process_1.execSync)("npm install orangeslice", { stdio: "inherit", cwd: process.cwd() });
61
68
  }
62
69
  catch {
63
70
  console.log(" (skipped - no package.json or npm not available)\n");
64
71
  }
65
- // 3. Show usage
66
- console.log("\n Done! Your AI agent is ready.\n");
67
- console.log(" Point your AI agent (Claude, Cursor, etc.) to:\n");
68
- console.log(" ./orangeslice-docs/AGENTS.md\n");
69
- console.log(" This tells the agent how to act as your sales research assistant");
70
- console.log(" with access to 1B+ LinkedIn profiles.\n");
71
- console.log(" Example usage:\n");
72
- console.log(' import { orangeslice } from "orangeslice";');
73
- console.log("");
74
- console.log(" const company = await orangeslice.b2b.sql(`");
75
- console.log(" SELECT company_name, employee_count, description");
76
- console.log(" FROM linkedin_company");
77
- console.log(" WHERE domain = 'stripe.com'");
78
- console.log(" `);\n");
72
+ // 4. Done
73
+ console.log("\n Done! Your AI agent is now a sales research assistant.\n");
74
+ console.log(" AGENTS.md is at your project root - Claude Code will auto-detect it.\n");
75
+ console.log(" Your agent can now:\n");
76
+ console.log(" Query 1B+ LinkedIn profiles (orangeslice.b2b.sql)");
77
+ console.log(" Search Google (orangeslice.serp.search)");
78
+ console.log(" Scrape websites (orangeslice.firecrawl.scrape)\n");
79
79
  }
80
80
  main().catch(console.error);
package/dist/firecrawl.js CHANGED
@@ -9,6 +9,30 @@ const API_URL = process.env.ORANGESLICE_API_URL || "https://orangeslice.ai/api/f
9
9
  // Shared queue for all Firecrawl requests
10
10
  const queue = (0, queue_1.createQueue)(2);
11
11
  const rateLimiter = (0, queue_1.createRateLimiter)(500); // 500ms between requests (crawls are expensive)
12
+ /**
13
+ * Helper to make POST request, handling redirects manually
14
+ * (Node.js fetch has issues with POST body on redirects)
15
+ */
16
+ async function fetchWithRedirect(url, body) {
17
+ let response = await fetch(url, {
18
+ method: "POST",
19
+ headers: { "Content-Type": "application/json" },
20
+ body,
21
+ redirect: "manual",
22
+ });
23
+ // Handle redirect manually - re-POST to the new location
24
+ if (response.status >= 300 && response.status < 400) {
25
+ const location = response.headers.get("location");
26
+ if (location) {
27
+ response = await fetch(location, {
28
+ method: "POST",
29
+ headers: { "Content-Type": "application/json" },
30
+ body,
31
+ });
32
+ }
33
+ }
34
+ return response;
35
+ }
12
36
  /**
13
37
  * Scrape a website and get markdown content.
14
38
  * Automatically rate-limited.
@@ -26,11 +50,8 @@ const rateLimiter = (0, queue_1.createRateLimiter)(500); // 500ms between reques
26
50
  async function scrape(url, limit = 1) {
27
51
  return queue(async () => {
28
52
  return rateLimiter(async () => {
29
- const response = await fetch(API_URL, {
30
- method: "POST",
31
- headers: { "Content-Type": "application/json" },
32
- body: JSON.stringify({ url, limit }),
33
- });
53
+ const body = JSON.stringify({ url, limit });
54
+ const response = await fetchWithRedirect(API_URL, body);
34
55
  if (!response.ok) {
35
56
  throw new Error(`Firecrawl request failed: ${response.status} ${response.statusText}`);
36
57
  }
package/dist/serp.js CHANGED
@@ -8,6 +8,30 @@ const API_URL = process.env.ORANGESLICE_API_URL || "https://orangeslice.ai/api/f
8
8
  // Shared queue for all SERP requests
9
9
  const queue = (0, queue_1.createQueue)(2);
10
10
  const rateLimiter = (0, queue_1.createRateLimiter)(200); // 200ms between requests
11
+ /**
12
+ * Helper to make POST request, handling redirects manually
13
+ * (Node.js fetch has issues with POST body on redirects)
14
+ */
15
+ async function fetchWithRedirect(url, body) {
16
+ let response = await fetch(url, {
17
+ method: "POST",
18
+ headers: { "Content-Type": "application/json" },
19
+ body,
20
+ redirect: "manual",
21
+ });
22
+ // Handle redirect manually - re-POST to the new location
23
+ if (response.status >= 300 && response.status < 400) {
24
+ const location = response.headers.get("location");
25
+ if (location) {
26
+ response = await fetch(location, {
27
+ method: "POST",
28
+ headers: { "Content-Type": "application/json" },
29
+ body,
30
+ });
31
+ }
32
+ }
33
+ return response;
34
+ }
11
35
  /**
12
36
  * Search Google via SERP API.
13
37
  * Automatically rate-limited.
@@ -19,14 +43,8 @@ const rateLimiter = (0, queue_1.createRateLimiter)(200); // 200ms between reques
19
43
  async function search(query, options = {}) {
20
44
  return queue(async () => {
21
45
  return rateLimiter(async () => {
22
- const response = await fetch(API_URL, {
23
- method: "POST",
24
- headers: { "Content-Type": "application/json" },
25
- body: JSON.stringify({
26
- query,
27
- ...options,
28
- }),
29
- });
46
+ const body = JSON.stringify({ query, ...options });
47
+ const response = await fetchWithRedirect(API_URL, body);
30
48
  if (!response.ok) {
31
49
  throw new Error(`SERP request failed: ${response.status} ${response.statusText}`);
32
50
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "orangeslice",
3
- "version": "1.4.0",
3
+ "version": "1.4.2",
4
4
  "description": "Turn any AI agent into a B2B sales research assistant with 1B+ LinkedIn profiles",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",