@zleap-ai/app-sdk 0.0.0-stage → 0.10.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.
@@ -0,0 +1,138 @@
1
+ /** @generated from packages/shared/src/apps/appSdkTypes.ts; do not edit.
2
+ * Source SHA-256: fae9b1c73efa81131d6a13d0dfc76476705c449930587116c4814c2591646dca
3
+ * Rebuild with: node scripts/build-app-sdk.mjs
4
+ */
5
+ /**
6
+ * @zleap/app-sdk 纯类型模块 —— 社交域 / 邀请域契约类型(自 appSdk.ts 拆出)。
7
+ *
8
+ * 拆分原因(2026-09-17 Lzm):单文件 700 行上限规则 —— appSdk.ts 逼近上限,
9
+ * 而本模块**仅含类型**(零运行时代码),appSdk.ts 以 `import type` 引用并
10
+ * re-export;经 build-app-sdk.mjs 类型擦除后产物依然零 import,自包含硬约束不破。
11
+ * 类型与 hostSocial.ts / appInvite.ts / hostCapabilities.tsx 保持**结构同形**
12
+ * (漂移由 appSdk.test.ts 的互赋值断言拦截)。
13
+ *
14
+ * 编码:utf8 | 语言:TypeScript | 作者:Lzm | 日期:2026-09-17
15
+ */
16
+ /** APP 私有对象分享卡片(与后端 `ShareCreate.app_object` 结构白名单同口径) */
17
+ export interface AppShareCardInput {
18
+ /** 卡片标题(必填 ≤100 字,服务端 trim) */
19
+ title: string;
20
+ /** 卡片摘要(可选 ≤500 字) */
21
+ summary?: string;
22
+ /** 图标(可选;必须平台自托管路径 `/api/v1/…`,缺省回退应用图标) */
23
+ icon_url?: string;
24
+ /** 点卡启动参数(必填,8 键 × 键≤32 × 值≤256;平台不解释语义) */
25
+ object_ref: Record<string, string>;
26
+ }
27
+ /** 选人返回的主体 */
28
+ export interface SocialPeer {
29
+ id: string;
30
+ name: string;
31
+ avatarUrl?: string | null;
32
+ /** 主体类型:user / agent */
33
+ type?: 'user' | 'agent';
34
+ }
35
+ /** 选会话返回的会话 */
36
+ export interface SocialConversation {
37
+ id: string;
38
+ name: string;
39
+ /** 外部 IM 平台标识;非空表示外部会话(分享卡片会 409,选会话时应禁用该行) */
40
+ externalPlatform?: string | null;
41
+ }
42
+ export interface SocialFollowResult {
43
+ ok: boolean;
44
+ /** 操作后的关注状态(follow → true;unfollow → false) */
45
+ following: boolean;
46
+ }
47
+ export interface SocialShareResult {
48
+ ok: boolean;
49
+ /** 失败的目标数量(shareToConversation 按会话扇出时可能部分失败) */
50
+ failedCount: number;
51
+ }
52
+ export interface SocialCreateGroupResult {
53
+ ok: boolean;
54
+ conversationId?: string;
55
+ }
56
+ /**
57
+ * 社交宿主能力面:关注 / 选人 / 建群 / 分享(规范 §6.5)。
58
+ * 分享的 `appId` 由宿主层强制注入/覆盖,调用方传入不生效(D1 身份锚定)。
59
+ */
60
+ export interface HostSocial {
61
+ /** 关注(单向,无需对方同意;黑名单拦截) */
62
+ follow(targetId: string, targetType?: 'user' | 'agent'): Promise<SocialFollowResult>;
63
+ /** 取关(单向) */
64
+ unfollow(targetId: string, targetType?: 'user' | 'agent'): Promise<SocialFollowResult>;
65
+ /** 是否已关注 */
66
+ isFollowing(targetId: string, targetType?: 'user' | 'agent'): Promise<boolean>;
67
+ /** 平台选人组件:返回用户选中的主体(单/多选);APP 不再自造通讯录 */
68
+ pickUsers(options?: { multiple?: boolean; excludeUserIds?: string[] }): Promise<SocialPeer[]>;
69
+ /** 平台选会话组件:返回用户选中的会话(用于分享) */
70
+ pickConversations(options?: { multiple?: boolean }): Promise<SocialConversation[]>;
71
+ /** 分享:按会话扇出落卡片消息(`app_object` 形态) */
72
+ shareToConversation(input: {
73
+ card: AppShareCardInput;
74
+ conversationIds: string[];
75
+ appId?: string;
76
+ }): Promise<SocialShareResult>;
77
+ /** 分享:发布为动态(作者 = 当前用户) */
78
+ shareToDynamic(input: {
79
+ card: AppShareCardInput;
80
+ visibility?: 'public' | 'friend' | 'private';
81
+ appId?: string;
82
+ }): Promise<SocialShareResult>;
83
+ /** 建群(交流群 = IM 群聊)并拉人 */
84
+ createGroup(input: { name: string; memberIds: string[] }): Promise<SocialCreateGroupResult>;
85
+ }
86
+ /** 按钮样式:`primary` 主行动,`danger` 拒绝类,缺省 `default` */
87
+ export type AppInviteActionStyle = 'default' | 'primary' | 'danger';
88
+ /** 动作声明的邀请终态 */
89
+ export type AppInviteActionResponse = 'accept' | 'reject';
90
+ /** 声明式动作:平台按此渲染按钮并通用执行(平台不解释动作语义) */
91
+ export interface AppInviteAction {
92
+ /** 动作 id(APP 私有语义),回投信号 payload 里带回 */
93
+ id: string;
94
+ /** 按钮文案(发起方语言;平台不二次翻译) */
95
+ label: string;
96
+ /** 回投的事件动作名,平台自动补前缀成 `app.<appId>.<event>` */
97
+ event: string;
98
+ /** 声明「点击 = 邀请被接受 / 被拒绝」;缺省为纯动作,邀请保持 pending */
99
+ response?: AppInviteActionResponse;
100
+ /** 点击时先由平台打开该应用并带参数(snake_case = 线上落库格式) */
101
+ open?: {
102
+ app_id: string;
103
+ params?: Record<string, string>;
104
+ };
105
+ style?: AppInviteActionStyle;
106
+ }
107
+ /** 统一邀请通道入参(规范 §6.4) */
108
+ export interface HostInviteSendInput {
109
+ /** 发起方 APP:卡片 `app_id` + 动作回投命名空间 `app.<appId>.<动作>` */
110
+ appId: string;
111
+ /** 对端用户 id(单聊会话按成员组合幂等创建/复用) */
112
+ peerUserId: string;
113
+ /** 邀请标识:同一邀请生命周期内不变(由 APP 生成,幂等与过期丢弃用) */
114
+ inviteId: string;
115
+ /** 卡片正文(人可读,必填) */
116
+ text: string;
117
+ /** 声明式动作:点击后回投 `app.<appId>.<action.event>` */
118
+ actions?: AppInviteAction[];
119
+ /** 过期时间戳(ms);到时平台把卡片按钮置灰 */
120
+ expiresAt?: number;
121
+ /** 同时投递的在线即时信号(事件名自动拼 `app.<appId>.<signal.action>`) */
122
+ signal?: {
123
+ action: string;
124
+ payload?: Record<string, unknown>;
125
+ };
126
+ }
127
+ /** 邀请投递结果;`reason` 供界面提示,不抛错 */
128
+ export interface HostInviteSendResult {
129
+ ok: boolean;
130
+ /** 承载本次邀请的单聊会话 id(成功时有值) */
131
+ conversationId?: string;
132
+ /** noIdentity=未登录;rejected=平台统一拒绝(准入 / 黑名单 / 应用不可用等) */
133
+ reason?: 'noIdentity' | 'rejected';
134
+ }
135
+ /** 统一邀请通道:一次调用 = 单聊会话 + 邀请卡片 + 可选实时信号 */
136
+ export interface HostInvite {
137
+ send(input: HostInviteSendInput): Promise<HostInviteSendResult>;
138
+ }
@@ -0,0 +1,232 @@
1
+ /** @generated from packages/shared/src/apps/appSdk.ts; do not edit.
2
+ * Source SHA-256: a1b1201cc3f85268156163232b439d80e8621c9d543d70ed5008c158880ab8ce
3
+ * Rebuild with: node scripts/build-app-sdk.mjs
4
+ */
5
+ /**
6
+ * @zleap/app-sdk 单文件源 —— 三形态统一 SDK(社交域方案 §6.1 / P4)。
7
+ *
8
+ * 三形态出口:
9
+ * - `connectZleapOs()` iframe 形态:类型化包裹宿主注入的 `window.__ZLEAP_OS__`
10
+ * - `connectHostedApp(options)` 托管静态包:MessageChannel protocol 1 握手(kv / files)
11
+ * - `connectHostCapabilities()` 内置形态:适配 HostCapabilities(React Context 值直传)
12
+ *
13
+ * 自包含硬约束(勿破):`scripts/build-app-sdk.mjs` 对本文件做类型擦除后断言产物无
14
+ * `import`,且 zleap-sdk.js / zleap-sdk.d.ts 要发给第三方独立使用 —— 故本文件**零运行时 import**。
15
+ * 社交 / 邀请等共享类型已拆至 appSdkTypes.ts(纯类型模块),此处以 `import type` 引用并
16
+ * re-export;类型擦除后产物依然零 import,约束不破。类型与 hostSocial.ts / appInvite.ts /
17
+ * hostCapabilities.tsx 保持**结构同形**(漂移由 appSdk.test.ts 的互赋值断言拦截)。
18
+ *
19
+ * 本地预校验(2026-09-17 Lzm,P0/P2/P5):kv.set / kv.delete 的键格式与值大小在 SDK 侧
20
+ * 先行校验并抛出带中文说明的 42200,避免「请求打到后端被桥脱敏成 Invalid app request」。
21
+ * 预校验二轮(2026-09-18 Lzm):expectedVersion 整数域 / 文件名安全规则 / KV 嵌套深度
22
+ * 上限与后端 app_runtime_validation 全口径对齐;canonicalJson 显式拒绝 toJSON 对象;
23
+ * connectZleapOs 对老版宿主缺失能力域给缺省拒绝实现(SDKError 40302,不再裸 TypeError)。
24
+ *
25
+ * 边界:SDK 只做协议封装与类型,不做权限判定(唯一裁决在后端 + 宿主桥 fail-closed)。
26
+ * 编码:utf8 | 语言:TypeScript | 作者:Lzm | 日期:2026-09-18
27
+ */
28
+ import type { HostInvite, HostSocial } from './zleap-sdk-types';
29
+ export type {
30
+ AppShareCardInput,
31
+ SocialPeer,
32
+ SocialConversation,
33
+ SocialFollowResult,
34
+ SocialShareResult,
35
+ SocialCreateGroupResult,
36
+ HostSocial,
37
+ AppInviteActionStyle,
38
+ AppInviteActionResponse,
39
+ AppInviteAction,
40
+ HostInviteSendInput,
41
+ HostInviteSendResult,
42
+ HostInvite,
43
+ } from './zleap-sdk-types';
44
+ export type NotifyLevel = 'info' | 'success' | 'warning' | 'error';
45
+ /** 当前登录用户基本信息 */
46
+ export interface ZleapUser {
47
+ id: string;
48
+ name: string;
49
+ }
50
+ export type HostedJSONValue =
51
+ | null
52
+ | boolean
53
+ | number
54
+ | string
55
+ | HostedJSONValue[]
56
+ | {
57
+ [key: string]: HostedJSONValue;
58
+ };
59
+ export interface HostedKVEntry {
60
+ key: string;
61
+ value: HostedJSONValue;
62
+ version: number;
63
+ exists: boolean;
64
+ }
65
+ export interface HostedFile {
66
+ id: string;
67
+ name: string;
68
+ mime_type: string | null;
69
+ size: number;
70
+ version: number;
71
+ }
72
+ export interface HostedFilePage {
73
+ list: HostedFile[];
74
+ total: number;
75
+ page: number;
76
+ pageSize: number;
77
+ }
78
+ export interface HostedAppClient {
79
+ kv: {
80
+ get(args: { key: string }): Promise<HostedKVEntry>;
81
+ set(args: {
82
+ key: string;
83
+ value: HostedJSONValue;
84
+ expectedVersion: number;
85
+ }): Promise<HostedKVEntry>;
86
+ delete(args: { key: string; expectedVersion: number }): Promise<HostedKVEntry>;
87
+ };
88
+ files: {
89
+ list(args?: { page?: number; pageSize?: number }): Promise<HostedFilePage>;
90
+ read(args: { productionId: string }): Promise<{
91
+ file: HostedFile;
92
+ data: Uint8Array;
93
+ }>;
94
+ write(args: {
95
+ name: string;
96
+ data: ArrayBuffer | Uint8Array;
97
+ mimeType?: string;
98
+ }): Promise<HostedFile>;
99
+ };
100
+ close(): void;
101
+ }
102
+ /** Server business codes are preserved; request headers, tokens and stacks are never exposed. */
103
+ export declare class SDKError extends Error {
104
+ readonly code: number;
105
+ constructor(message: string, code: number);
106
+ }
107
+ /** 错误码处置指引(2026-09-17 Lzm,P3) */
108
+ export interface SDKErrorInfo {
109
+ code: number;
110
+ /** 是否可安全重试(幂等重试或重新读取后再试) */
111
+ retryable: boolean;
112
+ /** 人可读的处置建议(中文) */
113
+ hint: string;
114
+ }
115
+ /** describeError:SDKError.code → 结构化处置指引(2026-09-17 Lzm,P3;2026-09-18 补 40400)。40400=资源不存在;40900=连接关闭/请求ID重用;40901=KV 版本冲突(重读后重试) */
116
+ export declare function describeError(code: number): SDKErrorInfo;
117
+ /** Connect once from the app bootstrap. The child transfers a port; the host never posts data to '*'. */
118
+ export declare function connectHostedApp(options?: {
119
+ timeoutMs?: number;
120
+ }): Promise<HostedAppClient>;
121
+ /** api.get 的查询参数(undefined 值被丢弃) */
122
+ export type ApiQueryParams = Record<string, string | number | boolean | undefined>;
123
+ /** 事件总线订阅回调:(载荷, 事件名) */
124
+ export type OsEventHandler = (payload: unknown, event: string) => void;
125
+ /**
126
+ * iframe 形态客户端:与宿主注入脚本 ZLEAP_OS_INJECT_SRC 的方法面逐一对齐。
127
+ * 能力未声明时调用被宿主桥 fail-closed 拒绝(reject),SDK 不做本地预判。
128
+ */
129
+ export interface ZleapOsClient {
130
+ auth: {
131
+ getToken(): Promise<string | null>;
132
+ getUser(): Promise<ZleapUser | null>;
133
+ /** 查询本 APP 是否被授予某项能力(manifest.capabilities) */
134
+ hasPermission(capability: string): Promise<boolean>;
135
+ };
136
+ storage: {
137
+ getItem(key: string): Promise<string | null>;
138
+ setItem(key: string, value: string): Promise<void>;
139
+ removeItem(key: string): Promise<void>;
140
+ };
141
+ notify: {
142
+ show(message: string, level?: NotifyLevel): Promise<void>;
143
+ /** 等待用户确认,无桥超时(用户可能长时间不点) */
144
+ confirm(title: string, content?: string): Promise<boolean>;
145
+ };
146
+ eventBus: {
147
+ emit(name: string, payload?: unknown): Promise<void>;
148
+ /** 订阅事件;返回 subscriptionId,供 off 退订 */
149
+ on(name: string, handler: OsEventHandler): Promise<string>;
150
+ off(subscriptionId: string): Promise<void>;
151
+ };
152
+ api: {
153
+ get<T = unknown>(path: string, params?: ApiQueryParams): Promise<T>;
154
+ post<T = unknown>(path: string, body?: unknown): Promise<T>;
155
+ put<T = unknown>(path: string, body?: unknown): Promise<T>;
156
+ del<T = unknown>(path: string): Promise<T>;
157
+ };
158
+ app: {
159
+ getManifest(): Promise<Record<string, unknown>>;
160
+ getAppId(): Promise<string>;
161
+ };
162
+ invite: HostInvite;
163
+ social: HostSocial;
164
+ }
165
+ /**
166
+ * iframe 形态入口:包裹宿主注入的 `window.__ZLEAP_OS__`(类型化 + 存在性校验)。
167
+ * 桥由 srcdoc 注入脚本同步建立,故本函数同步返回;缺桥即抛 SDKError(40301)。
168
+ */
169
+ export declare function connectZleapOs(): ZleapOsClient;
170
+ /**
171
+ * HostCapabilities 的 SDK 所需子集(结构同形,见 hostCapabilities.tsx)。
172
+ * 内置 APP 用法:`connectHostCapabilities(useHostCapabilities(), { appId: 'app-xxx' })`。
173
+ */
174
+ export interface HostCapabilitiesSource {
175
+ confirm(options: { title: string; content?: string }): Promise<boolean>;
176
+ notify(level: NotifyLevel, title: string): void;
177
+ apiProxy<T = unknown>(
178
+ endpoint: string,
179
+ options?: {
180
+ method?: string;
181
+ body?: unknown;
182
+ headers?: Record<string, string>;
183
+ },
184
+ ): Promise<T>;
185
+ storage: {
186
+ getItem(key: string): string | null;
187
+ setItem(key: string, value: string): void;
188
+ removeItem(key: string): void;
189
+ };
190
+ auth: {
191
+ getToken(): string | null;
192
+ getUser(): ZleapUser | null;
193
+ };
194
+ invite?: HostInvite;
195
+ social?: HostSocial;
196
+ }
197
+ export interface ConnectHostCapabilitiesOptions {
198
+ /**
199
+ * 内置 APP 的 appId。通道 A 的宿主是全局单例、不带 per-app 身份,
200
+ * 故 appId 只能由调用方显式声明(内置 APP 静态已知自己的 id)。
201
+ */
202
+ appId?: string;
203
+ }
204
+ /**
205
+ * 内置形态客户端(与 ZleapOsClient 的差异 = 平台真实差异):
206
+ * - 无 `auth.hasPermission`:通道 A 不带 per-app 身份,无法判定「本 APP」授权;
207
+ * - 无 `eventBus` / `app.getManifest`:HostCapabilities 未暴露;
208
+ * - `invite` / `social` 可选:宿主未提供时按不支持处理(字段缺省为 undefined)。
209
+ */
210
+ export interface BuiltinClient {
211
+ auth: {
212
+ getToken(): Promise<string | null>;
213
+ getUser(): Promise<ZleapUser | null>;
214
+ };
215
+ storage: ZleapOsClient['storage'];
216
+ notify: ZleapOsClient['notify'];
217
+ api: ZleapOsClient['api'];
218
+ app: {
219
+ /** 来自 options.appId;未传时 reject SDKError(40302) */
220
+ getAppId(): Promise<string>;
221
+ };
222
+ invite?: HostInvite;
223
+ social?: HostSocial;
224
+ }
225
+ /**
226
+ * 内置形态入口:把 HostCapabilities 适配成与 iframe 形态尽量一致的异步面。
227
+ * 同步宿主方法(storage / auth / notify.show)统一包成 Promise,跨形态代码可复用。
228
+ */
229
+ export declare function connectHostCapabilities(
230
+ host: HostCapabilitiesSource,
231
+ options?: ConnectHostCapabilitiesOptions,
232
+ ): BuiltinClient;
@@ -0,0 +1,2 @@
1
+ /*! @zleap-ai/app-sdk v0.10.0 | (c) 2026 Zleap | 专有许可,仅限在 zleapOS 应用中使用,见 LICENSE */
2
+ var I=Object.defineProperty;var E=(i,t,o)=>t in i?I(i,t,{enumerable:!0,configurable:!0,writable:!0,value:o}):i[t]=o;var _=(i,t,o)=>E(i,typeof t!="symbol"?t+"":t,o);var a=class extends Error{constructor(o,u){super(o);_(this,"code");_(this,"operationId");this.name="WorkspaceError",this.code=o,this.operationId=u}};function y(){if(window.parent===window)return Promise.reject(new a("OPEN_IN_ZLEAP_OS"));let i=window.location.pathname.match(/^\/api\/v1\/app-packages\/runtime\/([A-Za-z0-9_-]{43})\//)?.[1];if(!i)return Promise.reject(new a("OPEN_IN_ZLEAP_OS"));let t=new MessageChannel,o=!1,u=!1,l=new Map;function w(){if(!o){o=!0;for(let e of l.values())clearTimeout(e.timer),e.reject(new a(e.operationId?"COMMIT_UNKNOWN":"CONNECTION_CLOSED",e.operationId));l.clear(),t.port1.postMessage({type:"__zleap_workspace_close"}),t.port1.close()}}window.addEventListener("pagehide",w,{once:!0});let m=new Promise((e,s)=>{let r=setTimeout(()=>{u||(u=!0,w(),s(new a("WORKSPACE_UNAVAILABLE")))},15e3);t.port1.onmessage=c=>{let n=c.data;if(!u&&n?.type==="__zleap_workspace_ready"&&n.protocol===1){u=!0,clearTimeout(r),e();return}if(typeof n?.requestId!="string")return;let p=l.get(n.requestId);p&&(l.delete(n.requestId),clearTimeout(p.timer),typeof n.error=="string"?p.reject(new a(n.error,p.operationId)):p.resolve(n.result))},t.port1.onmessageerror=()=>w(),t.port1.start(),window.parent.postMessage({type:"__zleap_workspace_connect",protocol:1,nonce:i},"*",[t.port2])});async function d(e,s={},r){if(await m,o)throw new a("CONNECTION_CLOSED",r);if(l.size>=4)throw new a("TOO_MANY_REQUESTS");return new Promise((c,n)=>{let p=crypto.randomUUID(),O=setTimeout(()=>{l.delete(p),n(new a(r?"COMMIT_UNKNOWN":"CALL_TIMEOUT",r))},e==="select"?18e4:3e4);l.set(p,{resolve:N=>c(N),reject:n,timer:O,operationId:r}),t.port1.postMessage({requestId:p,method:e,args:s})})}async function f(e,s,r=crypto.randomUUID()){let c=await d(e,{...s,operationId:r},r);if(c.status!=="succeeded")throw new a(c.status==="failed"?c.code??"MOVE_FAILED":"COMMIT_UNKNOWN",r);return c}return m.then(()=>({selectFolder:()=>d("select"),restoreFolder:()=>d("restore"),list:e=>d("list",{handle:e}),readImage:(e,s,r)=>d("image",{handle:e,fileId:s,expectedVersion:r}),createFolder:async(e,s,r)=>(await f("mkdir",{handle:e,name:s},r)).result,move:async(e,s,r,c)=>(await f("move",{source:e,destination:s,fileIds:r},c)).result,operation:e=>d("operation",{operationId:e}),createOperationId:()=>crypto.randomUUID(),close:w}))}export{a as WorkspaceError,y as connectWorkspace};
package/package.json CHANGED
@@ -1,6 +1,44 @@
1
1
  {
2
2
  "name": "@zleap-ai/app-sdk",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.10.0",
4
+ "description": "zleapOS 云开发前端 SDK:Cloud 数据库 / 文件 / 云函数(zl.cloud)、宿主能力(connectHostedApp)与工作区连接",
5
+ "license": "SEE LICENSE IN LICENSE",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/zleap-ai/zleap-app-kit.git",
9
+ "directory": "packages/app-sdk"
10
+ },
11
+ "type": "module",
12
+ "main": "./dist/index.js",
13
+ "module": "./dist/index.js",
14
+ "types": "./dist/types/index.d.ts",
15
+ "exports": {
16
+ ".": {
17
+ "types": "./dist/types/index.d.ts",
18
+ "import": "./dist/index.js",
19
+ "default": "./dist/index.js"
20
+ },
21
+ "./host": {
22
+ "types": "./dist/types/zleap-sdk.d.ts",
23
+ "import": "./dist/host.js",
24
+ "default": "./dist/host.js"
25
+ },
26
+ "./workspace": {
27
+ "types": "./dist/types/workspace.d.ts",
28
+ "import": "./dist/workspace.js",
29
+ "default": "./dist/workspace.js"
30
+ },
31
+ "./package.json": "./package.json"
32
+ },
33
+ "files": [
34
+ "dist",
35
+ "LICENSE",
36
+ "README.md"
37
+ ],
38
+ "keywords": [
39
+ "zleap",
40
+ "zleapos",
41
+ "app-cloud",
42
+ "sdk"
43
+ ]
44
+ }