@geoly-ai/social-hub-sdk 0.0.57 → 0.1.0

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/index.d.ts CHANGED
@@ -352,6 +352,68 @@ export type ListCommentDraftsParams = {
352
352
  /** 把聚合收窄到指定可见团队(逗号拼);空数组=不收窄。 */
353
353
  scopeTeamIds?: string[];
354
354
  };
355
+ /**
356
+ * R12(迁移 0153)——「**显式**声明这条内容不做品牌提及」。
357
+ *
358
+ * 只有 `"none"` 一个值,对应契约的 `brandMentionDeclarationSchema`
359
+ * (`packages/contracts/src/brand-mention-declaration.ts`)。
360
+ *
361
+ * 🔴 **缺失 ≠ 无意图**:省略 `brandId` 而不带这个声明,服务端按「忘了传」判 400,
362
+ * 不会静默降级成无品牌。判定规则全在服务端(`refineBrandMentionDeclaration` +
363
+ * 路由的四值比较 + db 层兜底),**SDK 只表达类型、不复刻校验** —— 复刻必然两边漂移。
364
+ */
365
+ export type BrandMentionDeclaration = "none";
366
+ /**
367
+ * `POST /content-drafts` 的 body。
368
+ *
369
+ * ⚠️ `brandId` 与 `brandMention` 的互斥/必填关系**故意不用类型联合表达**:
370
+ * 服务端的 `superRefine` 是唯一判定处,在 SDK 里再写一遍会漂移(见
371
+ * {@link BrandMentionDeclaration})。类型只负责让「无品牌草稿」可以被表达出来。
372
+ */
373
+ export type CreateContentDraftBody = {
374
+ /** R12:可选。省略时**必须**同时显式给 `brandMention: "none"`(服务端校验)。 */
375
+ brandId?: string;
376
+ /** R12:显式声明本草稿不做品牌提及。见 {@link BrandMentionDeclaration}。 */
377
+ brandMention?: BrandMentionDeclaration;
378
+ /** @deprecated legacy 归因;新草稿只用 brandId。 */
379
+ campaignId?: string;
380
+ title: string;
381
+ body: string;
382
+ /** 目标板块(内容语义真源);服务端规范化后落库。省略/null → NULL。 */
383
+ subreddit?: string | null;
384
+ /**
385
+ * 写作参考 / 归因备注 URL:「这篇内容围绕哪个落地页写的」。
386
+ * ⚠️ **不参与发布执行** —— 系统没有 Reddit link post 概念,执行只冻结 title+body。
387
+ */
388
+ referenceUrl?: string | null;
389
+ };
390
+ /** `POST /publishing-plans` 里的单条待排期条目。 */
391
+ export type CreatePublishingPlanEntryInput = {
392
+ contentDraftId?: string;
393
+ socialAccountId: string;
394
+ subreddit: string;
395
+ /** ISO-8601 datetime。 */
396
+ plannedAt: string;
397
+ /** 缺省 = `hub_managed`。见 {@link CalendarEntryDeliveryMode}。 */
398
+ deliveryMode?: CalendarEntryDeliveryMode;
399
+ };
400
+ /**
401
+ * `POST /publishing-plans` 的 body(此前是 `Record<string, unknown>`,运行时不挡、
402
+ * 类型也表达不出 R12 的无品牌计划)。
403
+ *
404
+ * ⚠️ 与 {@link CreateContentDraftBody} 同理:brandId / brandMention 的四条 fail-closed
405
+ * 规则**只在服务端**判,SDK 不复刻。
406
+ */
407
+ export type CreatePublishingPlanBody = {
408
+ /** R12:可选。省略时**必须**同时显式给 `brandMention: "none"`(服务端校验)。 */
409
+ brandId?: string;
410
+ /** R12:显式声明本计划不做品牌提及。见 {@link BrandMentionDeclaration}。 */
411
+ brandMention?: BrandMentionDeclaration;
412
+ /** @deprecated legacy 归因。 */
413
+ campaignId?: string;
414
+ name: string;
415
+ entries: CreatePublishingPlanEntryInput[];
416
+ };
355
417
  export type CreateCommentDraftBody = {
356
418
  brandId: string;
357
419
  campaignId?: string;
@@ -636,6 +698,13 @@ export type ListScheduledJobsParams = {
636
698
  from?: string;
637
699
  to?: string;
638
700
  };
701
+ export type ListAccountRiskProfilesParams = {
702
+ /** 服务端上限 200;缺省 100。 */
703
+ limit?: number;
704
+ /** 翻页起始偏移量(offset,不是 cursor):每次 += limit。 */
705
+ offset?: number;
706
+ search?: string;
707
+ };
639
708
  export type ListAccountsParams = {
640
709
  limit?: number;
641
710
  offset?: number;
@@ -996,7 +1065,19 @@ export declare class SocialHubClient {
996
1065
  private teamBase;
997
1066
  /** GET /health — no API key required. */
998
1067
  getHealth(): Promise<HealthCheckJson>;
1068
+ /**
1069
+ * 绝对 URL 拼接的**唯一**入口:`path` 一律是站内相对路径(如 `/v1/teams/x/events`)。
1070
+ * 直接把相对路径交给 `fetch()` 在 Node 下会抛
1071
+ * `TypeError: Failed to parse URL from /v1/...`,所以新增请求方法必须走这里。
1072
+ */
1073
+ private buildUrl;
1074
+ /** 鉴权 + 默认 Content-Type;调用方 headers 覆盖默认值(与历史行为一致)。 */
1075
+ private buildHeaders;
1076
+ /** 共享请求管线:统一 base-url 拼接、鉴权头与错误体解析,返回原始响应文本。 */
1077
+ private requestText;
999
1078
  private fetchJson;
1079
+ /** 与 `fetchJson` 同一条 base-url/鉴权/错误处理路径,但返回文本(CSV 等非 JSON 响应)。 */
1080
+ private fetchText;
1000
1081
  appendEvent(teamId: string, body: {
1001
1082
  type: string;
1002
1083
  socialAccountId?: string;
@@ -1234,19 +1315,7 @@ export declare class SocialHubClient {
1234
1315
  limit: number;
1235
1316
  offset: number;
1236
1317
  }>;
1237
- createContentDraft(teamId: string, body: {
1238
- brandId: string;
1239
- campaignId?: string;
1240
- title: string;
1241
- body: string;
1242
- /** 目标板块(内容语义真源);服务端规范化后落库。省略/null → NULL。 */
1243
- subreddit?: string | null;
1244
- /**
1245
- * 写作参考 / 归因备注 URL:「这篇内容围绕哪个落地页写的」。
1246
- * ⚠️ **不参与发布执行** —— 系统没有 Reddit link post 概念,执行只冻结 title+body。
1247
- */
1248
- referenceUrl?: string | null;
1249
- }): Promise<{
1318
+ createContentDraft(teamId: string, body: CreateContentDraftBody): Promise<{
1250
1319
  id: string;
1251
1320
  }>;
1252
1321
  /**
@@ -1414,6 +1483,10 @@ export declare class SocialHubClient {
1414
1483
  }): Promise<unknown>;
1415
1484
  listAccounts(teamId: string, params?: ListAccountsParams): Promise<{
1416
1485
  items: unknown[];
1486
+ /** 满足过滤条件的总数(与 limit/offset 无关);翻页终止判据。 */
1487
+ total?: number;
1488
+ limit?: number;
1489
+ offset?: number;
1417
1490
  }>;
1418
1491
  createAccount(teamId: string, body: Record<string, unknown>): Promise<{
1419
1492
  id: string;
@@ -1607,7 +1680,7 @@ export declare class SocialHubClient {
1607
1680
  listPublishingPlans(teamId: string, params?: ListPublishingPlansParams): Promise<{
1608
1681
  items: unknown[];
1609
1682
  }>;
1610
- createPublishingPlan(teamId: string, body: Record<string, unknown>): Promise<unknown>;
1683
+ createPublishingPlan(teamId: string, body: CreatePublishingPlanBody): Promise<unknown>;
1611
1684
  listAuditLogs(teamId: string, params?: ListAuditLogsParams): Promise<{
1612
1685
  items: unknown[];
1613
1686
  }>;
@@ -1797,8 +1870,23 @@ export declare class SocialHubClient {
1797
1870
  deleteSubredditSanction(teamId: string, id: string): Promise<{
1798
1871
  ok: boolean;
1799
1872
  }>;
1800
- listAccountRiskProfiles(teamId: string, limit?: number): Promise<{
1873
+ /**
1874
+ * 列出团队下账号的风险画像。
1875
+ *
1876
+ * `limit` 上限 200(contracts `listAccountRiskProfilesQuerySchema`),所以账号数
1877
+ * 超过 200 的 team 必须用 `offset` 翻页,否则会**静默截断**。第二参数保留
1878
+ * `number` 形式只为兼容已发布包的老调用方(等价于 `{ limit }`)。
1879
+ */
1880
+ listAccountRiskProfiles(teamId: string, paramsOrLimit?: number | ListAccountRiskProfilesParams): Promise<{
1801
1881
  items: unknown[];
1882
+ /**
1883
+ * 满足过滤条件的总数(与 limit/offset 无关)。集合在翻页期间不变时可用作
1884
+ * 翻页终止判据;offset 分页不是快照分页,并发写入下 total 会漂移,
1885
+ * 同一行也可能重复出现或被跳过。
1886
+ */
1887
+ total?: number;
1888
+ limit?: number;
1889
+ offset?: number;
1802
1890
  }>;
1803
1891
  getAccountRiskProfile(teamId: string, socialAccountId: string): Promise<unknown>;
1804
1892
  upsertAccountRiskProfile(teamId: string, socialAccountId: string, body: Record<string, unknown>): Promise<unknown>;
@@ -3160,6 +3248,8 @@ export declare class SocialHubClient {
3160
3248
  items: {
3161
3249
  sourceId: string;
3162
3250
  canonicalTopic: string;
3251
+ /** source **类型**展示名的 i18n key(registry 真源;不是模板的 displayName)。 */
3252
+ labelKey: string;
3163
3253
  sourceDefinitionVersion: number;
3164
3254
  payloadSchemaVersion: string;
3165
3255
  activeTemplate: NotificationSourceTemplateDto | null;
@@ -3685,7 +3775,13 @@ export type PublishingCalendarPreflightRejectionReason =
3685
3775
  /** 条目没绑草稿,或草稿行已不在。 */
3686
3776
  | "draft_detached"
3687
3777
  /** 当前草稿的 canonical review target 不存在、身份漂移,或状态不是 `passed`。 */
3688
- | "review_not_passed";
3778
+ | "review_not_passed"
3779
+ /**
3780
+ * 发布护栏判定当前不可发布(账号被封/受限、cluster 暂停等)。
3781
+ * **与其余 reason 不同:这条通常是暂时的,不要删 cron**,按原节奏重试即可。
3782
+ * 护栏评估本身失败不走这条(那是 5xx 系统故障)。
3783
+ */
3784
+ | "guardrail_blocked";
3689
3785
  /** preflight 放行:**唯一**能拿到正文的分支。 */
3690
3786
  export type PublishingCalendarPreflightOkDto = {
3691
3787
  decision: "ok";
@@ -3741,7 +3837,15 @@ export type CalendarEntryListItemDto = {
3741
3837
  id: string;
3742
3838
  teamId: string;
3743
3839
  publishingPlanId: string;
3744
- brandId: string;
3840
+ /**
3841
+ * R12(迁移 0153):**可为 null** —— `null` 表示这条条目所属计划显式声明了
3842
+ * 无品牌提及(`plan.brandId` 与 `campaign.brandId` 都是 NULL)。
3843
+ *
3844
+ * 读侧对 `brands` 已由 innerJoin 改成 **leftJoin**,无品牌行不再被静默丢掉,
3845
+ * 所以服务端**确实会**在这里回 null。契约真源:
3846
+ * `packages/contracts/src/publishing-plans.ts` 的 `calendarEntryListItemSchema`。
3847
+ */
3848
+ brandId: string | null;
3745
3849
  /** legacy;brand-first 建的计划为 null。 */
3746
3850
  campaignId: string | null;
3747
3851
  contentDraftId: string | null;
@@ -3762,7 +3866,11 @@ export type CalendarEntryListItemDto = {
3762
3866
  createdAt: string;
3763
3867
  /** 迁移 0149 起维护;更早的真实修改时间已不可考。 */
3764
3868
  updatedAt?: string;
3765
- brandName: string;
3869
+ /**
3870
+ * R12:无品牌条目没有 `brands` 行可 join → **null**(不是空串)。
3871
+ * ⚠️ 直接 `.toUpperCase()` / `.slice()` 会在运行时炸;先判空再用。
3872
+ */
3873
+ brandName: string | null;
3766
3874
  campaignName: string | null;
3767
3875
  socialAccountHandle: string | null;
3768
3876
  socialAccountPlatform: string;