@byldd/seo-tools-plugin 1.0.1 → 1.0.3

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/manifest.js CHANGED
@@ -1,3 +1,14 @@
1
+ // src/types/index.ts
2
+ var RerunStage = /* @__PURE__ */ ((RerunStage2) => {
3
+ RerunStage2["GEO"] = "geo";
4
+ RerunStage2["SCHEMA"] = "schema";
5
+ RerunStage2["OUTLINE"] = "outline";
6
+ RerunStage2["ENRICHMENT"] = "enrichment";
7
+ RerunStage2["INTENT"] = "intent";
8
+ RerunStage2["STRATEGY"] = "strategy";
9
+ return RerunStage2;
10
+ })(RerunStage || {});
11
+
1
12
  // src/manifest.ts
2
13
  var manifest = {
3
14
  id: "byldd.seo-tools",
@@ -55,9 +66,9 @@ var manifest = {
55
66
  },
56
67
  tools: [
57
68
  {
58
- name: "runKeywordResearch",
59
- displayName: "Run Keyword Research",
60
- description: "Call this when user asks for keyword research or Keyword Planner. Starts an async job \u2014 returns a keywordSessionRef immediately. Research takes ~20-30s. Wait ~20 seconds, then poll getKeywordSessionStatus every 10 seconds until status is 'completed' or 'failed' (max ~16 attempts, ~3 min).",
69
+ name: "startKeywordResearch",
70
+ displayName: "Start a New Keyword Research",
71
+ description: "ONLY entry point for new keyword research. Handles discovery AND enrichment in one pipeline. Returns a keywordSessionRef immediately \u2014 the job runs in the background. Research typically takes ~20-30s. Wait ~20 seconds, then poll getKeywordSessionStatus with that keywordSessionRef every 10 seconds until status is 'completed' or 'failed'. Max ~16 poll attempts (~3 minutes including the initial wait) before reporting timeout.",
61
72
  parametersSchema: {
62
73
  type: "object",
63
74
  properties: {
@@ -69,7 +80,7 @@ var manifest = {
69
80
  {
70
81
  name: "getKeywordSessionStatus",
71
82
  displayName: "Get Keyword Session Status",
72
- description: "Poll the status of a KeywordSession started with runKeywordResearch. Wait ~20 seconds before the first poll, then call every 10 seconds until status is 'completed' or 'failed' (max ~16 attempts, ~3 min).",
83
+ description: "Poll the status of a KeywordSession started by startKeywordResearch. Wait ~20 seconds before the first poll (research takes ~20-30s), then call every 10 seconds. Stop when status is 'completed' or 'failed'. Max ~16 attempts (~3 min) \u2014 if still running after that, report timeout to the user and stop. When status is 'completed', the response contains the keywordSessionRef \u2014 the single id for this research run; pass it to clusterKeywords. Save it.",
73
84
  parametersSchema: {
74
85
  type: "object",
75
86
  properties: {
@@ -79,33 +90,9 @@ var manifest = {
79
90
  }
80
91
  },
81
92
  {
82
- name: "enrichKeywords",
83
- displayName: "Enrich Keywords",
84
- description: "Use only to re-enrich an EXISTING session that was previously discovered. For new keyword research, use runKeywordResearch which handles everything end-to-end.",
85
- parametersSchema: {
86
- type: "object",
87
- properties: {
88
- keywordSessionRef: { type: "string" }
89
- },
90
- required: ["keywordSessionRef"]
91
- }
92
- },
93
- {
94
- name: "getKeywordSuggestions",
95
- displayName: "Get Keyword Suggestions",
96
- description: "List raw expansion keywords for a session WITHOUT triggering the costly enrich step.",
97
- parametersSchema: {
98
- type: "object",
99
- properties: {
100
- keywordSessionRef: { type: "string" }
101
- },
102
- required: ["keywordSessionRef"]
103
- }
104
- },
105
- {
106
- name: "listKeywordSessions",
93
+ name: "listKeywordResearchSessions",
107
94
  displayName: "List Keyword Sessions",
108
- description: "List all past keyword research sessions.",
95
+ description: "List all past keyword research sessions with a brief overview \u2014 seedKeyword, status, and keyword count only.",
109
96
  parametersSchema: {
110
97
  type: "object",
111
98
  properties: {}
@@ -114,7 +101,7 @@ var manifest = {
114
101
  {
115
102
  name: "clusterKeywords",
116
103
  displayName: "Cluster Keywords",
117
- description: "Call this AFTER getKeywordSessionStatus returns 'completed' (and the user approves). Group enriched keywords into topical clusters. Returns a clusterId. Clustering can take ~20s to 1 min or more. Wait ~20 seconds, then poll getClusterStatus every 15 seconds until status is 'completed' (max ~18 attempts, ~5 min).",
104
+ description: "Call this AFTER getKeywordSessionStatus returns 'completed'. Pass the keywordSessionRef from that completed response (or from listKeywordResearchSessions). Returns a clusterId. Clustering can take ~20s to 1 min or more. Wait ~20 seconds, then poll getClusterStatus every 15 seconds until status is 'completed'. Max ~18 attempts (~5 min) before reporting timeout.",
118
105
  parametersSchema: {
119
106
  type: "object",
120
107
  properties: {
@@ -126,7 +113,7 @@ var manifest = {
126
113
  {
127
114
  name: "getClusterStatus",
128
115
  displayName: "Get Cluster Status",
129
- description: "Fetch status and results of a clustering session. After clusterKeywords, wait ~20 seconds, then poll every 15 seconds until status is completed (max ~18 attempts, ~5 min).",
116
+ description: "Poll the status of a clustering job. After clusterKeywords, wait ~20 seconds, then call every 15 seconds until status is 'completed' or 'failed'. Max ~18 attempts (~5 min) before reporting timeout. When completed, the response contains the full cluster plan \u2014 render it as a Markdown table immediately.",
130
117
  parametersSchema: {
131
118
  type: "object",
132
119
  properties: {
@@ -138,7 +125,7 @@ var manifest = {
138
125
  {
139
126
  name: "listClusterSessions",
140
127
  displayName: "List Cluster Sessions",
141
- description: "List all past clustering sessions.",
128
+ description: "List all past clustering sessions with a brief overview \u2014 seedKeyword, status, and keyword count only.",
142
129
  parametersSchema: {
143
130
  type: "object",
144
131
  properties: {}
@@ -147,7 +134,7 @@ var manifest = {
147
134
  {
148
135
  name: "generateContentBrief",
149
136
  displayName: "Generate Content Brief",
150
- description: "Call this once user approves a cluster. Returns a briefId. You MUST then poll getBriefStatus until status is 'COMPLETED'. Start the async content-brief pipeline.",
137
+ description: "Call this once user approves a cluster or passed only a keyword. Returns a briefId. You MUST then poll getBriefStatus until status is 'COMPLETED'. When source is 'cluster', clusterSessionRef is REQUIRED (the clusterId from a completed clusterKeywords run); for source 'standalone' omit clusterSessionRef and pass only keyword.",
151
138
  parametersSchema: {
152
139
  type: "object",
153
140
  properties: {
@@ -190,7 +177,10 @@ var manifest = {
190
177
  type: "object",
191
178
  properties: {
192
179
  briefId: { type: "string" },
193
- stage: { type: "string" }
180
+ stage: {
181
+ type: "string",
182
+ enum: Object.values(RerunStage)
183
+ }
194
184
  },
195
185
  required: ["briefId", "stage"]
196
186
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/manifest.ts"],
4
- "sourcesContent": ["import type { PaperclipPluginManifestV1 } from \"@paperclipai/plugin-sdk\";\n\nconst manifest: PaperclipPluginManifestV1 = {\n id: \"byldd.seo-tools\",\n apiVersion: 1,\n version: \"0.1.0\",\n displayName: \"Seo Tools\",\n description: \"A Paperclip plugin\",\n author: \"Plugin Author\",\n categories: [\"connector\"],\n capabilities: [\n \"agent.tools.register\",\n \"http.outbound\",\n \"ui.detailTab.register\",\n \"events.subscribe\",\n \"plugin.state.read\",\n \"plugin.state.write\",\n \"ui.dashboardWidget.register\",\n ],\n instanceConfigSchema: {\n type: \"object\",\n properties: {\n backendUrl: {\n type: \"string\",\n title: \"Backend URL\",\n description: \"Base URL of the SEO Byldd Server\",\n },\n authToken: {\n type: \"string\",\n title: \"Auth Token\",\n description: \"JWT auth token for the SEO Byldd Server\",\n },\n },\n required: [\"backendUrl\", \"authToken\"],\n },\n entrypoints: {\n worker: \"./dist/worker.js\",\n ui: \"./dist/ui\",\n },\n ui: {\n slots: [\n {\n type: \"dashboardWidget\",\n id: \"health-widget\",\n displayName: \"Seo Tools Health\",\n exportName: \"DashboardWidget\",\n },\n {\n type: \"detailTab\",\n id: \"keyword-research-tab\",\n displayName: \"Keyword Research\",\n exportName: \"KeywordResearchTab\",\n entityTypes: [\"issue\"],\n },\n ],\n },\n tools: [\n {\n name: \"runKeywordResearch\",\n displayName: \"Run Keyword Research\",\n description:\n \"Call this when user asks for keyword research or Keyword Planner. Starts an async job \u2014 returns a keywordSessionRef immediately. Research takes ~20-30s. Wait ~20 seconds, then poll getKeywordSessionStatus every 10 seconds until status is 'completed' or 'failed' (max ~16 attempts, ~3 min).\",\n parametersSchema: {\n type: \"object\",\n properties: {\n keyword: { type: \"string\" },\n },\n required: [\"keyword\"],\n },\n },\n {\n name: \"getKeywordSessionStatus\",\n displayName: \"Get Keyword Session Status\",\n description:\n \"Poll the status of a KeywordSession started with runKeywordResearch. Wait ~20 seconds before the first poll, then call every 10 seconds until status is 'completed' or 'failed' (max ~16 attempts, ~3 min).\",\n parametersSchema: {\n type: \"object\",\n properties: {\n keywordSessionRef: { type: \"string\" },\n },\n required: [\"keywordSessionRef\"],\n },\n },\n {\n name: \"enrichKeywords\",\n displayName: \"Enrich Keywords\",\n description:\n \"Use only to re-enrich an EXISTING session that was previously discovered. For new keyword research, use runKeywordResearch which handles everything end-to-end.\",\n parametersSchema: {\n type: \"object\",\n properties: {\n keywordSessionRef: { type: \"string\" },\n },\n required: [\"keywordSessionRef\"],\n },\n },\n {\n name: \"getKeywordSuggestions\",\n displayName: \"Get Keyword Suggestions\",\n description:\n \"List raw expansion keywords for a session WITHOUT triggering the costly enrich step.\",\n parametersSchema: {\n type: \"object\",\n properties: {\n keywordSessionRef: { type: \"string\" },\n },\n required: [\"keywordSessionRef\"],\n },\n },\n {\n name: \"listKeywordSessions\",\n displayName: \"List Keyword Sessions\",\n description: \"List all past keyword research sessions.\",\n parametersSchema: {\n type: \"object\",\n properties: {},\n },\n },\n {\n name: \"clusterKeywords\",\n displayName: \"Cluster Keywords\",\n description:\n \"Call this AFTER getKeywordSessionStatus returns 'completed' (and the user approves). Group enriched keywords into topical clusters. Returns a clusterId. Clustering can take ~20s to 1 min or more. Wait ~20 seconds, then poll getClusterStatus every 15 seconds until status is 'completed' (max ~18 attempts, ~5 min).\",\n parametersSchema: {\n type: \"object\",\n properties: {\n keywordSessionRef: { type: \"string\" },\n },\n required: [\"keywordSessionRef\"],\n },\n },\n {\n name: \"getClusterStatus\",\n displayName: \"Get Cluster Status\",\n description:\n \"Fetch status and results of a clustering session. After clusterKeywords, wait ~20 seconds, then poll every 15 seconds until status is completed (max ~18 attempts, ~5 min).\",\n parametersSchema: {\n type: \"object\",\n properties: {\n clusterId: { type: \"string\" },\n },\n required: [\"clusterId\"],\n },\n },\n {\n name: \"listClusterSessions\",\n displayName: \"List Cluster Sessions\",\n description: \"List all past clustering sessions.\",\n parametersSchema: {\n type: \"object\",\n properties: {},\n },\n },\n {\n name: \"generateContentBrief\",\n displayName: \"Generate Content Brief\",\n description:\n \"Call this once user approves a cluster. Returns a briefId. You MUST then poll getBriefStatus until status is 'COMPLETED'. Start the async content-brief pipeline.\",\n parametersSchema: {\n type: \"object\",\n properties: {\n source: { type: \"string\", enum: [\"cluster\", \"standalone\"] },\n keyword: { type: \"string\" },\n clusterSessionRef: { type: \"string\" },\n isSelfReferentialListicle: { type: \"boolean\" },\n },\n required: [\"source\", \"keyword\"],\n },\n },\n {\n name: \"getBriefStatus\",\n displayName: \"Get Brief Status\",\n description:\n \"Fetch the current state of a brief. Poll this until status is COMPLETED.\",\n parametersSchema: {\n type: \"object\",\n properties: {\n briefId: { type: \"string\" },\n },\n required: [\"briefId\"],\n },\n },\n {\n name: \"listContentBriefs\",\n displayName: \"List Content Briefs\",\n description: \"List content briefs, optionally filtered by cluster.\",\n parametersSchema: {\n type: \"object\",\n properties: {\n clusterSessionRef: { type: \"string\" },\n },\n },\n },\n {\n name: \"rerunBriefStage\",\n displayName: \"Rerun Brief Stage\",\n description: \"Regenerate a single stage of the brief pipeline.\",\n parametersSchema: {\n type: \"object\",\n properties: {\n briefId: { type: \"string\" },\n stage: { type: \"string\" },\n },\n required: [\"briefId\", \"stage\"],\n },\n },\n {\n name: \"attachProofPoints\",\n displayName: \"Attach Proof Points\",\n description: \"Inject business-specific proof points into a brief.\",\n parametersSchema: {\n type: \"object\",\n properties: {\n briefId: { type: \"string\" },\n pricingRanges: { type: \"string\" },\n timelines: { type: \"string\" },\n clientOutcomes: { type: \"array\", items: { type: \"string\" } },\n methodology: { type: \"string\" },\n },\n required: [\"briefId\"],\n },\n },\n ],\n};\n\nexport default manifest;\n"],
5
- "mappings": "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",
6
- "names": []
3
+ "sources": ["../src/types/index.ts", "../src/manifest.ts"],
4
+ "sourcesContent": ["// Tool param types \u2014 mirror parametersSchema definitions in worker.ts\nexport interface RunKeywordResearchParams {\n keyword: string;\n}\n\nexport interface GetKeywordSessionStatusParams {\n keywordSessionRef: string;\n}\n\nexport interface ClusterKeywordsParams {\n keywordSessionRef: string;\n}\n\nexport interface GetClusterStatusParams {\n clusterId: string;\n}\n\nexport enum BriefSource {\n CLUSTER = \"cluster\",\n STANDALONE = \"standalone\",\n}\n\nexport interface GenerateContentBriefParams {\n source: BriefSource;\n keyword: string;\n clusterSessionRef?: string;\n isSelfReferentialListicle?: boolean;\n}\n\nexport interface GetBriefStatusParams {\n briefId: string;\n}\n\nexport interface ListContentBriefsParams {\n clusterSessionRef?: string;\n}\n\nexport interface RerunBriefStageParams {\n briefId: string;\n stage: RerunStage;\n}\n\nexport interface AttachProofPointsParams {\n briefId: string;\n pricingRanges?: string;\n timelines?: string;\n clientOutcomes?: string[];\n methodology?: string;\n}\n\n// Keyword session status\nexport enum KeywordSessionStatus {\n PENDING = \"pending\",\n DISCOVERING = \"discovering\",\n ENRICHING = \"enriching\",\n COMPLETED = \"completed\",\n FAILED = \"failed\",\n}\n\n// Raw KeywordSession item as returned by GET /api/keyword-research/.\n// Mongo ObjectIds and Dates are serialized to strings over JSON.\nexport interface KeywordSessionApiItem {\n _id: string;\n seedKeyword: string;\n status: KeywordSessionStatus;\n keywordCount?: number;\n createdAt: string;\n}\n\n// Output of listKeywordResearchSessions \u2014 one summary row per session.\nexport interface KeywordResearchSessionSummary {\n keywordSessionRef: string;\n seedKeyword: string;\n status: KeywordSessionStatus;\n keywordCount: number;\n createdAt: string;\n}\n\n// Brief pipeline rerun stages\nexport enum RerunStage {\n GEO = \"geo\",\n SCHEMA = \"schema\",\n OUTLINE = \"outline\",\n ENRICHMENT = \"enrichment\",\n INTENT = \"intent\",\n STRATEGY = \"strategy\",\n}\n\n// Clustering session status\nexport enum ClusterStatus {\n PENDING = \"pending\",\n FETCHING_SERPS = \"fetching_serps\",\n PROCESSING = \"processing\",\n ARCHITECTING = \"architecting\",\n COMPLETED = \"completed\",\n FAILED = \"failed\",\n}\n\n// Raw ClusterSession item as returned by GET /api/clustering/.\n// Mongo ObjectIds and Dates are serialized to strings over JSON.\nexport interface ClusterSessionApiItem {\n _id: string;\n seedKeyword?: string;\n status: ClusterStatus;\n keywordCount?: number;\n createdAt: string;\n}\n\n// Output of listClusterSessions \u2014 one summary row per session.\nexport interface ClusterSessionSummary {\n clusterId: string;\n seedKeyword?: string;\n status: ClusterStatus;\n keywordCount: number;\n createdAt: string;\n}\n\n// Raw ContentBrief item as returned by GET /api/content-brief/ (list).\n// Mongo ObjectIds and Dates are serialized to strings over JSON.\nexport interface ContentBriefApiItem {\n _id: string;\n keyword: string;\n status: string;\n createdAt: string;\n updatedAt: string;\n}\n\n// Output of listContentBriefs \u2014 one summary row per brief.\nexport interface ContentBriefSummary {\n briefId: string;\n keyword: string;\n status: string;\n createdAt: string;\n updatedAt: string;\n}\n\n// Cluster plan shapes\nexport interface ClusterPost {\n keyword: string;\n volume: number;\n intent: string;\n pageType: string;\n title: string;\n}\n\nexport interface ClusterGroup {\n name: string;\n posts: ClusterPost[];\n}\n\nexport interface ClusterPillar {\n keyword: string;\n volume: number;\n intent: string;\n pageType: string;\n title: string;\n}\n\nexport interface ClusterLandingPage {\n keyword: string;\n pageType: string;\n urlSlug: string;\n}\n\nexport interface ClusterInternalLinking {\n pillarLinksTo: string[];\n spokesLinkTo: string[];\n}\n\nexport interface ClusterArchitecture {\n pillar: ClusterPillar | null;\n clusters: ClusterGroup[];\n landingPage: ClusterLandingPage | null;\n internalLinking: ClusterInternalLinking | null;\n}\n\n// Brief writer-view shapes \u2014 the trimmed projection getBriefStatus returns to\n// the agent. Only the writer-facing fields survive; raw SERP/enrichment/schema\n// JSON, EEAT, and ops/meta are dropped here so RENDERING.md never has to.\nexport interface BriefOutlineSectionView {\n heading: string;\n level: number;\n wordCount: number;\n importance: string | null;\n format: string;\n guidance: string;\n subSections?: BriefOutlineSectionView[];\n}\n\nexport interface BriefInternalLinkView {\n anchor: string;\n targetUrl: string;\n reason: string;\n}\n\nexport interface BriefClusterSpokeView {\n keyword: string;\n title: string;\n url: string;\n}\n\nexport interface BriefWriterView {\n status: string;\n // Q1 \u2014 page identity\n pageType: string;\n intent: string;\n targetKeyword: string;\n targetAudience?: string;\n priorityScore?: number;\n priorityTier?: string;\n clusterPosition?: string;\n recommendedTitle?: string;\n metaDescription?: string;\n urlSlug?: string;\n // Q2 \u2014 coverage & depth\n supportingKeywords: string[];\n mustAnswer: string[];\n niceToAnswer: string[];\n targetWordCount?: number;\n competitorAvgWordCount?: number;\n outline: BriefOutlineSectionView[];\n // coverage checklist material (derived from coverageMatrix)\n requiredTopics: string[];\n contentGaps: string[];\n differentiatorOpportunities: string[];\n faq: string[];\n // Q3 \u2014 citability\n tldrBlock?: {\n text: string;\n wordCount: number;\n placement: string;\n fsTarget: boolean;\n };\n objectiveLanguageInstruction?: string;\n requiredSignals: string[];\n schemaRequired: string[];\n // Q4 \u2014 differentiation\n contentAngle?: string;\n competitorGap?: string;\n mustOwnTopics: string[];\n uniqueAssets: string[];\n proofPointsToInclude: string[];\n competitorBlindSpots: string[];\n competitorPagesToReference: string[];\n // Q5 \u2014 site connection\n internalLinks: BriefInternalLinkView[];\n internalLinksFrom: string[];\n isSelfReferentialListicle: boolean;\n clusterContext?: {\n pillarTitle: string;\n pillarUrl: string;\n spokes: BriefClusterSpokeView[];\n };\n // kept for the agent's polling / Manager report \u2014 not for the writer doc\n flags: { code: string; note?: string }[];\n}\n", "import type { PaperclipPluginManifestV1 } from \"@paperclipai/plugin-sdk\";\nimport { RerunStage } from \"./types/index.js\";\n\nconst manifest: PaperclipPluginManifestV1 = {\n id: \"byldd.seo-tools\",\n apiVersion: 1,\n version: \"0.1.0\",\n displayName: \"Seo Tools\",\n description: \"A Paperclip plugin\",\n author: \"Plugin Author\",\n categories: [\"connector\"],\n capabilities: [\n \"agent.tools.register\",\n \"http.outbound\",\n \"ui.detailTab.register\",\n \"events.subscribe\",\n \"plugin.state.read\",\n \"plugin.state.write\",\n \"ui.dashboardWidget.register\",\n ],\n instanceConfigSchema: {\n type: \"object\",\n properties: {\n backendUrl: {\n type: \"string\",\n title: \"Backend URL\",\n description: \"Base URL of the SEO Byldd Server\",\n },\n authToken: {\n type: \"string\",\n title: \"Auth Token\",\n description: \"JWT auth token for the SEO Byldd Server\",\n },\n },\n required: [\"backendUrl\", \"authToken\"],\n },\n entrypoints: {\n worker: \"./dist/worker.js\",\n ui: \"./dist/ui\",\n },\n ui: {\n slots: [\n {\n type: \"dashboardWidget\",\n id: \"health-widget\",\n displayName: \"Seo Tools Health\",\n exportName: \"DashboardWidget\",\n },\n {\n type: \"detailTab\",\n id: \"keyword-research-tab\",\n displayName: \"Keyword Research\",\n exportName: \"KeywordResearchTab\",\n entityTypes: [\"issue\"],\n },\n ],\n },\n tools: [\n {\n name: \"startKeywordResearch\",\n displayName: \"Start a New Keyword Research\",\n description:\n \"ONLY entry point for new keyword research. Handles discovery AND enrichment in one pipeline. Returns a keywordSessionRef immediately \u2014 the job runs in the background. Research typically takes ~20-30s. Wait ~20 seconds, then poll getKeywordSessionStatus with that keywordSessionRef every 10 seconds until status is 'completed' or 'failed'. Max ~16 poll attempts (~3 minutes including the initial wait) before reporting timeout.\",\n parametersSchema: {\n type: \"object\",\n properties: {\n keyword: { type: \"string\" },\n },\n required: [\"keyword\"],\n },\n },\n {\n name: \"getKeywordSessionStatus\",\n displayName: \"Get Keyword Session Status\",\n description:\n \"Poll the status of a KeywordSession started by startKeywordResearch. Wait ~20 seconds before the first poll (research takes ~20-30s), then call every 10 seconds. Stop when status is 'completed' or 'failed'. Max ~16 attempts (~3 min) \u2014 if still running after that, report timeout to the user and stop. When status is 'completed', the response contains the keywordSessionRef \u2014 the single id for this research run; pass it to clusterKeywords. Save it.\",\n parametersSchema: {\n type: \"object\",\n properties: {\n keywordSessionRef: { type: \"string\" },\n },\n required: [\"keywordSessionRef\"],\n },\n },\n {\n name: \"listKeywordResearchSessions\",\n displayName: \"List Keyword Sessions\",\n description:\n \"List all past keyword research sessions with a brief overview \u2014 seedKeyword, status, and keyword count only.\",\n parametersSchema: {\n type: \"object\",\n properties: {},\n },\n },\n {\n name: \"clusterKeywords\",\n displayName: \"Cluster Keywords\",\n description:\n \"Call this AFTER getKeywordSessionStatus returns 'completed'. Pass the keywordSessionRef from that completed response (or from listKeywordResearchSessions). Returns a clusterId. Clustering can take ~20s to 1 min or more. Wait ~20 seconds, then poll getClusterStatus every 15 seconds until status is 'completed'. Max ~18 attempts (~5 min) before reporting timeout.\",\n parametersSchema: {\n type: \"object\",\n properties: {\n keywordSessionRef: { type: \"string\" },\n },\n required: [\"keywordSessionRef\"],\n },\n },\n {\n name: \"getClusterStatus\",\n displayName: \"Get Cluster Status\",\n description:\n \"Poll the status of a clustering job. After clusterKeywords, wait ~20 seconds, then call every 15 seconds until status is 'completed' or 'failed'. Max ~18 attempts (~5 min) before reporting timeout. When completed, the response contains the full cluster plan \u2014 render it as a Markdown table immediately.\",\n parametersSchema: {\n type: \"object\",\n properties: {\n clusterId: { type: \"string\" },\n },\n required: [\"clusterId\"],\n },\n },\n {\n name: \"listClusterSessions\",\n displayName: \"List Cluster Sessions\",\n description:\n \"List all past clustering sessions with a brief overview \u2014 seedKeyword, status, and keyword count only.\",\n parametersSchema: {\n type: \"object\",\n properties: {},\n },\n },\n {\n name: \"generateContentBrief\",\n displayName: \"Generate Content Brief\",\n description:\n \"Call this once user approves a cluster or passed only a keyword. Returns a briefId. You MUST then poll getBriefStatus until status is 'COMPLETED'. When source is 'cluster', clusterSessionRef is REQUIRED (the clusterId from a completed clusterKeywords run); for source 'standalone' omit clusterSessionRef and pass only keyword.\",\n parametersSchema: {\n type: \"object\",\n properties: {\n source: { type: \"string\", enum: [\"cluster\", \"standalone\"] },\n keyword: { type: \"string\" },\n clusterSessionRef: { type: \"string\" },\n isSelfReferentialListicle: { type: \"boolean\" },\n },\n required: [\"source\", \"keyword\"],\n },\n },\n {\n name: \"getBriefStatus\",\n displayName: \"Get Brief Status\",\n description:\n \"Fetch the current state of a brief. Poll this until status is COMPLETED.\",\n parametersSchema: {\n type: \"object\",\n properties: {\n briefId: { type: \"string\" },\n },\n required: [\"briefId\"],\n },\n },\n {\n name: \"listContentBriefs\",\n displayName: \"List Content Briefs\",\n description: \"List content briefs, optionally filtered by cluster.\",\n parametersSchema: {\n type: \"object\",\n properties: {\n clusterSessionRef: { type: \"string\" },\n },\n },\n },\n {\n name: \"rerunBriefStage\",\n displayName: \"Rerun Brief Stage\",\n description: \"Regenerate a single stage of the brief pipeline.\",\n parametersSchema: {\n type: \"object\",\n properties: {\n briefId: { type: \"string\" },\n stage: {\n type: \"string\",\n enum: Object.values(RerunStage),\n },\n },\n required: [\"briefId\", \"stage\"],\n },\n },\n {\n name: \"attachProofPoints\",\n displayName: \"Attach Proof Points\",\n description: \"Inject business-specific proof points into a brief.\",\n parametersSchema: {\n type: \"object\",\n properties: {\n briefId: { type: \"string\" },\n pricingRanges: { type: \"string\" },\n timelines: { type: \"string\" },\n clientOutcomes: { type: \"array\", items: { type: \"string\" } },\n methodology: { type: \"string\" },\n },\n required: [\"briefId\"],\n },\n },\n ],\n};\n\nexport default manifest;\n"],
5
+ "mappings": "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",
6
+ "names": ["RerunStage"]
7
7
  }