seo 0.15.0 → 0.15.1

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/dist/mcp.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { createRequire as __seoCreateRequire } from 'node:module'; const require = __seoCreateRequire(import.meta.url);
2
- import { i as __toESM, n as version, r as __commonJSMin, t as load } from "./esm-DieyhVZ-.js";
2
+ import { i as __toESM, n as version, r as __commonJSMin, t as load } from "./esm-D12ZCG_1.js";
3
3
  import { createHash, randomUUID, sign } from "node:crypto";
4
4
  import { ZodOptional, z } from "zod";
5
5
  import { arch, homedir, platform, tmpdir, totalmem } from "node:os";
@@ -42378,8 +42378,15 @@ async function runAiAnswers(input, headers, deps, more) {
42378
42378
  const keys = dataForSeoKeys(headers);
42379
42379
  const domain = registrableDomain(input.site)?.domain;
42380
42380
  if (!domain) throw new CommandError("INVALID_INPUT", `ai_answers needs a site with a domain, not "${input.site}".`);
42381
+ const given = [...new Set((input.questions ?? []).map((q) => q.trim()).filter(Boolean))];
42382
+ if (given.length > 10) throw new CommandError("INVALID_INPUT", `ai_answers takes up to 10 questions, not ${given.length}.`);
42381
42383
  const range = dateWindow({}, QUESTION_DAYS);
42382
- const questions = ((await aiQueriesReport({
42384
+ let questions;
42385
+ if (given.length) questions = given.map((query) => ({
42386
+ query,
42387
+ impressions: null
42388
+ }));
42389
+ else questions = ((await aiQueriesReport({
42383
42390
  site: input.site,
42384
42391
  ...range
42385
42392
  }, deps.searchAnalytics)).items ?? []).filter((item) => item.askable).slice(0, 10);
@@ -42396,7 +42403,7 @@ async function runAiAnswers(input, headers, deps, more) {
42396
42403
  }))));
42397
42404
  const cost = usd(answers.reduce((sum, row) => sum + row.cost_usd, 0));
42398
42405
  const count = (result) => answers.filter((row) => row.result === result).length;
42399
- const notes = [questions.length ? `The top ${questions.length} askable questions in Search Console’s AI-shaped queries for ${range.startDate} to ${range.endDate}, by impressions. No calls were made for other questions.` : `No askable questions in Search Console’s AI-shaped queries for ${range.startDate} to ${range.endDate}, so no answers were checked and nothing was spent.`, ...questions.length ? [
42406
+ const notes = [given.length ? `The ${given.length} questions you gave, asked as written. Impressions are blank because they don't come from Search Console.` : questions.length ? `The top ${questions.length} askable questions in Search Console’s AI-shaped queries for ${range.startDate} to ${range.endDate}, by impressions. No calls were made for other questions.` : `No askable questions in Search Console’s AI-shaped queries for ${range.startDate} to ${range.endDate}, so no answers were checked and nothing was spent.`, ...questions.length ? [
42400
42407
  `Cited ${count("cited")}, mentioned ${count("mentioned")}, neither ${count("neither")}, no answer shown ${count("no_answer")}, unavailable ${count("unavailable")}. DataForSEO cost: $${cost}.`,
42401
42408
  "Each row is one sample of an answer that changes from run to run, not a ranking.",
42402
42409
  `cited: the answer lists or links a page on ${domain} or a subdomain. mentioned: no such source, but the answer text names ${[domain, ...site.terms].join(" or ")}, a text match. no_answer: the engine showed no AI answer for the question. model: the model DataForSEO reports for the answer, when it reports one.`,
@@ -42417,7 +42424,7 @@ async function runAiAnswers(input, headers, deps, more) {
42417
42424
  action: "ai_answers",
42418
42425
  site: input.site,
42419
42426
  country: input.country,
42420
- questionsFrom: {
42427
+ questionsFrom: given.length ? { section: "given" } : {
42421
42428
  section: "ai-queries",
42422
42429
  ...range
42423
42430
  },
@@ -45564,7 +45571,7 @@ const RESEARCH_ACTIONS = [
45564
45571
  "ai_answers"
45565
45572
  ];
45566
45573
  const RESEARCH_PROVIDERS = ["dataforseo", "ahrefs"];
45567
- const RESEARCH_HELP = `keyword_metrics (keywords: volume, difficulty, CPC), ranked_keywords (target: keywords a domain or URL ranks for), serp (keywords, up to 5: the ranking pages), competitors (target: domains that share keywords), backlinks (target: referring domains), ai_answers (DataForSEO only; target: the site. It takes the site’s top 10 chat-style and long questions from Search Console’s AI-shaped queries itself, then asks ChatGPT search, Google AI Mode and Google AI Overviews each one and says whether the answer cites or mentions the site. DataForSEO’s live prices are $0.012 a question, so up to about $0.12 a run: tell the person before running it). Rows with a domain, and the target, get a free Ahrefs domain_rating column. Numbers are provider estimates, not Search Console data.`;
45574
+ const RESEARCH_HELP = `keyword_metrics (keywords: volume, difficulty, CPC), ranked_keywords (target: keywords a domain or URL ranks for), serp (keywords, up to 5: the ranking pages), competitors (target: domains that share keywords), backlinks (target: referring domains), ai_answers (DataForSEO only; target: the site. Without keywords it takes the site’s top 10 chat-style and long questions from Search Console’s AI-shaped queries itself. With up to 10 questions in keywords it asks those instead, and the target can be any domain, such as a competitor's. It asks ChatGPT search, Google AI Mode and Google AI Overviews each one and says whether the answer cites or mentions the site. DataForSEO’s live prices are $0.012 a question, so up to about $0.12 a run: tell the person before running it). Rows with a domain, and the target, get a free Ahrefs domain_rating column. Numbers are provider estimates, not Search Console data.`;
45568
45575
  const GENERIC_PLATFORMS = [
45569
45576
  "youtube.com",
45570
45577
  "facebook.com",
@@ -46520,10 +46527,11 @@ const SHARED_TOOLS = [
46520
46527
  if (input.action === "ai_answers") {
46521
46528
  if (input.provider !== "dataforseo") throw new CommandError("INVALID_INPUT", "ai_answers uses dataforseo.");
46522
46529
  return runAiAnswers({
46523
- site: await surface.resolveSite(input.target),
46530
+ site: input.keywords.length ? input.target : await surface.resolveSite(input.target),
46524
46531
  country: input.country,
46525
46532
  detail: input.detail,
46526
- offset: input.offset
46533
+ offset: input.offset,
46534
+ questions: input.keywords
46527
46535
  }, await surface.keys(), surface.deps, more);
46528
46536
  }
46529
46537
  return runResearch(input, await surface.keys(), {