@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/worker.js CHANGED
@@ -4873,14 +4873,19 @@ var instanceGeneralSettingsSchema = external_exports.object({
4873
4873
  censorUsernameInLogs: external_exports.boolean().default(false),
4874
4874
  keyboardShortcuts: external_exports.boolean().default(false),
4875
4875
  feedbackDataSharingPreference: feedbackDataSharingPreferenceSchema.default(DEFAULT_FEEDBACK_DATA_SHARING_PREFERENCE),
4876
- backupRetention: backupRetentionPolicySchema.default(DEFAULT_BACKUP_RETENTION)
4876
+ backupRetention: backupRetentionPolicySchema.default(DEFAULT_BACKUP_RETENTION),
4877
+ // Execution policy. Absent/"any" = unrestricted; "kubernetes" forces the
4878
+ // Kubernetes sandbox provider and denies local/ssh execution (cloud_tenant).
4879
+ executionMode: external_exports.enum(["kubernetes", "any"]).optional()
4877
4880
  }).strict();
4878
4881
  var patchInstanceGeneralSettingsSchema = instanceGeneralSettingsSchema.partial();
4879
4882
  var instanceExperimentalSettingsSchema = external_exports.object({
4880
4883
  enableEnvironments: external_exports.boolean().default(false),
4881
4884
  enableIsolatedWorkspaces: external_exports.boolean().default(false),
4882
4885
  enableStreamlinedLeftNavigation: external_exports.boolean().default(false),
4886
+ enableConferenceRoomChat: external_exports.boolean().default(false),
4883
4887
  enableIssuePlanDecompositions: external_exports.boolean().default(false),
4888
+ enableExperimentalFileViewer: external_exports.boolean().default(false),
4884
4889
  enableCloudSync: external_exports.boolean().default(false),
4885
4890
  autoRestartDevServerWhenIdle: external_exports.boolean().default(false),
4886
4891
  enableIssueGraphLivenessAutoRecovery: external_exports.boolean().default(false),
@@ -4982,10 +4987,15 @@ var companySkillSourceTypeSchema = external_exports.enum(["local_path", "github"
4982
4987
  var companySkillTrustLevelSchema = external_exports.enum(["markdown_only", "assets", "scripts_executables"]);
4983
4988
  var companySkillCompatibilitySchema = external_exports.enum(["compatible", "unknown", "invalid"]);
4984
4989
  var companySkillSourceBadgeSchema = external_exports.enum(["paperclip", "github", "local", "url", "catalog", "skills_sh"]);
4990
+ var companySkillSharingScopeSchema = external_exports.enum(["private", "company", "public_link"]);
4991
+ var companySkillListSortSchema = external_exports.enum(["alphabetical", "recent", "installs", "stars", "agents", "forks"]);
4985
4992
  var companySkillFileInventoryEntrySchema = external_exports.object({
4986
4993
  path: external_exports.string().min(1),
4987
4994
  kind: external_exports.enum(["skill", "markdown", "reference", "script", "asset", "other"])
4988
4995
  });
4996
+ var companySkillVersionFileInventoryEntrySchema = companySkillFileInventoryEntrySchema.extend({
4997
+ content: external_exports.string()
4998
+ });
4989
4999
  var companySkillSchema = external_exports.object({
4990
5000
  id: external_exports.string().uuid(),
4991
5001
  companyId: external_exports.string().uuid(),
@@ -5000,6 +5010,20 @@ var companySkillSchema = external_exports.object({
5000
5010
  trustLevel: companySkillTrustLevelSchema,
5001
5011
  compatibility: companySkillCompatibilitySchema,
5002
5012
  fileInventory: external_exports.array(companySkillFileInventoryEntrySchema).default([]),
5013
+ iconUrl: external_exports.string().nullable(),
5014
+ color: external_exports.string().nullable(),
5015
+ tagline: external_exports.string().nullable(),
5016
+ authorName: external_exports.string().nullable(),
5017
+ homepageUrl: external_exports.string().nullable(),
5018
+ categories: external_exports.array(external_exports.string().min(1)).default([]),
5019
+ sharingScope: companySkillSharingScopeSchema,
5020
+ publicShareToken: external_exports.string().nullable(),
5021
+ forkedFromSkillId: external_exports.string().uuid().nullable(),
5022
+ forkedFromCompanyId: external_exports.string().uuid().nullable(),
5023
+ starCount: external_exports.number().int().nonnegative(),
5024
+ installCount: external_exports.number().int().nonnegative(),
5025
+ forkCount: external_exports.number().int().nonnegative(),
5026
+ currentVersionId: external_exports.string().uuid().nullable(),
5003
5027
  metadata: external_exports.record(external_exports.string(), external_exports.unknown()).nullable(),
5004
5028
  createdAt: external_exports.coerce.date(),
5005
5029
  updatedAt: external_exports.coerce.date()
@@ -5021,7 +5045,29 @@ var companySkillUsageAgentSchema = external_exports.object({
5021
5045
  urlKey: external_exports.string().min(1),
5022
5046
  adapterType: external_exports.string().min(1),
5023
5047
  desired: external_exports.boolean(),
5024
- actualState: external_exports.string().nullable().describe("Runtime adapter skill state when explicitly fetched; company skill detail reads return null without probing agent runtimes.")
5048
+ actualState: external_exports.string().nullable().describe("Runtime adapter skill state when explicitly fetched; company skill detail reads return null without probing agent runtimes."),
5049
+ versionId: external_exports.string().uuid().nullable()
5050
+ });
5051
+ var companySkillListQuerySchema = external_exports.object({
5052
+ q: external_exports.string().min(1).optional(),
5053
+ sort: companySkillListSortSchema.optional(),
5054
+ categories: external_exports.array(external_exports.string().min(1)).optional(),
5055
+ scope: companySkillSharingScopeSchema.optional()
5056
+ });
5057
+ var companySkillCategoryCountSchema = external_exports.object({
5058
+ slug: external_exports.string().min(1),
5059
+ count: external_exports.number().int().nonnegative()
5060
+ });
5061
+ var companySkillVersionSchema = external_exports.object({
5062
+ id: external_exports.string().uuid(),
5063
+ companyId: external_exports.string().uuid(),
5064
+ companySkillId: external_exports.string().uuid(),
5065
+ revisionNumber: external_exports.number().int().positive(),
5066
+ label: external_exports.string().nullable(),
5067
+ fileInventory: external_exports.array(companySkillVersionFileInventoryEntrySchema).default([]),
5068
+ authorAgentId: external_exports.string().uuid().nullable(),
5069
+ authorUserId: external_exports.string().nullable(),
5070
+ createdAt: external_exports.coerce.date()
5025
5071
  });
5026
5072
  var companySkillDetailSchema = companySkillSchema.extend({
5027
5073
  attachedAgentCount: external_exports.number().int().nonnegative(),
@@ -5029,8 +5075,52 @@ var companySkillDetailSchema = companySkillSchema.extend({
5029
5075
  editable: external_exports.boolean(),
5030
5076
  editableReason: external_exports.string().nullable(),
5031
5077
  sourceLabel: external_exports.string().nullable(),
5032
- sourceBadge: companySkillSourceBadgeSchema
5078
+ sourceBadge: companySkillSourceBadgeSchema,
5079
+ currentVersion: companySkillVersionSchema.nullable(),
5080
+ starredByCurrentActor: external_exports.boolean()
5081
+ });
5082
+ var companySkillVersionCreateSchema = external_exports.object({
5083
+ label: external_exports.string().trim().min(1).nullable().optional()
5084
+ }).default({});
5085
+ var companySkillStarResultSchema = external_exports.object({
5086
+ skillId: external_exports.string().uuid(),
5087
+ starred: external_exports.boolean(),
5088
+ starCount: external_exports.number().int().nonnegative()
5089
+ });
5090
+ var companySkillCommentSchema = external_exports.object({
5091
+ id: external_exports.string().uuid(),
5092
+ companyId: external_exports.string().uuid(),
5093
+ companySkillId: external_exports.string().uuid(),
5094
+ parentCommentId: external_exports.string().uuid().nullable(),
5095
+ authorAgentId: external_exports.string().uuid().nullable(),
5096
+ authorUserId: external_exports.string().nullable(),
5097
+ body: external_exports.string(),
5098
+ deletedAt: external_exports.coerce.date().nullable(),
5099
+ createdAt: external_exports.coerce.date(),
5100
+ updatedAt: external_exports.coerce.date()
5101
+ });
5102
+ var companySkillCommentCreateSchema = external_exports.object({
5103
+ body: external_exports.string().min(1),
5104
+ parentCommentId: external_exports.string().uuid().nullable().optional()
5033
5105
  });
5106
+ var companySkillCommentUpdateSchema = external_exports.object({
5107
+ body: external_exports.string().min(1)
5108
+ });
5109
+ var companySkillForkSchema = external_exports.object({
5110
+ name: external_exports.string().min(1).nullable().optional(),
5111
+ slug: external_exports.string().min(1).nullable().optional(),
5112
+ sharingScope: companySkillSharingScopeSchema.optional()
5113
+ }).default({});
5114
+ var companySkillUpdateSchema = external_exports.object({
5115
+ description: external_exports.string().nullable().optional(),
5116
+ iconUrl: external_exports.string().nullable().optional(),
5117
+ color: external_exports.string().nullable().optional(),
5118
+ tagline: external_exports.string().max(120).nullable().optional(),
5119
+ authorName: external_exports.string().nullable().optional(),
5120
+ homepageUrl: external_exports.string().nullable().optional(),
5121
+ categories: external_exports.array(external_exports.string().min(1)).optional(),
5122
+ sharingScope: companySkillSharingScopeSchema.optional()
5123
+ }).default({});
5034
5124
  var companySkillUpdateStatusSchema = external_exports.object({
5035
5125
  supported: external_exports.boolean(),
5036
5126
  reason: external_exports.string().nullable(),
@@ -5115,7 +5205,15 @@ var companySkillCreateSchema = external_exports.object({
5115
5205
  name: external_exports.string().min(1),
5116
5206
  slug: external_exports.string().min(1).nullable().optional(),
5117
5207
  description: external_exports.string().nullable().optional(),
5118
- markdown: external_exports.string().nullable().optional()
5208
+ markdown: external_exports.string().nullable().optional(),
5209
+ iconUrl: external_exports.string().nullable().optional(),
5210
+ color: external_exports.string().nullable().optional(),
5211
+ tagline: external_exports.string().max(120).nullable().optional(),
5212
+ authorName: external_exports.string().nullable().optional(),
5213
+ homepageUrl: external_exports.string().nullable().optional(),
5214
+ categories: external_exports.array(external_exports.string().min(1)).optional(),
5215
+ sharingScope: companySkillSharingScopeSchema.optional(),
5216
+ forkedFromSkillId: external_exports.string().uuid().nullable().optional()
5119
5217
  });
5120
5218
  var companySkillFileDetailSchema = external_exports.object({
5121
5219
  skillId: external_exports.string().uuid(),
@@ -6791,9 +6889,19 @@ var agentSkillSyncModeSchema = external_exports.enum([
6791
6889
  "persistent",
6792
6890
  "ephemeral"
6793
6891
  ]);
6892
+ var agentDesiredSkillEntrySchema = external_exports.object({
6893
+ key: external_exports.string().min(1),
6894
+ versionId: external_exports.string().uuid().nullable()
6895
+ });
6896
+ var agentDesiredSkillSelectionSchema = external_exports.union([
6897
+ external_exports.string().min(1),
6898
+ agentDesiredSkillEntrySchema
6899
+ ]);
6794
6900
  var agentSkillEntrySchema = external_exports.object({
6795
6901
  key: external_exports.string().min(1),
6796
6902
  runtimeName: external_exports.string().min(1).nullable(),
6903
+ versionId: external_exports.string().uuid().nullable().optional(),
6904
+ currentVersionId: external_exports.string().uuid().nullable().optional(),
6797
6905
  desired: external_exports.boolean(),
6798
6906
  managed: external_exports.boolean(),
6799
6907
  required: external_exports.boolean().optional(),
@@ -6812,11 +6920,12 @@ var agentSkillSnapshotSchema = external_exports.object({
6812
6920
  supported: external_exports.boolean(),
6813
6921
  mode: agentSkillSyncModeSchema,
6814
6922
  desiredSkills: external_exports.array(external_exports.string().min(1)),
6923
+ desiredSkillEntries: external_exports.array(agentDesiredSkillEntrySchema).optional(),
6815
6924
  entries: external_exports.array(agentSkillEntrySchema),
6816
6925
  warnings: external_exports.array(external_exports.string())
6817
6926
  });
6818
6927
  var agentSkillSyncSchema = external_exports.object({
6819
- desiredSkills: external_exports.array(external_exports.string().min(1))
6928
+ desiredSkills: external_exports.array(agentDesiredSkillSelectionSchema)
6820
6929
  });
6821
6930
 
6822
6931
  // node_modules/@paperclipai/shared/dist/validators/agent.js
@@ -6873,7 +6982,7 @@ var createAgentSchema = external_exports.object({
6873
6982
  icon: external_exports.enum(AGENT_ICON_NAMES).optional().nullable(),
6874
6983
  reportsTo: external_exports.string().uuid().optional().nullable(),
6875
6984
  capabilities: external_exports.string().optional().nullable(),
6876
- desiredSkills: external_exports.array(external_exports.string().min(1)).optional(),
6985
+ desiredSkills: external_exports.array(agentDesiredSkillSelectionSchema).optional(),
6877
6986
  adapterType: agentAdapterTypeSchema,
6878
6987
  adapterConfig: adapterConfigSchema.optional().default({}),
6879
6988
  instructionsBundle: createAgentInstructionsBundleSchema.optional(),
@@ -7125,6 +7234,92 @@ var releaseIssueTreeHoldSchema = external_exports.object({
7125
7234
  metadata: external_exports.record(external_exports.string(), external_exports.unknown()).optional().nullable()
7126
7235
  }).strict();
7127
7236
 
7237
+ // node_modules/@paperclipai/shared/dist/validators/workspace-file-resource.js
7238
+ var workspaceFileListSearchMaxBytes = 128;
7239
+ function utf8ByteLength(value) {
7240
+ return new TextEncoder().encode(value).length;
7241
+ }
7242
+ var workspaceFileWorkspaceKindSchema = external_exports.enum(["execution_workspace", "project_workspace"]);
7243
+ var workspaceFileSelectorSchema = external_exports.enum(["auto", "execution", "project"]).default("auto");
7244
+ var workspaceFileListModeSchema = external_exports.enum(["all", "recent", "changed"]).default("all");
7245
+ var workspaceFilePreviewKindSchema = external_exports.enum(["text", "image", "video", "pdf", "unsupported"]);
7246
+ var workspaceFileResourceKindSchema = external_exports.enum(["file", "directory", "remote_resource"]);
7247
+ var workspaceFileRefSchema = external_exports.object({
7248
+ kind: external_exports.literal("workspace_file"),
7249
+ issueId: external_exports.string().uuid().optional(),
7250
+ projectId: external_exports.string().uuid().optional(),
7251
+ projectName: external_exports.string().min(1).optional(),
7252
+ workspaceKind: workspaceFileWorkspaceKindSchema,
7253
+ workspaceId: external_exports.string().uuid(),
7254
+ relativePath: external_exports.string().min(1),
7255
+ line: external_exports.number().int().positive().nullable().optional(),
7256
+ column: external_exports.number().int().positive().nullable().optional(),
7257
+ displayPath: external_exports.string().min(1)
7258
+ });
7259
+ var workspaceFileResourceQuerySchema = external_exports.object({
7260
+ projectId: external_exports.string().uuid().optional(),
7261
+ workspaceId: external_exports.string().uuid().optional(),
7262
+ path: external_exports.string().min(1).refine((value) => !/[\x00-\x1f\x7f]/.test(value), {
7263
+ message: "Workspace file path contains an invalid character",
7264
+ params: { code: "invalid_path" }
7265
+ }),
7266
+ workspace: workspaceFileSelectorSchema.optional()
7267
+ }).refine((value) => Boolean(value.projectId) === Boolean(value.workspaceId), {
7268
+ message: "Workspace file target requires both projectId and workspaceId",
7269
+ path: ["workspaceId"],
7270
+ params: { code: "invalid_target" }
7271
+ });
7272
+ var workspaceFileListQuerySchema = external_exports.object({
7273
+ projectId: external_exports.string().uuid().optional(),
7274
+ workspaceId: external_exports.string().uuid().optional(),
7275
+ workspace: workspaceFileSelectorSchema.optional(),
7276
+ path: external_exports.string().min(1).refine((value) => !/[\x00-\x1f\x7f]/.test(value), {
7277
+ message: "Workspace folder path contains an invalid character",
7278
+ params: { code: "invalid_path" }
7279
+ }).optional(),
7280
+ mode: workspaceFileListModeSchema.optional(),
7281
+ q: external_exports.string().refine((value) => !/[\x00-\x1f\x7f]/.test(value), {
7282
+ message: "Workspace file search contains an invalid character",
7283
+ params: { code: "invalid_query" }
7284
+ }).refine((value) => utf8ByteLength(value.trim()) <= workspaceFileListSearchMaxBytes, {
7285
+ message: "Workspace file search is too long",
7286
+ params: { code: "invalid_query" }
7287
+ }).optional(),
7288
+ limit: external_exports.coerce.number().int().min(1).max(100).default(25),
7289
+ offset: external_exports.coerce.number().int().min(0).max(1e4).default(0)
7290
+ }).refine((value) => Boolean(value.projectId) === Boolean(value.workspaceId), {
7291
+ message: "Workspace file target requires both projectId and workspaceId",
7292
+ path: ["workspaceId"],
7293
+ params: { code: "invalid_target" }
7294
+ });
7295
+ var resolvedWorkspaceResourceSchema = external_exports.object({
7296
+ kind: workspaceFileResourceKindSchema,
7297
+ provider: external_exports.string().min(1),
7298
+ title: external_exports.string().min(1),
7299
+ displayPath: external_exports.string().min(1),
7300
+ workspaceLabel: external_exports.string().min(1),
7301
+ workspaceKind: workspaceFileWorkspaceKindSchema,
7302
+ workspaceId: external_exports.string().uuid(),
7303
+ projectId: external_exports.string().uuid().nullable().optional(),
7304
+ projectName: external_exports.string().min(1).nullable().optional(),
7305
+ contentType: external_exports.string().nullable().optional(),
7306
+ byteSize: external_exports.number().int().nonnegative().nullable().optional(),
7307
+ previewKind: workspaceFilePreviewKindSchema,
7308
+ denialReason: external_exports.string().nullable().optional(),
7309
+ capabilities: external_exports.object({
7310
+ preview: external_exports.boolean(),
7311
+ download: external_exports.literal(false),
7312
+ listChildren: external_exports.boolean()
7313
+ })
7314
+ });
7315
+ var workspaceFileContentSchema = external_exports.object({
7316
+ resource: resolvedWorkspaceResourceSchema,
7317
+ content: external_exports.object({
7318
+ encoding: external_exports.enum(["utf8", "base64"]),
7319
+ data: external_exports.string()
7320
+ })
7321
+ });
7322
+
7128
7323
  // node_modules/@paperclipai/shared/dist/validators/work-product.js
7129
7324
  function attachmentContentPath(attachmentId) {
7130
7325
  return `/api/attachments/${attachmentId}/content`;
@@ -7187,6 +7382,9 @@ var attachmentArtifactWorkProductMetadataSchema = external_exports.object({
7187
7382
  });
7188
7383
  }
7189
7384
  });
7385
+ var issueWorkProductMetadataSchema = external_exports.object({
7386
+ resourceRef: workspaceFileRefSchema.optional().nullable()
7387
+ }).passthrough();
7190
7388
  var createIssueWorkProductSchema = external_exports.object({
7191
7389
  projectId: external_exports.string().uuid().optional().nullable(),
7192
7390
  executionWorkspaceId: external_exports.string().uuid().optional().nullable(),
@@ -7201,7 +7399,7 @@ var createIssueWorkProductSchema = external_exports.object({
7201
7399
  isPrimary: external_exports.boolean().optional().default(false),
7202
7400
  healthStatus: external_exports.enum(["unknown", "healthy", "unhealthy"]).optional().default("unknown"),
7203
7401
  summary: external_exports.string().optional().nullable(),
7204
- metadata: external_exports.record(external_exports.string(), external_exports.unknown()).optional().nullable(),
7402
+ metadata: issueWorkProductMetadataSchema.optional().nullable(),
7205
7403
  createdByRunId: external_exports.string().uuid().optional().nullable()
7206
7404
  });
7207
7405
  var updateIssueWorkProductSchema = createIssueWorkProductSchema.partial();
@@ -8388,6 +8586,18 @@ var paperclipConfigSchema = external_exports.object({
8388
8586
  }
8389
8587
  });
8390
8588
 
8589
+ // node_modules/@paperclipai/shared/dist/validators/adapter-registry.js
8590
+ var adapterRegistryEntrySchema = external_exports.object({
8591
+ adapterType: external_exports.string().min(1),
8592
+ enabled: external_exports.boolean().default(true),
8593
+ runtimeImage: external_exports.string().optional(),
8594
+ envKeys: external_exports.array(external_exports.string()).optional(),
8595
+ allowFqdns: external_exports.array(external_exports.string()).optional(),
8596
+ probeCommand: external_exports.array(external_exports.string()).optional(),
8597
+ defaultEnv: external_exports.record(external_exports.string()).optional()
8598
+ }).strict();
8599
+ var adapterRegistrySchema = external_exports.array(adapterRegistryEntrySchema);
8600
+
8391
8601
  // node_modules/@paperclipai/plugin-sdk/dist/worker-rpc-host.js
8392
8602
  import fs from "node:fs";
8393
8603
  import { AsyncLocalStorage } from "node:async_hooks";
@@ -9773,88 +9983,16 @@ function startWorkerRpcHost(options) {
9773
9983
  };
9774
9984
  }
9775
9985
 
9776
- // src/utils/brief-view.ts
9777
- var SCHEMA_KEY_LABELS = {
9778
- article: "Article",
9779
- itemList: "ItemList",
9780
- breadcrumbList: "BreadcrumbList",
9781
- faqPage: "FAQPage",
9782
- howTo: "HowTo",
9783
- service: "Service",
9784
- offer: "Offer"
9785
- };
9786
- function toBriefWriterView(d) {
9787
- const brief = d.brief ?? {};
9788
- const coverage = d.coverageMatrix ?? {};
9789
- const intentSat = d.searchIntentSatisfaction ?? {};
9790
- const diff = d.differentiationStrategy ?? {};
9791
- const schemaBundle = d.schemaBundle ?? {};
9792
- const mapOutline = (s) => ({
9793
- heading: s.heading,
9794
- level: s.level,
9795
- wordCount: s.wordCount,
9796
- importance: s.importance ?? null,
9797
- format: s.formatNotes,
9798
- guidance: s.keywordGuidance,
9799
- ...Array.isArray(s.subSections) && s.subSections.length ? { subSections: s.subSections.map(mapOutline) } : {}
9800
- });
9801
- return {
9802
- status: d.status,
9803
- pageType: d.template,
9804
- intent: d.intent,
9805
- targetKeyword: d.keyword,
9806
- targetAudience: d.targetAudience,
9807
- priorityScore: d.priorityScore,
9808
- priorityTier: d.priorityTier,
9809
- clusterPosition: d.clusterPosition,
9810
- recommendedTitle: brief.title,
9811
- metaDescription: brief.metaDescription,
9812
- urlSlug: brief.urlSlug,
9813
- supportingKeywords: d.supportingKeywords ?? [],
9814
- mustAnswer: intentSat.mustAnswer ?? [],
9815
- niceToAnswer: intentSat.niceToAnswer ?? [],
9816
- targetWordCount: brief.targetWordCount,
9817
- competitorAvgWordCount: brief.competitorAvgWordCount,
9818
- outline: (brief.outline ?? []).map(mapOutline),
9819
- requiredTopics: (coverage.requiredTopics ?? []).map((t) => t.topic),
9820
- contentGaps: coverage.contentGaps ?? [],
9821
- differentiatorOpportunities: coverage.differentiatorOpportunities ?? [],
9822
- faq: (brief.faq ?? []).map((f) => f.q),
9823
- tldrBlock: d.tldrBlock ? {
9824
- text: d.tldrBlock.text,
9825
- wordCount: d.tldrBlock.wordCount,
9826
- placement: d.tldrBlock.placement,
9827
- fsTarget: d.tldrBlock.fsTarget
9828
- } : void 0,
9829
- objectiveLanguageInstruction: d.objectiveLanguageInstruction,
9830
- requiredSignals: d.geo?.requiredSignals ?? [],
9831
- schemaRequired: Object.keys(SCHEMA_KEY_LABELS).filter((k) => schemaBundle[k]).map((k) => SCHEMA_KEY_LABELS[k]),
9832
- contentAngle: d.contentAngle,
9833
- competitorGap: d.competitorGap,
9834
- mustOwnTopics: diff.mustOwnTopics ?? [],
9835
- uniqueAssets: diff.uniqueAssets ?? [],
9836
- proofPointsToInclude: diff.proofPointsToInclude ?? [],
9837
- competitorBlindSpots: diff.competitorBlindSpots ?? [],
9838
- competitorPagesToReference: d.competitorPagesToReference ?? [],
9839
- internalLinks: (brief.internalLinks ?? []).map((l) => ({
9840
- anchor: l.anchor,
9841
- targetUrl: l.targetUrl,
9842
- reason: l.reason
9843
- })),
9844
- internalLinksFrom: brief.internalLinksFrom ?? [],
9845
- isSelfReferentialListicle: Boolean(d.isSelfReferentialListicle),
9846
- clusterContext: d.clusterContext ? {
9847
- pillarTitle: d.clusterContext.pillarTitle,
9848
- pillarUrl: d.clusterContext.pillarUrl,
9849
- spokes: (d.clusterContext.spokes ?? []).map((s) => ({
9850
- keyword: s.keyword,
9851
- title: s.title,
9852
- url: s.url
9853
- }))
9854
- } : void 0,
9855
- flags: (d.flags ?? []).map((f) => ({ code: f.code, note: f.note }))
9856
- };
9857
- }
9986
+ // src/types/index.ts
9987
+ var RerunStage = /* @__PURE__ */ ((RerunStage2) => {
9988
+ RerunStage2["GEO"] = "geo";
9989
+ RerunStage2["SCHEMA"] = "schema";
9990
+ RerunStage2["OUTLINE"] = "outline";
9991
+ RerunStage2["ENRICHMENT"] = "enrichment";
9992
+ RerunStage2["INTENT"] = "intent";
9993
+ RerunStage2["STRATEGY"] = "strategy";
9994
+ return RerunStage2;
9995
+ })(RerunStage || {});
9858
9996
 
9859
9997
  // src/worker.ts
9860
9998
  var plugin = definePlugin({
@@ -9862,6 +10000,8 @@ var plugin = definePlugin({
9862
10000
  const config = await ctx.config.get();
9863
10001
  const BASE = config.backendUrl;
9864
10002
  const AUTH_TOKEN = config.authToken;
10003
+ const API_PREFIX2 = "/api";
10004
+ const apiRoot = `${BASE}${API_PREFIX2}`;
9865
10005
  ctx.logger.info("Loaded config on startup", {
9866
10006
  BACKEND_URL: BASE,
9867
10007
  hasApiToken: !!AUTH_TOKEN
@@ -9869,7 +10009,7 @@ var plugin = definePlugin({
9869
10009
  const api = async (path2, method = "GET", body) => {
9870
10010
  ctx.logger.info(`pluggin called - ${method} ${path2}`);
9871
10011
  try {
9872
- const res = await ctx.http.fetch(`${BASE}${path2}`, {
10012
+ const res = await ctx.http.fetch(`${apiRoot}${path2}`, {
9873
10013
  method,
9874
10014
  headers: {
9875
10015
  "Content-Type": "application/json",
@@ -9894,9 +10034,9 @@ var plugin = definePlugin({
9894
10034
  }
9895
10035
  };
9896
10036
  ctx.tools.register(
9897
- "runKeywordResearch",
10037
+ "startKeywordResearch",
9898
10038
  {
9899
- displayName: "Run Keyword Research",
10039
+ displayName: "Start a New Keyword Research",
9900
10040
  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.",
9901
10041
  parametersSchema: {
9902
10042
  type: "object",
@@ -9907,7 +10047,7 @@ var plugin = definePlugin({
9907
10047
  async (params) => {
9908
10048
  const { keyword } = params;
9909
10049
  try {
9910
- const json = await api("/api/keyword-research/start", "POST", {
10050
+ const json = await api("/keyword-research/start", "POST", {
9911
10051
  keyword
9912
10052
  });
9913
10053
  const d = json?.data ?? {};
@@ -9927,7 +10067,7 @@ var plugin = definePlugin({
9927
10067
  "getKeywordSessionStatus",
9928
10068
  {
9929
10069
  displayName: "Get Keyword Session Status",
9930
- description: "Poll the status of a KeywordSession started by runKeywordResearch. 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.",
10070
+ 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.",
9931
10071
  parametersSchema: {
9932
10072
  type: "object",
9933
10073
  properties: { keywordSessionRef: { type: "string" } },
@@ -9938,40 +10078,43 @@ var plugin = definePlugin({
9938
10078
  const { keywordSessionRef } = params;
9939
10079
  try {
9940
10080
  const json = await api(
9941
- `/api/keyword-research/${keywordSessionRef}/status`,
10081
+ `/keyword-research/${keywordSessionRef}/status`,
9942
10082
  "GET"
9943
10083
  );
9944
- const d = json?.data ?? {};
9945
- if (d.status === "completed") {
10084
+ const sessionStatus = json?.data ?? {};
10085
+ if (sessionStatus.status === "completed" /* COMPLETED */) {
9946
10086
  return {
9947
- content: `Keyword research for "${d.seedKeyword}" complete: ${d.highCount} HIGH, ${d.medCount} MEDIUM, ${d.lowCount} LOW, ${d.deadCount} DEAD out of ${d.totalEnriched} enriched keywords. keywordSessionRef is "${d.keywordSessionRef}" \u2014 save it for clusterKeywords. Full keyword list is in the 'keywords' array \u2014 render it as a Markdown table now.`,
10087
+ content: `Keyword research for "${sessionStatus.seedKeyword}" complete: ${sessionStatus.highCount} HIGH, ${sessionStatus.medCount} MEDIUM, ${sessionStatus.lowCount} LOW, ${sessionStatus.deadCount} DEAD out of ${sessionStatus.totalEnriched} enriched keywords. keywordSessionRef is "${sessionStatus.keywordSessionRef}" \u2014 save it for clusterKeywords. Full keyword list is in the 'keywords' array \u2014 render it as a Markdown table now.`,
9948
10088
  data: {
9949
- status: d.status,
9950
- keywordSessionRef: d.keywordSessionRef,
9951
- seedKeyword: d.seedKeyword,
9952
- totalSuggestions: d.totalSuggestions,
9953
- totalEnriched: d.totalEnriched,
9954
- highCount: d.highCount,
9955
- medCount: d.medCount,
9956
- lowCount: d.lowCount,
9957
- deadCount: d.deadCount,
9958
- keywords: d.keywords ?? []
10089
+ status: sessionStatus.status,
10090
+ keywordSessionRef: sessionStatus.keywordSessionRef,
10091
+ seedKeyword: sessionStatus.seedKeyword,
10092
+ totalSuggestions: sessionStatus.totalSuggestions,
10093
+ totalEnriched: sessionStatus.totalEnriched,
10094
+ highCount: sessionStatus.highCount,
10095
+ medCount: sessionStatus.medCount,
10096
+ lowCount: sessionStatus.lowCount,
10097
+ deadCount: sessionStatus.deadCount,
10098
+ keywords: sessionStatus.keywords ?? []
9959
10099
  }
9960
10100
  };
9961
10101
  }
9962
- if (d.status === "failed") {
10102
+ if (sessionStatus.status === "failed" /* FAILED */) {
9963
10103
  return {
9964
- content: `Keyword research for "${d.seedKeyword}" failed: ${d.errorMessage}`,
10104
+ content: `Keyword research for "${sessionStatus.seedKeyword}" failed: ${sessionStatus.errorMessage}`,
9965
10105
  data: {
9966
- status: d.status,
9967
- keywordSessionRef: d.keywordSessionRef,
9968
- errorMessage: d.errorMessage
10106
+ status: sessionStatus.status,
10107
+ keywordSessionRef: sessionStatus.keywordSessionRef,
10108
+ errorMessage: sessionStatus.errorMessage
9969
10109
  }
9970
10110
  };
9971
10111
  }
9972
10112
  return {
9973
- content: `Job is still running (phase: ${d.status}). Poll again in 10 seconds.`,
9974
- data: { status: d.status, keywordSessionRef: d.keywordSessionRef }
10113
+ content: `Job is still running (phase: ${sessionStatus.status}). Poll again in 10 seconds.`,
10114
+ data: {
10115
+ status: sessionStatus.status,
10116
+ keywordSessionRef: sessionStatus.keywordSessionRef
10117
+ }
9975
10118
  };
9976
10119
  } catch (e) {
9977
10120
  return { error: String(e) };
@@ -9979,7 +10122,7 @@ var plugin = definePlugin({
9979
10122
  }
9980
10123
  );
9981
10124
  ctx.tools.register(
9982
- "listKeywordSessions",
10125
+ "listKeywordResearchSessions",
9983
10126
  {
9984
10127
  displayName: "List Keyword Sessions",
9985
10128
  description: "List all past keyword research sessions with a brief overview \u2014 seedKeyword, status, and keyword count only.",
@@ -9987,17 +10130,16 @@ var plugin = definePlugin({
9987
10130
  },
9988
10131
  async () => {
9989
10132
  try {
9990
- const json = await api("/api/keyword-research/", "GET");
10133
+ const json = await api("/keyword-research/", "GET");
9991
10134
  const sessions = json?.data ?? [];
9992
- return {
9993
- data: sessions.map((s) => ({
9994
- keywordSessionRef: String(s._id ?? ""),
9995
- seedKeyword: s.seedKeyword,
9996
- status: s.status,
9997
- keywordCount: s.keywordCount ?? 0,
9998
- createdAt: s.createdAt
9999
- }))
10000
- };
10135
+ const data = sessions.map((s) => ({
10136
+ keywordSessionRef: String(s._id ?? ""),
10137
+ seedKeyword: s.seedKeyword,
10138
+ status: s.status,
10139
+ keywordCount: s.keywordCount ?? 0,
10140
+ createdAt: s.createdAt
10141
+ }));
10142
+ return { data };
10001
10143
  } catch (e) {
10002
10144
  return { error: String(e) };
10003
10145
  }
@@ -10007,7 +10149,7 @@ var plugin = definePlugin({
10007
10149
  "clusterKeywords",
10008
10150
  {
10009
10151
  displayName: "Cluster Keywords",
10010
- description: "Call this AFTER getKeywordSessionStatus returns 'completed'. Pass the keywordSessionRef from that completed response (or from listKeywordSessions). 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.",
10152
+ 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.",
10011
10153
  parametersSchema: {
10012
10154
  type: "object",
10013
10155
  properties: { keywordSessionRef: { type: "string" } },
@@ -10017,7 +10159,7 @@ var plugin = definePlugin({
10017
10159
  async (params) => {
10018
10160
  const { keywordSessionRef } = params;
10019
10161
  try {
10020
- const json = await api("/api/clustering", "POST", {
10162
+ const json = await api("/clustering", "POST", {
10021
10163
  keywordSessionRef
10022
10164
  });
10023
10165
  const d = json?.data ?? {};
@@ -10044,9 +10186,10 @@ var plugin = definePlugin({
10044
10186
  async (params) => {
10045
10187
  const { clusterId } = params;
10046
10188
  try {
10047
- const json = await api(`/api/clustering/${clusterId}`, "GET");
10189
+ const json = await api(`/clustering/${clusterId}`, "GET");
10048
10190
  const d = json?.data ?? {};
10049
- if (d.status === "completed" || d.status === "COMPLETED") {
10191
+ const clusterStatus = String(d.status ?? "").toLowerCase();
10192
+ if (clusterStatus === "completed" /* COMPLETED */) {
10050
10193
  const plan = d.clusterPlan ?? {};
10051
10194
  const architectures = (plan.architectures ?? []).map((arch) => ({
10052
10195
  pillar: arch.pillar ? {
@@ -10086,7 +10229,7 @@ var plugin = definePlugin({
10086
10229
  }
10087
10230
  };
10088
10231
  }
10089
- if (d.status === "failed" || d.status === "FAILED") {
10232
+ if (clusterStatus === "failed" /* FAILED */) {
10090
10233
  return {
10091
10234
  content: `Clustering failed: ${d.error ?? "Unknown error"}`,
10092
10235
  data: { status: d.status, error: d.error }
@@ -10110,17 +10253,16 @@ var plugin = definePlugin({
10110
10253
  },
10111
10254
  async () => {
10112
10255
  try {
10113
- const json = await api("/api/clustering/", "GET");
10256
+ const json = await api("/clustering/", "GET");
10114
10257
  const sessions = json?.data ?? [];
10115
- return {
10116
- data: sessions.map((s) => ({
10117
- clusterId: String(s._id ?? ""),
10118
- seedKeyword: s.seedKeyword,
10119
- status: s.status,
10120
- keywordCount: s.keywordCount ?? 0,
10121
- createdAt: s.createdAt
10122
- }))
10123
- };
10258
+ const data = sessions.map((s) => ({
10259
+ clusterId: String(s._id ?? ""),
10260
+ seedKeyword: s.seedKeyword,
10261
+ status: s.status,
10262
+ keywordCount: s.keywordCount ?? 0,
10263
+ createdAt: s.createdAt
10264
+ }));
10265
+ return { data };
10124
10266
  } catch (e) {
10125
10267
  return { error: String(e) };
10126
10268
  }
@@ -10130,7 +10272,7 @@ var plugin = definePlugin({
10130
10272
  "generateContentBrief",
10131
10273
  {
10132
10274
  displayName: "Generate Content Brief",
10133
- 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'.",
10275
+ 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.",
10134
10276
  parametersSchema: {
10135
10277
  type: "object",
10136
10278
  properties: {
@@ -10145,8 +10287,8 @@ var plugin = definePlugin({
10145
10287
  async (params) => {
10146
10288
  const p = params;
10147
10289
  try {
10148
- const data = await api("/api/content-brief/generate", "POST", p);
10149
- return { data };
10290
+ const json = await api("/content-brief/generate", "POST", p);
10291
+ return { data: json?.data ?? {} };
10150
10292
  } catch (e) {
10151
10293
  return { error: String(e) };
10152
10294
  }
@@ -10166,24 +10308,8 @@ var plugin = definePlugin({
10166
10308
  async (params) => {
10167
10309
  const { briefId } = params;
10168
10310
  try {
10169
- const json = await api(`/api/content-brief/${briefId}`, "GET");
10170
- const d = json?.data ?? {};
10171
- if (d.status === "COMPLETED" || d.status === "NEEDS_REVIEW") {
10172
- return {
10173
- content: `Brief ${d.status} for "${d.keyword}". The 'brief' object is the trimmed writer view \u2014 render it per RENDERING.md.`,
10174
- data: { briefId, brief: toBriefWriterView(d) }
10175
- };
10176
- }
10177
- if (d.status === "FAILED") {
10178
- return {
10179
- content: `Brief generation failed: ${d.error ?? "Unknown error"}`,
10180
- data: { briefId, status: d.status, error: d.error }
10181
- };
10182
- }
10183
- return {
10184
- content: `Brief is still running (status: ${d.status}). Poll again in ~10 seconds.`,
10185
- data: { briefId, status: d.status }
10186
- };
10311
+ const json = await api(`/content-brief/${briefId}`, "GET");
10312
+ return { data: json?.data ?? {} };
10187
10313
  } catch (e) {
10188
10314
  return { error: String(e) };
10189
10315
  }
@@ -10203,7 +10329,15 @@ var plugin = definePlugin({
10203
10329
  const { clusterSessionRef } = params;
10204
10330
  try {
10205
10331
  const qs = clusterSessionRef ? `?clusterSessionRef=${clusterSessionRef}` : "";
10206
- const data = await api(`/api/content-brief/${qs}`, "GET");
10332
+ const json = await api(`/content-brief/${qs}`, "GET");
10333
+ const briefs = json?.data ?? [];
10334
+ const data = briefs.map((b) => ({
10335
+ briefId: String(b._id ?? ""),
10336
+ keyword: b.keyword,
10337
+ status: b.status,
10338
+ createdAt: b.createdAt,
10339
+ updatedAt: b.updatedAt
10340
+ }));
10207
10341
  return { data };
10208
10342
  } catch (e) {
10209
10343
  return { error: String(e) };
@@ -10219,7 +10353,10 @@ var plugin = definePlugin({
10219
10353
  type: "object",
10220
10354
  properties: {
10221
10355
  briefId: { type: "string" },
10222
- stage: { type: "string" }
10356
+ stage: {
10357
+ type: "string",
10358
+ enum: Object.values(RerunStage)
10359
+ }
10223
10360
  },
10224
10361
  required: ["briefId", "stage"]
10225
10362
  }
@@ -10227,11 +10364,11 @@ var plugin = definePlugin({
10227
10364
  async (params) => {
10228
10365
  const { briefId, stage } = params;
10229
10366
  try {
10230
- const data = await api(
10231
- `/api/content-brief/${briefId}/rerun?stage=${stage}`,
10367
+ const json = await api(
10368
+ `/content-brief/${briefId}/rerun?stage=${stage}`,
10232
10369
  "POST"
10233
10370
  );
10234
- return { data };
10371
+ return { data: json?.data ?? {} };
10235
10372
  } catch (e) {
10236
10373
  return { error: String(e) };
10237
10374
  }
@@ -10257,12 +10394,12 @@ var plugin = definePlugin({
10257
10394
  async (params) => {
10258
10395
  const { briefId, ...bodyParams } = params;
10259
10396
  try {
10260
- const data = await api(
10261
- `/api/content-brief/${briefId}/proof-points`,
10397
+ const json = await api(
10398
+ `/content-brief/${briefId}/proof-points`,
10262
10399
  "PATCH",
10263
10400
  bodyParams
10264
10401
  );
10265
- return { data };
10402
+ return { data: json?.data ?? {} };
10266
10403
  } catch (e) {
10267
10404
  return { error: String(e) };
10268
10405
  }
@@ -10281,7 +10418,7 @@ var plugin = definePlugin({
10281
10418
  });
10282
10419
  ctx.data.register("sessions", async () => {
10283
10420
  try {
10284
- const json = await api("/api/keyword-research/", "GET");
10421
+ const json = await api("/keyword-research/", "GET");
10285
10422
  return { sessions: json?.data ?? [] };
10286
10423
  } catch (err) {
10287
10424
  ctx.logger.error("sessions handler failed", { error: String(err) });
@@ -10297,7 +10434,7 @@ var plugin = definePlugin({
10297
10434
  }
10298
10435
  try {
10299
10436
  const json = await api(
10300
- `/api/keyword-research/${encodeURIComponent(keywordSessionRef)}/status`,
10437
+ `/keyword-research/${encodeURIComponent(keywordSessionRef)}/status`,
10301
10438
  "GET"
10302
10439
  );
10303
10440
  return {