@aixnn/aixautots 0.0.0-stage → 0.5.2
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 +239 -2
- package/dist/ScriptStudio-DaCqOF5H.d.ts +43 -0
- package/dist/agent-runner-V60B0is1.d.ts +57 -0
- package/dist/automation-queue-8HqRJV_K.d.ts +72 -0
- package/dist/chunk-536WVCTB.js +5744 -0
- package/dist/chunk-5BMFMDQR.js +18 -0
- package/dist/chunk-64Q7BBIQ.js +1347 -0
- package/dist/chunk-6YUAACW6.js +866 -0
- package/dist/chunk-AIUOLJZA.js +412 -0
- package/dist/chunk-CVV7FOMQ.js +175 -0
- package/dist/chunk-EHF2WQUR.js +2042 -0
- package/dist/chunk-EVHTAXQG.js +273 -0
- package/dist/chunk-FW23FLAF.js +56 -0
- package/dist/chunk-GKEPMDXO.js +410 -0
- package/dist/chunk-H7MHGYF3.js +341 -0
- package/dist/chunk-MRQ7VJFJ.js +1074 -0
- package/dist/chunk-NWFYTFMI.js +65 -0
- package/dist/chunk-OEZFYKL6.js +1 -0
- package/dist/chunk-PCYERBNZ.js +1564 -0
- package/dist/chunk-PUPVZRKZ.js +668 -0
- package/dist/chunk-SUKFJ73W.js +217 -0
- package/dist/config-Bm1hmXhD.d.ts +1380 -0
- package/dist/coords-LPR_MPyp.d.ts +22 -0
- package/dist/core/index.d.ts +135 -0
- package/dist/core/index.js +5 -0
- package/dist/device-normalize-BaThgnH7.d.ts +43 -0
- package/dist/device-session-KZVGLPOI.js +2 -0
- package/dist/i18n/index.d.ts +30 -0
- package/dist/i18n/index.js +1 -0
- package/dist/mirror-session-C_1vFkRV.d.ts +108 -0
- package/dist/nav/index.d.ts +19 -0
- package/dist/nav/index.js +1 -0
- package/dist/react/index.d.ts +487 -0
- package/dist/react/index.js +7 -0
- package/dist/script-debugger-Cw5jVRoz.d.ts +114 -0
- package/dist/task-agent-runner-eD9-SCJz.d.ts +160 -0
- package/dist/types-C2WXVcam.d.ts +1005 -0
- package/dist/ui/billing.d.ts +48 -0
- package/dist/ui/billing.js +425 -0
- package/dist/ui/device-create.d.ts +55 -0
- package/dist/ui/device-create.js +9 -0
- package/dist/ui/device-mirror.d.ts +42 -0
- package/dist/ui/device-mirror.js +10 -0
- package/dist/ui/devices.d.ts +223 -0
- package/dist/ui/devices.js +15 -0
- package/dist/ui/editor.d.ts +64 -0
- package/dist/ui/editor.js +344 -0
- package/dist/ui/index.d.ts +104 -0
- package/dist/ui/index.js +676 -0
- package/dist/ui/inspector.d.ts +5 -0
- package/dist/ui/inspector.js +1250 -0
- package/dist/ui/market.d.ts +10 -0
- package/dist/ui/market.js +60 -0
- package/dist/ui/mirror.d.ts +52 -0
- package/dist/ui/mirror.js +3 -0
- package/dist/ui/primitives/index.d.ts +101 -0
- package/dist/ui/primitives/index.js +1 -0
- package/dist/ui/script-studio.d.ts +85 -0
- package/dist/ui/script-studio.js +10 -0
- package/dist/ui/scripts.d.ts +18 -0
- package/dist/ui/scripts.js +210 -0
- package/dist/ui/tasks.d.ts +10 -0
- package/dist/ui/tasks.js +1039 -0
- package/dist/use-script-run-Diay7ibY.d.ts +50 -0
- package/package.json +76 -4
- package/styles.css +97 -0
- package/tailwind-preset.cjs +84 -0
package/README.md
CHANGED
|
@@ -1,3 +1,240 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @aixnn/aixautots
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
发布包已迁移到 npm 用户 `aixnn` 的 scope,完整包名为 `@aixnn/aixautots`。本仓库目录仍为 `aixautots/`,各子包入口保持不变,例如 `@aixnn/aixautots/core`。
|
|
4
|
+
|
|
5
|
+
```sh
|
|
6
|
+
npm install @aixnn/aixautots
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
发布(在 `aixautots/` 目录,使用有权限的 npm 账号):
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
npm run typecheck
|
|
13
|
+
npm test
|
|
14
|
+
npm run build
|
|
15
|
+
python3 ../scripts/npm-with-access-key.py publish --access public
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
发布脚本读取 `~/.aixenv` 的 `NPM_ACCESS_KEY`,通过临时 npm 配置使用令牌,结束后删除临时配置,不修改全局登录配置。令牌需拥有 `@aixnn/aixautots` 的发布权限;第三方项目也可使用自身 npm 凭据执行 `npm publish --access public`。若令牌未允许绕过双重验证,npm 仍可能要求一次性验证码。
|
|
19
|
+
|
|
20
|
+
aixautobot 的 TypeScript 客户端 SDK。core/react 是 headless 的数据/传输/鉴权层;ui 既提供细粒度
|
|
21
|
+
部件,也提供**开箱即用的成品页面**(设备/任务/市场/脚本/编辑器/检查器)+ 一套可换肤主题,
|
|
22
|
+
让任意项目都能"轻松接入"。桌面端 `frontend/` 是全量改用本 SDK 的参考实现。
|
|
23
|
+
|
|
24
|
+
子路径导出:
|
|
25
|
+
|
|
26
|
+
| 子包 | 职责 |
|
|
27
|
+
|---|---|
|
|
28
|
+
| `@aixnn/aixautots/core` | 资源 REST 客户端(`AixClient`)+ 会话层(设备通道 / Flow / 镜像)+ 类型 + 错误 |
|
|
29
|
+
| `@aixnn/aixautots/react` | 上述能力的 React hooks(`AixProvider` + 资源/会话 hooks) |
|
|
30
|
+
| `@aixnn/aixautots/ui` | 设备向细粒度部件(`MirrorView`/`ControlBar`/`ScriptEditor`/`DebugConsole`/`ScriptPanel`) |
|
|
31
|
+
| `@aixnn/aixautots/ui/primitives` | 基础件(`Button`/`Input`/`Select`/`Badge`/`Dialog`/`Popover`) |
|
|
32
|
+
| `@aixnn/aixautots/ui/{devices,tasks,market,scripts,editor,inspector}` | 成品页面组件 |
|
|
33
|
+
| `@aixnn/aixautots/nav` | 路由无关导航注入(`AixNavProvider`/`useAixNav`) |
|
|
34
|
+
| `@aixnn/aixautots/i18n` | 内置 i18n(`AixI18nProvider`/`useAixT`,en/zh,无 i18next 依赖) |
|
|
35
|
+
| `@aixnn/aixautots/tailwind-preset` · `@aixnn/aixautots/styles.css` | Tailwind 预设 + 主题 token |
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
npm i @aixnn/aixautots # peer: react(react 子包用);ui 子包另需 @uiw/react-codemirror
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## 接入(三步)
|
|
42
|
+
|
|
43
|
+
用到 `@aixnn/aixautots/ui` 的成品页面/部件时,按以下三步接入样式与运行时上下文:
|
|
44
|
+
|
|
45
|
+
**1) 样式** —— Tailwind 预设 + 主题 token + content 扫描:
|
|
46
|
+
|
|
47
|
+
```js
|
|
48
|
+
// tailwind.config.js
|
|
49
|
+
module.exports = {
|
|
50
|
+
presets: [require('@aixnn/aixautots/tailwind-preset')],
|
|
51
|
+
content: [
|
|
52
|
+
'./src/**/*.{ts,tsx}',
|
|
53
|
+
'./node_modules/@aixnn/aixautots/dist/**/*.js', // 关键:否则 aixautots 组件的类名不会被生成
|
|
54
|
+
],
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
```css
|
|
59
|
+
/* 入口 CSS */
|
|
60
|
+
@import "@aixnn/aixautots/styles.css"; /* :root 浅色 + .dark 深色 token,可覆盖换肤 */
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
**2) Provider** —— 在 `AixProvider` 内注入导航与语言:
|
|
64
|
+
|
|
65
|
+
```tsx
|
|
66
|
+
import { AixProvider } from '@aixnn/aixautots/react'
|
|
67
|
+
import { AixNavProvider } from '@aixnn/aixautots/nav'
|
|
68
|
+
import { AixI18nProvider } from '@aixnn/aixautots/i18n'
|
|
69
|
+
import { useNavigate } from 'react-router-dom' // 任意路由库都行
|
|
70
|
+
|
|
71
|
+
function Providers({ children }) {
|
|
72
|
+
const navigate = useNavigate()
|
|
73
|
+
return (
|
|
74
|
+
<AixProvider config={{ baseUrl, auth }}>
|
|
75
|
+
<AixNavProvider nav={{ navigate }}>
|
|
76
|
+
<AixI18nProvider lang="zh">{children}</AixI18nProvider>
|
|
77
|
+
</AixProvider>
|
|
78
|
+
</AixNavProvider>
|
|
79
|
+
)
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
**3) 用页面** —— 直接挂成品页面,路由参数以 props 传入:
|
|
84
|
+
|
|
85
|
+
```tsx
|
|
86
|
+
import { DevicesPage } from '@aixnn/aixautots/ui/devices'
|
|
87
|
+
import { ScriptEditorPage } from '@aixnn/aixautots/ui/editor'
|
|
88
|
+
|
|
89
|
+
<DevicesPage />
|
|
90
|
+
<ScriptEditorPage scriptId={params.id} />
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Quickstart
|
|
94
|
+
|
|
95
|
+
```ts
|
|
96
|
+
import { AixClient } from '@aixnn/aixautots/core'
|
|
97
|
+
|
|
98
|
+
const client = new AixClient({
|
|
99
|
+
baseUrl: 'https://aixautobot.com',
|
|
100
|
+
auth: { kind: 'user', getToken: async () => myUserJwt },
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
const devices = await client.devices.list()
|
|
104
|
+
const { run_id } = await client.fleet.start({ flow, device_ids: [devices[0].id] })
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
React:
|
|
108
|
+
|
|
109
|
+
```tsx
|
|
110
|
+
import { AixProvider, useDevices } from '@aixnn/aixautots/react'
|
|
111
|
+
|
|
112
|
+
function App() {
|
|
113
|
+
return (
|
|
114
|
+
<AixProvider config={{ baseUrl, auth: { kind: 'user', getToken } }}>
|
|
115
|
+
<DeviceList />
|
|
116
|
+
</AixProvider>
|
|
117
|
+
)
|
|
118
|
+
}
|
|
119
|
+
function DeviceList() {
|
|
120
|
+
const { data, loading, refetch } = useDevices()
|
|
121
|
+
// ...
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## 鉴权
|
|
126
|
+
|
|
127
|
+
`AixConfig.auth` 接受单个或多个凭据;SDK 按请求 **scope** 自动选用并注入请求头。**浏览器只需 bearer 或
|
|
128
|
+
project key/secret——不需要、也不应携带网关 `X-API-Key`**(后端 `require_principal` 已放行任一有效主体)。
|
|
129
|
+
|
|
130
|
+
```ts
|
|
131
|
+
type Credential =
|
|
132
|
+
| { kind: 'project'; key: string; secret: string } // 第三方:X-Project-Key / X-Project-Secret
|
|
133
|
+
| { kind: 'user'; getToken: () => string | Promise<string> } // 自家前端:user JWT
|
|
134
|
+
| { kind: 'developer'; getToken: () => string | Promise<string> } // 项目管理 / 平台管理
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
| Scope | 用到的凭据 | 覆盖的资源 |
|
|
138
|
+
|---|---|---|
|
|
139
|
+
| `caller` | project key/secret **或** user JWT | devices / scripts / clusters / fleet / tasks / locators / nodes |
|
|
140
|
+
| `developer` | developer JWT | projects / auth 管理 / webhooks / llm |
|
|
141
|
+
| `admin` | developer JWT(后端校验 admin) | admin(rate/plan/billing)/ images |
|
|
142
|
+
| `public` | 无 | auth.login / register / send-code / verify-code |
|
|
143
|
+
|
|
144
|
+
多凭据示例(自家前端同时持 developer + user):
|
|
145
|
+
|
|
146
|
+
```ts
|
|
147
|
+
auth: [
|
|
148
|
+
{ kind: 'user', getToken: currentUserToken }, // caller 资源用
|
|
149
|
+
{ kind: 'developer', getToken: () => devJwt }, // developer/admin 资源用
|
|
150
|
+
]
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
第三方前端(浏览器不持 project secret):后端铸 user JWT,前端用 `createCachedUserCredential` 自动缓存/刷新(按 `expiresIn` 或 JWT `exp`,并发去重):
|
|
154
|
+
|
|
155
|
+
```ts
|
|
156
|
+
import { createCachedUserCredential } from '@aixnn/aixautots/core'
|
|
157
|
+
|
|
158
|
+
const auth = createCachedUserCredential({
|
|
159
|
+
mint: () => fetch('/mint-token').then((r) => r.json()), // 你的后端 → { token, expiresIn? } 或 token 字符串
|
|
160
|
+
})
|
|
161
|
+
new AixClient({ baseUrl, auth })
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
> 兼容旧写法:`getAuthToken: () => userJwt` 等价于 `auth: { kind: 'user', getToken }`。
|
|
165
|
+
|
|
166
|
+
## 资源总览(`AixClient` + hooks)
|
|
167
|
+
|
|
168
|
+
| 资源 | `client.*` | React hook |
|
|
169
|
+
|---|---|---|
|
|
170
|
+
| 鉴权 | `auth` | `useAuth` |
|
|
171
|
+
| 项目 | `projects` | `useProjects` |
|
|
172
|
+
| 设备 | `devices` | `useDevices` / `useDeviceActions` |
|
|
173
|
+
| 节点 | `nodes` | `useNodes` |
|
|
174
|
+
| 集群 | `clusters` | `useClusters` |
|
|
175
|
+
| 脚本 | `scripts` | `useScripts` |
|
|
176
|
+
| 定位器 | `locators` | `useLocators` |
|
|
177
|
+
| Fleet 运行 | `fleet` | `useFleetRun` |
|
|
178
|
+
| Webhook 任务 | `tasks` | `useTasks` / `useTaskStatus` |
|
|
179
|
+
| Webhook 配置 | `webhooks` | `useWebhooks` |
|
|
180
|
+
| LLM | `llm` | `useLlm` |
|
|
181
|
+
| 管理/计费/镜像 | `admin` | `useAdmin` / `useImages` |
|
|
182
|
+
| 巡检(截图+UI树) | (`devices.op`) | `useInspector` |
|
|
183
|
+
|
|
184
|
+
## 设备操作:两条路径
|
|
185
|
+
|
|
186
|
+
| | REST `devices.op` | WS `DeviceChannel` |
|
|
187
|
+
|---|---|---|
|
|
188
|
+
| 形态 | 一次性、无状态 | 长连、低延迟 |
|
|
189
|
+
| 适用 | 截图 / UI 树 / 安装 / 电源 等 | adb / wda / frida / scriptlet 流式 + 原始隧道、重交互调试 |
|
|
190
|
+
| 入口 | `client.devices.op(id, { op, ... })` | `DeviceChannel.open(cfg, id)` |
|
|
191
|
+
|
|
192
|
+
**通用命令**:`devices.op(id, op)` 是唯一入口,`op` 类型为开放联合——已知命令有自动补全,
|
|
193
|
+
**任意新命令无需新 SDK 方法**直接透传。`screenshot()/captureUiTree()/installApkUrl()/power()` 等都是它的薄包装。
|
|
194
|
+
|
|
195
|
+
```ts
|
|
196
|
+
await client.devices.screenshot(id) // 薄糖
|
|
197
|
+
await client.devices.op(id, { op: 'some_future_op', x: 1 }) // 新命令零改动
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
## 运行 flow:两条链路
|
|
201
|
+
|
|
202
|
+
| | Fleet(`fleet` / `useFleetRun`) | Webhook 任务(`FlowRun` / `tasks` / `useTaskStatus`) |
|
|
203
|
+
|---|---|---|
|
|
204
|
+
| 端点 | `POST /api/fleet/runs` | `POST /api/webhook/tasks` |
|
|
205
|
+
| 触发方 | 自家 app 交互式运行 | 第三方 webhook |
|
|
206
|
+
| 进度 | 轮询 `fleet.get(runId)` | 流式 `/ws/execution/:task_id`(`FlowRun`)或轮询 `tasks.get(id)` / 事件 `tasks.events(id)` |
|
|
207
|
+
| 控制 | `cancel` / `pause` / `resume` | `tasks.cancel(id)`(v1:DB 侧取消未完成 target) |
|
|
208
|
+
|
|
209
|
+
## AI(生成 / 精炼 / 解释)
|
|
210
|
+
|
|
211
|
+
LLM 由后端网关代理(OpenAI 兼容),developer scope。
|
|
212
|
+
|
|
213
|
+
```ts
|
|
214
|
+
const { flow } = await client.llm.generate({ prompt: '写一个登录流程', platform: 'android' })
|
|
215
|
+
const refined = await client.llm.refine({ flow, instruction: '登录后再点设置' }) // → { ok, flow? }
|
|
216
|
+
const { explanation } = await client.llm.explain(flow) // → 自然语言说明
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
React:`useLlm()` → `{ generate, refine, explain, test }`(参考实现见 frontend 的 `AIPanel`)。
|
|
220
|
+
|
|
221
|
+
## 镜像
|
|
222
|
+
|
|
223
|
+
```ts
|
|
224
|
+
import { MirrorSession } from '@aixnn/aixautots/core'
|
|
225
|
+
const s = await MirrorSession.join(cfg, deviceId)
|
|
226
|
+
s.onStream((stream) => { videoEl.srcObject = stream })
|
|
227
|
+
s.sendInput({ t: 'tap', x, y }) // 归一坐标 [0,1]
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
React:`useMirror(deviceId)` → `{ stream, sendInput }`;UI:`<MirrorView>` + `<ControlBar>`。
|
|
231
|
+
|
|
232
|
+
## 错误
|
|
233
|
+
|
|
234
|
+
所有失败抛 `AixError`(含网络层失败,`code: 'offline'`)。按 `code` 区分:
|
|
235
|
+
`auth` / `timeout` / `offline` / `locked` / `protocol` / `unknown`。
|
|
236
|
+
|
|
237
|
+
## 参考实现 & 规划
|
|
238
|
+
|
|
239
|
+
- 参考实现:`frontend/`(Tauri 桌面控制台,全量消费本 SDK)。
|
|
240
|
+
- 规划与契约:`docs/superpowers/plans/2026-06-07-aixautots-full-client-sdk.md`。
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
/** Context handed to host-injected slots (agent / inspector). */
|
|
5
|
+
interface ScriptStudioSlotContext {
|
|
6
|
+
/** Persisted script id (undefined until first save). */
|
|
7
|
+
scriptId?: string;
|
|
8
|
+
/** Currently selected run device id. */
|
|
9
|
+
deviceId: string | null;
|
|
10
|
+
/** Resolved platform of the selected device ('android' | 'ios' | …). */
|
|
11
|
+
platform: 'android' | 'ios';
|
|
12
|
+
/** Current editor source. */
|
|
13
|
+
code: string;
|
|
14
|
+
/** Replace the entire editor source. */
|
|
15
|
+
setCode: (code: string) => void;
|
|
16
|
+
/** Append a snippet to the editor source (newline-separated). */
|
|
17
|
+
insertSnippet: (snippet: string) => void;
|
|
18
|
+
/** Open the host-injected device inspector (same as the header button). */
|
|
19
|
+
openInspector: () => void;
|
|
20
|
+
}
|
|
21
|
+
interface ScriptStudioProps {
|
|
22
|
+
/** Route param: the script to open. Undefined ⇒ a fresh "New Script". */
|
|
23
|
+
scriptId?: string;
|
|
24
|
+
/** Called after the first create assigns an id, so the host can switch the
|
|
25
|
+
* URL to `/editor/:id` (the SDK does not depend on a router). */
|
|
26
|
+
onScriptIdChange?: (id: string) => void;
|
|
27
|
+
/** Host-injected LLM agent panel (right column). Not rendered if omitted. */
|
|
28
|
+
renderAgentPanel?: (ctx: ScriptStudioSlotContext) => ReactNode;
|
|
29
|
+
/** Host-injected device inspector (modal/overlay). Not rendered if omitted.
|
|
30
|
+
* `open`/`onClose` are driven by the studio's "设备/Inspector" button. */
|
|
31
|
+
renderInspector?: (ctx: ScriptStudioSlotContext & {
|
|
32
|
+
open: boolean;
|
|
33
|
+
onClose: () => void;
|
|
34
|
+
}) => ReactNode;
|
|
35
|
+
/** localStorage key for the resizable console height. */
|
|
36
|
+
consoleHeightStorageKey?: string;
|
|
37
|
+
/** Extra controls rendered at the right end of the header (e.g. a language
|
|
38
|
+
* toggle). The studio itself stays app-chrome-agnostic. */
|
|
39
|
+
headerExtra?: ReactNode;
|
|
40
|
+
}
|
|
41
|
+
declare function ScriptStudio({ scriptId, onScriptIdChange, renderAgentPanel, renderInspector, consoleHeightStorageKey, headerExtra, }: ScriptStudioProps): react.JSX.Element;
|
|
42
|
+
|
|
43
|
+
export { type ScriptStudioProps as S, type ScriptStudioSlotContext as a, ScriptStudio as b };
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LLM agent 传输的注入接口。`AgentPanel` 的 UI 与可移植逻辑在 aixautots 内,但「如何
|
|
3
|
+
* 真正跑一个本地 agent」是宿主特有的(桌面端经 Tauri IPC spawn claude/codex CLI,
|
|
4
|
+
* 经事件流式回传)——所以这部分由宿主实现 `AgentRunner` 注入,aixautots 不依赖 Tauri。
|
|
5
|
+
*
|
|
6
|
+
* 非桌面/无本地 agent 的宿主可传 `available: false`,面板会显示「需在桌面应用中使用」。
|
|
7
|
+
*
|
|
8
|
+
* ── 实现是可替换的:Tauri 只是其中一种 ──
|
|
9
|
+
* 本接口刻意与传输解耦,`AgentPanel` 不知底层是本机还是服务端。已有/可有的实现:
|
|
10
|
+
* 1) 本机 CLI(现状):桌面端 `frontend/src/lib/agentRunner.ts` 用 Tauri `invoke`/`listen`
|
|
11
|
+
* spawn 本机 claude/codex CLI(密钥/算力在用户机器)。
|
|
12
|
+
* 2) 服务端 agent:服务器跑 claude/codex CLI(密钥/算力在后端),HTTP 起停 + SSE 流式
|
|
13
|
+
* 回传。**SDK 已内置实现** `createBackendAgentRunner(client)`(见 `backend-agent-runner.ts`);
|
|
14
|
+
* editor 薄壳按环境切换即可,aixautots 与 AgentPanel 零改动:
|
|
15
|
+
* agentRunner={isTauri() ? tauriAgentRunner : createBackendAgentRunner(client)}
|
|
16
|
+
* (仅待后端落地 `/api/agent/*` 端点;客户端侧已就绪。)
|
|
17
|
+
*
|
|
18
|
+
* 后端端点契约(详见 `backend-agent-runner.ts`):`POST /api/agent/{start,send,stop}` +
|
|
19
|
+
* `GET /api/agent/stream`(SSE);事件载荷映射到本文件的 `AgentStreamEvent`
|
|
20
|
+
* (`stream: 'stdout'|'stderr'|'done'`,done 带最终 `script` 全文)。鉴权复用 user JWT。
|
|
21
|
+
* 失败可经 `stream:'stderr'` 文本上报,或 `done` 不带 `script` 表示无产出。
|
|
22
|
+
*/
|
|
23
|
+
type AgentKind = 'claude' | 'codex';
|
|
24
|
+
interface AgentStreamEvent {
|
|
25
|
+
/** 该事件所属脚本 id(面板按当前 scriptId 过滤)。 */
|
|
26
|
+
scriptId: string;
|
|
27
|
+
stream: 'stdout' | 'stderr' | 'done';
|
|
28
|
+
/** stdout/stderr 增量文本。 */
|
|
29
|
+
chunk?: string;
|
|
30
|
+
/** done 时回带的最终 script.ts 全文(非空且有变化则替换编辑器)。 */
|
|
31
|
+
script?: string;
|
|
32
|
+
}
|
|
33
|
+
interface AgentSendRequest {
|
|
34
|
+
agent: AgentKind;
|
|
35
|
+
scriptId: string;
|
|
36
|
+
code: string;
|
|
37
|
+
deviceId: string;
|
|
38
|
+
userMsg: string;
|
|
39
|
+
/** 本轮是否是会话首轮(决定 start vs send 语义,由实现自行处理)。 */
|
|
40
|
+
isFirst: boolean;
|
|
41
|
+
}
|
|
42
|
+
interface AgentRunner {
|
|
43
|
+
/** 本机 agent 后端是否可用(如桌面/Tauri 环境)。false 时面板显示提示而不渲染交互。 */
|
|
44
|
+
available: boolean;
|
|
45
|
+
/** 可选:从宿主设置读默认 agent / 权限模式(面板挂载时调用)。 */
|
|
46
|
+
defaults?: () => Promise<{
|
|
47
|
+
agent?: AgentKind;
|
|
48
|
+
}>;
|
|
49
|
+
/** 启动或继续一轮 agent。权限模式等宿主细节由实现内部处理。 */
|
|
50
|
+
send: (req: AgentSendRequest) => Promise<void>;
|
|
51
|
+
/** 停止进行中的一轮。 */
|
|
52
|
+
stop: (scriptId: string) => Promise<void>;
|
|
53
|
+
/** 订阅流式输出;返回取消订阅函数。面板内部按 scriptId 过滤事件。 */
|
|
54
|
+
subscribe: (on: (ev: AgentStreamEvent) => void) => () => void;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export type { AgentKind as A, AgentRunner as a, AgentSendRequest as b, AgentStreamEvent as c };
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { a as RunEventKind, A as AixConfig, R as ResolvedConfig } from './config-Bm1hmXhD.js';
|
|
2
|
+
import { S as Script } from './types-C2WXVcam.js';
|
|
3
|
+
|
|
4
|
+
interface FlowSubmit {
|
|
5
|
+
/** Inline flow JSON (XOR scriptId). */
|
|
6
|
+
flow?: unknown;
|
|
7
|
+
/** Reference a stored script by id (XOR flow). */
|
|
8
|
+
scriptId?: string;
|
|
9
|
+
/** Internal device UUIDs (non-empty). */
|
|
10
|
+
deviceIds: string[];
|
|
11
|
+
params?: unknown;
|
|
12
|
+
mode?: unknown;
|
|
13
|
+
expiresIn?: number;
|
|
14
|
+
}
|
|
15
|
+
/** A normalized per-device execution event. */
|
|
16
|
+
interface FlowEvent {
|
|
17
|
+
deviceId: string;
|
|
18
|
+
event: RunEventKind;
|
|
19
|
+
}
|
|
20
|
+
declare class FlowRun {
|
|
21
|
+
readonly taskId: string;
|
|
22
|
+
readonly targets: string[];
|
|
23
|
+
private readonly socket;
|
|
24
|
+
private readonly eventListeners;
|
|
25
|
+
private readonly doneListeners;
|
|
26
|
+
private readonly finished;
|
|
27
|
+
private doneFired;
|
|
28
|
+
private cursor;
|
|
29
|
+
private constructor();
|
|
30
|
+
static submit(cfg: AixConfig | ResolvedConfig, body: FlowSubmit): Promise<FlowRun>;
|
|
31
|
+
on(event: 'event', cb: (e: FlowEvent) => void): () => void;
|
|
32
|
+
on(event: 'done', cb: () => void): () => void;
|
|
33
|
+
/** Called (via microtask) when submit() returns targets:[]. */
|
|
34
|
+
fireDoneIfEmpty(): void;
|
|
35
|
+
private onMessage;
|
|
36
|
+
close(): void;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** 批次派发模式。`'round-robin'` 为默认(行分摊到设备);`'broadcast'` 每行全量。 */
|
|
40
|
+
type QueueMode = 'round-robin' | 'broadcast';
|
|
41
|
+
/** 一个批次的输入。`script` 与 `flow` 二选一(与 `FlowRun`/后端的 flow XOR
|
|
42
|
+
* script 约束一致)。`rows` 每项是一组动态参数值(覆写 `flow.variables`);空
|
|
43
|
+
* 数组等价于「无参数」单组(提交一次,沿用脚本自带 variables)。 */
|
|
44
|
+
interface BatchConfig {
|
|
45
|
+
/** 引用已存库脚本(XOR flow)。 */
|
|
46
|
+
script?: Pick<Script, 'id'> & {
|
|
47
|
+
id: string;
|
|
48
|
+
};
|
|
49
|
+
/** 内联 flow JSON(XOR script)。 */
|
|
50
|
+
flow?: unknown;
|
|
51
|
+
/** 每行 = 一组动态参数(如不同账户)。空 ⇒ 视作单组空参数,提交一次。 */
|
|
52
|
+
rows: Array<Record<string, unknown>>;
|
|
53
|
+
/** 目标设备内部 UUID(非空)。 */
|
|
54
|
+
deviceIds: string[];
|
|
55
|
+
/** 派发模式,默认 `'round-robin'`。 */
|
|
56
|
+
mode?: QueueMode;
|
|
57
|
+
/** 透传给 `FlowRun.submit` 的任务过期秒数(可选)。 */
|
|
58
|
+
expiresIn?: number;
|
|
59
|
+
}
|
|
60
|
+
/** 把 rows×mode 展开为多次 `FlowRun.submit`,返回每次提交得到的 task id 顺序数组。
|
|
61
|
+
* 逐行顺序提交(保留行序);任一行失败即抛出(已提交的行不回滚——它们是独立任务)。 */
|
|
62
|
+
declare function submitBatch(cfg: AixConfig | ResolvedConfig, config: BatchConfig): Promise<string[]>;
|
|
63
|
+
/** 自动化队列的薄封装:绑定一份 config,`submit(batch)` 即提交。无状态——
|
|
64
|
+
* 追踪/暂停/恢复由 `TasksApi`(`useAutomationQueue`)负责。 */
|
|
65
|
+
declare class AutomationQueue {
|
|
66
|
+
private readonly cfg;
|
|
67
|
+
constructor(cfg: AixConfig | ResolvedConfig);
|
|
68
|
+
/** 展开并提交一个批次,返回 task id 数组。见 [`submitBatch`]。 */
|
|
69
|
+
submit(config: BatchConfig): Promise<string[]>;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export { AutomationQueue as A, type BatchConfig as B, type FlowEvent as F, type QueueMode as Q, FlowRun as a, type FlowSubmit as b, submitBatch as s };
|