Skip to content

Commit 801b6bd

Browse files
zhubzyclaude
andcommitted
fix(tools): instanceId on duplicate bubbles + pass this.context to HttpBubble
- people-search-tool + company-enrichment-tool: add instanceId to inner FullEnrichBubble calls (require-instance-id) - reddit-scrape-tool: pass this.context to HttpBubble (no-null-context); type Reddit API response without any Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 0f71f24 commit 801b6bd

10 files changed

Lines changed: 117 additions & 87 deletions

File tree

packages/bubble-core/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@bubblelab/bubble-core",
3-
"version": "0.1.296",
3+
"version": "0.1.297",
44
"type": "module",
55
"license": "Apache-2.0",
66
"main": "./dist/index.js",

packages/bubble-core/src/bubbles/tool-bubble/company-enrichment-tool.ts

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -343,41 +343,43 @@ export class CompanyEnrichmentTool extends ToolBubble<
343343
const { companyIdentifier } = this.params;
344344
const identifierType = this.detectIdentifierType(companyIdentifier);
345345

346-
// Build FullEnrich search body based on identifier type.
346+
// Build FullEnrich search filters based on identifier type.
347347
// FullEnrich doesn't support LinkedIn URL search directly — fall back
348348
// to parsing the slug as a name filter.
349-
const params: Record<string, unknown> = {
350-
operation: 'company_search',
351-
limit: 1,
352-
credentials,
353-
};
354-
349+
let filterKey: 'domains' | 'names';
350+
let filterValue: string;
355351
if (identifierType === 'domain') {
356-
params.domains = [{ value: companyIdentifier }];
352+
filterKey = 'domains';
353+
filterValue = companyIdentifier;
357354
} else if (identifierType === 'linkedin') {
358-
// Extract slug: linkedin.com/company/<slug>/... → <slug>
359355
const match = companyIdentifier.match(
360356
/linkedin\.com\/company\/([^/?]+)/
361357
);
362-
const slug = match?.[1] ?? companyIdentifier;
363-
params.names = [{ value: slug }];
358+
filterKey = 'names';
359+
filterValue = match?.[1] ?? companyIdentifier;
364360
} else {
365-
params.names = [{ value: companyIdentifier }];
361+
filterKey = 'names';
362+
filterValue = companyIdentifier;
366363
}
367364

368-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
369-
const feResult = await new FullEnrichBubble(
370-
params as any,
371-
this.context
365+
const company_search = await new FullEnrichBubble(
366+
{
367+
operation: 'company_search',
368+
limit: 1,
369+
[filterKey]: [{ value: filterValue }],
370+
credentials,
371+
},
372+
this.context,
373+
'company_search'
372374
).action();
373375

374-
if (!feResult.success) {
376+
if (!company_search.success) {
375377
return this.createErrorResult(
376-
feResult.error || 'FullEnrich company search failed'
378+
company_search.error || 'FullEnrich company search failed'
377379
);
378380
}
379381

380-
const data = feResult.data as {
382+
const data = company_search.data as {
381383
companies?: Array<Record<string, unknown>>;
382384
};
383385
const company = data.companies?.[0];

packages/bubble-core/src/bubbles/tool-bubble/people-search-tool.ts

Lines changed: 46 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -987,57 +987,59 @@ export class PeopleSearchTool extends ToolBubble<
987987
const feLimit = Math.min(limit, 100);
988988

989989
try {
990-
const fullEnrichParams: Record<string, unknown> = {
991-
operation: 'people_search',
992-
limit: feLimit,
993-
credentials,
994-
};
995-
if (allJobTitles.length > 0)
996-
fullEnrichParams.current_position_titles = allJobTitles.map((v) => ({
997-
value: v,
998-
}));
999-
if (companyName)
1000-
fullEnrichParams.current_company_names = [{ value: companyName }];
1001-
if (pastCompanyName)
1002-
fullEnrichParams.past_company_names = [{ value: pastCompanyName }];
1003-
if (allLocations.length > 0)
1004-
fullEnrichParams.person_locations = allLocations.map((v) => ({
1005-
value: v,
1006-
}));
1007-
if (skills?.length)
1008-
fullEnrichParams.person_skills = skills.map((v) => ({ value: v }));
1009-
if (seniorityLevels?.length)
1010-
fullEnrichParams.current_position_seniority_level = seniorityLevels.map(
1011-
(v) => ({ value: v })
1012-
);
1013-
if (companyIndustries?.length)
1014-
fullEnrichParams.current_company_industries = companyIndustries.map(
1015-
(v) => ({ value: v })
1016-
);
1017-
if (
1018-
minCompanyHeadcount !== undefined ||
1019-
maxCompanyHeadcount !== undefined
1020-
) {
1021-
const range: { min?: number; max?: number } = {};
1022-
if (minCompanyHeadcount !== undefined) range.min = minCompanyHeadcount;
1023-
if (maxCompanyHeadcount !== undefined) range.max = maxCompanyHeadcount;
1024-
fullEnrichParams.current_company_headcounts = [range];
1025-
}
1026-
if (cursor) fullEnrichParams.search_after = cursor;
990+
const headcountRange: { min?: number; max?: number } = {};
991+
if (minCompanyHeadcount !== undefined)
992+
headcountRange.min = minCompanyHeadcount;
993+
if (maxCompanyHeadcount !== undefined)
994+
headcountRange.max = maxCompanyHeadcount;
1027995

1028-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
1029-
const feResult = await new FullEnrichBubble(
1030-
fullEnrichParams as any,
1031-
this.context
996+
const people_search = await new FullEnrichBubble(
997+
{
998+
operation: 'people_search',
999+
limit: feLimit,
1000+
...(allJobTitles.length > 0 && {
1001+
current_position_titles: allJobTitles.map((v) => ({ value: v })),
1002+
}),
1003+
...(companyName && {
1004+
current_company_names: [{ value: companyName }],
1005+
}),
1006+
...(pastCompanyName && {
1007+
past_company_names: [{ value: pastCompanyName }],
1008+
}),
1009+
...(allLocations.length > 0 && {
1010+
person_locations: allLocations.map((v) => ({ value: v })),
1011+
}),
1012+
...(skills?.length && {
1013+
person_skills: skills.map((v) => ({ value: v })),
1014+
}),
1015+
...(seniorityLevels?.length && {
1016+
current_position_seniority_level: seniorityLevels.map((v) => ({
1017+
value: v,
1018+
})),
1019+
}),
1020+
...(companyIndustries?.length && {
1021+
current_company_industries: companyIndustries.map((v) => ({
1022+
value: v,
1023+
})),
1024+
}),
1025+
...((minCompanyHeadcount !== undefined ||
1026+
maxCompanyHeadcount !== undefined) && {
1027+
current_company_headcounts: [headcountRange],
1028+
}),
1029+
...(cursor && { search_after: cursor }),
1030+
credentials,
1031+
},
1032+
this.context,
1033+
'people_search'
10321034
).action();
10331035

1034-
if (!feResult.success) {
1036+
if (!people_search.success) {
10351037
return this.createErrorResult(
1036-
feResult.error || 'FullEnrich people search failed'
1038+
people_search.error || 'FullEnrich people search failed'
10371039
);
10381040
}
10391041

1040-
const data = feResult.data as {
1042+
const data = people_search.data as {
10411043
people?: Array<Record<string, unknown>>;
10421044
metadata?: {
10431045
total: number;

packages/bubble-core/src/bubbles/tool-bubble/reddit-scrape-tool.ts

Lines changed: 40 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,25 @@ import type { BubbleContext } from '../../types/bubble.js';
44
import { CredentialType, type BubbleName } from '@bubblelab/shared-schemas';
55
import { HttpBubble } from '../service-bubble/http.js';
66

7+
// Raw Reddit API post shape — subset of fields we read.
8+
interface RedditApiPost {
9+
title?: string;
10+
url?: string;
11+
author?: string;
12+
score?: number;
13+
num_comments?: number;
14+
created_utc?: number;
15+
permalink?: string;
16+
selftext?: string;
17+
selftext_html?: string;
18+
is_self?: boolean;
19+
subreddit?: string;
20+
post_hint?: string;
21+
thumbnail?: string;
22+
domain?: string;
23+
link_flair_text?: string;
24+
}
25+
726
// Reddit post structure schema
827
const RedditPostSchema = z.object({
928
title: z.string().describe('Post title'),
@@ -304,7 +323,8 @@ export class RedditScrapeTool extends ToolBubble<
304323
}
305324

306325
// Get the 'after' parameter for next page
307-
after = redditData?.data?.after || null;
326+
const listing = redditData as { data?: { after?: string } } | undefined;
327+
after = listing?.data?.after ?? null;
308328

309329
// If no more posts available, break
310330
if (!after || posts.length === 0) {
@@ -355,24 +375,27 @@ export class RedditScrapeTool extends ToolBubble<
355375
/**
356376
* Fetch data from Reddit's JSON API via HttpBubble (wall-clock timeout via AbortController).
357377
*/
358-
private async fetchRedditData(url: string): Promise<any> {
359-
const result = await new HttpBubble({
360-
url,
361-
method: 'GET',
362-
headers: {
363-
'User-Agent': this.getRandomUserAgent(),
378+
private async fetchRedditData(url: string): Promise<unknown> {
379+
const reddit_http = await new HttpBubble(
380+
{
381+
url,
382+
method: 'GET',
383+
headers: {
384+
'User-Agent': this.getRandomUserAgent(),
385+
},
386+
timeout: 15000,
387+
followRedirects: true,
364388
},
365-
timeout: 15000,
366-
followRedirects: true,
367-
}).action();
389+
this.context
390+
).action();
368391

369-
if (!result.success || !result.data) {
392+
if (!reddit_http.success || !reddit_http.data) {
370393
throw new Error(
371-
`Network error: ${result.error ?? 'HttpBubble returned no data'}`
394+
`Network error: ${reddit_http.error ?? 'HttpBubble returned no data'}`
372395
);
373396
}
374397

375-
const { status, statusText, json, body } = result.data;
398+
const { status, statusText, json, body } = reddit_http.data;
376399
if (status !== 200) {
377400
throw new Error(`Reddit API returned status ${status}: ${statusText}`);
378401
}
@@ -389,8 +412,11 @@ export class RedditScrapeTool extends ToolBubble<
389412
/**
390413
* Parse Reddit JSON response into standardized post objects
391414
*/
392-
private parseRedditResponse(data: any): RedditPost[] {
415+
private parseRedditResponse(raw: unknown): RedditPost[] {
393416
const posts: RedditPost[] = [];
417+
const data = raw as
418+
| { data?: { children?: Array<{ data?: RedditApiPost }> } }
419+
| undefined;
394420

395421
try {
396422
if (data?.data?.children) {

packages/bubble-runtime/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@bubblelab/bubble-runtime",
3-
"version": "0.1.296",
3+
"version": "0.1.297",
44
"type": "module",
55
"license": "Apache-2.0",
66
"main": "./dist/index.js",

packages/bubble-scope-manager/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@bubblelab/ts-scope-manager",
3-
"version": "0.1.296",
3+
"version": "0.1.297",
44
"private": false,
55
"license": "MIT",
66
"type": "commonjs",

packages/bubble-shared-schemas/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@bubblelab/shared-schemas",
3-
"version": "0.1.296",
3+
"version": "0.1.297",
44
"type": "module",
55
"license": "Apache-2.0",
66
"main": "./dist/index.js",

packages/create-bubblelab-app/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "create-bubblelab-app",
3-
"version": "0.1.296",
3+
"version": "0.1.297",
44
"type": "module",
55
"license": "Apache-2.0",
66
"description": "Create BubbleLab AI agent applications with one command",

packages/create-bubblelab-app/templates/basic/package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@
1111
"typecheck": "tsc --noEmit"
1212
},
1313
"dependencies": {
14-
"@bubblelab/bubble-core": "^0.1.296",
15-
"@bubblelab/bubble-runtime": "^0.1.296",
16-
"@bubblelab/shared-schemas": "^0.1.296",
14+
"@bubblelab/bubble-core": "^0.1.297",
15+
"@bubblelab/bubble-runtime": "^0.1.297",
16+
"@bubblelab/shared-schemas": "^0.1.297",
1717
"dotenv": "^16.4.5"
1818
},
1919
"devDependencies": {

packages/create-bubblelab-app/templates/reddit-scraper/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
"typecheck": "tsc --noEmit"
1212
},
1313
"dependencies": {
14-
"@bubblelab/bubble-core": "^0.1.296",
15-
"@bubblelab/bubble-runtime": "^0.1.296",
14+
"@bubblelab/bubble-core": "^0.1.297",
15+
"@bubblelab/bubble-runtime": "^0.1.297",
1616
"dotenv": "^16.4.5"
1717
},
1818
"devDependencies": {

0 commit comments

Comments
 (0)