firecrawl-cli 1.17.0 → 1.18.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/README.md +13 -35
- package/dist/__tests__/commands/init.test.js +4 -2
- package/dist/__tests__/commands/init.test.js.map +1 -1
- package/dist/__tests__/commands/setup.test.js +6 -2
- package/dist/__tests__/commands/setup.test.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +27 -4
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/monitor.d.ts +23 -0
- package/dist/commands/monitor.d.ts.map +1 -0
- package/dist/commands/monitor.js +395 -0
- package/dist/commands/monitor.js.map +1 -0
- package/dist/commands/setup.d.ts +1 -1
- package/dist/commands/setup.d.ts.map +1 -1
- package/dist/commands/setup.js +9 -5
- package/dist/commands/setup.js.map +1 -1
- package/dist/commands/skills-install.d.ts +9 -1
- package/dist/commands/skills-install.d.ts.map +1 -1
- package/dist/commands/skills-install.js +13 -2
- package/dist/commands/skills-install.js.map +1 -1
- package/dist/index.js +7 -8
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/dist/commands/experimental/backends.d.ts +0 -19
- package/dist/commands/experimental/backends.d.ts.map +0 -1
- package/dist/commands/experimental/backends.js +0 -74
- package/dist/commands/experimental/backends.js.map +0 -1
- package/dist/commands/experimental/index.d.ts +0 -13
- package/dist/commands/experimental/index.d.ts.map +0 -1
- package/dist/commands/experimental/index.js +0 -200
- package/dist/commands/experimental/index.js.map +0 -1
- package/dist/commands/experimental/shared.d.ts +0 -17
- package/dist/commands/experimental/shared.d.ts.map +0 -1
- package/dist/commands/experimental/shared.js +0 -152
- package/dist/commands/experimental/shared.js.map +0 -1
- package/dist/commands/experimental/workflows/company-directories.d.ts +0 -11
- package/dist/commands/experimental/workflows/company-directories.d.ts.map +0 -1
- package/dist/commands/experimental/workflows/company-directories.js +0 -245
- package/dist/commands/experimental/workflows/company-directories.js.map +0 -1
- package/dist/commands/experimental/workflows/competitive-intel.d.ts +0 -11
- package/dist/commands/experimental/workflows/competitive-intel.d.ts.map +0 -1
- package/dist/commands/experimental/workflows/competitive-intel.js +0 -226
- package/dist/commands/experimental/workflows/competitive-intel.js.map +0 -1
- package/dist/commands/experimental/workflows/competitor-analysis.d.ts +0 -10
- package/dist/commands/experimental/workflows/competitor-analysis.d.ts.map +0 -1
- package/dist/commands/experimental/workflows/competitor-analysis.js +0 -196
- package/dist/commands/experimental/workflows/competitor-analysis.js.map +0 -1
- package/dist/commands/experimental/workflows/dashboard-reporting.d.ts +0 -11
- package/dist/commands/experimental/workflows/dashboard-reporting.d.ts.map +0 -1
- package/dist/commands/experimental/workflows/dashboard-reporting.js +0 -254
- package/dist/commands/experimental/workflows/dashboard-reporting.js.map +0 -1
- package/dist/commands/experimental/workflows/deep-research.d.ts +0 -11
- package/dist/commands/experimental/workflows/deep-research.d.ts.map +0 -1
- package/dist/commands/experimental/workflows/deep-research.js +0 -159
- package/dist/commands/experimental/workflows/deep-research.js.map +0 -1
- package/dist/commands/experimental/workflows/demo.d.ts +0 -11
- package/dist/commands/experimental/workflows/demo.d.ts.map +0 -1
- package/dist/commands/experimental/workflows/demo.js +0 -190
- package/dist/commands/experimental/workflows/demo.js.map +0 -1
- package/dist/commands/experimental/workflows/knowledge-base.d.ts +0 -11
- package/dist/commands/experimental/workflows/knowledge-base.d.ts.map +0 -1
- package/dist/commands/experimental/workflows/knowledge-base.js +0 -319
- package/dist/commands/experimental/workflows/knowledge-base.js.map +0 -1
- package/dist/commands/experimental/workflows/knowledge-ingest.d.ts +0 -12
- package/dist/commands/experimental/workflows/knowledge-ingest.d.ts.map +0 -1
- package/dist/commands/experimental/workflows/knowledge-ingest.js +0 -251
- package/dist/commands/experimental/workflows/knowledge-ingest.js.map +0 -1
- package/dist/commands/experimental/workflows/lead-gen.d.ts +0 -11
- package/dist/commands/experimental/workflows/lead-gen.d.ts.map +0 -1
- package/dist/commands/experimental/workflows/lead-gen.js +0 -257
- package/dist/commands/experimental/workflows/lead-gen.js.map +0 -1
- package/dist/commands/experimental/workflows/lead-research.d.ts +0 -11
- package/dist/commands/experimental/workflows/lead-research.d.ts.map +0 -1
- package/dist/commands/experimental/workflows/lead-research.js +0 -146
- package/dist/commands/experimental/workflows/lead-research.js.map +0 -1
- package/dist/commands/experimental/workflows/market-research.d.ts +0 -11
- package/dist/commands/experimental/workflows/market-research.d.ts.map +0 -1
- package/dist/commands/experimental/workflows/market-research.js +0 -260
- package/dist/commands/experimental/workflows/market-research.js.map +0 -1
- package/dist/commands/experimental/workflows/qa.d.ts +0 -11
- package/dist/commands/experimental/workflows/qa.d.ts.map +0 -1
- package/dist/commands/experimental/workflows/qa.js +0 -184
- package/dist/commands/experimental/workflows/qa.js.map +0 -1
- package/dist/commands/experimental/workflows/research-papers.d.ts +0 -11
- package/dist/commands/experimental/workflows/research-papers.d.ts.map +0 -1
- package/dist/commands/experimental/workflows/research-papers.js +0 -151
- package/dist/commands/experimental/workflows/research-papers.js.map +0 -1
- package/dist/commands/experimental/workflows/seo-audit.d.ts +0 -11
- package/dist/commands/experimental/workflows/seo-audit.d.ts.map +0 -1
- package/dist/commands/experimental/workflows/seo-audit.js +0 -155
- package/dist/commands/experimental/workflows/seo-audit.js.map +0 -1
- package/dist/commands/experimental/workflows/shop.d.ts +0 -11
- package/dist/commands/experimental/workflows/shop.d.ts.map +0 -1
- package/dist/commands/experimental/workflows/shop.js +0 -155
- package/dist/commands/experimental/workflows/shop.js.map +0 -1
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Shared constants and helpers for AI workflows.
|
|
4
|
-
*/
|
|
5
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
6
|
-
if (k2 === undefined) k2 = k;
|
|
7
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
8
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
9
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
10
|
-
}
|
|
11
|
-
Object.defineProperty(o, k2, desc);
|
|
12
|
-
}) : (function(o, m, k, k2) {
|
|
13
|
-
if (k2 === undefined) k2 = k;
|
|
14
|
-
o[k2] = m[k];
|
|
15
|
-
}));
|
|
16
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
17
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
18
|
-
}) : function(o, v) {
|
|
19
|
-
o["default"] = v;
|
|
20
|
-
});
|
|
21
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
22
|
-
var ownKeys = function(o) {
|
|
23
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
24
|
-
var ar = [];
|
|
25
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
26
|
-
return ar;
|
|
27
|
-
};
|
|
28
|
-
return ownKeys(o);
|
|
29
|
-
};
|
|
30
|
-
return function (mod) {
|
|
31
|
-
if (mod && mod.__esModule) return mod;
|
|
32
|
-
var result = {};
|
|
33
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
34
|
-
__setModuleDefault(result, mod);
|
|
35
|
-
return result;
|
|
36
|
-
};
|
|
37
|
-
})();
|
|
38
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
exports.SUBAGENT_INSTRUCTIONS = exports.QA_TOOLS_BLOCK = exports.FIRECRAWL_TOOLS_BLOCK = exports.validateRequired = exports.validateUrl = void 0;
|
|
40
|
-
exports.normalizeUrl = normalizeUrl;
|
|
41
|
-
exports.normalizeSource = normalizeSource;
|
|
42
|
-
exports.buildMessage = buildMessage;
|
|
43
|
-
exports.askPermissionMode = askPermissionMode;
|
|
44
|
-
const backends_1 = require("./backends");
|
|
45
|
-
// ─── Validators ─────────────────────────────────────────────────────────────
|
|
46
|
-
const validateUrl = (value) => {
|
|
47
|
-
if (!value.trim())
|
|
48
|
-
return 'URL is required';
|
|
49
|
-
try {
|
|
50
|
-
new URL(value.startsWith('http') ? value : `https://${value}`);
|
|
51
|
-
return true;
|
|
52
|
-
}
|
|
53
|
-
catch {
|
|
54
|
-
return 'Please enter a valid URL';
|
|
55
|
-
}
|
|
56
|
-
};
|
|
57
|
-
exports.validateUrl = validateUrl;
|
|
58
|
-
const validateRequired = (label) => (value) => value.trim() ? true : `${label} is required`;
|
|
59
|
-
exports.validateRequired = validateRequired;
|
|
60
|
-
// ─── URL helpers ────────────────────────────────────────────────────────────
|
|
61
|
-
/** Ensure a URL has a protocol prefix. */
|
|
62
|
-
function normalizeUrl(url) {
|
|
63
|
-
return url.startsWith('http') ? url : `https://${url}`;
|
|
64
|
-
}
|
|
65
|
-
/** Normalize a source that might be a URL or a plain topic string. */
|
|
66
|
-
function normalizeSource(source) {
|
|
67
|
-
if (source.startsWith('http'))
|
|
68
|
-
return source;
|
|
69
|
-
if (/\.\w{2,}/.test(source))
|
|
70
|
-
return `https://${source}`;
|
|
71
|
-
return source;
|
|
72
|
-
}
|
|
73
|
-
// ─── Prompt blocks ──────────────────────────────────────────────────────────
|
|
74
|
-
exports.FIRECRAWL_TOOLS_BLOCK = `## Your Tools -- READ THIS FIRST
|
|
75
|
-
|
|
76
|
-
Use ONLY \`firecrawl\` for ALL web operations. It is already installed and authenticated. Run firecrawl commands via Bash. Do not use any other tools, skills, plugins, or built-in web features for web access -- only \`firecrawl\`. If the CLI has issues, you may fall back to Firecrawl MCP tools if available.
|
|
77
|
-
|
|
78
|
-
**First step: run \`firecrawl --help\` to see all available commands.** Then run \`firecrawl <command> --help\` for any command you plan to use heavily.
|
|
79
|
-
|
|
80
|
-
Quick reference:
|
|
81
|
-
- \`firecrawl search "<query>"\` -- Search the web
|
|
82
|
-
- \`firecrawl scrape <url>\` -- Scrape a page as markdown
|
|
83
|
-
- \`firecrawl map <url>\` -- Discover all URLs on a site
|
|
84
|
-
- \`firecrawl crawl <url>\` -- Crawl an entire site
|
|
85
|
-
- \`firecrawl interact "Click the login button"\` -- Interact with a scraped page
|
|
86
|
-
- \`firecrawl agent "<prompt>"\` -- AI agent for complex extraction`;
|
|
87
|
-
exports.QA_TOOLS_BLOCK = `## Your Tools -- READ THIS FIRST
|
|
88
|
-
|
|
89
|
-
Use ONLY \`firecrawl\` for ALL web operations. It is already installed and authenticated. Run firecrawl commands via Bash. Do not use any other tools, skills, plugins, or built-in web features for web access -- only \`firecrawl\`. If the CLI has issues, you may fall back to Firecrawl MCP tools if available.
|
|
90
|
-
|
|
91
|
-
**First step: run \`firecrawl --help\` to see all available commands.** Tell each subagent to do the same.
|
|
92
|
-
|
|
93
|
-
## IMPORTANT: Launch Browser with Live View FIRST
|
|
94
|
-
|
|
95
|
-
Before doing anything else, launch a browser session with streaming enabled so the user can watch in real-time:
|
|
96
|
-
|
|
97
|
-
\`\`\`bash
|
|
98
|
-
firecrawl browser launch-session --json
|
|
99
|
-
\`\`\`
|
|
100
|
-
|
|
101
|
-
This prints a **Live View URL**. Try to open it automatically for the user:
|
|
102
|
-
|
|
103
|
-
\`\`\`bash
|
|
104
|
-
open "<liveViewUrl>" # macOS
|
|
105
|
-
xdg-open "<liveViewUrl>" # Linux
|
|
106
|
-
\`\`\`
|
|
107
|
-
|
|
108
|
-
If the \`open\` command fails or errors, just print the URL clearly so the user can copy-paste it into their browser. Either way, make sure the user sees the live view URL before you start working.
|
|
109
|
-
|
|
110
|
-
Quick reference:
|
|
111
|
-
- \`firecrawl browser "open <url>"\` -- Navigate to a URL in a cloud browser
|
|
112
|
-
- \`firecrawl browser "snapshot"\` -- Get the current page state (accessibility tree)
|
|
113
|
-
- \`firecrawl browser "click @<ref>"\` -- Click an element by its reference ID
|
|
114
|
-
- \`firecrawl browser "type @<ref> <text>"\` -- Type text into an input
|
|
115
|
-
- \`firecrawl browser "scrape"\` -- Get the full page content as markdown
|
|
116
|
-
- \`firecrawl browser "scroll down"\` / \`"scroll up"\` -- Scroll the page
|
|
117
|
-
- \`firecrawl scrape <url>\` -- Quick scrape without browser session
|
|
118
|
-
- \`firecrawl map <url>\` -- Discover all URLs on the site`;
|
|
119
|
-
exports.SUBAGENT_INSTRUCTIONS = `**IMPORTANT:** When spawning agents with the Agent tool:
|
|
120
|
-
- Use \`subagent_type: "general-purpose"\` for each agent
|
|
121
|
-
- Give each agent a clear, specific mandate in the prompt
|
|
122
|
-
- Tell each agent: "Use ONLY firecrawl for all web access via Bash. Do not use any other tools, skills, or plugins for web access. If the CLI has issues, fall back to Firecrawl MCP tools. Run \`firecrawl --help\` first."
|
|
123
|
-
- Launch ALL agents in a SINGLE message (parallel, not sequential)
|
|
124
|
-
- Each agent should return structured findings with source URLs`;
|
|
125
|
-
// ─── Message builder ────────────────────────────────────────────────────────
|
|
126
|
-
/** Join non-empty parts into a message string. */
|
|
127
|
-
function buildMessage(parts) {
|
|
128
|
-
return parts.filter(Boolean).join('. ') + '.';
|
|
129
|
-
}
|
|
130
|
-
// ─── Permission helper ──────────────────────────────────────────────────────
|
|
131
|
-
async function askPermissionMode(backend) {
|
|
132
|
-
const { select } = await Promise.resolve().then(() => __importStar(require('@inquirer/prompts')));
|
|
133
|
-
const config = backends_1.BACKENDS[backend];
|
|
134
|
-
const skipLabel = backend === 'codex' ? '--full-auto' : '--dangerously-skip-permissions';
|
|
135
|
-
const mode = await select({
|
|
136
|
-
message: 'How should the agent handle tool permissions?',
|
|
137
|
-
choices: [
|
|
138
|
-
{
|
|
139
|
-
name: 'Auto-approve all (recommended)',
|
|
140
|
-
value: 'skip',
|
|
141
|
-
description: `Runs fully autonomous, no manual approvals. Uses ${skipLabel}.`,
|
|
142
|
-
},
|
|
143
|
-
{
|
|
144
|
-
name: 'Ask me each time',
|
|
145
|
-
value: 'ask',
|
|
146
|
-
description: `${config.displayName} will prompt before running each tool (slower but more control).`,
|
|
147
|
-
},
|
|
148
|
-
],
|
|
149
|
-
});
|
|
150
|
-
return mode === 'skip';
|
|
151
|
-
}
|
|
152
|
-
//# sourceMappingURL=shared.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"shared.js","sourceRoot":"","sources":["../../../src/commands/experimental/shared.ts"],"names":[],"mappings":";AAAA;;GAEG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwBH,oCAEC;AAGD,0CAIC;AA6DD,oCAEC;AAID,8CAwBC;AA1HD,yCAAoD;AAEpD,+EAA+E;AAExE,MAAM,WAAW,GAAG,CAAC,KAAa,EAAiB,EAAE;IAC1D,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE;QAAE,OAAO,iBAAiB,CAAC;IAC5C,IAAI,CAAC;QACH,IAAI,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,WAAW,KAAK,EAAE,CAAC,CAAC;QAC/D,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,0BAA0B,CAAC;IACpC,CAAC;AACH,CAAC,CAAC;AARW,QAAA,WAAW,eAQtB;AAEK,MAAM,gBAAgB,GAC3B,CAAC,KAAa,EAAE,EAAE,CAClB,CAAC,KAAa,EAAiB,EAAE,CAC/B,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,KAAK,cAAc,CAAC;AAHpC,QAAA,gBAAgB,oBAGoB;AAEjD,+EAA+E;AAE/E,0CAA0C;AAC1C,SAAgB,YAAY,CAAC,GAAW;IACtC,OAAO,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,GAAG,EAAE,CAAC;AACzD,CAAC;AAED,sEAAsE;AACtE,SAAgB,eAAe,CAAC,MAAc;IAC5C,IAAI,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC;QAAE,OAAO,MAAM,CAAC;IAC7C,IAAI,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC;QAAE,OAAO,WAAW,MAAM,EAAE,CAAC;IACxD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,+EAA+E;AAElE,QAAA,qBAAqB,GAAG;;;;;;;;;;;;oEAY+B,CAAC;AAExD,QAAA,cAAc,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2DA+B6B,CAAC;AAE/C,QAAA,qBAAqB,GAAG;;;;;gEAK2B,CAAC;AAEjE,+EAA+E;AAE/E,kDAAkD;AAClD,SAAgB,YAAY,CAAC,KAAe;IAC1C,OAAO,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC;AAChD,CAAC;AAED,+EAA+E;AAExE,KAAK,UAAU,iBAAiB,CAAC,OAAgB;IACtD,MAAM,EAAE,MAAM,EAAE,GAAG,wDAAa,mBAAmB,GAAC,CAAC;IACrD,MAAM,MAAM,GAAG,mBAAQ,CAAC,OAAO,CAAC,CAAC;IAEjC,MAAM,SAAS,GACb,OAAO,KAAK,OAAO,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,gCAAgC,CAAC;IAEzE,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC;QACxB,OAAO,EAAE,+CAA+C;QACxD,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,gCAAgC;gBACtC,KAAK,EAAE,MAAM;gBACb,WAAW,EAAE,oDAAoD,SAAS,GAAG;aAC9E;YACD;gBACE,IAAI,EAAE,kBAAkB;gBACxB,KAAK,EAAE,KAAK;gBACZ,WAAW,EAAE,GAAG,MAAM,CAAC,WAAW,kEAAkE;aACrG;SACF;KACF,CAAC,CAAC;IAEH,OAAO,IAAI,KAAK,MAAM,CAAC;AACzB,CAAC"}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Workflow: Company Directories
|
|
3
|
-
*
|
|
4
|
-
* Browses startup directories (YC, Crunchbase, Product Hunt, etc.), applies
|
|
5
|
-
* filters, paginates through results, and builds targeted company lists
|
|
6
|
-
* with structured data for outreach, research, or CRM import.
|
|
7
|
-
*/
|
|
8
|
-
import { Command } from 'commander';
|
|
9
|
-
import { type Backend } from '../backends';
|
|
10
|
-
export declare function register(parentCmd: Command, backend: Backend): void;
|
|
11
|
-
//# sourceMappingURL=company-directories.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"company-directories.d.ts","sourceRoot":"","sources":["../../../../src/commands/experimental/workflows/company-directories.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,KAAK,OAAO,EAAyB,MAAM,aAAa,CAAC;AAgNlE,wBAAgB,QAAQ,CAAC,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAsCnE"}
|
|
@@ -1,245 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Workflow: Company Directories
|
|
4
|
-
*
|
|
5
|
-
* Browses startup directories (YC, Crunchbase, Product Hunt, etc.), applies
|
|
6
|
-
* filters, paginates through results, and builds targeted company lists
|
|
7
|
-
* with structured data for outreach, research, or CRM import.
|
|
8
|
-
*/
|
|
9
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
12
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
13
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
14
|
-
}
|
|
15
|
-
Object.defineProperty(o, k2, desc);
|
|
16
|
-
}) : (function(o, m, k, k2) {
|
|
17
|
-
if (k2 === undefined) k2 = k;
|
|
18
|
-
o[k2] = m[k];
|
|
19
|
-
}));
|
|
20
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
21
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
22
|
-
}) : function(o, v) {
|
|
23
|
-
o["default"] = v;
|
|
24
|
-
});
|
|
25
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
26
|
-
var ownKeys = function(o) {
|
|
27
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
28
|
-
var ar = [];
|
|
29
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
30
|
-
return ar;
|
|
31
|
-
};
|
|
32
|
-
return ownKeys(o);
|
|
33
|
-
};
|
|
34
|
-
return function (mod) {
|
|
35
|
-
if (mod && mod.__esModule) return mod;
|
|
36
|
-
var result = {};
|
|
37
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
38
|
-
__setModuleDefault(result, mod);
|
|
39
|
-
return result;
|
|
40
|
-
};
|
|
41
|
-
})();
|
|
42
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
43
|
-
exports.register = register;
|
|
44
|
-
const backends_1 = require("../backends");
|
|
45
|
-
const shared_1 = require("../shared");
|
|
46
|
-
// ─── Input gathering ────────────────────────────────────────────────────────
|
|
47
|
-
async function gatherInputs(prefill) {
|
|
48
|
-
if (prefill?.directory) {
|
|
49
|
-
return {
|
|
50
|
-
directory: prefill.directory,
|
|
51
|
-
filters: '',
|
|
52
|
-
maxResults: '50',
|
|
53
|
-
output: 'json',
|
|
54
|
-
context: '',
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
const { input, select } = await Promise.resolve().then(() => __importStar(require('@inquirer/prompts')));
|
|
58
|
-
const directory = await select({
|
|
59
|
-
message: 'Which directory do you want to scrape?',
|
|
60
|
-
choices: [
|
|
61
|
-
{ name: 'Y Combinator (ycombinator.com/companies)', value: 'yc' },
|
|
62
|
-
{ name: 'Crunchbase', value: 'crunchbase' },
|
|
63
|
-
{ name: 'Product Hunt', value: 'producthunt' },
|
|
64
|
-
{ name: 'G2', value: 'g2' },
|
|
65
|
-
{ name: 'Custom URL', value: 'custom' },
|
|
66
|
-
],
|
|
67
|
-
});
|
|
68
|
-
let directoryValue = directory;
|
|
69
|
-
if (directory === 'custom') {
|
|
70
|
-
directoryValue = await input({
|
|
71
|
-
message: 'Enter the directory URL:',
|
|
72
|
-
validate: (0, shared_1.validateRequired)('URL'),
|
|
73
|
-
});
|
|
74
|
-
}
|
|
75
|
-
const filters = await input({
|
|
76
|
-
message: 'What filters should the agent apply? (e.g., "Series A, B2B SaaS, founded 2023+")',
|
|
77
|
-
default: '',
|
|
78
|
-
});
|
|
79
|
-
const maxResults = await input({
|
|
80
|
-
message: 'How many companies to extract?',
|
|
81
|
-
default: '50',
|
|
82
|
-
});
|
|
83
|
-
const output = await select({
|
|
84
|
-
message: 'Output format?',
|
|
85
|
-
choices: [
|
|
86
|
-
{ name: 'JSON (structured, CRM-ready)', value: 'json' },
|
|
87
|
-
{ name: 'CSV (spreadsheet-ready)', value: 'csv' },
|
|
88
|
-
{ name: 'Print to terminal', value: 'terminal' },
|
|
89
|
-
],
|
|
90
|
-
});
|
|
91
|
-
const context = await input({
|
|
92
|
-
message: 'Any other criteria? (e.g., "only companies with pricing pages", "must have API")',
|
|
93
|
-
default: '',
|
|
94
|
-
});
|
|
95
|
-
return {
|
|
96
|
-
directory: directoryValue,
|
|
97
|
-
filters,
|
|
98
|
-
maxResults,
|
|
99
|
-
output,
|
|
100
|
-
context,
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
// ─── System prompt ──────────────────────────────────────────────────────────
|
|
104
|
-
function buildSystemPrompt(opts) {
|
|
105
|
-
const directoryUrls = {
|
|
106
|
-
yc: 'https://www.ycombinator.com/companies',
|
|
107
|
-
crunchbase: 'https://www.crunchbase.com/discover/organization.companies',
|
|
108
|
-
producthunt: 'https://www.producthunt.com',
|
|
109
|
-
g2: 'https://www.g2.com/categories',
|
|
110
|
-
};
|
|
111
|
-
const startUrl = directoryUrls[opts.directory] || opts.directory;
|
|
112
|
-
const outputInstructions = {
|
|
113
|
-
terminal: 'Print the full company list to the terminal as a formatted markdown table.',
|
|
114
|
-
json: `Save the results to \`company-list.json\` in the current directory. Tell the user the file path when done.
|
|
115
|
-
|
|
116
|
-
Use this schema:
|
|
117
|
-
\`\`\`json
|
|
118
|
-
{
|
|
119
|
-
"source": "string (directory name)",
|
|
120
|
-
"filters": "string (filters applied)",
|
|
121
|
-
"extractedAt": "ISO-8601",
|
|
122
|
-
"totalResults": 0,
|
|
123
|
-
"companies": [
|
|
124
|
-
{
|
|
125
|
-
"name": "string",
|
|
126
|
-
"url": "string",
|
|
127
|
-
"description": "string",
|
|
128
|
-
"industry": "string",
|
|
129
|
-
"stage": "string (e.g. Seed, Series A)",
|
|
130
|
-
"founded": "string",
|
|
131
|
-
"location": "string",
|
|
132
|
-
"teamSize": "string",
|
|
133
|
-
"funding": "string",
|
|
134
|
-
"tags": ["string"],
|
|
135
|
-
"profileUrl": "string (directory listing URL)",
|
|
136
|
-
"websiteUrl": "string (company website)"
|
|
137
|
-
}
|
|
138
|
-
]
|
|
139
|
-
}
|
|
140
|
-
\`\`\``,
|
|
141
|
-
csv: `Save the results to \`company-list.csv\` in the current directory with columns: name, url, description, industry, stage, founded, location, teamSize, funding, tags, profileUrl, websiteUrl. Tell the user the file path when done.`,
|
|
142
|
-
};
|
|
143
|
-
return `You are a company directory scraping agent powered by Firecrawl. You use a real cloud browser to navigate startup directories, apply filters, paginate through results, and extract structured company data.
|
|
144
|
-
|
|
145
|
-
## STEP 1: Launch Browser and Open Live View
|
|
146
|
-
|
|
147
|
-
Before anything else, launch a browser session so the user can watch:
|
|
148
|
-
|
|
149
|
-
\`\`\`bash
|
|
150
|
-
firecrawl browser launch-session --json
|
|
151
|
-
\`\`\`
|
|
152
|
-
|
|
153
|
-
Extract the \`interactiveLiveViewUrl\` from the JSON output and open it (NOT the regular \`liveViewUrl\` -- the interactive one lets the user click and interact):
|
|
154
|
-
|
|
155
|
-
\`\`\`bash
|
|
156
|
-
open "<interactiveLiveViewUrl>" # macOS
|
|
157
|
-
xdg-open "<interactiveLiveViewUrl>" # Linux
|
|
158
|
-
\`\`\`
|
|
159
|
-
|
|
160
|
-
If the \`open\` command fails, print the URL clearly.
|
|
161
|
-
|
|
162
|
-
## STEP 2: Navigate to Directory
|
|
163
|
-
|
|
164
|
-
Open the directory:
|
|
165
|
-
\`\`\`bash
|
|
166
|
-
firecrawl browser "open ${startUrl}"
|
|
167
|
-
\`\`\`
|
|
168
|
-
|
|
169
|
-
## STEP 3: Apply Filters
|
|
170
|
-
|
|
171
|
-
Take a snapshot to see the page layout:
|
|
172
|
-
\`\`\`bash
|
|
173
|
-
firecrawl browser "snapshot"
|
|
174
|
-
\`\`\`
|
|
175
|
-
|
|
176
|
-
Look for filter controls (dropdowns, checkboxes, search fields, sidebar filters) and apply the user's requested filters by clicking and typing.
|
|
177
|
-
|
|
178
|
-
### Browser commands:
|
|
179
|
-
\`\`\`bash
|
|
180
|
-
firecrawl browser "click @<ref>"
|
|
181
|
-
firecrawl browser "type @<ref> <text>"
|
|
182
|
-
firecrawl browser "scroll down"
|
|
183
|
-
firecrawl browser "snapshot"
|
|
184
|
-
firecrawl browser "scrape"
|
|
185
|
-
\`\`\`
|
|
186
|
-
|
|
187
|
-
## STEP 4: Paginate and Extract
|
|
188
|
-
|
|
189
|
-
After applying filters:
|
|
190
|
-
|
|
191
|
-
1. **Snapshot** the results page to see company listings
|
|
192
|
-
2. **Extract** data from each visible company (name, description, tags, etc.)
|
|
193
|
-
3. **Click into** individual company profiles if the listing doesn't have enough detail
|
|
194
|
-
4. **Navigate back** and continue to the next listing
|
|
195
|
-
5. **Paginate** -- find and click "Next", "Load More", or scroll to trigger infinite scroll
|
|
196
|
-
6. Repeat until you've collected ~${opts.maxResults} companies or exhausted results
|
|
197
|
-
|
|
198
|
-
### Pagination tips:
|
|
199
|
-
- Look for "Next" / ">" buttons, page number links, or "Load More"
|
|
200
|
-
- Some directories use infinite scroll -- keep scrolling down and snapshotting
|
|
201
|
-
- Track how many companies you've extracted to know when to stop
|
|
202
|
-
- If a page loads slowly, wait a moment and snapshot again
|
|
203
|
-
|
|
204
|
-
## Output Format
|
|
205
|
-
|
|
206
|
-
${outputInstructions[opts.output]}
|
|
207
|
-
|
|
208
|
-
## Quality Guidelines
|
|
209
|
-
|
|
210
|
-
- Extract real data from the page, don't infer or guess
|
|
211
|
-
- If a field isn't visible, leave it empty rather than fabricating
|
|
212
|
-
- Deduplicate companies (same company might appear in multiple pages)
|
|
213
|
-
- For each company, try to get at minimum: name, description, and URL
|
|
214
|
-
|
|
215
|
-
Do everything sequentially. Start immediately.`;
|
|
216
|
-
}
|
|
217
|
-
// ─── Command registration ───────────────────────────────────────────────────
|
|
218
|
-
function register(parentCmd, backend) {
|
|
219
|
-
const config = backends_1.BACKENDS[backend];
|
|
220
|
-
parentCmd
|
|
221
|
-
.command('company-directories')
|
|
222
|
-
.description('Scrape startup directories (YC, Crunchbase, etc.) into structured lists')
|
|
223
|
-
.argument('[query...]', 'Directory name or filters to apply')
|
|
224
|
-
.option('-y, --yes', 'Auto-approve all tool permissions')
|
|
225
|
-
.action(async (queryParts, options) => {
|
|
226
|
-
const prefillDir = queryParts.length > 0 ? queryParts.join(' ') : undefined;
|
|
227
|
-
const inputs = await gatherInputs(prefillDir ? { directory: prefillDir } : undefined);
|
|
228
|
-
const parts = [`Scrape directory: ${inputs.directory}`];
|
|
229
|
-
if (inputs.filters)
|
|
230
|
-
parts.push(`Filters: ${inputs.filters}`);
|
|
231
|
-
if (inputs.maxResults)
|
|
232
|
-
parts.push(`Extract up to ${inputs.maxResults} companies`);
|
|
233
|
-
if (inputs.context)
|
|
234
|
-
parts.push(inputs.context);
|
|
235
|
-
const userMessage = parts.join('. ') + '.';
|
|
236
|
-
const skipPermissions = true;
|
|
237
|
-
console.log(`\nLaunching ${config.displayName}...\n`);
|
|
238
|
-
(0, backends_1.launchAgent)(backend, buildSystemPrompt({
|
|
239
|
-
directory: inputs.directory,
|
|
240
|
-
output: inputs.output,
|
|
241
|
-
maxResults: inputs.maxResults,
|
|
242
|
-
}), userMessage, skipPermissions);
|
|
243
|
-
});
|
|
244
|
-
}
|
|
245
|
-
//# sourceMappingURL=company-directories.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"company-directories.js","sourceRoot":"","sources":["../../../../src/commands/experimental/workflows/company-directories.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Workflow: Competitive Intelligence
|
|
3
|
-
*
|
|
4
|
-
* Logs into competitor dashboards using saved browser profiles, clicks through
|
|
5
|
-
* pricing tiers, feature pages, and changelogs to detect plan changes.
|
|
6
|
-
* Designed for weekly monitoring runs with structured diff output.
|
|
7
|
-
*/
|
|
8
|
-
import { Command } from 'commander';
|
|
9
|
-
import { type Backend } from '../backends';
|
|
10
|
-
export declare function register(parentCmd: Command, backend: Backend): void;
|
|
11
|
-
//# sourceMappingURL=competitive-intel.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"competitive-intel.d.ts","sourceRoot":"","sources":["../../../../src/commands/experimental/workflows/competitive-intel.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,KAAK,OAAO,EAAyB,MAAM,aAAa,CAAC;AAsMlE,wBAAgB,QAAQ,CAAC,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAmCnE"}
|
|
@@ -1,226 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Workflow: Competitive Intelligence
|
|
4
|
-
*
|
|
5
|
-
* Logs into competitor dashboards using saved browser profiles, clicks through
|
|
6
|
-
* pricing tiers, feature pages, and changelogs to detect plan changes.
|
|
7
|
-
* Designed for weekly monitoring runs with structured diff output.
|
|
8
|
-
*/
|
|
9
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
12
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
13
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
14
|
-
}
|
|
15
|
-
Object.defineProperty(o, k2, desc);
|
|
16
|
-
}) : (function(o, m, k, k2) {
|
|
17
|
-
if (k2 === undefined) k2 = k;
|
|
18
|
-
o[k2] = m[k];
|
|
19
|
-
}));
|
|
20
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
21
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
22
|
-
}) : function(o, v) {
|
|
23
|
-
o["default"] = v;
|
|
24
|
-
});
|
|
25
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
26
|
-
var ownKeys = function(o) {
|
|
27
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
28
|
-
var ar = [];
|
|
29
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
30
|
-
return ar;
|
|
31
|
-
};
|
|
32
|
-
return ownKeys(o);
|
|
33
|
-
};
|
|
34
|
-
return function (mod) {
|
|
35
|
-
if (mod && mod.__esModule) return mod;
|
|
36
|
-
var result = {};
|
|
37
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
38
|
-
__setModuleDefault(result, mod);
|
|
39
|
-
return result;
|
|
40
|
-
};
|
|
41
|
-
})();
|
|
42
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
43
|
-
exports.register = register;
|
|
44
|
-
const backends_1 = require("../backends");
|
|
45
|
-
const shared_1 = require("../shared");
|
|
46
|
-
// ─── Input gathering ────────────────────────────────────────────────────────
|
|
47
|
-
async function gatherInputs(prefill) {
|
|
48
|
-
if (prefill?.competitors) {
|
|
49
|
-
return {
|
|
50
|
-
competitors: prefill.competitors,
|
|
51
|
-
focus: 'all',
|
|
52
|
-
profile: '',
|
|
53
|
-
output: 'json',
|
|
54
|
-
context: '',
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
const { input, select } = await Promise.resolve().then(() => __importStar(require('@inquirer/prompts')));
|
|
58
|
-
const competitors = await input({
|
|
59
|
-
message: 'Which competitors to monitor? (URLs or names, comma-separated)',
|
|
60
|
-
validate: (0, shared_1.validateRequired)('At least one competitor'),
|
|
61
|
-
});
|
|
62
|
-
const focus = await select({
|
|
63
|
-
message: 'What should the agent focus on?',
|
|
64
|
-
choices: [
|
|
65
|
-
{ name: 'Everything (pricing, features, changelog)', value: 'all' },
|
|
66
|
-
{ name: 'Pricing tiers & plan changes only', value: 'pricing' },
|
|
67
|
-
{ name: 'Feature pages & product updates', value: 'features' },
|
|
68
|
-
{ name: 'Blog / changelog / release notes', value: 'changelog' },
|
|
69
|
-
],
|
|
70
|
-
});
|
|
71
|
-
const profile = await input({
|
|
72
|
-
message: 'Browser profile to use for auth? (leave blank for anonymous browsing)',
|
|
73
|
-
default: '',
|
|
74
|
-
});
|
|
75
|
-
const output = await select({
|
|
76
|
-
message: 'How should the report be delivered?',
|
|
77
|
-
choices: [
|
|
78
|
-
{ name: 'Print to terminal', value: 'terminal' },
|
|
79
|
-
{ name: 'Save as JSON (structured diffs)', value: 'json' },
|
|
80
|
-
{ name: 'Save as Markdown file', value: 'markdown' },
|
|
81
|
-
],
|
|
82
|
-
});
|
|
83
|
-
const context = await input({
|
|
84
|
-
message: 'Any other context? (e.g., "compare to our Pro plan", "focus on API limits")',
|
|
85
|
-
default: '',
|
|
86
|
-
});
|
|
87
|
-
return { competitors, focus, profile, output, context };
|
|
88
|
-
}
|
|
89
|
-
// ─── System prompt ──────────────────────────────────────────────────────────
|
|
90
|
-
function buildSystemPrompt(opts) {
|
|
91
|
-
const focusInstructions = {
|
|
92
|
-
all: 'Extract pricing tiers (plan names, prices, feature lists, limits), product feature pages, and recent changelog/blog entries.',
|
|
93
|
-
pricing: 'Focus exclusively on pricing pages. Extract every plan name, price, billing period, feature list, and usage limit. Note any "Contact Sales" tiers.',
|
|
94
|
-
features: 'Focus on product/feature pages. Extract feature names, descriptions, availability per plan, and any recent additions or deprecations.',
|
|
95
|
-
changelog: 'Focus on blogs, changelogs, and release notes. Extract recent product updates, new features, breaking changes, and deprecation notices.',
|
|
96
|
-
};
|
|
97
|
-
const profileBlock = opts.profile
|
|
98
|
-
? `\n### Browser Profile\n\nUse the saved browser profile \`${opts.profile}\` to access auth-gated pages:\n\`\`\`bash\nfirecrawl browser "open <url>" --profile ${opts.profile}\n\`\`\`\nAfter the first \`open\` with \`--profile\`, subsequent browser commands don't need the flag.`
|
|
99
|
-
: '';
|
|
100
|
-
const outputInstructions = {
|
|
101
|
-
terminal: 'Print the full intelligence report to the terminal in well-formatted markdown.',
|
|
102
|
-
json: `Save the report as structured JSON to \`competitive-intel.json\` in the current directory. Tell the user the file path when done.
|
|
103
|
-
|
|
104
|
-
Use this schema:
|
|
105
|
-
\`\`\`json
|
|
106
|
-
{
|
|
107
|
-
"generatedAt": "ISO-8601",
|
|
108
|
-
"competitors": [
|
|
109
|
-
{
|
|
110
|
-
"name": "string",
|
|
111
|
-
"url": "string",
|
|
112
|
-
"pricing": {
|
|
113
|
-
"lastChecked": "ISO-8601",
|
|
114
|
-
"tiers": [{ "name": "string", "price": "string", "period": "string", "features": ["string"], "limits": {} }]
|
|
115
|
-
},
|
|
116
|
-
"recentChanges": [{ "date": "string", "type": "pricing | feature | deprecation", "summary": "string", "details": "string", "source": "url" }],
|
|
117
|
-
"features": [{ "name": "string", "description": "string", "availableOn": ["plan names"] }],
|
|
118
|
-
"sources": ["url"]
|
|
119
|
-
}
|
|
120
|
-
]
|
|
121
|
-
}
|
|
122
|
-
\`\`\``,
|
|
123
|
-
markdown: 'Save the report to a file called `competitive-intel.md` in the current directory. Tell the user the file path when done.',
|
|
124
|
-
};
|
|
125
|
-
return `You are a competitive intelligence agent powered by Firecrawl. You use a real cloud browser to visit competitor sites, navigate dashboards, and extract pricing and feature data.
|
|
126
|
-
|
|
127
|
-
## STEP 1: Launch Browser and Open Live View
|
|
128
|
-
|
|
129
|
-
Before anything else, launch a browser session so the user can watch:
|
|
130
|
-
|
|
131
|
-
\`\`\`bash
|
|
132
|
-
firecrawl browser launch-session --json
|
|
133
|
-
\`\`\`
|
|
134
|
-
|
|
135
|
-
Extract the \`interactiveLiveViewUrl\` from the JSON output and open it (NOT the regular \`liveViewUrl\` -- the interactive one lets the user click and interact):
|
|
136
|
-
|
|
137
|
-
\`\`\`bash
|
|
138
|
-
open "<interactiveLiveViewUrl>" # macOS
|
|
139
|
-
xdg-open "<interactiveLiveViewUrl>" # Linux
|
|
140
|
-
\`\`\`
|
|
141
|
-
|
|
142
|
-
If the \`open\` command fails, print the URL clearly so the user can copy-paste it.
|
|
143
|
-
${profileBlock}
|
|
144
|
-
|
|
145
|
-
## STEP 2: Visit Each Competitor
|
|
146
|
-
|
|
147
|
-
For each competitor:
|
|
148
|
-
|
|
149
|
-
1. Navigate to their main site
|
|
150
|
-
2. Find and visit their **pricing page** -- click through every tier, toggle annual/monthly, expand feature comparison tables
|
|
151
|
-
3. Find **feature/product pages** -- click into each feature, note capabilities and limits
|
|
152
|
-
4. Find **changelog / blog / release notes** -- look for recent updates in the last 30 days
|
|
153
|
-
5. Take snapshots at each step to extract data
|
|
154
|
-
|
|
155
|
-
### Browser commands:
|
|
156
|
-
\`\`\`bash
|
|
157
|
-
firecrawl browser "open <url>"
|
|
158
|
-
firecrawl browser "snapshot"
|
|
159
|
-
firecrawl browser "click @<ref>"
|
|
160
|
-
firecrawl browser "type @<ref> <text>"
|
|
161
|
-
firecrawl browser "scroll down"
|
|
162
|
-
firecrawl browser "scrape"
|
|
163
|
-
\`\`\`
|
|
164
|
-
|
|
165
|
-
You can also use \`firecrawl scrape <url>\` for quick page grabs when browser interaction isn't needed.
|
|
166
|
-
|
|
167
|
-
## Focus
|
|
168
|
-
|
|
169
|
-
${focusInstructions[opts.focus]}
|
|
170
|
-
|
|
171
|
-
## Output Format
|
|
172
|
-
|
|
173
|
-
${outputInstructions[opts.output]}
|
|
174
|
-
|
|
175
|
-
Structure your report with:
|
|
176
|
-
|
|
177
|
-
### Per-Competitor Breakdown
|
|
178
|
-
- Company name & URL
|
|
179
|
-
- Pricing tiers (plan name, price, billing period, key features, limits)
|
|
180
|
-
- Recent changes detected (with dates and source URLs)
|
|
181
|
-
- Feature inventory
|
|
182
|
-
|
|
183
|
-
### Cross-Competitor Comparison
|
|
184
|
-
- Pricing comparison table (plans side-by-side)
|
|
185
|
-
- Feature matrix
|
|
186
|
-
- Key differentiators
|
|
187
|
-
|
|
188
|
-
### Alerts & Insights
|
|
189
|
-
- Notable pricing changes or new tiers
|
|
190
|
-
- Feature gaps or opportunities
|
|
191
|
-
- Market positioning shifts
|
|
192
|
-
|
|
193
|
-
### Sources
|
|
194
|
-
- Every URL visited with what was found
|
|
195
|
-
|
|
196
|
-
---
|
|
197
|
-
|
|
198
|
-
Do everything sequentially -- visit one competitor at a time. Be thorough: click toggle switches, expand accordions, scroll to load lazy content. Extract real data, not summaries of page titles.
|
|
199
|
-
|
|
200
|
-
Start immediately.`;
|
|
201
|
-
}
|
|
202
|
-
// ─── Command registration ───────────────────────────────────────────────────
|
|
203
|
-
function register(parentCmd, backend) {
|
|
204
|
-
const config = backends_1.BACKENDS[backend];
|
|
205
|
-
parentCmd
|
|
206
|
-
.command('competitive-intel')
|
|
207
|
-
.description('Monitor competitor pricing, features, and changes via browser')
|
|
208
|
-
.argument('[competitors...]', 'Competitor URLs or names')
|
|
209
|
-
.option('-y, --yes', 'Auto-approve all tool permissions')
|
|
210
|
-
.action(async (competitorParts, options) => {
|
|
211
|
-
const prefillCompetitors = competitorParts.length > 0 ? competitorParts.join(' ') : undefined;
|
|
212
|
-
const inputs = await gatherInputs(prefillCompetitors ? { competitors: prefillCompetitors } : undefined);
|
|
213
|
-
const parts = [`Monitor these competitors: ${inputs.competitors}`];
|
|
214
|
-
if (inputs.context)
|
|
215
|
-
parts.push(inputs.context);
|
|
216
|
-
const userMessage = parts.join('. ') + '.';
|
|
217
|
-
const skipPermissions = true;
|
|
218
|
-
console.log(`\nLaunching ${config.displayName}...\n`);
|
|
219
|
-
(0, backends_1.launchAgent)(backend, buildSystemPrompt({
|
|
220
|
-
focus: inputs.focus,
|
|
221
|
-
profile: inputs.profile,
|
|
222
|
-
output: inputs.output,
|
|
223
|
-
}), userMessage, skipPermissions);
|
|
224
|
-
});
|
|
225
|
-
}
|
|
226
|
-
//# sourceMappingURL=competitive-intel.js.map
|