@narumitw/pi-firecrawl 0.1.10 → 0.1.12

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 CHANGED
@@ -14,6 +14,7 @@ Use it to give your AI coding agent reliable web research capabilities for docum
14
14
  - Discover URLs with Firecrawl map.
15
15
  - Search the web and optionally scrape search result pages.
16
16
  - Supports Firecrawl API endpoint overrides.
17
+ - Shows statusline activity only while Firecrawl tools are running.
17
18
  - Never logs or displays your Firecrawl API key.
18
19
 
19
20
  ## 📦 Install
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@narumitw/pi-firecrawl",
3
- "version": "0.1.10",
3
+ "version": "0.1.12",
4
4
  "description": "Pi extension that exposes Firecrawl web scraping and crawling tools.",
5
5
  "type": "module",
6
6
  "license": "MIT",
package/src/firecrawl.ts CHANGED
@@ -10,6 +10,10 @@ interface FirecrawlState {
10
10
  apiUrl: string;
11
11
  }
12
12
 
13
+ interface StatusContext {
14
+ ui: { setStatus: (key: string, value: string | undefined) => void };
15
+ }
16
+
13
17
  const state: FirecrawlState = {
14
18
  apiUrl: normalizeApiUrl(process.env.FIRECRAWL_API_URL ?? process.env.FIRECRAWL_BASE_URL),
15
19
  };
@@ -68,9 +72,11 @@ const scrapeTool = defineTool({
68
72
  ),
69
73
  location: Type.Optional(Type.Any({ description: "Firecrawl location options." })),
70
74
  }),
71
- async execute(_toolCallId, params, signal) {
72
- const payload = await firecrawlRequest("POST", "/scrape", cleanObject(params), signal);
73
- return jsonResult(payload);
75
+ async execute(_toolCallId, params, signal, _onUpdate, ctx) {
76
+ return withStatus(ctx, "firecrawl: scrape", async () => {
77
+ const payload = await firecrawlRequest("POST", "/scrape", cleanObject(params), signal);
78
+ return jsonResult(payload);
79
+ });
74
80
  },
75
81
  });
76
82
 
@@ -104,9 +110,11 @@ const crawlTool = defineTool({
104
110
  ),
105
111
  webhook: Type.Optional(Type.Any({ description: "Firecrawl webhook configuration." })),
106
112
  }),
107
- async execute(_toolCallId, params, signal) {
108
- const payload = await firecrawlRequest("POST", "/crawl", cleanObject(params), signal);
109
- return jsonResult(payload);
113
+ async execute(_toolCallId, params, signal, _onUpdate, ctx) {
114
+ return withStatus(ctx, "firecrawl: crawl", async () => {
115
+ const payload = await firecrawlRequest("POST", "/crawl", cleanObject(params), signal);
116
+ return jsonResult(payload);
117
+ });
110
118
  },
111
119
  });
112
120
 
@@ -118,14 +126,16 @@ const crawlStatusTool = defineTool({
118
126
  parameters: Type.Object({
119
127
  id: Type.String({ description: "Crawl job id returned by firecrawl_crawl." }),
120
128
  }),
121
- async execute(_toolCallId, params, signal) {
122
- const payload = await firecrawlRequest(
123
- "GET",
124
- `/crawl/${encodeURIComponent(params.id)}`,
125
- undefined,
126
- signal,
127
- );
128
- return jsonResult(payload);
129
+ async execute(_toolCallId, params, signal, _onUpdate, ctx) {
130
+ return withStatus(ctx, "firecrawl: crawl status", async () => {
131
+ const payload = await firecrawlRequest(
132
+ "GET",
133
+ `/crawl/${encodeURIComponent(params.id)}`,
134
+ undefined,
135
+ signal,
136
+ );
137
+ return jsonResult(payload);
138
+ });
129
139
  },
130
140
  });
131
141
 
@@ -148,9 +158,11 @@ const mapTool = defineTool({
148
158
  ),
149
159
  limit: Type.Optional(Type.Number({ description: "Maximum number of URLs to return." })),
150
160
  }),
151
- async execute(_toolCallId, params, signal) {
152
- const payload = await firecrawlRequest("POST", "/map", cleanObject(params), signal);
153
- return jsonResult(payload);
161
+ async execute(_toolCallId, params, signal, _onUpdate, ctx) {
162
+ return withStatus(ctx, "firecrawl: map", async () => {
163
+ const payload = await firecrawlRequest("POST", "/map", cleanObject(params), signal);
164
+ return jsonResult(payload);
165
+ });
154
166
  },
155
167
  });
156
168
 
@@ -170,9 +182,11 @@ const searchTool = defineTool({
170
182
  Type.Any({ description: "Firecrawl scrapeOptions for search result pages." }),
171
183
  ),
172
184
  }),
173
- async execute(_toolCallId, params, signal) {
174
- const payload = await firecrawlRequest("POST", "/search", cleanObject(params), signal);
175
- return jsonResult(payload);
185
+ async execute(_toolCallId, params, signal, _onUpdate, ctx) {
186
+ return withStatus(ctx, "firecrawl: search", async () => {
187
+ const payload = await firecrawlRequest("POST", "/search", cleanObject(params), signal);
188
+ return jsonResult(payload);
189
+ });
176
190
  },
177
191
  });
178
192
 
@@ -187,12 +201,11 @@ export default function firecrawl(pi: ExtensionAPI) {
187
201
  description: "Show Firecrawl extension configuration status",
188
202
  handler: async (_args, ctx) => {
189
203
  ctx.ui.notify(buildStatusMessage(), hasApiKey() ? "info" : "warning");
190
- updateStatus(ctx);
191
204
  },
192
205
  });
193
206
 
194
207
  pi.on("session_start", (_event, ctx) => {
195
- updateStatus(ctx);
208
+ ctx.ui.setStatus(STATUS_KEY, undefined);
196
209
  });
197
210
 
198
211
  pi.on("session_shutdown", (_event, ctx) => {
@@ -270,10 +283,13 @@ function jsonResult(payload: unknown) {
270
283
  };
271
284
  }
272
285
 
273
- function updateStatus(ctx: {
274
- ui: { setStatus: (key: string, value: string | undefined) => void };
275
- }) {
276
- ctx.ui.setStatus(STATUS_KEY, hasApiKey() ? "firecrawl: configured" : "firecrawl: missing key");
286
+ async function withStatus<T>(ctx: StatusContext, status: string, callback: () => Promise<T>) {
287
+ ctx.ui.setStatus(STATUS_KEY, status);
288
+ try {
289
+ return await callback();
290
+ } finally {
291
+ ctx.ui.setStatus(STATUS_KEY, undefined);
292
+ }
277
293
  }
278
294
 
279
295
  function buildStatusMessage() {