android-midscene-automation 0.1.24 → 0.1.26
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 +15 -5
- package/README.md +15 -5
- package/package.json +1 -1
- package/server/http-api.ts +141 -105
- package/server/script-agent.ts +50 -45
- package/src/App.vue +133 -54
- package/src/api.ts +15 -10
- package/src/appium-recorder/AppiumPage.vue +156 -55
- package/src/appium-recorder/components/FlowCanvas.vue +2 -2
- package/src/appium-recorder/components/FlowStepEditor.vue +93 -3
- package/src/appium-recorder/components/NestedConditionBranches.vue +6 -0
- package/src/appium-recorder/flow-copy.ts +49 -18
- package/src/appium-recorder/flow-graph.ts +3 -2
- package/src/appium-recorder/flow-labels.ts +4 -1
- package/src/config/prompt-example.ts +4 -0
- package/src/config/prompt-presets.ts +172 -0
- package/src/pages/AiGeneratorPage.vue +188 -5
- package/src/pages/AutomationPage.vue +3 -3
- package/src/pages/ConfigPage.vue +13 -35
- package/src/pages/GeneratorPage.vue +7 -0
- package/src/style.css +108 -139
- package/src/types.ts +0 -14
- package/server/model-call-usage-importer.ts +0 -108
- package/server/model-usage-repository.ts +0 -131
- package/src/components/config/ModelUsageChart.vue +0 -188
|
@@ -1,188 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
import { computed } from 'vue';
|
|
3
|
-
import type { ModelUsageRecord } from '../../types';
|
|
4
|
-
|
|
5
|
-
const CHART_WIDTH = 720;
|
|
6
|
-
const CHART_HEIGHT = 180;
|
|
7
|
-
const CHART_PADDING = 28;
|
|
8
|
-
|
|
9
|
-
const props = defineProps<{
|
|
10
|
-
records: ModelUsageRecord[];
|
|
11
|
-
}>();
|
|
12
|
-
|
|
13
|
-
type ChartPoint = {
|
|
14
|
-
x: number;
|
|
15
|
-
y: number;
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
const recentRecords = computed(() => props.records.slice(-20));
|
|
19
|
-
const displayRecords = computed(() => recentRecords.value.slice().reverse());
|
|
20
|
-
const latestRecord = computed(() => recentRecords.value[recentRecords.value.length - 1]);
|
|
21
|
-
const tokenRecords = computed(() =>
|
|
22
|
-
recentRecords.value.filter((record) => typeof record.totalTokens === 'number'),
|
|
23
|
-
);
|
|
24
|
-
|
|
25
|
-
const maxDurationMs = computed(() =>
|
|
26
|
-
Math.max(1, ...recentRecords.value.map((record) => record.durationMs)),
|
|
27
|
-
);
|
|
28
|
-
|
|
29
|
-
const maxTotalTokens = computed(() =>
|
|
30
|
-
Math.max(
|
|
31
|
-
1,
|
|
32
|
-
...tokenRecords.value.flatMap((record) => [
|
|
33
|
-
record.promptTokens || 0,
|
|
34
|
-
record.completionTokens || 0,
|
|
35
|
-
record.totalTokens || 0,
|
|
36
|
-
]),
|
|
37
|
-
),
|
|
38
|
-
);
|
|
39
|
-
|
|
40
|
-
const buildPoints = (records: ModelUsageRecord[], valueOf: (record: ModelUsageRecord) => number, maxValue: number) => {
|
|
41
|
-
const plotWidth = CHART_WIDTH - CHART_PADDING * 2;
|
|
42
|
-
const plotHeight = CHART_HEIGHT - CHART_PADDING * 2;
|
|
43
|
-
return records.map<ChartPoint>((record, index) => {
|
|
44
|
-
const count = Math.max(1, records.length - 1);
|
|
45
|
-
return {
|
|
46
|
-
x: CHART_PADDING + (plotWidth * index) / count,
|
|
47
|
-
y: CHART_HEIGHT - CHART_PADDING - (plotHeight * valueOf(record)) / maxValue,
|
|
48
|
-
};
|
|
49
|
-
});
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
const durationPoints = computed(() =>
|
|
53
|
-
buildPoints(recentRecords.value, (record) => record.durationMs, maxDurationMs.value),
|
|
54
|
-
);
|
|
55
|
-
|
|
56
|
-
const promptTokenPoints = computed(() =>
|
|
57
|
-
buildPoints(tokenRecords.value, (record) => record.promptTokens || 0, maxTotalTokens.value),
|
|
58
|
-
);
|
|
59
|
-
|
|
60
|
-
const completionTokenPoints = computed(() =>
|
|
61
|
-
buildPoints(tokenRecords.value, (record) => record.completionTokens || 0, maxTotalTokens.value),
|
|
62
|
-
);
|
|
63
|
-
|
|
64
|
-
const toPolyline = (points: ChartPoint[]) =>
|
|
65
|
-
points.map((point) => `${point.x.toFixed(1)},${point.y.toFixed(1)}`).join(' ');
|
|
66
|
-
|
|
67
|
-
const durationPolyline = computed(() => toPolyline(durationPoints.value));
|
|
68
|
-
const promptTokenPolyline = computed(() => toPolyline(promptTokenPoints.value));
|
|
69
|
-
const completionTokenPolyline = computed(() => toPolyline(completionTokenPoints.value));
|
|
70
|
-
|
|
71
|
-
const tokenLabel = (value?: number) => (typeof value === 'number' ? String(value) : '未返回');
|
|
72
|
-
|
|
73
|
-
const formatTime = (isoTime: string) =>
|
|
74
|
-
new Intl.DateTimeFormat('zh-CN', {
|
|
75
|
-
hour: '2-digit',
|
|
76
|
-
minute: '2-digit',
|
|
77
|
-
second: '2-digit',
|
|
78
|
-
}).format(new Date(isoTime));
|
|
79
|
-
</script>
|
|
80
|
-
|
|
81
|
-
<template>
|
|
82
|
-
<section class="model-usage-chart">
|
|
83
|
-
<div class="panel-header panel-header--sub">
|
|
84
|
-
<div class="panel-header__title">
|
|
85
|
-
<span>测试消耗统计</span>
|
|
86
|
-
</div>
|
|
87
|
-
</div>
|
|
88
|
-
|
|
89
|
-
<div v-if="recentRecords.length" class="model-usage-chart__body">
|
|
90
|
-
<div class="model-usage-chart__summary">
|
|
91
|
-
<span>最近 {{ recentRecords.length }} 次</span>
|
|
92
|
-
<span>最新耗时 {{ latestRecord?.durationMs || 0 }}ms</span>
|
|
93
|
-
<span>输入 {{ tokenLabel(latestRecord?.promptTokens) }}</span>
|
|
94
|
-
<span>输出 {{ tokenLabel(latestRecord?.completionTokens) }}</span>
|
|
95
|
-
<span>总计 {{ tokenLabel(latestRecord?.totalTokens) }}</span>
|
|
96
|
-
</div>
|
|
97
|
-
|
|
98
|
-
<svg
|
|
99
|
-
class="model-usage-chart__svg"
|
|
100
|
-
:viewBox="`0 0 ${CHART_WIDTH} ${CHART_HEIGHT}`"
|
|
101
|
-
role="img"
|
|
102
|
-
aria-label="测试模型消耗统计曲线"
|
|
103
|
-
>
|
|
104
|
-
<line
|
|
105
|
-
:x1="CHART_PADDING"
|
|
106
|
-
:y1="CHART_HEIGHT - CHART_PADDING"
|
|
107
|
-
:x2="CHART_WIDTH - CHART_PADDING"
|
|
108
|
-
:y2="CHART_HEIGHT - CHART_PADDING"
|
|
109
|
-
class="model-usage-chart__axis"
|
|
110
|
-
/>
|
|
111
|
-
<line
|
|
112
|
-
:x1="CHART_PADDING"
|
|
113
|
-
:y1="CHART_PADDING"
|
|
114
|
-
:x2="CHART_PADDING"
|
|
115
|
-
:y2="CHART_HEIGHT - CHART_PADDING"
|
|
116
|
-
class="model-usage-chart__axis"
|
|
117
|
-
/>
|
|
118
|
-
<polyline
|
|
119
|
-
v-if="promptTokenPolyline"
|
|
120
|
-
:points="promptTokenPolyline"
|
|
121
|
-
class="model-usage-chart__line model-usage-chart__line--prompt"
|
|
122
|
-
/>
|
|
123
|
-
<polyline
|
|
124
|
-
v-if="completionTokenPolyline"
|
|
125
|
-
:points="completionTokenPolyline"
|
|
126
|
-
class="model-usage-chart__line model-usage-chart__line--completion"
|
|
127
|
-
/>
|
|
128
|
-
<polyline
|
|
129
|
-
:points="durationPolyline"
|
|
130
|
-
class="model-usage-chart__line model-usage-chart__line--duration"
|
|
131
|
-
/>
|
|
132
|
-
<circle
|
|
133
|
-
v-for="point in promptTokenPoints"
|
|
134
|
-
:key="`prompt-${point.x}-${point.y}`"
|
|
135
|
-
:cx="point.x"
|
|
136
|
-
:cy="point.y"
|
|
137
|
-
r="3"
|
|
138
|
-
class="model-usage-chart__point model-usage-chart__point--prompt"
|
|
139
|
-
/>
|
|
140
|
-
<circle
|
|
141
|
-
v-for="point in completionTokenPoints"
|
|
142
|
-
:key="`completion-${point.x}-${point.y}`"
|
|
143
|
-
:cx="point.x"
|
|
144
|
-
:cy="point.y"
|
|
145
|
-
r="3"
|
|
146
|
-
class="model-usage-chart__point model-usage-chart__point--completion"
|
|
147
|
-
/>
|
|
148
|
-
<circle
|
|
149
|
-
v-for="point in durationPoints"
|
|
150
|
-
:key="`duration-${point.x}-${point.y}`"
|
|
151
|
-
:cx="point.x"
|
|
152
|
-
:cy="point.y"
|
|
153
|
-
r="3"
|
|
154
|
-
class="model-usage-chart__point model-usage-chart__point--duration"
|
|
155
|
-
/>
|
|
156
|
-
</svg>
|
|
157
|
-
|
|
158
|
-
<div class="model-usage-chart__legend">
|
|
159
|
-
<span><i class="model-usage-chart__swatch model-usage-chart__swatch--prompt"></i>输入 tokens</span>
|
|
160
|
-
<span><i class="model-usage-chart__swatch model-usage-chart__swatch--completion"></i>输出 tokens</span>
|
|
161
|
-
<span><i class="model-usage-chart__swatch model-usage-chart__swatch--duration"></i>耗时 ms</span>
|
|
162
|
-
</div>
|
|
163
|
-
|
|
164
|
-
<div class="model-usage-chart__records">
|
|
165
|
-
<div class="model-usage-chart__record model-usage-chart__record--head">
|
|
166
|
-
<span>时间</span>
|
|
167
|
-
<span>状态</span>
|
|
168
|
-
<span>模型</span>
|
|
169
|
-
<span>输入</span>
|
|
170
|
-
<span>输出</span>
|
|
171
|
-
<span>总计</span>
|
|
172
|
-
<span>耗时</span>
|
|
173
|
-
</div>
|
|
174
|
-
<div v-for="record in displayRecords" :key="record.id" class="model-usage-chart__record">
|
|
175
|
-
<span>{{ formatTime(record.createdAt) }}</span>
|
|
176
|
-
<span>{{ record.success ? '成功' : '失败' }}</span>
|
|
177
|
-
<span>{{ record.modelName }}</span>
|
|
178
|
-
<span>{{ tokenLabel(record.promptTokens) }}</span>
|
|
179
|
-
<span>{{ tokenLabel(record.completionTokens) }}</span>
|
|
180
|
-
<span>{{ tokenLabel(record.totalTokens) }}</span>
|
|
181
|
-
<span>{{ record.durationMs }}ms</span>
|
|
182
|
-
</div>
|
|
183
|
-
</div>
|
|
184
|
-
</div>
|
|
185
|
-
|
|
186
|
-
<el-empty v-else description="测试 AI 生成模型或生成脚本后显示消耗曲线" />
|
|
187
|
-
</section>
|
|
188
|
-
</template>
|