@geoly-ai/social-hub-cli 0.2.20 → 0.2.22
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/CHANGELOG.md +13 -0
- package/dist/cmd-manifest.json +20 -2
- package/dist/index.d.ts +0 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +175 -12
- package/dist/index.js.map +1 -1
- package/dist/index.test.js +20 -0
- package/dist/index.test.js.map +1 -1
- package/dist/voc-acquire.test.js +12 -22
- package/dist/voc-acquire.test.js.map +1 -1
- package/package.json +2 -2
- package/skills/manifest.json +1 -1
- package/skills/social-hub-intelligence/SKILL.md +11 -3
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,19 @@ All notable changes to `@geoly-ai/social-hub-cli` are documented in this file.
|
|
|
4
4
|
|
|
5
5
|
Release workflow: `pnpm release:cli` → `pnpm publish:cli`.
|
|
6
6
|
|
|
7
|
+
## [0.2.22] - 2026-07-23
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- Trigger P1-D3 —— 四眼 registry 管理面 CLI 命令(social-hub)
|
|
12
|
+
|
|
13
|
+
## [0.2.21] - 2026-07-22
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
- 支持受限主体 + 维度派发前鉴权(板块情报收尾 B)
|
|
18
|
+
- 评论回灌直接带分析标签 + 正文编辑标签失效(板块情报收尾 A)
|
|
19
|
+
|
|
7
20
|
## [0.2.20] - 2026-07-22
|
|
8
21
|
|
|
9
22
|
### Added
|
package/dist/cmd-manifest.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
"generatedAt": "2026-07-
|
|
3
|
-
"cliVersion": "0.2.
|
|
2
|
+
"generatedAt": "2026-07-23T02:34:54.974Z",
|
|
3
|
+
"cliVersion": "0.2.22",
|
|
4
4
|
"commands": [
|
|
5
5
|
"accounts",
|
|
6
6
|
"accounts brand-bindings",
|
|
@@ -67,6 +67,24 @@
|
|
|
67
67
|
"brand-fit",
|
|
68
68
|
"brand-fit migrate",
|
|
69
69
|
"brand-fit show",
|
|
70
|
+
"brand-fit-registry",
|
|
71
|
+
"brand-fit-registry avoid-contexts",
|
|
72
|
+
"brand-fit-registry avoid-contexts list",
|
|
73
|
+
"brand-fit-registry avoid-contexts show",
|
|
74
|
+
"brand-fit-registry proposals",
|
|
75
|
+
"brand-fit-registry proposals apply",
|
|
76
|
+
"brand-fit-registry proposals approve",
|
|
77
|
+
"brand-fit-registry proposals cancel",
|
|
78
|
+
"brand-fit-registry proposals list",
|
|
79
|
+
"brand-fit-registry proposals propose",
|
|
80
|
+
"brand-fit-registry proposals reject",
|
|
81
|
+
"brand-fit-registry proposals show",
|
|
82
|
+
"brand-fit-registry rule-signals",
|
|
83
|
+
"brand-fit-registry rule-signals list",
|
|
84
|
+
"brand-fit-registry rule-signals show",
|
|
85
|
+
"brand-fit-registry triggers",
|
|
86
|
+
"brand-fit-registry triggers list",
|
|
87
|
+
"brand-fit-registry triggers show",
|
|
70
88
|
"brand-members",
|
|
71
89
|
"brand-members create",
|
|
72
90
|
"brand-members list",
|
package/dist/index.d.ts
CHANGED
|
@@ -4,9 +4,6 @@ declare const program: Command;
|
|
|
4
4
|
/** 返回放错位置字段的指引(无则 null)。用于 accounts update / sync core 防呆。 */
|
|
5
5
|
export declare function detectMisplacedAccountFields(body: Record<string, unknown>): string | null;
|
|
6
6
|
export type VocAcquireClient = {
|
|
7
|
-
getAuthContext(): Promise<{
|
|
8
|
-
role: string;
|
|
9
|
-
}>;
|
|
10
7
|
vocQuery(body: unknown): Promise<Record<string, unknown>>;
|
|
11
8
|
getIntelRunProgress(runId: string): Promise<{
|
|
12
9
|
status: string;
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA2BpC,QAAA,MAAM,OAAO,SAAgB,CAAC;AAiqD9B,8DAA8D;AAC9D,wBAAgB,4BAA4B,CAC1C,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,MAAM,GAAG,IAAI,CAOf;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA2BpC,QAAA,MAAM,OAAO,SAAgB,CAAC;AAiqD9B,8DAA8D;AAC9D,wBAAgB,4BAA4B,CAC1C,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,MAAM,GAAG,IAAI,CAOf;AAs+BD,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAC1D,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACjE,CAAC;AAQF,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,gBAAgB,EACxB,MAAM,EAAE;IACN,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,OAAO,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACvC,GACA,OAAO,CAAC;IAAE,QAAQ,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,CAAC,CAkJnE;AA+1ED,OAAO,EAAE,OAAO,EAAE,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -2083,17 +2083,8 @@ export async function orchestrateVocAcquire(client, params) {
|
|
|
2083
2083
|
},
|
|
2084
2084
|
});
|
|
2085
2085
|
try {
|
|
2086
|
-
//
|
|
2087
|
-
|
|
2088
|
-
if (auth.role === "client") {
|
|
2089
|
-
return {
|
|
2090
|
-
exitCode: 1,
|
|
2091
|
-
output: {
|
|
2092
|
-
status: "forbidden",
|
|
2093
|
-
reason: "voc-acquire 第一版仅 unrestricted 角色(client 恒拒);先派发再发现越权会白占额度",
|
|
2094
|
-
},
|
|
2095
|
-
};
|
|
2096
|
-
}
|
|
2086
|
+
// 无角色预检:权限由服务端强制。voc-query(第一次调用)若无 evidence create 会在**任何派发副作用前**
|
|
2087
|
+
// 403 → 抛出 → 命令层退 1;有权则派发 + 轮询(受限主体持 runId + dimension read 可轮询 /runs/:runId)。
|
|
2097
2088
|
let round = 0;
|
|
2098
2089
|
let last = {};
|
|
2099
2090
|
while (round < params.maxRounds) {
|
|
@@ -2203,7 +2194,7 @@ intel
|
|
|
2203
2194
|
.command("voc-acquire")
|
|
2204
2195
|
.description("VOC 有界编排(Hub-native):循环 voc-query --dispatch-on-gap → 轮询 run 到终态 → 重算 coverage 验收 → " +
|
|
2205
2196
|
"缺口再派一轮。退出码 0=coverage 满足 / 2=尚未满足(超时/多轮后仍缺口,可能需外部 import)/ 1=错误。" +
|
|
2206
|
-
"评估口径同 voc-query
|
|
2197
|
+
"评估口径同 voc-query;受限主体亦可(权限由服务端强制:需 evidence create + 该 dimension read);--async 只派发不等待。")
|
|
2207
2198
|
.option("--brand-keywords <list>", "品牌词,逗号分隔")
|
|
2208
2199
|
.option("--competitor-keywords <list>", "竞品词,逗号分隔")
|
|
2209
2200
|
.option("--subreddits <list>", "板块,逗号分隔")
|
|
@@ -3783,6 +3774,178 @@ brandRegistry
|
|
|
3783
3774
|
cursor: opts.cursor,
|
|
3784
3775
|
}), null, 2));
|
|
3785
3776
|
});
|
|
3777
|
+
// ── Trigger 注册表四眼管理面(P1-D3)——只提案/审批/执行,不提供直写命令 ──────────────
|
|
3778
|
+
const bfRegistry = program
|
|
3779
|
+
.command("brand-fit-registry")
|
|
3780
|
+
.description("Trigger 注册表四眼管理面:trigger/avoid/rule_signal 的 create/update/scope/mandate/retire 全走 propose→approve→apply(无直写命令)");
|
|
3781
|
+
const out = (v) => console.log(JSON.stringify(v, null, 2));
|
|
3782
|
+
/** apply 的 stale 友好提示(不解析 message,靠 SDK RegistryProposalSdkError.isStale)。 */
|
|
3783
|
+
function handleProposalError(err) {
|
|
3784
|
+
const e = err;
|
|
3785
|
+
if (e && e.isStale) {
|
|
3786
|
+
console.error(`proposal 已过时(staleCode=${e.staleCode}):目标已变更,请 show 最新状态后重新 propose`);
|
|
3787
|
+
}
|
|
3788
|
+
else if (e && e.code) {
|
|
3789
|
+
console.error(`${e.code}: ${e.message ?? ""}`);
|
|
3790
|
+
}
|
|
3791
|
+
else {
|
|
3792
|
+
console.error(e?.message ?? String(err));
|
|
3793
|
+
}
|
|
3794
|
+
process.exit(1);
|
|
3795
|
+
}
|
|
3796
|
+
const bfrProposals = bfRegistry
|
|
3797
|
+
.command("proposals")
|
|
3798
|
+
.description("四眼提案(propose/approve/reject/cancel/apply/list/show)");
|
|
3799
|
+
bfrProposals
|
|
3800
|
+
.command("propose")
|
|
3801
|
+
.description("提交一个 registry 变更提案(RegistryProposalInput)")
|
|
3802
|
+
.requiredOption("--input <json>", 'RegistryProposalInput JSON,如 {"type":"trigger.create","triggerKey":"...","matchDefinition":{...},"scopeMode":"global"}')
|
|
3803
|
+
.requiredOption("--idempotency-key <key>", "幂等键(同 proposer 同 key 返既有)")
|
|
3804
|
+
.option("--expires-at <iso>", "过期时间 ISO(可选,须晚于当前)")
|
|
3805
|
+
.action(async (opts) => {
|
|
3806
|
+
let input;
|
|
3807
|
+
try {
|
|
3808
|
+
input = JSON.parse(opts.input);
|
|
3809
|
+
}
|
|
3810
|
+
catch {
|
|
3811
|
+
console.error("Invalid --input JSON");
|
|
3812
|
+
process.exit(1);
|
|
3813
|
+
}
|
|
3814
|
+
try {
|
|
3815
|
+
out(await requireClient().proposeRegistryChange({
|
|
3816
|
+
input,
|
|
3817
|
+
idempotencyKey: opts.idempotencyKey,
|
|
3818
|
+
expiresAt: opts.expiresAt,
|
|
3819
|
+
}));
|
|
3820
|
+
}
|
|
3821
|
+
catch (err) {
|
|
3822
|
+
handleProposalError(err);
|
|
3823
|
+
}
|
|
3824
|
+
});
|
|
3825
|
+
bfrProposals
|
|
3826
|
+
.command("approve")
|
|
3827
|
+
.description("批准提案(四眼第二只眼;审批人须≠提案人)")
|
|
3828
|
+
.requiredOption("--id <id>", "proposal id")
|
|
3829
|
+
.option("--comment <text>", "审批备注")
|
|
3830
|
+
.action(async (opts) => {
|
|
3831
|
+
try {
|
|
3832
|
+
out(await requireClient().approveRegistryProposal(opts.id, {
|
|
3833
|
+
approvalComment: opts.comment,
|
|
3834
|
+
}));
|
|
3835
|
+
}
|
|
3836
|
+
catch (err) {
|
|
3837
|
+
handleProposalError(err);
|
|
3838
|
+
}
|
|
3839
|
+
});
|
|
3840
|
+
bfrProposals
|
|
3841
|
+
.command("reject")
|
|
3842
|
+
.description("拒绝提案")
|
|
3843
|
+
.requiredOption("--id <id>", "proposal id")
|
|
3844
|
+
.option("--reason <text>", "拒绝原因")
|
|
3845
|
+
.action(async (opts) => {
|
|
3846
|
+
try {
|
|
3847
|
+
out(await requireClient().rejectRegistryProposal(opts.id, {
|
|
3848
|
+
rejectionReason: opts.reason,
|
|
3849
|
+
}));
|
|
3850
|
+
}
|
|
3851
|
+
catch (err) {
|
|
3852
|
+
handleProposalError(err);
|
|
3853
|
+
}
|
|
3854
|
+
});
|
|
3855
|
+
bfrProposals
|
|
3856
|
+
.command("cancel")
|
|
3857
|
+
.description("取消提案(proposed 或 approved;apply 前)")
|
|
3858
|
+
.requiredOption("--id <id>", "proposal id")
|
|
3859
|
+
.action(async (opts) => {
|
|
3860
|
+
try {
|
|
3861
|
+
out(await requireClient().cancelRegistryProposal(opts.id));
|
|
3862
|
+
}
|
|
3863
|
+
catch (err) {
|
|
3864
|
+
handleProposalError(err);
|
|
3865
|
+
}
|
|
3866
|
+
});
|
|
3867
|
+
bfrProposals
|
|
3868
|
+
.command("apply")
|
|
3869
|
+
.description("执行已批准提案(stale→提示重新提案)")
|
|
3870
|
+
.requiredOption("--id <id>", "proposal id")
|
|
3871
|
+
.action(async (opts) => {
|
|
3872
|
+
try {
|
|
3873
|
+
out(await requireClient().applyRegistryProposal(opts.id));
|
|
3874
|
+
}
|
|
3875
|
+
catch (err) {
|
|
3876
|
+
handleProposalError(err);
|
|
3877
|
+
}
|
|
3878
|
+
});
|
|
3879
|
+
bfrProposals
|
|
3880
|
+
.command("list")
|
|
3881
|
+
.description("列出提案(可按 status 过滤)")
|
|
3882
|
+
.option("--status <status>", "proposed|approved|rejected|cancelled|applied|stale")
|
|
3883
|
+
.action(async (opts) => {
|
|
3884
|
+
out(await requireClient().listRegistryProposals({ status: opts.status }));
|
|
3885
|
+
});
|
|
3886
|
+
bfrProposals
|
|
3887
|
+
.command("show")
|
|
3888
|
+
.description("查看单个提案")
|
|
3889
|
+
.requiredOption("--id <id>", "proposal id")
|
|
3890
|
+
.action(async (opts) => {
|
|
3891
|
+
try {
|
|
3892
|
+
out(await requireClient().getRegistryProposal(opts.id));
|
|
3893
|
+
}
|
|
3894
|
+
catch (err) {
|
|
3895
|
+
handleProposalError(err);
|
|
3896
|
+
}
|
|
3897
|
+
});
|
|
3898
|
+
const bfrTriggers = bfRegistry
|
|
3899
|
+
.command("triggers")
|
|
3900
|
+
.description("trigger 注册表(只读;写走 proposals)");
|
|
3901
|
+
bfrTriggers
|
|
3902
|
+
.command("list")
|
|
3903
|
+
.action(async () => out(await requireClient().listBrandFitTriggers()));
|
|
3904
|
+
bfrTriggers
|
|
3905
|
+
.command("show")
|
|
3906
|
+
.requiredOption("--key <triggerKey>")
|
|
3907
|
+
.action(async (opts) => {
|
|
3908
|
+
try {
|
|
3909
|
+
out(await requireClient().getBrandFitTrigger(opts.key));
|
|
3910
|
+
}
|
|
3911
|
+
catch (err) {
|
|
3912
|
+
handleProposalError(err);
|
|
3913
|
+
}
|
|
3914
|
+
});
|
|
3915
|
+
const bfrAvoids = bfRegistry
|
|
3916
|
+
.command("avoid-contexts")
|
|
3917
|
+
.description("avoid_context 注册表(只读;写走 proposals)");
|
|
3918
|
+
bfrAvoids
|
|
3919
|
+
.command("list")
|
|
3920
|
+
.action(async () => out(await requireClient().listBrandFitAvoidContexts()));
|
|
3921
|
+
bfrAvoids
|
|
3922
|
+
.command("show")
|
|
3923
|
+
.requiredOption("--key <avoidKey>")
|
|
3924
|
+
.action(async (opts) => {
|
|
3925
|
+
try {
|
|
3926
|
+
out(await requireClient().getBrandFitAvoidContext(opts.key));
|
|
3927
|
+
}
|
|
3928
|
+
catch (err) {
|
|
3929
|
+
handleProposalError(err);
|
|
3930
|
+
}
|
|
3931
|
+
});
|
|
3932
|
+
const bfrSignals = bfRegistry
|
|
3933
|
+
.command("rule-signals")
|
|
3934
|
+
.description("rule_signal 注册表(只读;写走 proposals)");
|
|
3935
|
+
bfrSignals
|
|
3936
|
+
.command("list")
|
|
3937
|
+
.action(async () => out(await requireClient().listBrandFitRuleSignals()));
|
|
3938
|
+
bfrSignals
|
|
3939
|
+
.command("show")
|
|
3940
|
+
.requiredOption("--key <signalKey>")
|
|
3941
|
+
.action(async (opts) => {
|
|
3942
|
+
try {
|
|
3943
|
+
out(await requireClient().getBrandFitRuleSignal(opts.key));
|
|
3944
|
+
}
|
|
3945
|
+
catch (err) {
|
|
3946
|
+
handleProposalError(err);
|
|
3947
|
+
}
|
|
3948
|
+
});
|
|
3786
3949
|
const brandFit = program
|
|
3787
3950
|
.command("brand-fit")
|
|
3788
3951
|
.description("Persona Brand Fit 分级(persona×brand 正式关系):关系表查看 + 受控迁移 validate/apply");
|