@reachv2/sdk 0.1.0 → 0.2.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/README.md +41 -1
- package/dist/client.d.ts +6 -0
- package/dist/client.js +6 -0
- package/dist/index.d.ts +4 -1
- package/dist/index.js +3 -0
- package/dist/resources/auth.d.ts +7 -6
- package/dist/resources/auth.js +9 -9
- package/dist/resources/health.d.ts +13 -0
- package/dist/resources/health.js +13 -0
- package/dist/resources/team.d.ts +34 -0
- package/dist/resources/team.js +35 -0
- package/dist/resources/tenants.d.ts +52 -0
- package/dist/resources/tenants.js +59 -0
- package/dist/types.d.ts +110 -5
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ Reach(reach.codes)统一平台的官方 TypeScript SDK —— 由 aiservicer
|
|
|
8
8
|
|
|
9
9
|
## 文档
|
|
10
10
|
|
|
11
|
-
- **[API Reference](docs/API-REFERENCE.md)**(P2.6
|
|
11
|
+
- **[API Reference](docs/API-REFERENCE.md)**(P2.6,v0.2.0 扩展统一租户):全部 23 个资源类 + `ReachClient` 共 **136 个方法**的签名 / 端点 / 参数 / 返回类型 / 错误 / 示例,与 `sdk/src` 源码一一对应。
|
|
12
12
|
|
|
13
13
|
## 安装
|
|
14
14
|
|
|
@@ -68,6 +68,38 @@ client.setToken(jwt); // SDK 不会自动接线,需手动 setToken 切换为 J
|
|
|
68
68
|
|
|
69
69
|
> `setToken()` 是全局切换,调用后所有资源请求优先使用 JWT。
|
|
70
70
|
|
|
71
|
+
## MCP 接入(Phase 5 P5.2)
|
|
72
|
+
|
|
73
|
+
Reach 将自身能力以 **MCP(Model Context Protocol)** 形式对外开放(Streamable HTTP,路径 `/mcp`),
|
|
74
|
+
让支持 MCP 的客户端(Claude Desktop / Cursor / 自研 Agent)可直接调用 crm + social 域工具。
|
|
75
|
+
|
|
76
|
+
- 端点:`https://reach.codes/mcp`(探活:`GET https://reach.codes/mcp/health`)
|
|
77
|
+
- 鉴权:`X-API-Key: reach-xxx` 或 `Authorization: Bearer sk-xxx`(复用 REST API Key,租户隔离由此 Key 决定)
|
|
78
|
+
- 权限:MCP 工具调用为写操作,API Key 需含 `write` / `all` scope
|
|
79
|
+
- 工具域:按平台配置白名单裁剪(当前 `crm` / `social`),`tools/list` 返回实际可用集合
|
|
80
|
+
|
|
81
|
+
会话按 MCP Streamable HTTP 规范:先 `initialize` 取得 `mcp-session-id`,
|
|
82
|
+
再发 `notifications/initialized`,之后 `tools/call`,结束时 `DELETE` 会话。
|
|
83
|
+
|
|
84
|
+
```ts
|
|
85
|
+
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
86
|
+
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
|
87
|
+
|
|
88
|
+
const transport = new StreamableHTTPClientTransport(
|
|
89
|
+
new URL("https://reach.codes/mcp"),
|
|
90
|
+
{ requestInit: { headers: { "X-API-Key": "reach-xxx" } } }
|
|
91
|
+
);
|
|
92
|
+
const client = new Client({ name: "my-agent", version: "1.0.0" });
|
|
93
|
+
await client.connect(transport);
|
|
94
|
+
|
|
95
|
+
const { tools } = await client.listTools(); // 实际可用的域白名单工具
|
|
96
|
+
const res = await client.callTool({ name: "social_accounts_list", arguments: {} });
|
|
97
|
+
await transport.close(); // 释放会话
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
> 平台内部闭环(reach server → mcp,`/api/bridge/mcp/discover|call`)走 `x-reach-internal-token`,
|
|
101
|
+
> 不对外暴露;外部集成一律使用 API Key。
|
|
102
|
+
|
|
71
103
|
## 统一网关(A.2.4)
|
|
72
104
|
|
|
73
105
|
合并后 Reach 采用**单后端 + 统一网关层**:`@reachv2/sdk` 只走网关。默认 `serverBaseUrl` 省略时等于 `baseUrl`,全部请求经统一网关;`serverBaseUrl` 仅作内部调试 override。
|
|
@@ -93,6 +125,14 @@ const client = new ReachClient({
|
|
|
93
125
|
| `client.dashboard` | **统一看板**(DashboardApi):crm 客服指标 + social 社媒运营看板 | 双域 |
|
|
94
126
|
| `client.orchestration` | 对话编排(多 task × 多 agent) | Server |
|
|
95
127
|
|
|
128
|
+
### 统一租户成员模型(G-1~G-3,v0.2.0 新增)
|
|
129
|
+
|
|
130
|
+
| 资源 | 主要能力 | API 域 |
|
|
131
|
+
|------|----------|--------|
|
|
132
|
+
| `client.tenants` | **统一租户(TenantsResource)**:清单/建 org/成员列表/直加/邀请(意图记录)/接受/撤销/改派/移除/owner 转让(shared.tenant_members 权威面) | Server |
|
|
133
|
+
| `client.team` | **社媒团队薄适配(TeamResource)**:/api/team/*(web 社媒后台 Team tab 契约;同表同 token 与 tenants 互通) | Server |
|
|
134
|
+
| `client.health` | **存活探活(HealthResource)**:GET /api/health(匿名 200) | Server |
|
|
135
|
+
|
|
96
136
|
### crm 域(源自 aiservicer)
|
|
97
137
|
|
|
98
138
|
| 资源 | 主要能力 | API 域 |
|
package/dist/client.d.ts
CHANGED
|
@@ -19,6 +19,9 @@ import { ContentResource } from "./resources/content.js";
|
|
|
19
19
|
import { TtsResource } from "./resources/tts.js";
|
|
20
20
|
import { AccountsResource } from "./resources/accounts.js";
|
|
21
21
|
import { DashboardApi } from "./resources/dashboard-api.js";
|
|
22
|
+
import { HealthResource } from "./resources/health.js";
|
|
23
|
+
import { TenantsResource } from "./resources/tenants.js";
|
|
24
|
+
import { TeamResource } from "./resources/team.js";
|
|
22
25
|
export declare class ReachClient {
|
|
23
26
|
private apiKey?;
|
|
24
27
|
private token?;
|
|
@@ -45,6 +48,9 @@ export declare class ReachClient {
|
|
|
45
48
|
content: ContentResource;
|
|
46
49
|
tts: TtsResource;
|
|
47
50
|
accounts: AccountsResource;
|
|
51
|
+
tenants: TenantsResource;
|
|
52
|
+
team: TeamResource;
|
|
53
|
+
health: HealthResource;
|
|
48
54
|
constructor(config: ReachClientConfig);
|
|
49
55
|
/** Set token after wallet login */
|
|
50
56
|
setToken(token: string): void;
|
package/dist/client.js
CHANGED
|
@@ -19,6 +19,9 @@ import { ContentResource } from "./resources/content.js";
|
|
|
19
19
|
import { TtsResource } from "./resources/tts.js";
|
|
20
20
|
import { AccountsResource } from "./resources/accounts.js";
|
|
21
21
|
import { DashboardApi } from "./resources/dashboard-api.js";
|
|
22
|
+
import { HealthResource } from "./resources/health.js";
|
|
23
|
+
import { TenantsResource } from "./resources/tenants.js";
|
|
24
|
+
import { TeamResource } from "./resources/team.js";
|
|
22
25
|
export class ReachClient {
|
|
23
26
|
constructor(config) {
|
|
24
27
|
if (!config.apiKey && !config.token) {
|
|
@@ -50,6 +53,9 @@ export class ReachClient {
|
|
|
50
53
|
this.content = new ContentResource(this.requestServer.bind(this));
|
|
51
54
|
this.tts = new TtsResource(this.requestServer.bind(this));
|
|
52
55
|
this.accounts = new AccountsResource(this.requestServer.bind(this));
|
|
56
|
+
this.tenants = new TenantsResource(this.requestServer.bind(this));
|
|
57
|
+
this.team = new TeamResource(this.requestServer.bind(this));
|
|
58
|
+
this.health = new HealthResource(this.requestServer.bind(this));
|
|
53
59
|
}
|
|
54
60
|
/** Set token after wallet login */
|
|
55
61
|
setToken(token) {
|
package/dist/index.d.ts
CHANGED
|
@@ -20,5 +20,8 @@ export { AbiResource } from "./resources/abis.js";
|
|
|
20
20
|
export { ContentResource } from "./resources/content.js";
|
|
21
21
|
export { TtsResource } from "./resources/tts.js";
|
|
22
22
|
export { AccountsResource } from "./resources/accounts.js";
|
|
23
|
-
export
|
|
23
|
+
export { HealthResource } from "./resources/health.js";
|
|
24
|
+
export { TenantsResource } from "./resources/tenants.js";
|
|
25
|
+
export { TeamResource } from "./resources/team.js";
|
|
26
|
+
export type { ReachClientConfig, BotType, AgentType, BotStatus, ChannelType, ChannelStatus, KnowledgeStatus, Pagination, PaginatedResponse, Project, ProjectCreateParams, ProjectUpdateParams, TransactionBotConfig, Bot, BotStats, BotCreateParams, BotUpdateParams, KnowledgeDoc, KnowledgeRecommendation, Channel, ChannelConfigureParams, Conversation, Message, ChatParams, ChatResponse, ChatToolDefinition, ChatToolFunction, DashboardData, BotMetrics, TxIntent, TxStep, PreparedTransaction, ContractInfo, ContractMethod, SimulationResult, DecodedCalldata, ProtocolSummary, ProtocolRegistryEntry, ChainDeployment, ProtocolAction, ParamHint, WalletChallenge, WalletLoginParams, AuthResult, CaptchaResponse, CaptchaAnswer, AgentXAgent, AgentXAgentDetail, AgentXMarketplaceResult, AgentXSubscriptionPlans, AgentXSubscriptionCheck, AgentXAgentContext, AgentXPublishParams, AgentXPublishResult, AgentXSkill, AgentXSkillCreateParams, AgentXAgentStatus, AgentXAgentUsage, AgentXSubscriptionDetail, AgentXSubscriptionList, ServerChatParams, ServerChatResponse, ChatUsage, ChatUsageSummary, AgentSummary, AgentListResult, AgentListParams, AgentChainInfo, AgentActionType, AgentCapabilities, AgentChatParams, AgentChatResult, LightRAGKeyInfo, LightRAGDocumentParams, LightRAGQueryParams, LightRAGQueryResult, LightRAGBatchItem, LightRAGBatchError, LightRAGBatchResult, GlobalAnalytics, AdminDashboard, AdminMerchant, AdminMerchantDetail, AdminBillingRecord, AdminCreateBillingParams, LlmSettings, LlmUpdateParams, ConversationTask, ConversationTaskStatus, ConversationSession, ConversationCapabilities, ConversationMessage, OrchestrationTaskParams, OrchestrateParams, OrchestratedTaskResult, OrchestrateResult, ScheduledTask, ScheduledTaskStatus, ScheduledTaskTriggerType, MonitorConnectorKind, EnterpriseDoc, MonitorConnector, MonitorEvent, MerchantAbi, MerchantAbiCreateParams, SimpleResult, TenantType, TenantMemberRole, TenantMemberStatus, Tenant, TenantMemberInfo, TenantInvite, PublicInviteInfo, InviteAcceptResult, MemberRoleUpdateResult, TransferOwnerResult, TeamMemberItem, TeamInviteResult, HealthInfo, } from "./types.js";
|
|
24
27
|
export type { ApiKeyInfo, ApiKeyCreated } from "./resources/api-key.js";
|
package/dist/index.js
CHANGED
|
@@ -20,3 +20,6 @@ export { AbiResource } from "./resources/abis.js";
|
|
|
20
20
|
export { ContentResource } from "./resources/content.js";
|
|
21
21
|
export { TtsResource } from "./resources/tts.js";
|
|
22
22
|
export { AccountsResource } from "./resources/accounts.js";
|
|
23
|
+
export { HealthResource } from "./resources/health.js";
|
|
24
|
+
export { TenantsResource } from "./resources/tenants.js";
|
|
25
|
+
export { TeamResource } from "./resources/team.js";
|
package/dist/resources/auth.d.ts
CHANGED
|
@@ -8,14 +8,15 @@ export declare class AuthResource {
|
|
|
8
8
|
/** 钱包签名登录,返回 token + user */
|
|
9
9
|
walletLogin(params: WalletLoginParams): Promise<AuthResult>;
|
|
10
10
|
/**
|
|
11
|
-
*
|
|
12
|
-
*
|
|
11
|
+
* 获取图形验证码(login/register 前置,可选)。
|
|
12
|
+
* image 为 `data:image/svg+xml;base64,...`,算式形如 "7 + 5 = ?",结果恒为非负。
|
|
13
|
+
* 服务端校验码存 Redis 5 分钟一次性(reach:captcha:*)。
|
|
13
14
|
*/
|
|
14
15
|
getCaptcha(): Promise<CaptchaResponse>;
|
|
15
|
-
/**
|
|
16
|
-
login(
|
|
17
|
-
/**
|
|
18
|
-
register(
|
|
16
|
+
/** 邮箱密码登录(server 契约:email+password;captcha 可选,传 captchaToken+captchaAnswer 时服务端强校验) */
|
|
17
|
+
login(email: string, password: string, captcha?: CaptchaAnswer): Promise<AuthResult>;
|
|
18
|
+
/** 邮箱密码注册(server 契约:email+password;captcha 可选) */
|
|
19
|
+
register(email: string, password: string, opts?: {
|
|
19
20
|
name?: string;
|
|
20
21
|
email?: string;
|
|
21
22
|
captcha?: CaptchaAnswer;
|
package/dist/resources/auth.js
CHANGED
|
@@ -11,28 +11,28 @@ export class AuthResource {
|
|
|
11
11
|
return this.request("POST", "/api/auth/wallet-login", params);
|
|
12
12
|
}
|
|
13
13
|
/**
|
|
14
|
-
*
|
|
15
|
-
*
|
|
14
|
+
* 获取图形验证码(login/register 前置,可选)。
|
|
15
|
+
* image 为 `data:image/svg+xml;base64,...`,算式形如 "7 + 5 = ?",结果恒为非负。
|
|
16
|
+
* 服务端校验码存 Redis 5 分钟一次性(reach:captcha:*)。
|
|
16
17
|
*/
|
|
17
18
|
getCaptcha() {
|
|
18
19
|
return this.request("POST", "/api/auth/captcha");
|
|
19
20
|
}
|
|
20
|
-
/**
|
|
21
|
-
login(
|
|
21
|
+
/** 邮箱密码登录(server 契约:email+password;captcha 可选,传 captchaToken+captchaAnswer 时服务端强校验) */
|
|
22
|
+
login(email, password, captcha) {
|
|
22
23
|
return this.request("POST", "/api/auth/login", {
|
|
23
|
-
|
|
24
|
+
email,
|
|
24
25
|
password,
|
|
25
26
|
captchaToken: captcha?.token,
|
|
26
27
|
captchaAnswer: captcha?.answer,
|
|
27
28
|
});
|
|
28
29
|
}
|
|
29
|
-
/**
|
|
30
|
-
register(
|
|
30
|
+
/** 邮箱密码注册(server 契约:email+password;captcha 可选) */
|
|
31
|
+
register(email, password, opts) {
|
|
31
32
|
return this.request("POST", "/api/auth/register", {
|
|
32
|
-
|
|
33
|
+
email,
|
|
33
34
|
password,
|
|
34
35
|
name: opts?.name,
|
|
35
|
-
email: opts?.email,
|
|
36
36
|
captchaToken: opts?.captcha?.token,
|
|
37
37
|
captchaAnswer: opts?.captcha?.answer,
|
|
38
38
|
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { RequestMethod, HealthInfo } from "../types.js";
|
|
2
|
+
type RequestFn = <T>(method: RequestMethod, path: string, body?: unknown) => Promise<T>;
|
|
3
|
+
/**
|
|
4
|
+
* Health 资源 — 平台存活探活(REQ-4)。
|
|
5
|
+
* GET /api/health 匿名 200(无需鉴权头,但 SDK 构造仍需 apiKey/token 任一)。
|
|
6
|
+
*/
|
|
7
|
+
export declare class HealthResource {
|
|
8
|
+
private request;
|
|
9
|
+
constructor(request: RequestFn);
|
|
10
|
+
/** 存活探活 */
|
|
11
|
+
check(): Promise<HealthInfo>;
|
|
12
|
+
}
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Health 资源 — 平台存活探活(REQ-4)。
|
|
3
|
+
* GET /api/health 匿名 200(无需鉴权头,但 SDK 构造仍需 apiKey/token 任一)。
|
|
4
|
+
*/
|
|
5
|
+
export class HealthResource {
|
|
6
|
+
constructor(request) {
|
|
7
|
+
this.request = request;
|
|
8
|
+
}
|
|
9
|
+
/** 存活探活 */
|
|
10
|
+
check() {
|
|
11
|
+
return this.request("GET", "/api/health");
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { RequestMethod, TenantMemberRole, TeamMemberItem, TeamInviteResult, SimpleResult } from "../types.js";
|
|
2
|
+
type RequestFn = <T>(method: RequestMethod, path: string, body?: unknown) => Promise<T>;
|
|
3
|
+
/**
|
|
4
|
+
* Team 资源 — 社媒团队面(/api/team/*,web 社媒后台 Settings Team tab 契约的薄适配层)。
|
|
5
|
+
*
|
|
6
|
+
* P4.6 后为统一租户成员模型(shared.tenant_members)的适配层:邀请为意图记录
|
|
7
|
+
* (accountId 可空,不预建占位账户),受邀者经统一 POST /invites/:token/accept 激活
|
|
8
|
+
* (可用 tenants.acceptInvite(token))。角色 GRANTABLE=admin/editor/member/viewer,
|
|
9
|
+
* owner 仅经 tenants.transferOwner 产生;PUT/DELETE 纪律对齐 G-3。
|
|
10
|
+
*
|
|
11
|
+
* 鉴权:JWT(Bearer token)。社媒上下文租户 = 账号默认(最早加入)active 租户;
|
|
12
|
+
* 明确租户作用域的成员管理请用 Tenants 资源(path 内显式 tenantId)。
|
|
13
|
+
*/
|
|
14
|
+
export declare class TeamResource {
|
|
15
|
+
private request;
|
|
16
|
+
constructor(request: RequestFn);
|
|
17
|
+
/** 当前上下文租户成员列表(受邀未接受行 userId=null;{items,total} 契约) */
|
|
18
|
+
members(): Promise<{
|
|
19
|
+
items: TeamMemberItem[];
|
|
20
|
+
total: number;
|
|
21
|
+
}>;
|
|
22
|
+
/** 邀请成员(email 必填;role 缺省 editor;未注册邮箱亦有效,接受时绑定) */
|
|
23
|
+
invite(params: {
|
|
24
|
+
email: string;
|
|
25
|
+
role?: TenantMemberRole;
|
|
26
|
+
}): Promise<TeamInviteResult>;
|
|
27
|
+
/** 改派成员角色(id = TenantMember.id 行 id,来自 members() 的 item.id) */
|
|
28
|
+
updateMemberRole(memberRowId: string, params: {
|
|
29
|
+
role: TenantMemberRole;
|
|
30
|
+
}): Promise<TeamMemberItem>;
|
|
31
|
+
/** 移除/撤销成员(id = TenantMember.id 行 id;撤销待接受邀请复用本方法) */
|
|
32
|
+
removeMember(memberRowId: string): Promise<SimpleResult>;
|
|
33
|
+
}
|
|
34
|
+
export {};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Team 资源 — 社媒团队面(/api/team/*,web 社媒后台 Settings Team tab 契约的薄适配层)。
|
|
3
|
+
*
|
|
4
|
+
* P4.6 后为统一租户成员模型(shared.tenant_members)的适配层:邀请为意图记录
|
|
5
|
+
* (accountId 可空,不预建占位账户),受邀者经统一 POST /invites/:token/accept 激活
|
|
6
|
+
* (可用 tenants.acceptInvite(token))。角色 GRANTABLE=admin/editor/member/viewer,
|
|
7
|
+
* owner 仅经 tenants.transferOwner 产生;PUT/DELETE 纪律对齐 G-3。
|
|
8
|
+
*
|
|
9
|
+
* 鉴权:JWT(Bearer token)。社媒上下文租户 = 账号默认(最早加入)active 租户;
|
|
10
|
+
* 明确租户作用域的成员管理请用 Tenants 资源(path 内显式 tenantId)。
|
|
11
|
+
*/
|
|
12
|
+
export class TeamResource {
|
|
13
|
+
constructor(request) {
|
|
14
|
+
this.request = request;
|
|
15
|
+
}
|
|
16
|
+
/** 当前上下文租户成员列表(受邀未接受行 userId=null;{items,total} 契约) */
|
|
17
|
+
members() {
|
|
18
|
+
return this.request("GET", "/api/team/members");
|
|
19
|
+
}
|
|
20
|
+
/** 邀请成员(email 必填;role 缺省 editor;未注册邮箱亦有效,接受时绑定) */
|
|
21
|
+
invite(params) {
|
|
22
|
+
return this.request("POST", "/api/team/invite", {
|
|
23
|
+
email: params.email,
|
|
24
|
+
role: params.role || "editor",
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
/** 改派成员角色(id = TenantMember.id 行 id,来自 members() 的 item.id) */
|
|
28
|
+
updateMemberRole(memberRowId, params) {
|
|
29
|
+
return this.request("PUT", `/api/team/members/${encodeURIComponent(memberRowId)}`, { role: params.role });
|
|
30
|
+
}
|
|
31
|
+
/** 移除/撤销成员(id = TenantMember.id 行 id;撤销待接受邀请复用本方法) */
|
|
32
|
+
removeMember(memberRowId) {
|
|
33
|
+
return this.request("DELETE", `/api/team/members/${encodeURIComponent(memberRowId)}`);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { RequestMethod, Tenant, TenantMemberRole, TenantMemberInfo, TenantInvite, PublicInviteInfo, InviteAcceptResult, SimpleResult, MemberRoleUpdateResult, TransferOwnerResult } from "../types.js";
|
|
2
|
+
type RequestFn = <T>(method: RequestMethod, path: string, body?: unknown) => Promise<T>;
|
|
3
|
+
/**
|
|
4
|
+
* Tenants 资源 — 平台统一租户成员模型(G-1~G-3,/api/shared/tenants)。
|
|
5
|
+
*
|
|
6
|
+
* 模型:注册即自动建 personal 个人租户(owner);可显式创建 org 企业租户(owner);
|
|
7
|
+
* 成员档位 owner(唯一,转让制) > admin > editor > member/viewer(GRANTABLE=admin/editor/member/viewer,
|
|
8
|
+
* owner 仅经 transferOwner 产生);未注册邮箱走 invite 意图记录(不预建占位账户),
|
|
9
|
+
* 受邀者注册/登录后经 acceptInvite 绑定身份激活(邮箱匹配防冒领)。
|
|
10
|
+
*
|
|
11
|
+
* 鉴权:除 getInvite(token) 公开外,全部需 JWT(Bearer token,client 以 token 构造)。
|
|
12
|
+
*/
|
|
13
|
+
export declare class TenantsResource {
|
|
14
|
+
private request;
|
|
15
|
+
constructor(request: RequestFn);
|
|
16
|
+
/** 我加入的租户清单(含 type 与我的角色) */
|
|
17
|
+
list(): Promise<Tenant[]>;
|
|
18
|
+
/** 创建企业/组织租户(创建者为 owner,type=org) */
|
|
19
|
+
create(params: {
|
|
20
|
+
name: string;
|
|
21
|
+
}): Promise<Tenant>;
|
|
22
|
+
/** 租户成员列表(含 invited 待接受行;owner/admin 可见 inviteToken 便于管理邀请链接) */
|
|
23
|
+
members(tenantId: string): Promise<TenantMemberInfo[]>;
|
|
24
|
+
/** 直加已注册账户(owner/admin;email 或 wallet 定位账户;未注册邮箱请用 invite) */
|
|
25
|
+
addMember(tenantId: string, params: {
|
|
26
|
+
email?: string;
|
|
27
|
+
wallet?: string;
|
|
28
|
+
role?: TenantMemberRole;
|
|
29
|
+
}): Promise<TenantMemberInfo>;
|
|
30
|
+
/** 邀请未注册邮箱(意图记录;受邀者注册/登录后 acceptInvite 激活) */
|
|
31
|
+
invite(tenantId: string, params: {
|
|
32
|
+
email: string;
|
|
33
|
+
role?: TenantMemberRole;
|
|
34
|
+
}): Promise<TenantInvite>;
|
|
35
|
+
/** 公开查询邀请(无需登录;展示租户/受邀邮箱/角色/状态) */
|
|
36
|
+
getInvite(token: string): Promise<PublicInviteInfo>;
|
|
37
|
+
/** 登录后接受邀请:邮箱须与邀请一致,绑定身份并激活(幂等) */
|
|
38
|
+
acceptInvite(token: string): Promise<InviteAcceptResult>;
|
|
39
|
+
/** 撤销待接受邀请(owner/admin) */
|
|
40
|
+
revokeInvite(tenantId: string, token: string): Promise<SimpleResult>;
|
|
41
|
+
/** 改派成员角色(owner 全权;admin 仅改 editor/member/viewer,不可授/动 admin;owner 只经转让) */
|
|
42
|
+
updateMemberRole(tenantId: string, accountId: string, params: {
|
|
43
|
+
role: TenantMemberRole;
|
|
44
|
+
}): Promise<MemberRoleUpdateResult>;
|
|
45
|
+
/** 移除成员(owner 移除非 owner;admin 仅移除 editor/member/viewer;owner 移除前须先转让) */
|
|
46
|
+
removeMember(tenantId: string, accountId: string): Promise<SimpleResult>;
|
|
47
|
+
/** owner 转让(仅当前 owner;目标须为 active 成员;转让后原 owner 降 admin) */
|
|
48
|
+
transferOwner(tenantId: string, params: {
|
|
49
|
+
accountId: string;
|
|
50
|
+
}): Promise<TransferOwnerResult>;
|
|
51
|
+
}
|
|
52
|
+
export {};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tenants 资源 — 平台统一租户成员模型(G-1~G-3,/api/shared/tenants)。
|
|
3
|
+
*
|
|
4
|
+
* 模型:注册即自动建 personal 个人租户(owner);可显式创建 org 企业租户(owner);
|
|
5
|
+
* 成员档位 owner(唯一,转让制) > admin > editor > member/viewer(GRANTABLE=admin/editor/member/viewer,
|
|
6
|
+
* owner 仅经 transferOwner 产生);未注册邮箱走 invite 意图记录(不预建占位账户),
|
|
7
|
+
* 受邀者注册/登录后经 acceptInvite 绑定身份激活(邮箱匹配防冒领)。
|
|
8
|
+
*
|
|
9
|
+
* 鉴权:除 getInvite(token) 公开外,全部需 JWT(Bearer token,client 以 token 构造)。
|
|
10
|
+
*/
|
|
11
|
+
export class TenantsResource {
|
|
12
|
+
constructor(request) {
|
|
13
|
+
this.request = request;
|
|
14
|
+
}
|
|
15
|
+
/** 我加入的租户清单(含 type 与我的角色) */
|
|
16
|
+
list() {
|
|
17
|
+
return this.request("GET", "/api/shared/tenants");
|
|
18
|
+
}
|
|
19
|
+
/** 创建企业/组织租户(创建者为 owner,type=org) */
|
|
20
|
+
create(params) {
|
|
21
|
+
return this.request("POST", "/api/shared/tenants", { name: params.name });
|
|
22
|
+
}
|
|
23
|
+
/** 租户成员列表(含 invited 待接受行;owner/admin 可见 inviteToken 便于管理邀请链接) */
|
|
24
|
+
members(tenantId) {
|
|
25
|
+
return this.request("GET", `/api/shared/tenants/${encodeURIComponent(tenantId)}/members`);
|
|
26
|
+
}
|
|
27
|
+
/** 直加已注册账户(owner/admin;email 或 wallet 定位账户;未注册邮箱请用 invite) */
|
|
28
|
+
addMember(tenantId, params) {
|
|
29
|
+
return this.request("POST", `/api/shared/tenants/${encodeURIComponent(tenantId)}/members`, { email: params.email, wallet: params.wallet, role: params.role || "member" });
|
|
30
|
+
}
|
|
31
|
+
/** 邀请未注册邮箱(意图记录;受邀者注册/登录后 acceptInvite 激活) */
|
|
32
|
+
invite(tenantId, params) {
|
|
33
|
+
return this.request("POST", `/api/shared/tenants/${encodeURIComponent(tenantId)}/invites`, { email: params.email, role: params.role || "member" });
|
|
34
|
+
}
|
|
35
|
+
/** 公开查询邀请(无需登录;展示租户/受邀邮箱/角色/状态) */
|
|
36
|
+
getInvite(token) {
|
|
37
|
+
return this.request("GET", `/api/shared/tenants/invites/${encodeURIComponent(token)}`);
|
|
38
|
+
}
|
|
39
|
+
/** 登录后接受邀请:邮箱须与邀请一致,绑定身份并激活(幂等) */
|
|
40
|
+
acceptInvite(token) {
|
|
41
|
+
return this.request("POST", `/api/shared/tenants/invites/${encodeURIComponent(token)}/accept`);
|
|
42
|
+
}
|
|
43
|
+
/** 撤销待接受邀请(owner/admin) */
|
|
44
|
+
revokeInvite(tenantId, token) {
|
|
45
|
+
return this.request("POST", `/api/shared/tenants/${encodeURIComponent(tenantId)}/invites/${encodeURIComponent(token)}/revoke`);
|
|
46
|
+
}
|
|
47
|
+
/** 改派成员角色(owner 全权;admin 仅改 editor/member/viewer,不可授/动 admin;owner 只经转让) */
|
|
48
|
+
updateMemberRole(tenantId, accountId, params) {
|
|
49
|
+
return this.request("PUT", `/api/shared/tenants/${encodeURIComponent(tenantId)}/members/${encodeURIComponent(accountId)}`, { role: params.role });
|
|
50
|
+
}
|
|
51
|
+
/** 移除成员(owner 移除非 owner;admin 仅移除 editor/member/viewer;owner 移除前须先转让) */
|
|
52
|
+
removeMember(tenantId, accountId) {
|
|
53
|
+
return this.request("DELETE", `/api/shared/tenants/${encodeURIComponent(tenantId)}/members/${encodeURIComponent(accountId)}`);
|
|
54
|
+
}
|
|
55
|
+
/** owner 转让(仅当前 owner;目标须为 active 成员;转让后原 owner 降 admin) */
|
|
56
|
+
transferOwner(tenantId, params) {
|
|
57
|
+
return this.request("POST", `/api/shared/tenants/${encodeURIComponent(tenantId)}/transfer-owner`, { accountId: params.accountId });
|
|
58
|
+
}
|
|
59
|
+
}
|
package/dist/types.d.ts
CHANGED
|
@@ -12,7 +12,7 @@ export type BotStatus = "running" | "stopped";
|
|
|
12
12
|
export type ChannelType = "telegram" | "whatsapp" | "webwidget";
|
|
13
13
|
export type ChannelStatus = "configured" | "unconfigured" | "pairing";
|
|
14
14
|
export type KnowledgeStatus = "processing" | "ready" | "error";
|
|
15
|
-
export type RequestMethod = "GET" | "POST" | "PATCH" | "DELETE";
|
|
15
|
+
export type RequestMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
|
|
16
16
|
export interface Pagination {
|
|
17
17
|
page: number;
|
|
18
18
|
pageSize: number;
|
|
@@ -292,13 +292,13 @@ export interface AuthResult {
|
|
|
292
292
|
walletAddress?: string;
|
|
293
293
|
};
|
|
294
294
|
}
|
|
295
|
-
/**
|
|
295
|
+
/** 图形验证码(login/register 前置,可选):image 为 data URI,算式恒为非负结果 */
|
|
296
296
|
export interface CaptchaResponse {
|
|
297
|
-
|
|
298
|
-
|
|
297
|
+
captchaId: string;
|
|
298
|
+
image: string;
|
|
299
299
|
expiresIn: number;
|
|
300
300
|
}
|
|
301
|
-
/**
|
|
301
|
+
/** 验证码作答参数(以 captchaId 为 token;服务端校验通过才放行登录/注册) */
|
|
302
302
|
export interface CaptchaAnswer {
|
|
303
303
|
token: string;
|
|
304
304
|
answer: number;
|
|
@@ -791,3 +791,108 @@ export interface MonitorEvent {
|
|
|
791
791
|
payload: Record<string, unknown>;
|
|
792
792
|
received_at: string;
|
|
793
793
|
}
|
|
794
|
+
/** 通用 ok 结果({ok:true} 契约:revoke/remove 等) */
|
|
795
|
+
export interface SimpleResult {
|
|
796
|
+
ok: boolean;
|
|
797
|
+
}
|
|
798
|
+
export type TenantType = "personal" | "org";
|
|
799
|
+
/** 租户内档位全集(owner 仅经转让产生;GRANTABLE=admin/editor/member/viewer) */
|
|
800
|
+
export type TenantMemberRole = "owner" | "admin" | "editor" | "member" | "viewer";
|
|
801
|
+
export type TenantMemberStatus = "active" | "invited";
|
|
802
|
+
/** 租户(清单响应含我在此租户的角色 role) */
|
|
803
|
+
export interface Tenant {
|
|
804
|
+
id: string;
|
|
805
|
+
name: string;
|
|
806
|
+
slug: string;
|
|
807
|
+
type: TenantType;
|
|
808
|
+
status?: string | null;
|
|
809
|
+
tokenBalance?: number | null;
|
|
810
|
+
createdAt?: string | null;
|
|
811
|
+
role?: TenantMemberRole;
|
|
812
|
+
}
|
|
813
|
+
/** 租户成员行(GET /:id/members;owner/admin 可见 inviteToken) */
|
|
814
|
+
export interface TenantMemberInfo {
|
|
815
|
+
id: string;
|
|
816
|
+
tenantId: string;
|
|
817
|
+
accountId: string | null;
|
|
818
|
+
role: TenantMemberRole;
|
|
819
|
+
status: TenantMemberStatus;
|
|
820
|
+
email: string | null;
|
|
821
|
+
username?: string | null;
|
|
822
|
+
wallet?: string | null;
|
|
823
|
+
/** 仅 owner/admin 可见;受邀未接受行存在 */
|
|
824
|
+
inviteToken?: string | null;
|
|
825
|
+
joinedAt?: string | null;
|
|
826
|
+
}
|
|
827
|
+
/** 邀请意图记录(POST /:id/invites 响应) */
|
|
828
|
+
export interface TenantInvite {
|
|
829
|
+
id: string;
|
|
830
|
+
tenantId: string;
|
|
831
|
+
email: string;
|
|
832
|
+
role: TenantMemberRole;
|
|
833
|
+
status: TenantMemberStatus;
|
|
834
|
+
inviteToken: string;
|
|
835
|
+
}
|
|
836
|
+
/** 公开邀请查询(GET /invites/:token) */
|
|
837
|
+
export interface PublicInviteInfo {
|
|
838
|
+
tenant: {
|
|
839
|
+
id: string;
|
|
840
|
+
name: string;
|
|
841
|
+
slug: string;
|
|
842
|
+
type: TenantType;
|
|
843
|
+
};
|
|
844
|
+
email: string;
|
|
845
|
+
role: TenantMemberRole;
|
|
846
|
+
status: TenantMemberStatus;
|
|
847
|
+
}
|
|
848
|
+
/** 接受邀请结果(POST /invites/:token/accept;幂等) */
|
|
849
|
+
export interface InviteAcceptResult {
|
|
850
|
+
accepted: boolean;
|
|
851
|
+
tenantId?: string;
|
|
852
|
+
role?: TenantMemberRole;
|
|
853
|
+
/** 该邀请此前已被处理(重复接受/已是成员) */
|
|
854
|
+
alreadyProcessed?: boolean;
|
|
855
|
+
alreadyMember?: boolean;
|
|
856
|
+
}
|
|
857
|
+
/** 改派成员角色结果(PUT /:id/members/:accountId) */
|
|
858
|
+
export interface MemberRoleUpdateResult {
|
|
859
|
+
id: string;
|
|
860
|
+
accountId: string;
|
|
861
|
+
role: TenantMemberRole;
|
|
862
|
+
status: TenantMemberStatus;
|
|
863
|
+
}
|
|
864
|
+
/** owner 转让结果(POST /:id/transfer-owner) */
|
|
865
|
+
export interface TransferOwnerResult {
|
|
866
|
+
ok: boolean;
|
|
867
|
+
newOwner: string;
|
|
868
|
+
}
|
|
869
|
+
/** 社媒团队成员行(GET /api/team/members item;id = TenantMember.id 行 id) */
|
|
870
|
+
export interface TeamMemberItem {
|
|
871
|
+
id: string;
|
|
872
|
+
tenantId: string;
|
|
873
|
+
/** 受邀未接受时 null(accountId 可空,不预建占位账户) */
|
|
874
|
+
userId: string | null;
|
|
875
|
+
role: TenantMemberRole;
|
|
876
|
+
status: TenantMemberStatus;
|
|
877
|
+
email: string | null;
|
|
878
|
+
name?: string | null;
|
|
879
|
+
username?: string | null;
|
|
880
|
+
avatarUrl?: string | null;
|
|
881
|
+
joinedAt?: string | null;
|
|
882
|
+
}
|
|
883
|
+
/** 社媒团队邀请结果(POST /api/team/invite) */
|
|
884
|
+
export interface TeamInviteResult {
|
|
885
|
+
invited: boolean;
|
|
886
|
+
id: string;
|
|
887
|
+
email: string;
|
|
888
|
+
role: TenantMemberRole;
|
|
889
|
+
inviteToken: string;
|
|
890
|
+
}
|
|
891
|
+
/** 存活探活(GET /api/health 匿名 200) */
|
|
892
|
+
export interface HealthInfo {
|
|
893
|
+
status: string;
|
|
894
|
+
service?: string;
|
|
895
|
+
version?: string;
|
|
896
|
+
uptime?: number;
|
|
897
|
+
[key: string]: unknown;
|
|
898
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reachv2/sdk",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Reach unified REST API client library for TypeScript — crm 域(AgentApi/Project/Bot/Knowledge/Channel/Conversation/Transaction/Auth/Chat/ApiKey/LightRAG/Orchestration/ScheduledTasks/Internal/Abis/Admin)+ social 域(Content/Tts/Accounts)+ 统一 DashboardApi(crm/social
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Reach unified REST API client library for TypeScript — crm 域(AgentApi/Project/Bot/Knowledge/Channel/Conversation/Transaction/Auth/Chat/ApiKey/LightRAG/Orchestration/ScheduledTasks/Internal/Abis/Admin)+ social 域(Content/Tts/Accounts)+ 统一 DashboardApi(crm/social 看板)+ 统一租户成员模型(Tenants/Team/Health,G-1~G-3)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
7
|
"types": "./dist/index.d.ts",
|