drip-agent 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/README.md ADDED
@@ -0,0 +1,116 @@
1
+ # drip-agent
2
+
3
+ Autonomous research intelligence from the command line. Company lookups, people enrichment, and web research — powered by [AgentCash](https://agentcash.dev) micropayments.
4
+
5
+ ## Quick Start
6
+
7
+ ```bash
8
+ # Set up wallet (one-time)
9
+ npx drip-agent setup
10
+
11
+ # Research a company
12
+ npx drip-agent research anthropic.com
13
+
14
+ # Enrich a person
15
+ npx drip-agent enrich john@company.com
16
+
17
+ # Check balance
18
+ npx drip-agent balance
19
+ ```
20
+
21
+ ## Install
22
+
23
+ ```bash
24
+ # Use directly with npx (no install needed)
25
+ npx drip-agent research coinbase.com
26
+
27
+ # Or install globally
28
+ npm install -g drip-agent
29
+ drip-agent research stripe.com
30
+ ```
31
+
32
+ ## Commands
33
+
34
+ ### `research <query>`
35
+
36
+ Look up company intelligence by domain or name.
37
+
38
+ ```bash
39
+ drip-agent research anthropic.com
40
+ drip-agent research "Coinbase" # auto-resolves to coinbase.com
41
+ drip-agent research stripe.com -f json # JSON output
42
+ ```
43
+
44
+ Returns: name, industry, funding, headcount, HQ, tech stack, key links.
45
+
46
+ **Cost:** ~$0.05 per lookup
47
+
48
+ ### `enrich <email|linkedin>`
49
+
50
+ Enrich a person's profile by email or LinkedIn URL.
51
+
52
+ ```bash
53
+ drip-agent enrich john@company.com
54
+ drip-agent enrich https://linkedin.com/in/johndoe
55
+ drip-agent enrich jane@startup.io -f json
56
+ ```
57
+
58
+ Returns: name, title, company, location, contact info, employment history.
59
+
60
+ **Cost:** ~$0.05 per lookup
61
+
62
+ ### `setup [invite-code]`
63
+
64
+ Set up your AgentCash wallet for paid API access.
65
+
66
+ ```bash
67
+ drip-agent setup # basic setup
68
+ drip-agent setup AC-XXXX-XXXX # with invite code for free credits
69
+ ```
70
+
71
+ ### `balance`
72
+
73
+ Check your AgentCash wallet balance and deposit link.
74
+
75
+ ```bash
76
+ drip-agent balance
77
+ ```
78
+
79
+ ## How It Works
80
+
81
+ 1. You run a command
82
+ 2. DRIP calls [StableEnrich](https://stableenrich.dev) via [AgentCash](https://agentcash.dev)
83
+ 3. Payment is automatic — USDC micropayment on Solana
84
+ 4. Results appear in your terminal
85
+
86
+ No API keys. No subscriptions. Pay per query.
87
+
88
+ ## Pricing
89
+
90
+ | Command | Cost |
91
+ |---------|------|
92
+ | `research` | ~$0.05 |
93
+ | `enrich` | ~$0.05 |
94
+
95
+ Payments settle on success only — failed requests don't cost anything.
96
+
97
+ ## Programmatic Usage
98
+
99
+ ```js
100
+ import { companyResearch, personEnrich } from "drip-agent";
101
+
102
+ const company = await companyResearch("anthropic.com");
103
+ const person = await personEnrich({ email: "john@company.com" });
104
+ ```
105
+
106
+ Requires AgentCash wallet set up locally (`npx drip-agent setup`).
107
+
108
+ ## Links
109
+
110
+ - **Website:** [drip.surf](https://drip.surf)
111
+ - **Agent:** [agent.drip.surf](https://agent.drip.surf)
112
+ - **Token:** $DRIP on PumpFun
113
+
114
+ ---
115
+
116
+ Built by DRIP × AgentCash
@@ -0,0 +1,46 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { createRequire } from "module";
4
+ import { program } from "commander";
5
+ import { researchCommand } from "../src/commands/research.js";
6
+ import { enrichCommand } from "../src/commands/enrich.js";
7
+ import { setupCommand } from "../src/commands/setup.js";
8
+ import { balanceCommand } from "../src/commands/balance.js";
9
+ import { interactiveMode } from "../src/interactive.js";
10
+
11
+ const require = createRequire(import.meta.url);
12
+ const pkg = require("../package.json");
13
+
14
+ program
15
+ .name("drip-agent")
16
+ .description("DRIP — autonomous research intelligence from the terminal")
17
+ .version(pkg.version);
18
+
19
+ program
20
+ .command("research <query>")
21
+ .description("Research a company by domain or name")
22
+ .option("-f, --format <type>", "Output format: text, json, markdown", "text")
23
+ .action(researchCommand);
24
+
25
+ program
26
+ .command("enrich <identifier>")
27
+ .description("Enrich a person by email or LinkedIn URL")
28
+ .option("-f, --format <type>", "Output format: text, json, markdown", "text")
29
+ .action(enrichCommand);
30
+
31
+ program
32
+ .command("setup [invite-code]")
33
+ .description("Set up AgentCash wallet for paid API access")
34
+ .action(setupCommand);
35
+
36
+ program
37
+ .command("balance")
38
+ .description("Check your AgentCash wallet balance")
39
+ .action(balanceCommand);
40
+
41
+ // No arguments → interactive mode
42
+ if (process.argv.length <= 2) {
43
+ interactiveMode();
44
+ } else {
45
+ program.parse();
46
+ }
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "drip-agent",
3
+ "version": "0.1.0",
4
+ "description": "DRIP — autonomous research intelligence from the command line. Company lookups, people enrichment, and web research powered by AgentCash micropayments.",
5
+ "keywords": [
6
+ "drip",
7
+ "research",
8
+ "agent",
9
+ "ai",
10
+ "company-research",
11
+ "people-enrichment",
12
+ "agentcash",
13
+ "x402"
14
+ ],
15
+ "license": "MIT",
16
+ "author": "DRIP",
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "https://github.com/drip-agent/drip"
20
+ },
21
+ "homepage": "https://drip.surf",
22
+ "bin": {
23
+ "drip-agent": "./bin/drip-agent.js"
24
+ },
25
+ "type": "module",
26
+ "exports": {
27
+ ".": "./src/index.js"
28
+ },
29
+ "files": [
30
+ "bin/",
31
+ "src/",
32
+ "README.md"
33
+ ],
34
+ "engines": {
35
+ "node": ">=18"
36
+ },
37
+ "dependencies": {
38
+ "@inquirer/prompts": "^8.3.0",
39
+ "chalk": "^5.4.0",
40
+ "commander": "^13.0.0",
41
+ "ora": "^8.0.0"
42
+ }
43
+ }
@@ -0,0 +1,28 @@
1
+ import { execSync } from "child_process";
2
+ import chalk from "chalk";
3
+
4
+ export async function balanceCommand() {
5
+ try {
6
+ const out = execSync("npx agentcash@latest wallet info", {
7
+ encoding: "utf-8",
8
+ stdio: ["pipe", "pipe", "pipe"],
9
+ });
10
+ const data = JSON.parse(out);
11
+ if (data.success) {
12
+ const w = data.data;
13
+ console.log(chalk.cyan.bold("\n 💧 DRIP Wallet\n"));
14
+ console.log(` Address: ${chalk.dim(w.address)}`);
15
+ console.log(` Balance: ${chalk.green.bold("$" + w.balance)} USDC`);
16
+ if (w.chains) {
17
+ for (const c of w.chains) {
18
+ console.log(` ${chalk.dim(c.paymentNetwork)}: $${c.balance}`);
19
+ }
20
+ }
21
+ console.log(`\n Deposit: ${chalk.underline(w.depositLink)}\n`);
22
+ } else {
23
+ console.log(out);
24
+ }
25
+ } catch {
26
+ console.error(chalk.red("No wallet found. Run: drip-agent setup"));
27
+ }
28
+ }
@@ -0,0 +1,109 @@
1
+ import chalk from "chalk";
2
+ import ora from "ora";
3
+ import { personEnrich } from "../index.js";
4
+
5
+ export async function enrichCommand(identifier, options) {
6
+ const isEmail = identifier.includes("@");
7
+ const isLinkedIn = identifier.includes("linkedin.com");
8
+
9
+ if (!isEmail && !isLinkedIn) {
10
+ console.error(
11
+ chalk.red("\n Provide an email address or LinkedIn URL\n")
12
+ );
13
+ console.log(
14
+ chalk.dim(" Examples:\n") +
15
+ chalk.dim(" drip-agent enrich john@company.com\n") +
16
+ chalk.dim(
17
+ " drip-agent enrich https://linkedin.com/in/johndoe\n"
18
+ )
19
+ );
20
+ process.exit(1);
21
+ }
22
+
23
+ const spinner = ora({
24
+ text: chalk.dim(`Enriching ${identifier}...`),
25
+ color: "cyan",
26
+ }).start();
27
+
28
+ try {
29
+ const params = isEmail
30
+ ? { email: identifier }
31
+ : { linkedinUrl: identifier };
32
+
33
+ const data = await personEnrich(params);
34
+ spinner.stop();
35
+
36
+ if (options.format === "json") {
37
+ console.log(JSON.stringify(data, null, 2));
38
+ return;
39
+ }
40
+
41
+ const person = data?.person || data?.data?.person || data;
42
+
43
+ if (!person || (typeof person === "object" && Object.keys(person).length === 0)) {
44
+ console.log(chalk.yellow(`\n No data found for ${identifier}\n`));
45
+ return;
46
+ }
47
+
48
+ console.log("");
49
+ console.log(
50
+ chalk.cyan.bold(
51
+ ` 💧 ${person.first_name || ""} ${person.last_name || ""}`
52
+ )
53
+ );
54
+ console.log(chalk.dim(` ${"─".repeat(50)}`));
55
+
56
+ if (person.title) {
57
+ console.log(`\n ${chalk.white(person.title)}`);
58
+ }
59
+
60
+ console.log("");
61
+
62
+ const fields = [
63
+ ["Company", person.organization?.name || person.organization_name],
64
+ ["Email", person.email],
65
+ ["Phone", person.phone_numbers?.[0]?.sanitized_number],
66
+ ["Location", [person.city, person.state, person.country].filter(Boolean).join(", ")],
67
+ ["LinkedIn", person.linkedin_url],
68
+ ["Twitter", person.twitter_url],
69
+ ["GitHub", person.github_url],
70
+ ["Seniority", person.seniority],
71
+ ["Department", person.departments?.join(", ")],
72
+ ];
73
+
74
+ for (const [label, value] of fields) {
75
+ if (value) {
76
+ console.log(` ${chalk.dim(label.padEnd(14))} ${value}`);
77
+ }
78
+ }
79
+
80
+ if (person.employment_history?.length > 0) {
81
+ console.log(chalk.dim(`\n Recent roles:`));
82
+ for (const job of person.employment_history.slice(0, 3)) {
83
+ const current = job.current ? chalk.green(" ●") : "";
84
+ console.log(
85
+ ` ${chalk.dim("·")} ${job.title} at ${job.organization_name}${current}`
86
+ );
87
+ }
88
+ }
89
+
90
+ console.log(chalk.dim(`\n ${"─".repeat(50)}`));
91
+ console.log(chalk.dim(" Powered by DRIP × AgentCash\n"));
92
+ } catch (err) {
93
+ spinner.stop();
94
+ const msg = err.message || String(err);
95
+
96
+ if (msg.includes("Insufficient balance") || msg.includes("balance")) {
97
+ console.error(
98
+ chalk.red("\n Insufficient balance. Run: drip-agent balance\n")
99
+ );
100
+ } else if (msg.includes("wallet") || msg.includes("agentcash")) {
101
+ console.error(
102
+ chalk.red("\n AgentCash not set up. Run: drip-agent setup\n")
103
+ );
104
+ } else {
105
+ console.error(chalk.red(`\n Enrichment failed: ${msg}\n`));
106
+ }
107
+ process.exit(1);
108
+ }
109
+ }
@@ -0,0 +1,88 @@
1
+ import chalk from "chalk";
2
+ import ora from "ora";
3
+ import { companyResearch } from "../index.js";
4
+
5
+ export async function researchCommand(query, options) {
6
+ // Normalize: if it looks like a domain, use directly; otherwise guess
7
+ const domain = query.includes(".")
8
+ ? query
9
+ : `${query.toLowerCase().replace(/\s+/g, "")}.com`;
10
+
11
+ const spinner = ora({
12
+ text: chalk.dim(`Researching ${domain}...`),
13
+ color: "cyan",
14
+ }).start();
15
+
16
+ try {
17
+ const data = await companyResearch(domain);
18
+ spinner.stop();
19
+
20
+ if (options.format === "json") {
21
+ console.log(JSON.stringify(data, null, 2));
22
+ return;
23
+ }
24
+
25
+ // Extract org data — handle Apollo's response shape
26
+ const org = data?.organization || data?.data?.organization || data;
27
+
28
+ if (!org || (typeof org === "object" && Object.keys(org).length === 0)) {
29
+ console.log(chalk.yellow(`\n No data found for ${domain}\n`));
30
+ return;
31
+ }
32
+
33
+ console.log("");
34
+ console.log(chalk.cyan.bold(` 💧 ${org.name || domain}`));
35
+ console.log(chalk.dim(` ${"─".repeat(50)}`));
36
+
37
+ if (org.short_description || org.description) {
38
+ console.log(
39
+ `\n ${chalk.white(org.short_description || org.description)}`
40
+ );
41
+ }
42
+
43
+ console.log("");
44
+
45
+ const fields = [
46
+ ["Industry", org.industry],
47
+ ["Founded", org.founded_year],
48
+ ["Employees", org.estimated_num_employees?.toLocaleString()],
49
+ ["HQ", [org.city, org.state, org.country].filter(Boolean).join(", ")],
50
+ ["Website", org.website_url || org.primary_domain],
51
+ ["LinkedIn", org.linkedin_url],
52
+ ["Funding", org.total_funding ? `$${(org.total_funding / 1_000_000).toFixed(1)}M` : null],
53
+ ["Latest Round", org.latest_funding_round_type],
54
+ ["Tech Stack", org.technologies?.slice(0, 5)?.join(", ")],
55
+ ];
56
+
57
+ for (const [label, value] of fields) {
58
+ if (value) {
59
+ console.log(` ${chalk.dim(label.padEnd(14))} ${value}`);
60
+ }
61
+ }
62
+
63
+ if (org.keywords?.length > 0) {
64
+ console.log(
65
+ `\n ${chalk.dim("Tags")} ${org.keywords.slice(0, 8).join(" · ")}`
66
+ );
67
+ }
68
+
69
+ console.log(chalk.dim(`\n ${"─".repeat(50)}`));
70
+ console.log(chalk.dim(" Powered by DRIP × AgentCash\n"));
71
+ } catch (err) {
72
+ spinner.stop();
73
+ const msg = err.message || String(err);
74
+
75
+ if (msg.includes("Insufficient balance") || msg.includes("balance")) {
76
+ console.error(
77
+ chalk.red("\n Insufficient balance. Run: drip-agent balance\n")
78
+ );
79
+ } else if (msg.includes("wallet") || msg.includes("agentcash")) {
80
+ console.error(
81
+ chalk.red("\n AgentCash not set up. Run: drip-agent setup\n")
82
+ );
83
+ } else {
84
+ console.error(chalk.red(`\n Research failed: ${msg}\n`));
85
+ }
86
+ process.exit(1);
87
+ }
88
+ }
@@ -0,0 +1,29 @@
1
+ import chalk from "chalk";
2
+ import { execSync } from "child_process";
3
+
4
+ export async function setupCommand(inviteCode) {
5
+ console.log(chalk.cyan.bold("\n 💧 DRIP Agent Setup\n"));
6
+
7
+ try {
8
+ const cmd = inviteCode
9
+ ? `npx agentcash@latest onboard ${inviteCode}`
10
+ : `npx agentcash@latest onboard`;
11
+
12
+ console.log(chalk.dim(" Setting up AgentCash wallet...\n"));
13
+
14
+ execSync(cmd, {
15
+ encoding: "utf-8",
16
+ stdio: "inherit",
17
+ timeout: 120_000,
18
+ });
19
+
20
+ console.log(chalk.green.bold("\n ✓ Setup complete!\n"));
21
+ console.log(chalk.dim(" Try it out:"));
22
+ console.log(` ${chalk.cyan("drip-agent research anthropic.com")}`);
23
+ console.log(` ${chalk.cyan("drip-agent enrich john@company.com")}`);
24
+ console.log(` ${chalk.cyan("drip-agent balance")}\n`);
25
+ } catch (err) {
26
+ console.error(chalk.red(`\n Setup failed: ${err.message}\n`));
27
+ process.exit(1);
28
+ }
29
+ }
package/src/index.js ADDED
@@ -0,0 +1,48 @@
1
+ import { execSync } from "child_process";
2
+
3
+ const STABLEENRICH = "https://stableenrich.dev";
4
+
5
+ /**
6
+ * Make a paid API call via AgentCash CLI.
7
+ * Returns parsed JSON response.
8
+ */
9
+ export function agentcashFetch(url, method = "GET", body = null) {
10
+ const args = [`npx agentcash@latest fetch '${url}'`, `-m ${method}`, `--format json`];
11
+ if (body) {
12
+ args.push(`-b '${JSON.stringify(body)}'`);
13
+ }
14
+
15
+ const output = execSync(args.join(" "), {
16
+ encoding: "utf-8",
17
+ timeout: 60_000,
18
+ stdio: ["pipe", "pipe", "pipe"],
19
+ });
20
+
21
+ return JSON.parse(output.trim());
22
+ }
23
+
24
+ /**
25
+ * Research a company via StableEnrich Apollo org enrichment.
26
+ */
27
+ export async function companyResearch(domain) {
28
+ return agentcashFetch(
29
+ `${STABLEENRICH}/api/apollo/org-enrich`,
30
+ "POST",
31
+ { domain }
32
+ );
33
+ }
34
+
35
+ /**
36
+ * Enrich a person via StableEnrich Apollo people enrichment.
37
+ */
38
+ export async function personEnrich({ email, linkedinUrl }) {
39
+ const body = {};
40
+ if (email) body.email = email;
41
+ if (linkedinUrl) body.linkedin_url = linkedinUrl;
42
+
43
+ return agentcashFetch(
44
+ `${STABLEENRICH}/api/apollo/people-enrich`,
45
+ "POST",
46
+ body
47
+ );
48
+ }
@@ -0,0 +1,95 @@
1
+ import { select, input } from "@inquirer/prompts";
2
+ import chalk from "chalk";
3
+ import { researchCommand } from "./commands/research.js";
4
+ import { enrichCommand } from "./commands/enrich.js";
5
+ import { setupCommand } from "./commands/setup.js";
6
+ import { balanceCommand } from "./commands/balance.js";
7
+
8
+ export async function interactiveMode() {
9
+ console.log(
10
+ chalk.cyan.bold("\n 💧 DRIP") +
11
+ chalk.dim(" — autonomous research intelligence\n")
12
+ );
13
+
14
+ const action = await select({
15
+ message: "What do you want to do?",
16
+ choices: [
17
+ {
18
+ name: "🔍 Research a company",
19
+ value: "research",
20
+ description: "Look up company intel by domain or name (~$0.05)",
21
+ },
22
+ {
23
+ name: "👤 Enrich a person",
24
+ value: "enrich",
25
+ description: "Find profile data by email or LinkedIn (~$0.05)",
26
+ },
27
+ {
28
+ name: "💰 Check balance",
29
+ value: "balance",
30
+ description: "View your AgentCash wallet balance",
31
+ },
32
+ {
33
+ name: "⚙️ Set up wallet",
34
+ value: "setup",
35
+ description: "Configure AgentCash for paid API access",
36
+ },
37
+ ],
38
+ });
39
+
40
+ switch (action) {
41
+ case "research": {
42
+ const query = await input({
43
+ message: "Company domain or name:",
44
+ required: true,
45
+ validate: (v) => (v.trim() ? true : "Enter a company domain or name"),
46
+ });
47
+ await researchCommand(query, { format: "text" });
48
+ break;
49
+ }
50
+
51
+ case "enrich": {
52
+ const identifier = await input({
53
+ message: "Email or LinkedIn URL:",
54
+ required: true,
55
+ validate: (v) => {
56
+ const s = v.trim();
57
+ if (!s) return "Enter an email or LinkedIn URL";
58
+ if (!s.includes("@") && !s.includes("linkedin.com"))
59
+ return "Enter a valid email or LinkedIn URL";
60
+ return true;
61
+ },
62
+ });
63
+ await enrichCommand(identifier, { format: "text" });
64
+ break;
65
+ }
66
+
67
+ case "balance":
68
+ await balanceCommand();
69
+ break;
70
+
71
+ case "setup": {
72
+ const code = await input({
73
+ message: "Invite code (leave empty to skip):",
74
+ });
75
+ await setupCommand(code || undefined);
76
+ break;
77
+ }
78
+ }
79
+
80
+ // Ask if they want to continue
81
+ console.log("");
82
+ const again = await select({
83
+ message: "Continue?",
84
+ choices: [
85
+ { name: "Yes — do something else", value: true },
86
+ { name: "No — exit", value: false },
87
+ ],
88
+ });
89
+
90
+ if (again) {
91
+ await interactiveMode();
92
+ } else {
93
+ console.log(chalk.dim("\n drip.surf · $DRIP\n"));
94
+ }
95
+ }