@geoly-ai/social-hub-sdk 0.0.58 → 0.1.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/index.d.ts +169 -16
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +33 -0
- package/dist/index.js.map +1 -1
- package/dist/index.test.js +237 -0
- package/dist/index.test.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -75,6 +75,43 @@ export type UpdateCalendarEntryBody = {
|
|
|
75
75
|
deliveryMode?: CalendarEntryDeliveryMode;
|
|
76
76
|
permalink?: string;
|
|
77
77
|
failureReason?: string;
|
|
78
|
+
/**
|
|
79
|
+
* R7 · 抢占执行权时的乐观版本钉子(只对 `scheduled → running` 有效)。
|
|
80
|
+
* 🔴 终态回写**不要带**:抢占那一次自己会把 revision 推到 N+1,终态再带 N 必然失败
|
|
81
|
+
* (得到 `expected_revision_not_applicable`)。
|
|
82
|
+
*/
|
|
83
|
+
expectedRevision?: number;
|
|
84
|
+
/**
|
|
85
|
+
* R7 · 服务端签发的执行 capability token。终态回写必带(只要条目有在途授权);
|
|
86
|
+
* 初次抢占**不得**带。⚠️ bearer 凭据,别打日志。
|
|
87
|
+
*/
|
|
88
|
+
executionToken?: string;
|
|
89
|
+
/**
|
|
90
|
+
* R7 · 抢占的幂等键(客户端生成,建议 UUID)。
|
|
91
|
+
* **强烈建议每次抢占都带** —— 它是「claim 已提交但响应丢失」的唯一补救。
|
|
92
|
+
*/
|
|
93
|
+
claimRequestId?: string;
|
|
94
|
+
/**
|
|
95
|
+
* R7 · 强制终结:宿主机死在 `running` 中途时的逃生口。
|
|
96
|
+
* 仅 manager/admin、仅 `failed`/`cancelled`、必须同时给 `failureReason`。
|
|
97
|
+
* ⚠️ 不是把执行权让给下一台机 —— 条目就此终结。
|
|
98
|
+
*/
|
|
99
|
+
forceTerminalize?: boolean;
|
|
100
|
+
};
|
|
101
|
+
/**
|
|
102
|
+
* R7 · 抢占成功时服务端回的执行授权。
|
|
103
|
+
* 🔴 `token` 是 bearer 凭据:存本机 state 文件,别打日志、别回显。
|
|
104
|
+
*/
|
|
105
|
+
export type CalendarEntryExecutionGrant = {
|
|
106
|
+
/** 单调递增的执行代数,仅供审计对账;授权判据是 `token`。 */
|
|
107
|
+
epoch: number;
|
|
108
|
+
token: string;
|
|
109
|
+
/**
|
|
110
|
+
* 抢占**之后**的 directiveRevision(= 抢占前 + 1)。
|
|
111
|
+
* ⚠️ 抢占会 append 一条 `cancel` 指令并广播给**包括赢家在内**的全部机器 ——
|
|
112
|
+
* 协议规定它只删**未来的** cron,**绝不中止已持 token 的在途执行**。
|
|
113
|
+
*/
|
|
114
|
+
directiveRevision: number;
|
|
78
115
|
};
|
|
79
116
|
export type ListRedditPostSnapshotsParams = {
|
|
80
117
|
limit?: number;
|
|
@@ -352,6 +389,84 @@ export type ListCommentDraftsParams = {
|
|
|
352
389
|
/** 把聚合收窄到指定可见团队(逗号拼);空数组=不收窄。 */
|
|
353
390
|
scopeTeamIds?: string[];
|
|
354
391
|
};
|
|
392
|
+
/**
|
|
393
|
+
* R12(迁移 0153)——「**显式**声明这条内容不做品牌提及」。
|
|
394
|
+
*
|
|
395
|
+
* 只有 `"none"` 一个值,对应契约的 `brandMentionDeclarationSchema`
|
|
396
|
+
* (`packages/contracts/src/brand-mention-declaration.ts`)。
|
|
397
|
+
*
|
|
398
|
+
* 🔴 **缺失 ≠ 无意图**:省略 `brandId` 而不带这个声明,服务端按「忘了传」判 400,
|
|
399
|
+
* 不会静默降级成无品牌。判定规则全在服务端(`refineBrandMentionDeclaration` +
|
|
400
|
+
* 路由的四值比较 + db 层兜底),**SDK 只表达类型、不复刻校验** —— 复刻必然两边漂移。
|
|
401
|
+
*/
|
|
402
|
+
export type BrandMentionDeclaration = "none";
|
|
403
|
+
/**
|
|
404
|
+
* `POST /content-drafts` 的 body。
|
|
405
|
+
*
|
|
406
|
+
* ⚠️ `brandId` 与 `brandMention` 的互斥/必填关系**故意不用类型联合表达**:
|
|
407
|
+
* 服务端的 `superRefine` 是唯一判定处,在 SDK 里再写一遍会漂移(见
|
|
408
|
+
* {@link BrandMentionDeclaration})。类型只负责让「无品牌草稿」可以被表达出来。
|
|
409
|
+
*/
|
|
410
|
+
export type CreateContentDraftBody = {
|
|
411
|
+
/** R12:可选。省略时**必须**同时显式给 `brandMention: "none"`(服务端校验)。 */
|
|
412
|
+
brandId?: string;
|
|
413
|
+
/** R12:显式声明本草稿不做品牌提及。见 {@link BrandMentionDeclaration}。 */
|
|
414
|
+
brandMention?: BrandMentionDeclaration;
|
|
415
|
+
/** @deprecated legacy 归因;新草稿只用 brandId。 */
|
|
416
|
+
campaignId?: string;
|
|
417
|
+
title: string;
|
|
418
|
+
body: string;
|
|
419
|
+
/** 目标板块(内容语义真源);服务端规范化后落库。省略/null → NULL。 */
|
|
420
|
+
subreddit?: string | null;
|
|
421
|
+
/**
|
|
422
|
+
* 写作参考 / 归因备注 URL:「这篇内容围绕哪个落地页写的」。
|
|
423
|
+
* ⚠️ **不参与发布执行** —— 系统没有 Reddit link post 概念,执行只冻结 title+body。
|
|
424
|
+
*/
|
|
425
|
+
referenceUrl?: string | null;
|
|
426
|
+
/**
|
|
427
|
+
* R2:**创建幂等键**(可选)。同一个 `(team, sourceRef)` 重复创建会复用首次那篇,
|
|
428
|
+
* 返回 `{ reused: true }` 而不是再造一篇。
|
|
429
|
+
*
|
|
430
|
+
* 用它包住会重试的调用(cron 重跑、超时重发、回执丢失后补发)。key 由调用方拥有,
|
|
431
|
+
* 服务端只做 NFKC + trim + 长度 1..200 + 拒控制字符,**不限制字符集** ——
|
|
432
|
+
* `agent:reports/2026-08.json#3` 这类带 `#` 的键是合法的。
|
|
433
|
+
*
|
|
434
|
+
* 🔴 唯一例外:**`openclaw:` 前缀是导入器专用的保留命名空间,写入面直接 400**
|
|
435
|
+
* (导入器有权用源文件覆盖同 key 的草稿;你占用它,你的草稿会在下次 ingest 被覆盖)。
|
|
436
|
+
* 换个自己的前缀即可。按 `openclaw:` 反查**不受限制**。
|
|
437
|
+
*
|
|
438
|
+
* ⚠️ **同 key 换内容 = 409**(`CONTENT_DRAFT_SOURCE_REF_CONFLICT`),不是静默覆盖。
|
|
439
|
+
* 改稿走 `PATCH`,或换一个新 key。删除会释放 key。
|
|
440
|
+
*/
|
|
441
|
+
sourceRef?: string;
|
|
442
|
+
};
|
|
443
|
+
/** `POST /publishing-plans` 里的单条待排期条目。 */
|
|
444
|
+
export type CreatePublishingPlanEntryInput = {
|
|
445
|
+
contentDraftId?: string;
|
|
446
|
+
socialAccountId: string;
|
|
447
|
+
subreddit: string;
|
|
448
|
+
/** ISO-8601 datetime。 */
|
|
449
|
+
plannedAt: string;
|
|
450
|
+
/** 缺省 = `hub_managed`。见 {@link CalendarEntryDeliveryMode}。 */
|
|
451
|
+
deliveryMode?: CalendarEntryDeliveryMode;
|
|
452
|
+
};
|
|
453
|
+
/**
|
|
454
|
+
* `POST /publishing-plans` 的 body(此前是 `Record<string, unknown>`,运行时不挡、
|
|
455
|
+
* 类型也表达不出 R12 的无品牌计划)。
|
|
456
|
+
*
|
|
457
|
+
* ⚠️ 与 {@link CreateContentDraftBody} 同理:brandId / brandMention 的四条 fail-closed
|
|
458
|
+
* 规则**只在服务端**判,SDK 不复刻。
|
|
459
|
+
*/
|
|
460
|
+
export type CreatePublishingPlanBody = {
|
|
461
|
+
/** R12:可选。省略时**必须**同时显式给 `brandMention: "none"`(服务端校验)。 */
|
|
462
|
+
brandId?: string;
|
|
463
|
+
/** R12:显式声明本计划不做品牌提及。见 {@link BrandMentionDeclaration}。 */
|
|
464
|
+
brandMention?: BrandMentionDeclaration;
|
|
465
|
+
/** @deprecated legacy 归因。 */
|
|
466
|
+
campaignId?: string;
|
|
467
|
+
name: string;
|
|
468
|
+
entries: CreatePublishingPlanEntryInput[];
|
|
469
|
+
};
|
|
355
470
|
export type CreateCommentDraftBody = {
|
|
356
471
|
brandId: string;
|
|
357
472
|
campaignId?: string;
|
|
@@ -1084,9 +1199,31 @@ export declare class SocialHubClient {
|
|
|
1084
1199
|
listCalendarEntries(teamId: string, params?: ListCalendarEntriesParams): Promise<{
|
|
1085
1200
|
items: unknown[];
|
|
1086
1201
|
}>;
|
|
1202
|
+
/**
|
|
1203
|
+
* PATCH 一条日历条目。
|
|
1204
|
+
*
|
|
1205
|
+
* ## R7 · 执行权排他(只对 `external_agent` 条目)
|
|
1206
|
+
* 协议是四步,**顺序不能换**:
|
|
1207
|
+
* 1. `calendar preflight`(可以两台都拿到 ok,它是纯读);
|
|
1208
|
+
* 2. **抢 `status:"running"`** —— 这一步才是排他。赢家在响应里拿到
|
|
1209
|
+
* `execution.token`;输的那台拿 **409 `EXECUTION_NOT_ACQUIRED`**,
|
|
1210
|
+
* `details.reason = "execution_already_acquired"`,应当安静退出并删本机 cron;
|
|
1211
|
+
* 3. 提交到 Reddit;
|
|
1212
|
+
* 4. 带 `executionToken` 回写 `succeeded` / `failed`。
|
|
1213
|
+
*
|
|
1214
|
+
* ⛔ **绝不能先提交再抢 running** —— 那样排他就完全失效了。
|
|
1215
|
+
*
|
|
1216
|
+
* 🔴 抢占时**务必带 `claimRequestId`**(客户端生成的幂等键)。没有它,
|
|
1217
|
+
* 「claim 已提交但 HTTP 响应丢失」会留下一条永久卡 `running`、
|
|
1218
|
+
* 却没有任何人握着 token 的条目,只能人工强制终结。带上它重试即可拿回原 token。
|
|
1219
|
+
*
|
|
1220
|
+
* ⚠️ `execution.token` 是 **bearer 凭据**:写进本机 state 文件,别打日志、别回显。
|
|
1221
|
+
*/
|
|
1087
1222
|
updateCalendarEntry(teamId: string, entryId: string, body: UpdateCalendarEntryBody): Promise<{
|
|
1088
1223
|
ok: boolean;
|
|
1089
1224
|
warning?: string;
|
|
1225
|
+
/** 仅在本次真正取得(或幂等重取)执行权时出现。老服务端不会回这个字段。 */
|
|
1226
|
+
execution?: CalendarEntryExecutionGrant;
|
|
1090
1227
|
}>;
|
|
1091
1228
|
/**
|
|
1092
1229
|
* 与 {@link SocialHubClient.listCalendarEntries} **同一个端点**,只是把返回体
|
|
@@ -1246,6 +1383,11 @@ export declare class SocialHubClient {
|
|
|
1246
1383
|
status?: string | string[];
|
|
1247
1384
|
/** 目标板块过滤(单值或数组;数组按逗号拼,同字段内 OR)。 */
|
|
1248
1385
|
subreddit?: string | string[];
|
|
1386
|
+
/**
|
|
1387
|
+
* R2:按创建幂等键反查(单值或数组;数组按逗号拼,同字段内 OR)。
|
|
1388
|
+
* 迁移期用它把本地 legacy key 映射到 Hub 草稿,不必靠标题去猜。
|
|
1389
|
+
*/
|
|
1390
|
+
sourceRef?: string | string[];
|
|
1249
1391
|
search?: string;
|
|
1250
1392
|
} | number): Promise<{
|
|
1251
1393
|
items: unknown[];
|
|
@@ -1253,20 +1395,19 @@ export declare class SocialHubClient {
|
|
|
1253
1395
|
limit: number;
|
|
1254
1396
|
offset: number;
|
|
1255
1397
|
}>;
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
referenceUrl?: string | null;
|
|
1268
|
-
}): Promise<{
|
|
1398
|
+
/**
|
|
1399
|
+
* `POST /content-drafts`。
|
|
1400
|
+
*
|
|
1401
|
+
* R2:传了 `body.sourceRef` 时,`reused` 表示这次是**复用**了既有草稿(HTTP 200)
|
|
1402
|
+
* 而不是新建(HTTP 201)。
|
|
1403
|
+
*
|
|
1404
|
+
* ⚠️ 没传 `sourceRef` 时服务端**不返回** `reused`(响应保持 R2 之前的 `{ id }`),
|
|
1405
|
+
* 所以这里的类型是可选的 —— 别写 `if (!res.reused)` 当作「新建」的判据,
|
|
1406
|
+
* 那在没传 key 时恒真但毫无意义;要判复用请先确认自己传了 key。
|
|
1407
|
+
*/
|
|
1408
|
+
createContentDraft(teamId: string, body: CreateContentDraftBody): Promise<{
|
|
1269
1409
|
id: string;
|
|
1410
|
+
reused?: boolean;
|
|
1270
1411
|
}>;
|
|
1271
1412
|
/**
|
|
1272
1413
|
* GET /content-review-targets — team-scoped 审核目标列表(status/contentType 过滤 +
|
|
@@ -1630,7 +1771,7 @@ export declare class SocialHubClient {
|
|
|
1630
1771
|
listPublishingPlans(teamId: string, params?: ListPublishingPlansParams): Promise<{
|
|
1631
1772
|
items: unknown[];
|
|
1632
1773
|
}>;
|
|
1633
|
-
createPublishingPlan(teamId: string, body:
|
|
1774
|
+
createPublishingPlan(teamId: string, body: CreatePublishingPlanBody): Promise<unknown>;
|
|
1634
1775
|
listAuditLogs(teamId: string, params?: ListAuditLogsParams): Promise<{
|
|
1635
1776
|
items: unknown[];
|
|
1636
1777
|
}>;
|
|
@@ -3787,7 +3928,15 @@ export type CalendarEntryListItemDto = {
|
|
|
3787
3928
|
id: string;
|
|
3788
3929
|
teamId: string;
|
|
3789
3930
|
publishingPlanId: string;
|
|
3790
|
-
|
|
3931
|
+
/**
|
|
3932
|
+
* R12(迁移 0153):**可为 null** —— `null` 表示这条条目所属计划显式声明了
|
|
3933
|
+
* 无品牌提及(`plan.brandId` 与 `campaign.brandId` 都是 NULL)。
|
|
3934
|
+
*
|
|
3935
|
+
* 读侧对 `brands` 已由 innerJoin 改成 **leftJoin**,无品牌行不再被静默丢掉,
|
|
3936
|
+
* 所以服务端**确实会**在这里回 null。契约真源:
|
|
3937
|
+
* `packages/contracts/src/publishing-plans.ts` 的 `calendarEntryListItemSchema`。
|
|
3938
|
+
*/
|
|
3939
|
+
brandId: string | null;
|
|
3791
3940
|
/** legacy;brand-first 建的计划为 null。 */
|
|
3792
3941
|
campaignId: string | null;
|
|
3793
3942
|
contentDraftId: string | null;
|
|
@@ -3808,7 +3957,11 @@ export type CalendarEntryListItemDto = {
|
|
|
3808
3957
|
createdAt: string;
|
|
3809
3958
|
/** 迁移 0149 起维护;更早的真实修改时间已不可考。 */
|
|
3810
3959
|
updatedAt?: string;
|
|
3811
|
-
|
|
3960
|
+
/**
|
|
3961
|
+
* R12:无品牌条目没有 `brands` 行可 join → **null**(不是空串)。
|
|
3962
|
+
* ⚠️ 直接 `.toUpperCase()` / `.slice()` 会在运行时炸;先判空再用。
|
|
3963
|
+
*/
|
|
3964
|
+
brandName: string | null;
|
|
3812
3965
|
campaignName: string | null;
|
|
3813
3966
|
socialAccountHandle: string | null;
|
|
3814
3967
|
socialAccountPlatform: string;
|