@geoly-ai/social-hub-sdk 0.0.52 → 0.0.53

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
@@ -190,6 +190,17 @@ export type UpdateContentDraftBody = {
190
190
  title?: string;
191
191
  body?: string;
192
192
  status?: string;
193
+ /**
194
+ * 目标板块(迁移 0136)。省略 = 不改;`null` = 清空;字符串 = 设置(服务端规范化)。
195
+ * 属内容身份 → **会** bump 草稿版本(旧内部审核 / 客户批准因此失效)。
196
+ */
197
+ subreddit?: string | null;
198
+ /**
199
+ * 写作参考 / 归因备注 URL(迁移 0136,原前端字段名 `targetUrl`)。
200
+ * ⚠️ **不参与发布执行** —— 系统没有 Reddit link post 概念,执行只冻结 title+body。
201
+ * 不属内容身份 → 单独改它**不** bump 版本、不使既有审核/批准失效。
202
+ */
203
+ referenceUrl?: string | null;
193
204
  /** Optimistic concurrency: last-loaded version; a mismatch is rejected 409. */
194
205
  expectedVersion?: number;
195
206
  };
@@ -364,12 +375,28 @@ export type ScheduleCommentDraftBody = {
364
375
  };
365
376
  export type DeliveryBundleStatusLike = "open" | "closed" | "cancelled";
366
377
  /** 客户面列 bundle:brandId 服务端**必填**(客户按 brand 收窄);SDK 类型强制。 */
378
+ /**
379
+ * `cursor` 与 `offset` **互斥**,用可辨识联合在**编译期**就拒掉错误组合 —— 服务端也会
380
+ * 400,但把它留到运行时等于让调用方先发一次注定失败的请求。
381
+ */
367
382
  export type ListClientDeliveryBundlesParams = {
368
383
  brandId: string;
369
384
  status?: DeliveryBundleStatusLike;
370
385
  limit?: number;
386
+ } & ({
387
+ /**
388
+ * keyset 游标 —— 上一次响应的 `nextCursor` 原样回传。对调用方是**不透明字符串**:
389
+ * 不要解析或构造,也不要换了 brandId/status 之后复用(游标绑定过滤条件指纹,会 400)。
390
+ */
391
+ cursor: string;
392
+ offset?: never;
393
+ } | {
394
+ cursor?: undefined;
395
+ /**
396
+ * @deprecated 用 `cursor`。offset 分页在并发写入下会重复/跳条(服务端已改 keyset)。
397
+ */
371
398
  offset?: number;
372
- };
399
+ });
373
400
  /** staff 建 bundle。 */
374
401
  export type CreateClientDeliveryBundleBody = {
375
402
  brandId: string;
@@ -472,6 +499,77 @@ export type ListSubredditWatchlistsParams = {
472
499
  /** 按板块名精确查归属(r/ 前缀可省,大小写不敏感)。 */
473
500
  subreddit?: string;
474
501
  };
502
+ export type ListSubredditMonitorsParams = {
503
+ limit?: number;
504
+ offset?: number;
505
+ /** 缺省 = 全部(含已停止的);服务端只认 "true"/"false" 字符串,方法内负责转换。 */
506
+ enabled?: boolean;
507
+ watchlistId?: string;
508
+ };
509
+ /**
510
+ * 监听配置行(POST 启用的返回)。时间字段一律 `string`(HTTP JSON 里是 ISO 串,
511
+ * SDK 不代为 `new Date()`,免得调用方拿到「有时 Date 有时 string」的混合类型)。
512
+ */
513
+ export type SubredditMonitorConfig = {
514
+ id: string;
515
+ watchlistId: string;
516
+ subreddit: string;
517
+ enabled: boolean;
518
+ sort: string;
519
+ fetchLimit: number;
520
+ createdAt: string;
521
+ updatedAt: string;
522
+ };
523
+ /**
524
+ * 监听列表的一行 = 配置行 + 三个派生水位字段。
525
+ * ⚠️ 这三个字段**只在列表读口有**,POST 启用返回的是裸配置行(见 SubredditMonitorConfig)。
526
+ */
527
+ export type SubredditMonitorItem = SubredditMonitorConfig & {
528
+ /** 该监听最近一次观察到帖子的时间;从未观察到 → null。 */
529
+ lastObservedAt: string | null;
530
+ /** 最近一轮 run 中该监听**首次观察**到的帖子数。 */
531
+ newPostsInLatestRun: number;
532
+ /** 已观察但尚未进入任何送达报告的积压数(报告水位落后的信号)。 */
533
+ unreportedCount: number;
534
+ };
535
+ export type SubredditMonitorRunStatus = "pending" | "claimed" | "collecting" | "reporting" | "completed" | "degraded" | "failed";
536
+ /** run 列表/摘要读口的形状:**不含** fetchDiagnostics / reportPayload 两个大字段。 */
537
+ export type SubredditMonitorRunSummary = {
538
+ id: string;
539
+ scheduleKey: "cron" | "manual";
540
+ windowStart: string;
541
+ windowEnd: string;
542
+ status: SubredditMonitorRunStatus;
543
+ attempts: number;
544
+ monitorCount: number;
545
+ succeededMonitorCount: number;
546
+ failedMonitorCount: number;
547
+ observedPostCount: number;
548
+ newPostCount: number;
549
+ errorCode: string | null;
550
+ createdAt: string;
551
+ completedAt: string | null;
552
+ };
553
+ /** run 详情:摘要 + 只有单条读口才投影的 jsonb 大字段与各阶段时间戳。 */
554
+ export type SubredditMonitorRunDetail = SubredditMonitorRunSummary & {
555
+ fetchDiagnostics: Record<string, unknown> | null;
556
+ reportPayload: Record<string, unknown> | null;
557
+ error: string | null;
558
+ fetchStartedAt: string | null;
559
+ fetchCompletedAt: string | null;
560
+ reportCompletedAt: string | null;
561
+ };
562
+ /** run 列表是 **keyset 分页**(无 offset):游标 = 上一页最后一行的 windowStart + id。 */
563
+ export type ListSubredditMonitorRunsParams = {
564
+ limit?: number;
565
+ status?: SubredditMonitorRunStatus;
566
+ beforeWindowStart?: string;
567
+ beforeId?: string;
568
+ };
569
+ export type EnableSubredditMonitorBody = {
570
+ watchlistId: string;
571
+ fetchLimit?: number;
572
+ };
475
573
  export type ListHotPostsParams = {
476
574
  limit?: number;
477
575
  offset?: number;
@@ -885,16 +983,31 @@ export declare class SocialHubClient {
885
983
  cancelScheduledJob(teamId: string, jobId: string): Promise<unknown>;
886
984
  listContentDrafts(teamId: string, params?: {
887
985
  limit?: number;
986
+ offset?: number;
888
987
  brandId?: string;
889
988
  campaignId?: string;
989
+ status?: string | string[];
990
+ /** 目标板块过滤(单值或数组;数组按逗号拼,同字段内 OR)。 */
991
+ subreddit?: string | string[];
992
+ search?: string;
890
993
  } | number): Promise<{
891
994
  items: unknown[];
995
+ total: number;
996
+ limit: number;
997
+ offset: number;
892
998
  }>;
893
999
  createContentDraft(teamId: string, body: {
894
1000
  brandId: string;
895
1001
  campaignId?: string;
896
1002
  title: string;
897
1003
  body: string;
1004
+ /** 目标板块(内容语义真源);服务端规范化后落库。省略/null → NULL。 */
1005
+ subreddit?: string | null;
1006
+ /**
1007
+ * 写作参考 / 归因备注 URL:「这篇内容围绕哪个落地页写的」。
1008
+ * ⚠️ **不参与发布执行** —— 系统没有 Reddit link post 概念,执行只冻结 title+body。
1009
+ */
1010
+ referenceUrl?: string | null;
898
1011
  }): Promise<{
899
1012
  id: string;
900
1013
  }>;
@@ -955,9 +1068,13 @@ export declare class SocialHubClient {
955
1068
  warning?: string;
956
1069
  }>;
957
1070
  private clientDeliveryBase;
958
- /** GET client-delivery/bundles?brandId=(必填)&status=&limit=&offset= — 客户面 bundle 列表。 */
1071
+ /**
1072
+ * GET client-delivery/bundles?brandId=(必填)&status=&limit=&cursor= — 客户面 bundle 列表。
1073
+ * `nextCursor === null` 表示已到末页;非 null 时原样回传到下次调用的 `cursor`。
1074
+ */
959
1075
  clientDeliveryListBundles(teamId: string, params: ListClientDeliveryBundlesParams): Promise<{
960
1076
  items: unknown[];
1077
+ nextCursor?: string | null;
961
1078
  }>;
962
1079
  /** GET client-delivery/bundles/:id — 单个 bundle(client 视图脱敏 / staff 完整)。 */
963
1080
  clientDeliveryGetBundle(teamId: string, bundleId: string): Promise<unknown>;
@@ -1578,7 +1695,36 @@ export declare class SocialHubClient {
1578
1695
  offset?: number;
1579
1696
  }): Promise<{
1580
1697
  items: unknown[];
1581
- total: number;
1698
+ /**
1699
+ * ⚠️ 0140 起**不再恒为精确值**,必须连着 `totalRelation` 一起读。
1700
+ * `null` = 未计算(keyword 路径)。想判断"还有没有下一页"请用 `hasMore`,
1701
+ * 不要写 `offset + limit >= total` —— 封顶/未知时它会误判成没有下一页。
1702
+ */
1703
+ total: number | null;
1704
+ /** "eq"=精确;"gte"=实际 ≥ total(封顶 10000);"unavailable"=未计算(total 为 null)。 */
1705
+ totalRelation: "eq" | "gte" | "unavailable";
1706
+ /** 权威分页信号:由服务端多取一行得出,与 total 精度无关。 */
1707
+ hasMore: boolean;
1708
+ }>;
1709
+ /**
1710
+ * 评论样本行的**精确 count**(与 list 同一组过滤谓词,无分页、不封顶)。
1711
+ * ⚠️ 故意**不接受 keyword**:keyword 走全文 ILIKE,精确 count 要全表扫
1712
+ * (服务端契约 strict,传了直接 400);keyword 口径请用 listRedditCommentSamples
1713
+ * (totalRelation=unavailable)。
1714
+ * ⚠️ 无过滤时是全表精确 count,属昂贵读——基线用途,**禁止轮询**。
1715
+ * 口径是库内 reddit_comment_samples 行数,不是 Reddit 线程真实评论总数。
1716
+ */
1717
+ countRedditCommentSamples(params?: {
1718
+ postId?: string;
1719
+ subreddit?: string;
1720
+ intent?: string;
1721
+ sentiment?: string;
1722
+ origin?: "hub_collector" | "import";
1723
+ }): Promise<{
1724
+ /** 精确匹配数(不封顶;恒精确,故无 relation 字段)。 */
1725
+ count: number;
1726
+ /** 采样口径恒为部分样本。 */
1727
+ sampleMode: "partial_sample";
1582
1728
  }>;
1583
1729
  dispatchRedditCommentCapture(body: {
1584
1730
  permalinks: string[];
@@ -1714,6 +1860,52 @@ export declare class SocialHubClient {
1714
1860
  ok: boolean;
1715
1861
  }>;
1716
1862
  deleteSubredditWatchlist(watchlistId: string): Promise<void>;
1863
+ listSubredditMonitors(params?: ListSubredditMonitorsParams): Promise<{
1864
+ items: SubredditMonitorItem[];
1865
+ total: number;
1866
+ /** 最近一轮 run(全局,一轮覆盖所有监听);从未跑过 → null。 */
1867
+ latestRun: SubredditMonitorRunSummary | null;
1868
+ limit: number;
1869
+ offset: number;
1870
+ }>;
1871
+ /**
1872
+ * 加入监听(**幂等**):同一 watchlist 已停止的会被重新启用,不新建行 ——
1873
+ * observation ledger 因此保留,重启后已报告过的帖子不会重复报告。
1874
+ */
1875
+ enableSubredditMonitor(body: EnableSubredditMonitorBody): Promise<SubredditMonitorConfig>;
1876
+ /**
1877
+ * 停止监听:DELETE 语义但服务端做**软停**(enabled=false),不删 observation ledger。
1878
+ * 幂等 —— 本来就没在监听时返回 `{ ok: true, updated: false }`,不是 404。
1879
+ */
1880
+ /**
1881
+ * 停止监听。默认是**软停**(`enabled=false`):保留观察 ledger,重新启用后已经报告过的
1882
+ * 帖子不会被再报一遍。
1883
+ *
1884
+ * `purge: true` 是另一个动作 —— **连历史观察一起硬删**。只有在要删掉整个 watchlist 时
1885
+ * 才需要:monitor 配置对 watchlist 的外键是 `ON DELETE RESTRICT`,不先 purge 就删不掉
1886
+ * watchlist(服务端会返回 409 并提示走这条路)。
1887
+ */
1888
+ disableSubredditMonitor(watchlistId: string, options?: {
1889
+ purge?: boolean;
1890
+ }): Promise<{
1891
+ ok: boolean;
1892
+ updated: boolean;
1893
+ purged?: boolean;
1894
+ }>;
1895
+ /** run 列表:keyset 分页,翻页用上一页最后一行的 windowStart + id 当游标。 */
1896
+ listSubredditMonitorRuns(params?: ListSubredditMonitorRunsParams): Promise<{
1897
+ items: SubredditMonitorRunSummary[];
1898
+ hasMore: boolean;
1899
+ }>;
1900
+ /** run 详情:唯一会带回 fetchDiagnostics / reportPayload 两个大字段的读口。 */
1901
+ getSubredditMonitorRun(runId: string): Promise<SubredditMonitorRunDetail>;
1902
+ /** 手工触发一轮(202 入队)。没有任何启用中的监听时服务端返回 400,不制造空跑 run。 */
1903
+ runSubredditMonitors(): Promise<{
1904
+ status: string;
1905
+ monitors: number;
1906
+ jobId?: string;
1907
+ warning?: string;
1908
+ }>;
1717
1909
  listHotPosts(params?: ListHotPostsParams): Promise<{
1718
1910
  items: HotPostListItem[];
1719
1911
  total: number;
@@ -1851,9 +2043,16 @@ export declare class SocialHubClient {
1851
2043
  sessionActiveTeam(body: {
1852
2044
  teamId: string;
1853
2045
  }): Promise<unknown>;
2046
+ /**
2047
+ * 管理员替他人重置密码。需要**不受限的交互式 admin 会话**(role=admin 的 api_key
2048
+ * 不行),且不能重置自己(自助改密走 `PUT /v1/auth/password`,它校验旧密码)。
2049
+ *
2050
+ * `userId` / `email` **恰好给一个**。原来的 `teamId` 参数已删除:密码是用户级全局
2051
+ * 凭证,团队参数从来没有限制过影响范围,只是误导。
2052
+ */
1854
2053
  sessionSetPassword(body: {
1855
- email: string;
1856
- teamId?: string;
2054
+ userId?: string;
2055
+ email?: string;
1857
2056
  password: string;
1858
2057
  }): Promise<unknown>;
1859
2058
  sessionUpdateProfile(body: {