imperium-crawl 1.5.0 → 1.5.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.
Files changed (89) hide show
  1. package/README.md +76 -12
  2. package/dist/captcha/detector.js +3 -3
  3. package/dist/captcha/detector.js.map +1 -1
  4. package/dist/captcha/solver.d.ts.map +1 -1
  5. package/dist/captcha/solver.js +4 -1
  6. package/dist/captcha/solver.js.map +1 -1
  7. package/dist/cli.d.ts.map +1 -1
  8. package/dist/cli.js +39 -3
  9. package/dist/cli.js.map +1 -1
  10. package/dist/constants.d.ts +1 -1
  11. package/dist/constants.js +1 -1
  12. package/dist/formatters.d.ts +14 -0
  13. package/dist/formatters.d.ts.map +1 -1
  14. package/dist/formatters.js +10 -0
  15. package/dist/formatters.js.map +1 -1
  16. package/dist/knowledge/store.d.ts.map +1 -1
  17. package/dist/knowledge/store.js +1 -9
  18. package/dist/knowledge/store.js.map +1 -1
  19. package/dist/llm/extractor.d.ts +1 -0
  20. package/dist/llm/extractor.d.ts.map +1 -1
  21. package/dist/llm/extractor.js +5 -4
  22. package/dist/llm/extractor.js.map +1 -1
  23. package/dist/llm/providers/anthropic.d.ts.map +1 -1
  24. package/dist/llm/providers/anthropic.js +34 -31
  25. package/dist/llm/providers/anthropic.js.map +1 -1
  26. package/dist/llm/providers/openai.d.ts.map +1 -1
  27. package/dist/llm/providers/openai.js +26 -23
  28. package/dist/llm/providers/openai.js.map +1 -1
  29. package/dist/llm/retry.d.ts +10 -0
  30. package/dist/llm/retry.d.ts.map +1 -0
  31. package/dist/llm/retry.js +35 -0
  32. package/dist/llm/retry.js.map +1 -0
  33. package/dist/recipes/crypto-websocket.json +11 -0
  34. package/dist/recipes/ecommerce-product.json +25 -0
  35. package/dist/recipes/github-trending.json +19 -0
  36. package/dist/recipes/hn-top-stories.json +22 -0
  37. package/dist/recipes/index.d.ts +3 -0
  38. package/dist/recipes/index.d.ts.map +1 -0
  39. package/dist/recipes/index.js +23 -0
  40. package/dist/recipes/index.js.map +1 -0
  41. package/dist/recipes/job-listings-greenhouse.json +17 -0
  42. package/dist/recipes/news-article-reader.json +9 -0
  43. package/dist/recipes/product-reviews.json +33 -0
  44. package/dist/recipes/reddit-posts.json +8 -0
  45. package/dist/recipes/seo-page-audit.json +26 -0
  46. package/dist/recipes/social-media-mentions.json +31 -0
  47. package/dist/server.d.ts.map +1 -1
  48. package/dist/server.js +11 -1
  49. package/dist/server.js.map +1 -1
  50. package/dist/skills/manager.d.ts +36 -1
  51. package/dist/skills/manager.d.ts.map +1 -1
  52. package/dist/skills/manager.js +22 -0
  53. package/dist/skills/manager.js.map +1 -1
  54. package/dist/stealth/antibot-detector.js +2 -2
  55. package/dist/stealth/antibot-detector.js.map +1 -1
  56. package/dist/stealth/chrome-profile.d.ts.map +1 -1
  57. package/dist/stealth/chrome-profile.js +6 -2
  58. package/dist/stealth/chrome-profile.js.map +1 -1
  59. package/dist/stealth/index.d.ts +7 -0
  60. package/dist/stealth/index.d.ts.map +1 -1
  61. package/dist/stealth/index.js +81 -22
  62. package/dist/stealth/index.js.map +1 -1
  63. package/dist/stealth/proxy.js +2 -2
  64. package/dist/stealth/proxy.js.map +1 -1
  65. package/dist/stealth/tls.d.ts.map +1 -1
  66. package/dist/stealth/tls.js +12 -2
  67. package/dist/stealth/tls.js.map +1 -1
  68. package/dist/tools/interact.d.ts.map +1 -1
  69. package/dist/tools/interact.js +5 -0
  70. package/dist/tools/interact.js.map +1 -1
  71. package/dist/tools/list-skills.d.ts +1 -1
  72. package/dist/tools/list-skills.d.ts.map +1 -1
  73. package/dist/tools/list-skills.js +23 -10
  74. package/dist/tools/list-skills.js.map +1 -1
  75. package/dist/tools/run-skill.d.ts +7 -1
  76. package/dist/tools/run-skill.d.ts.map +1 -1
  77. package/dist/tools/run-skill.js +288 -36
  78. package/dist/tools/run-skill.js.map +1 -1
  79. package/dist/utils/fetcher.d.ts.map +1 -1
  80. package/dist/utils/fetcher.js +8 -38
  81. package/dist/utils/fetcher.js.map +1 -1
  82. package/dist/utils/robots.d.ts.map +1 -1
  83. package/dist/utils/robots.js +5 -1
  84. package/dist/utils/robots.js.map +1 -1
  85. package/dist/utils/url.d.ts +4 -0
  86. package/dist/utils/url.d.ts.map +1 -1
  87. package/dist/utils/url.js +11 -0
  88. package/dist/utils/url.js.map +1 -1
  89. package/package.json +1 -1
@@ -80,13 +80,13 @@ export function parseJsonFromLLMResponse(text) {
80
80
  */
81
81
  function truncateContent(content, maxChars = 120_000) {
82
82
  if (content.length <= maxChars)
83
- return content;
84
- return content.slice(0, maxChars) + "\n\n[Content truncated due to length]";
83
+ return { text: content, wasTruncated: false };
84
+ return { text: content.slice(0, maxChars) + "\n\n[Content truncated due to length]", wasTruncated: true };
85
85
  }
86
86
  export async function extractWithLLM(client, content, schema, maxTokens = 2000) {
87
- const truncated = truncateContent(content);
87
+ const { text: truncatedContent, wasTruncated } = truncateContent(content);
88
88
  const systemPrompt = schema === "auto" ? SYSTEM_PROMPT_AUTO : SYSTEM_PROMPT_EXTRACT;
89
- const userPrompt = buildUserPrompt(schema, truncated);
89
+ const userPrompt = buildUserPrompt(schema, truncatedContent);
90
90
  const response = await client.complete([
91
91
  { role: "system", content: systemPrompt },
92
92
  { role: "user", content: userPrompt },
@@ -96,6 +96,7 @@ export async function extractWithLLM(client, content, schema, maxTokens = 2000)
96
96
  data,
97
97
  model: response.model,
98
98
  schemaUsed: schema,
99
+ ...(wasTruncated && { truncated: true }),
99
100
  tokenUsage: response.inputTokens !== undefined && response.outputTokens !== undefined
100
101
  ? { input: response.inputTokens, output: response.outputTokens }
101
102
  : undefined,
@@ -1 +1 @@
1
- {"version":3,"file":"extractor.js","sourceRoot":"","sources":["../../src/llm/extractor.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"extractor.js","sourceRoot":"","sources":["../../src/llm/extractor.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"anthropic.d.ts","sourceRoot":"","sources":["../../../src/llm/providers/anthropic.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAKtE,qBAAa,eAAgB,YAAW,SAAS;IAE7C,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,KAAK;gBADL,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM;IAG1B,QAAQ,CAAC,QAAQ,EAAE,UAAU,EAAE,EAAE,SAAS,SAAO,GAAG,OAAO,CAAC,WAAW,CAAC;CA0C/E"}
1
+ {"version":3,"file":"anthropic.d.ts","sourceRoot":"","sources":["../../../src/llm/providers/anthropic.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAMtE,qBAAa,eAAgB,YAAW,SAAS;IAE7C,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,KAAK;gBADL,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM;IAG1B,QAAQ,CAAC,QAAQ,EAAE,UAAU,EAAE,EAAE,SAAS,SAAO,GAAG,OAAO,CAAC,WAAW,CAAC;CA4C/E"}
@@ -1,3 +1,4 @@
1
+ import { withRetry } from "../retry.js";
1
2
  const ANTHROPIC_API_URL = "https://api.anthropic.com/v1/messages";
2
3
  const ANTHROPIC_VERSION = "2023-06-01";
3
4
  export class AnthropicClient {
@@ -8,38 +9,40 @@ export class AnthropicClient {
8
9
  this.model = model;
9
10
  }
10
11
  async complete(messages, maxTokens = 2000) {
11
- // Anthropic separates system messages from the messages array
12
- const systemMessages = messages.filter((m) => m.role === "system");
13
- const chatMessages = messages.filter((m) => m.role !== "system");
14
- const system = systemMessages.map((m) => m.content).join("\n") || undefined;
15
- const body = {
16
- model: this.model,
17
- max_tokens: maxTokens,
18
- messages: chatMessages.map((m) => ({ role: m.role, content: m.content })),
19
- };
20
- if (system)
21
- body.system = system;
22
- const res = await fetch(ANTHROPIC_API_URL, {
23
- method: "POST",
24
- headers: {
25
- "Content-Type": "application/json",
26
- "x-api-key": this.apiKey,
27
- "anthropic-version": ANTHROPIC_VERSION,
28
- },
29
- body: JSON.stringify(body),
12
+ return withRetry(async () => {
13
+ // Anthropic separates system messages from the messages array
14
+ const systemMessages = messages.filter((m) => m.role === "system");
15
+ const chatMessages = messages.filter((m) => m.role !== "system");
16
+ const system = systemMessages.map((m) => m.content).join("\n") || undefined;
17
+ const body = {
18
+ model: this.model,
19
+ max_tokens: maxTokens,
20
+ messages: chatMessages.map((m) => ({ role: m.role, content: m.content })),
21
+ };
22
+ if (system)
23
+ body.system = system;
24
+ const res = await fetch(ANTHROPIC_API_URL, {
25
+ method: "POST",
26
+ headers: {
27
+ "Content-Type": "application/json",
28
+ "x-api-key": this.apiKey,
29
+ "anthropic-version": ANTHROPIC_VERSION,
30
+ },
31
+ body: JSON.stringify(body),
32
+ });
33
+ if (!res.ok) {
34
+ const errorText = await res.text().catch(() => res.statusText);
35
+ throw new Error(`Anthropic API error ${res.status}: ${errorText}`);
36
+ }
37
+ const data = (await res.json());
38
+ const text = data.content.find((c) => c.type === "text")?.text || "";
39
+ return {
40
+ text,
41
+ model: data.model,
42
+ inputTokens: data.usage?.input_tokens,
43
+ outputTokens: data.usage?.output_tokens,
44
+ };
30
45
  });
31
- if (!res.ok) {
32
- const errorText = await res.text().catch(() => res.statusText);
33
- throw new Error(`Anthropic API error ${res.status}: ${errorText}`);
34
- }
35
- const data = (await res.json());
36
- const text = data.content.find((c) => c.type === "text")?.text || "";
37
- return {
38
- text,
39
- model: data.model,
40
- inputTokens: data.usage?.input_tokens,
41
- outputTokens: data.usage?.output_tokens,
42
- };
43
46
  }
44
47
  }
45
48
  //# sourceMappingURL=anthropic.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"anthropic.js","sourceRoot":"","sources":["../../../src/llm/providers/anthropic.ts"],"names":[],"mappings":"AAEA,MAAM,iBAAiB,GAAG,uCAAuC,CAAC;AAClE,MAAM,iBAAiB,GAAG,YAAY,CAAC;AAEvC,MAAM,OAAO,eAAe;IAEP;IACA;IAFnB,YACmB,MAAc,EACd,KAAa;QADb,WAAM,GAAN,MAAM,CAAQ;QACd,UAAK,GAAL,KAAK,CAAQ;IAC7B,CAAC;IAEJ,KAAK,CAAC,QAAQ,CAAC,QAAsB,EAAE,SAAS,GAAG,IAAI;QACrD,8DAA8D;QAC9D,MAAM,cAAc,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC;QACnE,MAAM,YAAY,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC;QACjE,MAAM,MAAM,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,SAAS,CAAC;QAE5E,MAAM,IAAI,GAA4B;YACpC,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,UAAU,EAAE,SAAS;YACrB,QAAQ,EAAE,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;SAC1E,CAAC;QACF,IAAI,MAAM;YAAE,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QAEjC,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,iBAAiB,EAAE;YACzC,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,WAAW,EAAE,IAAI,CAAC,MAAM;gBACxB,mBAAmB,EAAE,iBAAiB;aACvC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;SAC3B,CAAC,CAAC;QAEH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,SAAS,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;YAC/D,MAAM,IAAI,KAAK,CAAC,uBAAuB,GAAG,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC,CAAC;QACrE,CAAC;QAED,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAI7B,CAAC;QAEF,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,EAAE,IAAI,IAAI,EAAE,CAAC;QACrE,OAAO;YACL,IAAI;YACJ,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,WAAW,EAAE,IAAI,CAAC,KAAK,EAAE,YAAY;YACrC,YAAY,EAAE,IAAI,CAAC,KAAK,EAAE,aAAa;SACxC,CAAC;IACJ,CAAC;CACF"}
1
+ {"version":3,"file":"anthropic.js","sourceRoot":"","sources":["../../../src/llm/providers/anthropic.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,MAAM,iBAAiB,GAAG,uCAAuC,CAAC;AAClE,MAAM,iBAAiB,GAAG,YAAY,CAAC;AAEvC,MAAM,OAAO,eAAe;IAEP;IACA;IAFnB,YACmB,MAAc,EACd,KAAa;QADb,WAAM,GAAN,MAAM,CAAQ;QACd,UAAK,GAAL,KAAK,CAAQ;IAC7B,CAAC;IAEJ,KAAK,CAAC,QAAQ,CAAC,QAAsB,EAAE,SAAS,GAAG,IAAI;QACrD,OAAO,SAAS,CAAC,KAAK,IAAI,EAAE;YAC1B,8DAA8D;YAC9D,MAAM,cAAc,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC;YACnE,MAAM,YAAY,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC;YACjE,MAAM,MAAM,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,SAAS,CAAC;YAE5E,MAAM,IAAI,GAA4B;gBACpC,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,UAAU,EAAE,SAAS;gBACrB,QAAQ,EAAE,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;aAC1E,CAAC;YACF,IAAI,MAAM;gBAAE,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;YAEjC,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,iBAAiB,EAAE;gBACzC,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE;oBACP,cAAc,EAAE,kBAAkB;oBAClC,WAAW,EAAE,IAAI,CAAC,MAAM;oBACxB,mBAAmB,EAAE,iBAAiB;iBACvC;gBACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;aAC3B,CAAC,CAAC;YAEH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;gBACZ,MAAM,SAAS,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;gBAC/D,MAAM,IAAI,KAAK,CAAC,uBAAuB,GAAG,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC,CAAC;YACrE,CAAC;YAED,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAI7B,CAAC;YAEF,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,EAAE,IAAI,IAAI,EAAE,CAAC;YACrE,OAAO;gBACL,IAAI;gBACJ,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,WAAW,EAAE,IAAI,CAAC,KAAK,EAAE,YAAY;gBACrC,YAAY,EAAE,IAAI,CAAC,KAAK,EAAE,aAAa;aACxC,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC;CACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../../../src/llm/providers/openai.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAItE,qBAAa,YAAa,YAAW,SAAS;IAE1C,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAFN,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EACb,MAAM,GAAE,MAAuB;IAG5C,QAAQ,CAAC,QAAQ,EAAE,UAAU,EAAE,EAAE,SAAS,SAAO,GAAG,OAAO,CAAC,WAAW,CAAC;CAiC/E"}
1
+ {"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../../../src/llm/providers/openai.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAKtE,qBAAa,YAAa,YAAW,SAAS;IAE1C,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAFN,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EACb,MAAM,GAAE,MAAuB;IAG5C,QAAQ,CAAC,QAAQ,EAAE,UAAU,EAAE,EAAE,SAAS,SAAO,GAAG,OAAO,CAAC,WAAW,CAAC;CAmC/E"}
@@ -1,3 +1,4 @@
1
+ import { withRetry } from "../retry.js";
1
2
  const OPENAI_API_URL = "https://api.openai.com/v1/chat/completions";
2
3
  export class OpenAIClient {
3
4
  apiKey;
@@ -9,30 +10,32 @@ export class OpenAIClient {
9
10
  this.apiUrl = apiUrl;
10
11
  }
11
12
  async complete(messages, maxTokens = 2000) {
12
- const res = await fetch(this.apiUrl, {
13
- method: "POST",
14
- headers: {
15
- "Content-Type": "application/json",
16
- Authorization: `Bearer ${this.apiKey}`,
17
- },
18
- body: JSON.stringify({
19
- model: this.model,
20
- max_tokens: maxTokens,
21
- messages: messages.map((m) => ({ role: m.role, content: m.content })),
22
- }),
13
+ return withRetry(async () => {
14
+ const res = await fetch(this.apiUrl, {
15
+ method: "POST",
16
+ headers: {
17
+ "Content-Type": "application/json",
18
+ Authorization: `Bearer ${this.apiKey}`,
19
+ },
20
+ body: JSON.stringify({
21
+ model: this.model,
22
+ max_tokens: maxTokens,
23
+ messages: messages.map((m) => ({ role: m.role, content: m.content })),
24
+ }),
25
+ });
26
+ if (!res.ok) {
27
+ const errorText = await res.text().catch(() => res.statusText);
28
+ throw new Error(`OpenAI API error ${res.status}: ${errorText}`);
29
+ }
30
+ const data = (await res.json());
31
+ const text = data.choices[0]?.message?.content || "";
32
+ return {
33
+ text,
34
+ model: data.model,
35
+ inputTokens: data.usage?.prompt_tokens,
36
+ outputTokens: data.usage?.completion_tokens,
37
+ };
23
38
  });
24
- if (!res.ok) {
25
- const errorText = await res.text().catch(() => res.statusText);
26
- throw new Error(`OpenAI API error ${res.status}: ${errorText}`);
27
- }
28
- const data = (await res.json());
29
- const text = data.choices[0]?.message?.content || "";
30
- return {
31
- text,
32
- model: data.model,
33
- inputTokens: data.usage?.prompt_tokens,
34
- outputTokens: data.usage?.completion_tokens,
35
- };
36
39
  }
37
40
  }
38
41
  //# sourceMappingURL=openai.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"openai.js","sourceRoot":"","sources":["../../../src/llm/providers/openai.ts"],"names":[],"mappings":"AAEA,MAAM,cAAc,GAAG,4CAA4C,CAAC;AAEpE,MAAM,OAAO,YAAY;IAEJ;IACA;IACA;IAHnB,YACmB,MAAc,EACd,KAAa,EACb,SAAiB,cAAc;QAF/B,WAAM,GAAN,MAAM,CAAQ;QACd,UAAK,GAAL,KAAK,CAAQ;QACb,WAAM,GAAN,MAAM,CAAyB;IAC/C,CAAC;IAEJ,KAAK,CAAC,QAAQ,CAAC,QAAsB,EAAE,SAAS,GAAG,IAAI;QACrD,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE;YACnC,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,aAAa,EAAE,UAAU,IAAI,CAAC,MAAM,EAAE;aACvC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,UAAU,EAAE,SAAS;gBACrB,QAAQ,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;aACtE,CAAC;SACH,CAAC,CAAC;QAEH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,SAAS,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;YAC/D,MAAM,IAAI,KAAK,CAAC,oBAAoB,GAAG,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC,CAAC;QAClE,CAAC;QAED,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAI7B,CAAC;QAEF,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,IAAI,EAAE,CAAC;QACrD,OAAO;YACL,IAAI;YACJ,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,WAAW,EAAE,IAAI,CAAC,KAAK,EAAE,aAAa;YACtC,YAAY,EAAE,IAAI,CAAC,KAAK,EAAE,iBAAiB;SAC5C,CAAC;IACJ,CAAC;CACF"}
1
+ {"version":3,"file":"openai.js","sourceRoot":"","sources":["../../../src/llm/providers/openai.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,MAAM,cAAc,GAAG,4CAA4C,CAAC;AAEpE,MAAM,OAAO,YAAY;IAEJ;IACA;IACA;IAHnB,YACmB,MAAc,EACd,KAAa,EACb,SAAiB,cAAc;QAF/B,WAAM,GAAN,MAAM,CAAQ;QACd,UAAK,GAAL,KAAK,CAAQ;QACb,WAAM,GAAN,MAAM,CAAyB;IAC/C,CAAC;IAEJ,KAAK,CAAC,QAAQ,CAAC,QAAsB,EAAE,SAAS,GAAG,IAAI;QACrD,OAAO,SAAS,CAAC,KAAK,IAAI,EAAE;YAC1B,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE;gBACnC,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE;oBACP,cAAc,EAAE,kBAAkB;oBAClC,aAAa,EAAE,UAAU,IAAI,CAAC,MAAM,EAAE;iBACvC;gBACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;oBACnB,KAAK,EAAE,IAAI,CAAC,KAAK;oBACjB,UAAU,EAAE,SAAS;oBACrB,QAAQ,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;iBACtE,CAAC;aACH,CAAC,CAAC;YAEH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;gBACZ,MAAM,SAAS,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;gBAC/D,MAAM,IAAI,KAAK,CAAC,oBAAoB,GAAG,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC,CAAC;YAClE,CAAC;YAED,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAI7B,CAAC;YAEF,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,IAAI,EAAE,CAAC;YACrD,OAAO;gBACL,IAAI;gBACJ,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,WAAW,EAAE,IAAI,CAAC,KAAK,EAAE,aAAa;gBACtC,YAAY,EAAE,IAAI,CAAC,KAAK,EAAE,iBAAiB;aAC5C,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC;CACF"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Retry helper for LLM API calls — retries on 429 (rate limit) and 5xx (server error).
3
+ */
4
+ /**
5
+ * Wraps a fetch call with retry logic for transient errors.
6
+ * Extracts status from error message format "API error {status}: ..."
7
+ * and retries with exponential backoff (1s, 2s, 4s).
8
+ */
9
+ export declare function withRetry<T>(fn: () => Promise<T>): Promise<T>;
10
+ //# sourceMappingURL=retry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retry.d.ts","sourceRoot":"","sources":["../../src/llm/retry.ts"],"names":[],"mappings":"AAAA;;GAEG;AASH;;;;GAIG;AACH,wBAAsB,SAAS,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAwBnE"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Retry helper for LLM API calls — retries on 429 (rate limit) and 5xx (server error).
3
+ */
4
+ const MAX_RETRIES = 3;
5
+ const BACKOFF_BASE_MS = 1000;
6
+ function isRetryableStatus(status) {
7
+ return status === 429 || (status >= 500 && status < 600);
8
+ }
9
+ /**
10
+ * Wraps a fetch call with retry logic for transient errors.
11
+ * Extracts status from error message format "API error {status}: ..."
12
+ * and retries with exponential backoff (1s, 2s, 4s).
13
+ */
14
+ export async function withRetry(fn) {
15
+ let lastError;
16
+ for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
17
+ try {
18
+ return await fn();
19
+ }
20
+ catch (err) {
21
+ lastError = err instanceof Error ? err : new Error(String(err));
22
+ // Extract HTTP status from error message
23
+ const statusMatch = lastError.message.match(/error (\d{3}):/);
24
+ const status = statusMatch ? parseInt(statusMatch[1], 10) : 0;
25
+ if (attempt < MAX_RETRIES && isRetryableStatus(status)) {
26
+ const delay = BACKOFF_BASE_MS * Math.pow(2, attempt);
27
+ await new Promise((r) => setTimeout(r, delay));
28
+ continue;
29
+ }
30
+ throw lastError;
31
+ }
32
+ }
33
+ throw lastError;
34
+ }
35
+ //# sourceMappingURL=retry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retry.js","sourceRoot":"","sources":["../../src/llm/retry.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,GAAG,CAAC,CAAC;AACtB,MAAM,eAAe,GAAG,IAAI,CAAC;AAE7B,SAAS,iBAAiB,CAAC,MAAc;IACvC,OAAO,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,IAAI,GAAG,IAAI,MAAM,GAAG,GAAG,CAAC,CAAC;AAC3D,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAI,EAAoB;IACrD,IAAI,SAA4B,CAAC;IAEjC,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,WAAW,EAAE,OAAO,EAAE,EAAE,CAAC;QACxD,IAAI,CAAC;YACH,OAAO,MAAM,EAAE,EAAE,CAAC;QACpB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,SAAS,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;YAEhE,yCAAyC;YACzC,MAAM,WAAW,GAAG,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;YAC9D,MAAM,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAE9D,IAAI,OAAO,GAAG,WAAW,IAAI,iBAAiB,CAAC,MAAM,CAAC,EAAE,CAAC;gBACvD,MAAM,KAAK,GAAG,eAAe,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;gBACrD,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;gBAC/C,SAAS;YACX,CAAC;YAED,MAAM,SAAS,CAAC;QAClB,CAAC;IACH,CAAC;IAED,MAAM,SAAU,CAAC;AACnB,CAAC"}
@@ -0,0 +1,11 @@
1
+ {
2
+ "name": "crypto-websocket",
3
+ "description": "Monitor Binance BTC/USDT real-time trade WebSocket stream — captures live trade data",
4
+ "url": "https://www.binance.com/en/trade/BTC_USDT",
5
+ "created_at": "2025-01-01T00:00:00Z",
6
+ "builtin": true,
7
+ "tool": "monitor_websocket",
8
+ "duration_seconds": 10,
9
+ "max_messages": 50,
10
+ "filter_url": "stream.binance.com"
11
+ }
@@ -0,0 +1,25 @@
1
+ {
2
+ "name": "ecommerce-product",
3
+ "description": "Extract product details from any e-commerce page using AI — product name, price, currency, rating, availability, images, and description",
4
+ "url": "https://www.example.com/product",
5
+ "created_at": "2025-01-01T00:00:00Z",
6
+ "builtin": true,
7
+ "tool": "ai_extract",
8
+ "schema": {
9
+ "type": "object",
10
+ "properties": {
11
+ "product_name": { "type": "string" },
12
+ "price": { "type": "number" },
13
+ "currency": { "type": "string" },
14
+ "original_price": { "type": "number" },
15
+ "discount_percent": { "type": "number" },
16
+ "rating": { "type": "number" },
17
+ "review_count": { "type": "number" },
18
+ "availability": { "type": "string" },
19
+ "brand": { "type": "string" },
20
+ "description": { "type": "string" },
21
+ "images": { "type": "array", "items": { "type": "string" } }
22
+ }
23
+ },
24
+ "format": "json"
25
+ }
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "github-trending",
3
+ "description": "Scrape GitHub trending repositories — extracts repo name, description, stars, language, and forks",
4
+ "url": "https://github.com/trending",
5
+ "created_at": "2025-01-01T00:00:00Z",
6
+ "builtin": true,
7
+ "tool": "extract",
8
+ "selectors": {
9
+ "items": "article.Box-row",
10
+ "fields": {
11
+ "repo": "h2 a | href",
12
+ "description": "p.col-9",
13
+ "language": "span[itemprop='programmingLanguage']",
14
+ "stars": "a[href$='/stargazers']",
15
+ "forks": "a[href$='/forks']"
16
+ }
17
+ },
18
+ "output_format": "list"
19
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "name": "hn-top-stories",
3
+ "description": "Scrape Hacker News frontpage — extracts title, URL, points, and comment count for each story",
4
+ "url": "https://news.ycombinator.com/",
5
+ "created_at": "2025-01-01T00:00:00Z",
6
+ "builtin": true,
7
+ "tool": "extract",
8
+ "selectors": {
9
+ "items": ".athing",
10
+ "fields": {
11
+ "title": ".titleline > a",
12
+ "url": ".titleline > a | href",
13
+ "id": "@ id",
14
+ "site": ".titleline .sitebit .sitestr"
15
+ }
16
+ },
17
+ "output_format": "list",
18
+ "pagination": {
19
+ "next": "a.morelink",
20
+ "max_pages": 3
21
+ }
22
+ }
@@ -0,0 +1,3 @@
1
+ import type { SkillConfig } from "../skills/manager.js";
2
+ export declare const builtinRecipes: SkillConfig[];
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/recipes/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAaxD,eAAO,MAAM,cAAc,EAAE,WAAW,EAWtB,CAAC"}
@@ -0,0 +1,23 @@
1
+ import hnTopStories from "./hn-top-stories.json" with { type: "json" };
2
+ import githubTrending from "./github-trending.json" with { type: "json" };
3
+ import jobListingsGreenhouse from "./job-listings-greenhouse.json" with { type: "json" };
4
+ import ecommerceProduct from "./ecommerce-product.json" with { type: "json" };
5
+ import productReviews from "./product-reviews.json" with { type: "json" };
6
+ import cryptoWebsocket from "./crypto-websocket.json" with { type: "json" };
7
+ import newsArticleReader from "./news-article-reader.json" with { type: "json" };
8
+ import redditPosts from "./reddit-posts.json" with { type: "json" };
9
+ import seoPageAudit from "./seo-page-audit.json" with { type: "json" };
10
+ import socialMediaMentions from "./social-media-mentions.json" with { type: "json" };
11
+ export const builtinRecipes = [
12
+ hnTopStories,
13
+ githubTrending,
14
+ jobListingsGreenhouse,
15
+ ecommerceProduct,
16
+ productReviews,
17
+ cryptoWebsocket,
18
+ newsArticleReader,
19
+ redditPosts,
20
+ seoPageAudit,
21
+ socialMediaMentions,
22
+ ];
23
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/recipes/index.ts"],"names":[],"mappings":"AAEA,OAAO,YAAY,MAAM,uBAAuB,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AACvE,OAAO,cAAc,MAAM,wBAAwB,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AAC1E,OAAO,qBAAqB,MAAM,gCAAgC,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AACzF,OAAO,gBAAgB,MAAM,0BAA0B,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AAC9E,OAAO,cAAc,MAAM,wBAAwB,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AAC1E,OAAO,eAAe,MAAM,yBAAyB,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AAC5E,OAAO,iBAAiB,MAAM,4BAA4B,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AACjF,OAAO,WAAW,MAAM,qBAAqB,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AACpE,OAAO,YAAY,MAAM,uBAAuB,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AACvE,OAAO,mBAAmB,MAAM,8BAA8B,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AAErF,MAAM,CAAC,MAAM,cAAc,GAAkB;IAC3C,YAAY;IACZ,cAAc;IACd,qBAAqB;IACrB,gBAAgB;IAChB,cAAc;IACd,eAAe;IACf,iBAAiB;IACjB,WAAW;IACX,YAAY;IACZ,mBAAmB;CACH,CAAC"}
@@ -0,0 +1,17 @@
1
+ {
2
+ "name": "job-listings-greenhouse",
3
+ "description": "Scrape Greenhouse ATS job boards — extracts job title, URL, and location. Requires browser rendering (Greenhouse uses React SPA).",
4
+ "url": "https://boards.greenhouse.io/example",
5
+ "created_at": "2025-01-01T00:00:00Z",
6
+ "builtin": true,
7
+ "tool": "extract",
8
+ "selectors": {
9
+ "items": ".job-post",
10
+ "fields": {
11
+ "title": "a .body--medium",
12
+ "url": "a | href",
13
+ "location": "a .body--metadata"
14
+ }
15
+ },
16
+ "output_format": "list"
17
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "name": "news-article-reader",
3
+ "description": "Extract clean article content from any news page using Mozilla Readability — title, author, date, and full text",
4
+ "url": "https://www.example.com/article",
5
+ "created_at": "2025-01-01T00:00:00Z",
6
+ "builtin": true,
7
+ "tool": "readability",
8
+ "format": "markdown"
9
+ }
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "product-reviews",
3
+ "description": "Extract product reviews from any review page using AI — rating, reviewer, date, title, text, pros, and cons",
4
+ "url": "https://www.example.com/product/reviews",
5
+ "created_at": "2025-01-01T00:00:00Z",
6
+ "builtin": true,
7
+ "tool": "ai_extract",
8
+ "schema": {
9
+ "type": "object",
10
+ "properties": {
11
+ "product_name": { "type": "string" },
12
+ "overall_rating": { "type": "number" },
13
+ "total_reviews": { "type": "number" },
14
+ "reviews": {
15
+ "type": "array",
16
+ "items": {
17
+ "type": "object",
18
+ "properties": {
19
+ "rating": { "type": "number" },
20
+ "title": { "type": "string" },
21
+ "text": { "type": "string" },
22
+ "reviewer": { "type": "string" },
23
+ "date": { "type": "string" },
24
+ "verified": { "type": "boolean" },
25
+ "pros": { "type": "array", "items": { "type": "string" } },
26
+ "cons": { "type": "array", "items": { "type": "string" } }
27
+ }
28
+ }
29
+ }
30
+ }
31
+ },
32
+ "format": "json"
33
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "name": "reddit-posts",
3
+ "description": "Fetch raw subreddit posts via Reddit JSON API — returns post titles, scores, authors, URLs, and comment counts",
4
+ "url": "https://www.reddit.com/r/programming.json",
5
+ "created_at": "2025-01-01T00:00:00Z",
6
+ "builtin": true,
7
+ "tool": "scrape"
8
+ }
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "seo-page-audit",
3
+ "description": "Single-page SEO audit — extracts title, meta description, canonical URL, h1 tags, Open Graph tags, and structured data",
4
+ "url": "https://www.example.com",
5
+ "created_at": "2025-01-01T00:00:00Z",
6
+ "builtin": true,
7
+ "tool": "extract",
8
+ "selectors": {
9
+ "items": "html",
10
+ "fields": {
11
+ "title": "title",
12
+ "meta_description": "meta[name='description'] | content",
13
+ "canonical": "link[rel='canonical'] | href",
14
+ "h1": "h1",
15
+ "og_title": "meta[property='og:title'] | content",
16
+ "og_description": "meta[property='og:description'] | content",
17
+ "og_image": "meta[property='og:image'] | content",
18
+ "og_type": "meta[property='og:type'] | content",
19
+ "twitter_card": "meta[name='twitter:card'] | content",
20
+ "robots": "meta[name='robots'] | content",
21
+ "viewport": "meta[name='viewport'] | content",
22
+ "charset": "meta[charset] | charset"
23
+ }
24
+ },
25
+ "output_format": "single"
26
+ }
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "social-media-mentions",
3
+ "description": "Extract social media posts and mentions with sentiment analysis using AI — author, content, engagement metrics, and sentiment",
4
+ "url": "https://www.example.com/social",
5
+ "created_at": "2025-01-01T00:00:00Z",
6
+ "builtin": true,
7
+ "tool": "ai_extract",
8
+ "schema": {
9
+ "type": "object",
10
+ "properties": {
11
+ "platform": { "type": "string" },
12
+ "posts": {
13
+ "type": "array",
14
+ "items": {
15
+ "type": "object",
16
+ "properties": {
17
+ "author": { "type": "string" },
18
+ "content": { "type": "string" },
19
+ "date": { "type": "string" },
20
+ "likes": { "type": "number" },
21
+ "shares": { "type": "number" },
22
+ "comments": { "type": "number" },
23
+ "sentiment": { "type": "string", "enum": ["positive", "negative", "neutral"] },
24
+ "url": { "type": "string" }
25
+ }
26
+ }
27
+ }
28
+ }
29
+ },
30
+ "format": "json"
31
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAKpE,wBAAgB,eAAe,IAAI,SAAS,CA2B3C"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAKpE,wBAAgB,eAAe,IAAI,SAAS,CAyC3C"}
package/dist/server.js CHANGED
@@ -11,7 +11,17 @@ export function createMcpServer() {
11
11
  server.tool(tool.name, tool.description, zodSchema.shape, async (params) => {
12
12
  try {
13
13
  const parsed = tool.schema.parse(params);
14
- return (await tool.execute(parsed));
14
+ const result = await tool.execute(parsed);
15
+ // Validate MCP response format
16
+ if (!result ||
17
+ !Array.isArray(result.content) ||
18
+ result.content.length === 0 ||
19
+ !result.content.every((c) => typeof c.type === "string")) {
20
+ return {
21
+ content: [{ type: "text", text: JSON.stringify({ error: `Tool '${tool.name}' returned invalid response format` }) }],
22
+ };
23
+ }
24
+ return result;
15
25
  }
16
26
  catch (error) {
17
27
  const message = error instanceof Error ? error.message : String(error);
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAC/D,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C,MAAM,UAAU,eAAe;IAC7B,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;QAC3B,IAAI,EAAE,YAAY;QAClB,OAAO,EAAE,eAAe;KACzB,CAAC,CAAC;IAEH,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;QAC5B,MAAM,SAAS,GAAG,IAAI,CAAC,MAAoC,CAAC;QAC5D,MAAM,CAAC,IAAI,CACT,IAAI,CAAC,IAAI,EACT,IAAI,CAAC,WAAW,EAChB,SAAS,CAAC,KAAK,EACf,KAAK,EAAE,MAA+B,EAAE,EAAE;YACxC,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;gBACzC,OAAO,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAQ,CAAC;YAC7C,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBACvE,OAAO;oBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;iBAC/E,CAAC;YACJ,CAAC;QACH,CAAC,CACF,CAAC;IACJ,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAC/D,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C,MAAM,UAAU,eAAe;IAC7B,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;QAC3B,IAAI,EAAE,YAAY;QAClB,OAAO,EAAE,eAAe;KACzB,CAAC,CAAC;IAEH,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;QAC5B,MAAM,SAAS,GAAG,IAAI,CAAC,MAAoC,CAAC;QAC5D,MAAM,CAAC,IAAI,CACT,IAAI,CAAC,IAAI,EACT,IAAI,CAAC,WAAW,EAChB,SAAS,CAAC,KAAK,EACf,KAAK,EAAE,MAA+B,EAAE,EAAE;YACxC,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;gBACzC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;gBAE1C,+BAA+B;gBAC/B,IACE,CAAC,MAAM;oBACP,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC;oBAC9B,MAAM,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC;oBAC3B,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAA0B,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,EACjF,CAAC;oBACD,OAAO;wBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,SAAS,IAAI,CAAC,IAAI,oCAAoC,EAAE,CAAC,EAAE,CAAC;qBAC9H,CAAC;gBACJ,CAAC;gBAED,OAAO,MAAa,CAAC;YACvB,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBACvE,OAAO;oBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;iBAC/E,CAAC;YACJ,CAAC;QACH,CAAC,CACF,CAAC;IACJ,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -6,11 +6,16 @@ export interface SkillPagination {
6
6
  next?: string;
7
7
  max_pages?: number;
8
8
  }
9
- export interface SkillConfig {
9
+ export type RecipeTool = "extract" | "ai_extract" | "readability" | "scrape" | "monitor_websocket";
10
+ interface SkillConfigBase {
10
11
  name: string;
11
12
  description: string;
12
13
  url: string;
13
14
  created_at: string;
15
+ builtin?: boolean;
16
+ }
17
+ export interface ExtractSkillConfig extends SkillConfigBase {
18
+ tool?: "extract";
14
19
  selectors: {
15
20
  items: string;
16
21
  fields: SkillFieldSelectors;
@@ -18,8 +23,38 @@ export interface SkillConfig {
18
23
  output_format: "list" | "single";
19
24
  pagination?: SkillPagination;
20
25
  }
26
+ export interface AiExtractSkillConfig extends SkillConfigBase {
27
+ tool: "ai_extract";
28
+ schema: string | Record<string, unknown> | "auto";
29
+ format?: "json" | "csv";
30
+ max_tokens?: number;
31
+ }
32
+ export interface ReadabilitySkillConfig extends SkillConfigBase {
33
+ tool: "readability";
34
+ format?: "markdown" | "html" | "text";
35
+ }
36
+ export interface ScrapeSkillConfig extends SkillConfigBase {
37
+ tool: "scrape";
38
+ }
39
+ export interface WebSocketSkillConfig extends SkillConfigBase {
40
+ tool: "monitor_websocket";
41
+ duration_seconds?: number;
42
+ max_messages?: number;
43
+ filter_url?: string;
44
+ }
45
+ export type SkillConfig = ExtractSkillConfig | AiExtractSkillConfig | ReadabilitySkillConfig | ScrapeSkillConfig | WebSocketSkillConfig;
21
46
  export declare function save(name: string, config: SkillConfig): Promise<void>;
22
47
  export declare function load(name: string): Promise<SkillConfig | null>;
23
48
  export declare function list(): Promise<SkillConfig[]>;
49
+ /**
50
+ * List all skills: user skills + builtin recipes.
51
+ * User skills with the same name shadow builtin recipes.
52
+ */
53
+ export declare function listAll(): Promise<SkillConfig[]>;
54
+ /**
55
+ * Load a skill by name. Checks user skills first, then builtin recipes.
56
+ */
57
+ export declare function loadWithRecipes(name: string): Promise<SkillConfig | null>;
24
58
  export declare function remove(name: string): Promise<boolean>;
59
+ export {};
25
60
  //# sourceMappingURL=manager.d.ts.map