@aixnn/aixautots 0.0.0-stage → 0.5.3
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 +222 -2
- package/dist/chunk-5BMFMDQR.js +18 -0
- package/dist/chunk-64Q7BBIQ.js +1347 -0
- package/dist/chunk-BSHHYM72.js +1074 -0
- package/dist/chunk-CVV7FOMQ.js +175 -0
- package/dist/chunk-EVHTAXQG.js +273 -0
- package/dist/chunk-FW23FLAF.js +56 -0
- package/dist/chunk-IJVNII5N.js +668 -0
- package/dist/chunk-NWFYTFMI.js +65 -0
- package/dist/chunk-O34SNDQB.js +2042 -0
- package/dist/chunk-OEZFYKL6.js +1 -0
- package/dist/chunk-OXIM6EYO.js +410 -0
- package/dist/chunk-SVK2AY3J.js +412 -0
- package/dist/chunk-TATL3HTE.js +1511 -0
- package/dist/chunk-UINEPEIE.js +217 -0
- package/dist/chunk-V4MXFPDX.js +341 -0
- package/dist/chunk-XNKC6HU3.js +866 -0
- package/dist/chunk-YOT7HZBU.js +5744 -0
- package/dist/core/index.js +5 -0
- package/dist/device-session-W7I3WQXF.js +2 -0
- package/dist/i18n/index.js +1 -0
- package/dist/nav/index.js +1 -0
- package/dist/react/index.js +7 -0
- package/dist/ui/billing.js +425 -0
- package/dist/ui/device-create.js +9 -0
- package/dist/ui/device-mirror.js +10 -0
- package/dist/ui/devices.js +15 -0
- package/dist/ui/editor.js +344 -0
- package/dist/ui/index.js +665 -0
- package/dist/ui/inspector.js +1250 -0
- package/dist/ui/market.js +60 -0
- package/dist/ui/mirror.js +3 -0
- package/dist/ui/primitives/index.js +1 -0
- package/dist/ui/script-studio.js +10 -0
- package/dist/ui/scripts.js +210 -0
- package/dist/ui/tasks.js +1039 -0
- package/package.json +75 -4
- package/styles.css +97 -0
- package/tailwind-preset.cjs +84 -0
package/README.md
CHANGED
|
@@ -1,3 +1,223 @@
|
|
|
1
|
-
#
|
|
1
|
+
# aixautots
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
aixautobot 的 TypeScript 客户端 SDK。core/react 是 headless 的数据/传输/鉴权层;ui 既提供细粒度
|
|
4
|
+
部件,也提供**开箱即用的成品页面**(设备/任务/市场/脚本/编辑器/检查器)+ 一套可换肤主题,
|
|
5
|
+
让任意项目都能"轻松接入"。桌面端 `frontend/` 是全量改用本 SDK 的参考实现。
|
|
6
|
+
|
|
7
|
+
子路径导出:
|
|
8
|
+
|
|
9
|
+
| 子包 | 职责 |
|
|
10
|
+
|---|---|
|
|
11
|
+
| `aixautots/core` | 资源 REST 客户端(`AixClient`)+ 会话层(设备通道 / Flow / 镜像)+ 类型 + 错误 |
|
|
12
|
+
| `aixautots/react` | 上述能力的 React hooks(`AixProvider` + 资源/会话 hooks) |
|
|
13
|
+
| `aixautots/ui` | 设备向细粒度部件(`MirrorView`/`ControlBar`/`ScriptEditor`/`DebugConsole`/`ScriptPanel`) |
|
|
14
|
+
| `aixautots/ui/primitives` | 基础件(`Button`/`Input`/`Select`/`Badge`/`Dialog`/`Popover`) |
|
|
15
|
+
| `aixautots/ui/{devices,tasks,market,scripts,editor,inspector}` | 成品页面组件 |
|
|
16
|
+
| `aixautots/nav` | 路由无关导航注入(`AixNavProvider`/`useAixNav`) |
|
|
17
|
+
| `aixautots/i18n` | 内置 i18n(`AixI18nProvider`/`useAixT`,en/zh,无 i18next 依赖) |
|
|
18
|
+
| `aixautots/tailwind-preset` · `aixautots/styles.css` | Tailwind 预设 + 主题 token |
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm i aixautots # peer: react(react 子包用);ui 子包另需 @uiw/react-codemirror
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## 接入(三步)
|
|
25
|
+
|
|
26
|
+
用到 `aixautots/ui` 的成品页面/部件时,按以下三步接入样式与运行时上下文:
|
|
27
|
+
|
|
28
|
+
**1) 样式** —— Tailwind 预设 + 主题 token + content 扫描:
|
|
29
|
+
|
|
30
|
+
```js
|
|
31
|
+
// tailwind.config.js
|
|
32
|
+
module.exports = {
|
|
33
|
+
presets: [require('aixautots/tailwind-preset')],
|
|
34
|
+
content: [
|
|
35
|
+
'./src/**/*.{ts,tsx}',
|
|
36
|
+
'./node_modules/aixautots/dist/**/*.js', // 关键:否则 aixautots 组件的类名不会被生成
|
|
37
|
+
],
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
```css
|
|
42
|
+
/* 入口 CSS */
|
|
43
|
+
@import "aixautots/styles.css"; /* :root 浅色 + .dark 深色 token,可覆盖换肤 */
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
**2) Provider** —— 在 `AixProvider` 内注入导航与语言:
|
|
47
|
+
|
|
48
|
+
```tsx
|
|
49
|
+
import { AixProvider } from 'aixautots/react'
|
|
50
|
+
import { AixNavProvider } from 'aixautots/nav'
|
|
51
|
+
import { AixI18nProvider } from 'aixautots/i18n'
|
|
52
|
+
import { useNavigate } from 'react-router-dom' // 任意路由库都行
|
|
53
|
+
|
|
54
|
+
function Providers({ children }) {
|
|
55
|
+
const navigate = useNavigate()
|
|
56
|
+
return (
|
|
57
|
+
<AixProvider config={{ baseUrl, auth }}>
|
|
58
|
+
<AixNavProvider nav={{ navigate }}>
|
|
59
|
+
<AixI18nProvider lang="zh">{children}</AixI18nProvider>
|
|
60
|
+
</AixProvider>
|
|
61
|
+
</AixNavProvider>
|
|
62
|
+
)
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
**3) 用页面** —— 直接挂成品页面,路由参数以 props 传入:
|
|
67
|
+
|
|
68
|
+
```tsx
|
|
69
|
+
import { DevicesPage } from 'aixautots/ui/devices'
|
|
70
|
+
import { ScriptEditorPage } from 'aixautots/ui/editor'
|
|
71
|
+
|
|
72
|
+
<DevicesPage />
|
|
73
|
+
<ScriptEditorPage scriptId={params.id} />
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Quickstart
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
import { AixClient } from 'aixautots/core'
|
|
80
|
+
|
|
81
|
+
const client = new AixClient({
|
|
82
|
+
baseUrl: 'https://aixautobot.com',
|
|
83
|
+
auth: { kind: 'user', getToken: async () => myUserJwt },
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
const devices = await client.devices.list()
|
|
87
|
+
const { run_id } = await client.fleet.start({ flow, device_ids: [devices[0].id] })
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
React:
|
|
91
|
+
|
|
92
|
+
```tsx
|
|
93
|
+
import { AixProvider, useDevices } from 'aixautots/react'
|
|
94
|
+
|
|
95
|
+
function App() {
|
|
96
|
+
return (
|
|
97
|
+
<AixProvider config={{ baseUrl, auth: { kind: 'user', getToken } }}>
|
|
98
|
+
<DeviceList />
|
|
99
|
+
</AixProvider>
|
|
100
|
+
)
|
|
101
|
+
}
|
|
102
|
+
function DeviceList() {
|
|
103
|
+
const { data, loading, refetch } = useDevices()
|
|
104
|
+
// ...
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## 鉴权
|
|
109
|
+
|
|
110
|
+
`AixConfig.auth` 接受单个或多个凭据;SDK 按请求 **scope** 自动选用并注入请求头。**浏览器只需 bearer 或
|
|
111
|
+
project key/secret——不需要、也不应携带网关 `X-API-Key`**(后端 `require_principal` 已放行任一有效主体)。
|
|
112
|
+
|
|
113
|
+
```ts
|
|
114
|
+
type Credential =
|
|
115
|
+
| { kind: 'project'; key: string; secret: string } // 第三方:X-Project-Key / X-Project-Secret
|
|
116
|
+
| { kind: 'user'; getToken: () => string | Promise<string> } // 自家前端:user JWT
|
|
117
|
+
| { kind: 'developer'; getToken: () => string | Promise<string> } // 项目管理 / 平台管理
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
| Scope | 用到的凭据 | 覆盖的资源 |
|
|
121
|
+
|---|---|---|
|
|
122
|
+
| `caller` | project key/secret **或** user JWT | devices / scripts / clusters / fleet / tasks / locators / nodes |
|
|
123
|
+
| `developer` | developer JWT | projects / auth 管理 / webhooks / llm |
|
|
124
|
+
| `admin` | developer JWT(后端校验 admin) | admin(rate/plan/billing)/ images |
|
|
125
|
+
| `public` | 无 | auth.login / register / send-code / verify-code |
|
|
126
|
+
|
|
127
|
+
多凭据示例(自家前端同时持 developer + user):
|
|
128
|
+
|
|
129
|
+
```ts
|
|
130
|
+
auth: [
|
|
131
|
+
{ kind: 'user', getToken: currentUserToken }, // caller 资源用
|
|
132
|
+
{ kind: 'developer', getToken: () => devJwt }, // developer/admin 资源用
|
|
133
|
+
]
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
第三方前端(浏览器不持 project secret):后端铸 user JWT,前端用 `createCachedUserCredential` 自动缓存/刷新(按 `expiresIn` 或 JWT `exp`,并发去重):
|
|
137
|
+
|
|
138
|
+
```ts
|
|
139
|
+
import { createCachedUserCredential } from 'aixautots/core'
|
|
140
|
+
|
|
141
|
+
const auth = createCachedUserCredential({
|
|
142
|
+
mint: () => fetch('/mint-token').then((r) => r.json()), // 你的后端 → { token, expiresIn? } 或 token 字符串
|
|
143
|
+
})
|
|
144
|
+
new AixClient({ baseUrl, auth })
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
> 兼容旧写法:`getAuthToken: () => userJwt` 等价于 `auth: { kind: 'user', getToken }`。
|
|
148
|
+
|
|
149
|
+
## 资源总览(`AixClient` + hooks)
|
|
150
|
+
|
|
151
|
+
| 资源 | `client.*` | React hook |
|
|
152
|
+
|---|---|---|
|
|
153
|
+
| 鉴权 | `auth` | `useAuth` |
|
|
154
|
+
| 项目 | `projects` | `useProjects` |
|
|
155
|
+
| 设备 | `devices` | `useDevices` / `useDeviceActions` |
|
|
156
|
+
| 节点 | `nodes` | `useNodes` |
|
|
157
|
+
| 集群 | `clusters` | `useClusters` |
|
|
158
|
+
| 脚本 | `scripts` | `useScripts` |
|
|
159
|
+
| 定位器 | `locators` | `useLocators` |
|
|
160
|
+
| Fleet 运行 | `fleet` | `useFleetRun` |
|
|
161
|
+
| Webhook 任务 | `tasks` | `useTasks` / `useTaskStatus` |
|
|
162
|
+
| Webhook 配置 | `webhooks` | `useWebhooks` |
|
|
163
|
+
| LLM | `llm` | `useLlm` |
|
|
164
|
+
| 管理/计费/镜像 | `admin` | `useAdmin` / `useImages` |
|
|
165
|
+
| 巡检(截图+UI树) | (`devices.op`) | `useInspector` |
|
|
166
|
+
|
|
167
|
+
## 设备操作:两条路径
|
|
168
|
+
|
|
169
|
+
| | REST `devices.op` | WS `DeviceChannel` |
|
|
170
|
+
|---|---|---|
|
|
171
|
+
| 形态 | 一次性、无状态 | 长连、低延迟 |
|
|
172
|
+
| 适用 | 截图 / UI 树 / 安装 / 电源 等 | adb / wda / frida / scriptlet 流式 + 原始隧道、重交互调试 |
|
|
173
|
+
| 入口 | `client.devices.op(id, { op, ... })` | `DeviceChannel.open(cfg, id)` |
|
|
174
|
+
|
|
175
|
+
**通用命令**:`devices.op(id, op)` 是唯一入口,`op` 类型为开放联合——已知命令有自动补全,
|
|
176
|
+
**任意新命令无需新 SDK 方法**直接透传。`screenshot()/captureUiTree()/installApkUrl()/power()` 等都是它的薄包装。
|
|
177
|
+
|
|
178
|
+
```ts
|
|
179
|
+
await client.devices.screenshot(id) // 薄糖
|
|
180
|
+
await client.devices.op(id, { op: 'some_future_op', x: 1 }) // 新命令零改动
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
## 运行 flow:两条链路
|
|
184
|
+
|
|
185
|
+
| | Fleet(`fleet` / `useFleetRun`) | Webhook 任务(`FlowRun` / `tasks` / `useTaskStatus`) |
|
|
186
|
+
|---|---|---|
|
|
187
|
+
| 端点 | `POST /api/fleet/runs` | `POST /api/webhook/tasks` |
|
|
188
|
+
| 触发方 | 自家 app 交互式运行 | 第三方 webhook |
|
|
189
|
+
| 进度 | 轮询 `fleet.get(runId)` | 流式 `/ws/execution/:task_id`(`FlowRun`)或轮询 `tasks.get(id)` / 事件 `tasks.events(id)` |
|
|
190
|
+
| 控制 | `cancel` / `pause` / `resume` | `tasks.cancel(id)`(v1:DB 侧取消未完成 target) |
|
|
191
|
+
|
|
192
|
+
## AI(生成 / 精炼 / 解释)
|
|
193
|
+
|
|
194
|
+
LLM 由后端网关代理(OpenAI 兼容),developer scope。
|
|
195
|
+
|
|
196
|
+
```ts
|
|
197
|
+
const { flow } = await client.llm.generate({ prompt: '写一个登录流程', platform: 'android' })
|
|
198
|
+
const refined = await client.llm.refine({ flow, instruction: '登录后再点设置' }) // → { ok, flow? }
|
|
199
|
+
const { explanation } = await client.llm.explain(flow) // → 自然语言说明
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
React:`useLlm()` → `{ generate, refine, explain, test }`(参考实现见 frontend 的 `AIPanel`)。
|
|
203
|
+
|
|
204
|
+
## 镜像
|
|
205
|
+
|
|
206
|
+
```ts
|
|
207
|
+
import { MirrorSession } from 'aixautots/core'
|
|
208
|
+
const s = await MirrorSession.join(cfg, deviceId)
|
|
209
|
+
s.onStream((stream) => { videoEl.srcObject = stream })
|
|
210
|
+
s.sendInput({ t: 'tap', x, y }) // 归一坐标 [0,1]
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
React:`useMirror(deviceId)` → `{ stream, sendInput }`;UI:`<MirrorView>` + `<ControlBar>`。
|
|
214
|
+
|
|
215
|
+
## 错误
|
|
216
|
+
|
|
217
|
+
所有失败抛 `AixError`(含网络层失败,`code: 'offline'`)。按 `code` 区分:
|
|
218
|
+
`auth` / `timeout` / `offline` / `locked` / `protocol` / `unknown`。
|
|
219
|
+
|
|
220
|
+
## 参考实现 & 规划
|
|
221
|
+
|
|
222
|
+
- 参考实现:`frontend/`(Tauri 桌面控制台,全量消费本 SDK)。
|
|
223
|
+
- 规划与契约:`docs/superpowers/plans/2026-06-07-aixautots-full-client-sdk.md`。
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { createContext, createElement, useContext } from 'react';
|
|
2
|
+
|
|
3
|
+
// src/ui/nav/index.ts
|
|
4
|
+
var NavContext = createContext(null);
|
|
5
|
+
function AixNavProvider({ nav, children }) {
|
|
6
|
+
return createElement(NavContext.Provider, { value: nav }, children);
|
|
7
|
+
}
|
|
8
|
+
function useAixNav() {
|
|
9
|
+
const nav = useContext(NavContext);
|
|
10
|
+
if (nav) return nav;
|
|
11
|
+
return {
|
|
12
|
+
navigate: (to) => {
|
|
13
|
+
console.warn(`[aixautots] useAixNav(): no <AixNavProvider>; navigate(${to}) ignored`);
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export { AixNavProvider, useAixNav };
|