@autoglm.js/cli 0.0.1

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,167 @@
1
+ import { Box, Text } from "ink";
2
+ import { useTranslation } from "react-i18next";
3
+ import { useLocation } from "react-router";
4
+ import { jsx, jsxs } from "react/jsx-runtime";
5
+ import { ErrorCode } from "autoglm.js";
6
+
7
+ //#region src/components/HelpContent.tsx
8
+ function HelpSection({ title, items }) {
9
+ const { t } = useTranslation();
10
+ return /* @__PURE__ */ jsxs(Box, {
11
+ flexDirection: "column",
12
+ marginBottom: 2,
13
+ children: [/* @__PURE__ */ jsx(Box, {
14
+ marginBottom: 1,
15
+ children: /* @__PURE__ */ jsx(Text, {
16
+ color: "blue",
17
+ bold: true,
18
+ children: t(title)
19
+ })
20
+ }), items.map((item, index) => /* @__PURE__ */ jsxs(Box, {
21
+ flexDirection: "row",
22
+ marginBottom: 1,
23
+ children: [item.step && /* @__PURE__ */ jsx(Box, {
24
+ width: 4,
25
+ marginRight: 1,
26
+ children: /* @__PURE__ */ jsxs(Text, {
27
+ color: "yellow",
28
+ bold: true,
29
+ children: [item.step, "."]
30
+ })
31
+ }), /* @__PURE__ */ jsx(Box, {
32
+ flexGrow: 1,
33
+ children: /* @__PURE__ */ jsx(Text, {
34
+ color: item.important ? "yellow" : "white",
35
+ bold: item.important,
36
+ children: t(item.text)
37
+ })
38
+ })]
39
+ }, index))]
40
+ });
41
+ }
42
+ function HelpContent({ content }) {
43
+ const { t } = useTranslation();
44
+ return /* @__PURE__ */ jsxs(Box, {
45
+ flexDirection: "column",
46
+ paddingX: 2,
47
+ paddingY: 1,
48
+ children: [
49
+ /* @__PURE__ */ jsxs(Box, {
50
+ marginBottom: 2,
51
+ children: [/* @__PURE__ */ jsx(Text, {
52
+ color: content.titleColor || "red",
53
+ bold: true,
54
+ children: t(content.title)
55
+ }), content.errorCode && /* @__PURE__ */ jsxs(Text, {
56
+ color: "gray",
57
+ dimColor: true,
58
+ children: [
59
+ t("Error Code:"),
60
+ " ",
61
+ content.errorCode
62
+ ]
63
+ })]
64
+ }),
65
+ content.sections.map((section, index) => /* @__PURE__ */ jsx(HelpSection, {
66
+ title: section.title,
67
+ items: section.items
68
+ }, index)),
69
+ content.footer && /* @__PURE__ */ jsx(Box, {
70
+ marginTop: 2,
71
+ children: /* @__PURE__ */ jsx(Text, {
72
+ color: content.footer.color || "green",
73
+ bold: true,
74
+ children: t(content.footer.text)
75
+ })
76
+ })
77
+ ]
78
+ });
79
+ }
80
+
81
+ //#endregion
82
+ //#region src/config/helpContent.ts
83
+ const helpContentMap = { [ErrorCode.ADB_DEVICE_UNCONNECTED]: {
84
+ title: "help.adbDeviceUnconnected.title",
85
+ titleColor: "red",
86
+ errorCode: ErrorCode.ADB_DEVICE_UNCONNECTED,
87
+ sections: [
88
+ {
89
+ title: "help.adbDeviceUnconnected.problemDescription",
90
+ items: [{
91
+ text: "help.adbDeviceUnconnected.deviceUnconnected",
92
+ important: true
93
+ }, { text: "help.adbDeviceUnconnected.checkSteps" }]
94
+ },
95
+ {
96
+ title: "help.adbDeviceUnconnected.solution",
97
+ items: [
98
+ {
99
+ step: 1,
100
+ text: "help.adbDeviceUnconnected.ensureConnected",
101
+ important: true
102
+ },
103
+ {
104
+ step: 2,
105
+ text: "help.adbDeviceUnconnected.enableDeveloperOptions"
106
+ },
107
+ { text: "help.adbDeviceUnconnected.aboutPhone" },
108
+ { text: "help.adbDeviceUnconnected.tapVersion" },
109
+ {
110
+ step: 3,
111
+ text: "help.adbDeviceUnconnected.enableUsbDebugging"
112
+ },
113
+ { text: "help.adbDeviceUnconnected.developerOptions" },
114
+ { text: "help.adbDeviceUnconnected.turnOnUsbDebugging" },
115
+ {
116
+ step: 4,
117
+ text: "help.adbDeviceUnconnected.authorizeUsbDebugging"
118
+ },
119
+ { text: "help.adbDeviceUnconnected.allowUsbDebugging" },
120
+ { text: "help.adbDeviceUnconnected.alwaysAllow" },
121
+ {
122
+ step: 5,
123
+ text: "help.adbDeviceUnconnected.checkConnection"
124
+ },
125
+ { text: "help.adbDeviceUnconnected.reconnectUsb" },
126
+ { text: "help.adbDeviceUnconnected.fileTransferMode" }
127
+ ]
128
+ },
129
+ {
130
+ title: "help.adbDeviceUnconnected.commonIssues",
131
+ items: [
132
+ { text: "help.adbDeviceUnconnected.noUsbDebuggingOption" },
133
+ { text: "help.adbDeviceUnconnected.secureSettings" },
134
+ { text: "help.adbDeviceUnconnected.directConnection" },
135
+ { text: "help.adbDeviceUnconnected.dataCable" }
136
+ ]
137
+ }
138
+ ],
139
+ footer: {
140
+ text: "help.adbDeviceUnconnected.footer",
141
+ color: "green"
142
+ }
143
+ } };
144
+ const defaultHelpContent = {
145
+ title: "help.title",
146
+ titleColor: "blue",
147
+ sections: [{
148
+ title: "help.genericHelp",
149
+ items: [{ text: "help.noSpecificHelp" }, { text: "help.contactSupport" }]
150
+ }]
151
+ };
152
+
153
+ //#endregion
154
+ //#region src/pages/Help.tsx
155
+ function Help() {
156
+ const code = useLocation().state?.code;
157
+ const { t } = useTranslation();
158
+ const content = code ? helpContentMap[code] : null;
159
+ if (content) return /* @__PURE__ */ jsx(HelpContent, { content });
160
+ return /* @__PURE__ */ jsx(HelpContent, { content: {
161
+ ...defaultHelpContent,
162
+ errorCode: code ? t("help.noErrorCode", { code }) : void 0
163
+ } });
164
+ }
165
+
166
+ //#endregion
167
+ export { Help as default };
@@ -0,0 +1,71 @@
1
+ import { Box, Text } from "ink";
2
+ import { useTranslation } from "react-i18next";
3
+ import { jsx, jsxs } from "react/jsx-runtime";
4
+ import Spinner from "ink-spinner";
5
+
6
+ //#region src/pages/InstallKeyboard.tsx
7
+ function InstallKeyboard() {
8
+ const { t } = useTranslation();
9
+ return /* @__PURE__ */ jsxs(Box, {
10
+ flexDirection: "column",
11
+ alignItems: "center",
12
+ paddingY: 2,
13
+ children: [
14
+ /* @__PURE__ */ jsxs(Box, {
15
+ marginBottom: 2,
16
+ gap: 2,
17
+ alignItems: "center",
18
+ children: [/* @__PURE__ */ jsx(Spinner, { type: "dots" }), /* @__PURE__ */ jsx(Text, {
19
+ color: "cyan",
20
+ bold: true,
21
+ children: t("installKeyboard.title")
22
+ })]
23
+ }),
24
+ /* @__PURE__ */ jsx(Box, {
25
+ flexDirection: "column",
26
+ marginBottom: 2,
27
+ width: 60,
28
+ children: /* @__PURE__ */ jsx(Text, {
29
+ color: "gray",
30
+ children: t("installKeyboard.description")
31
+ })
32
+ }),
33
+ /* @__PURE__ */ jsxs(Box, {
34
+ flexDirection: "column",
35
+ width: 60,
36
+ children: [/* @__PURE__ */ jsx(Text, {
37
+ color: "yellow",
38
+ children: t("installKeyboard.confirmPrompt")
39
+ }), /* @__PURE__ */ jsx(Text, {
40
+ color: "gray",
41
+ dimColor: true,
42
+ children: t("installKeyboard.confirmHint")
43
+ })]
44
+ }),
45
+ /* @__PURE__ */ jsxs(Box, {
46
+ marginTop: 3,
47
+ flexDirection: "column",
48
+ width: 60,
49
+ children: [
50
+ /* @__PURE__ */ jsx(Text, {
51
+ color: "gray",
52
+ dimColor: true,
53
+ children: t("installKeyboard.manualInstall.hint")
54
+ }),
55
+ /* @__PURE__ */ jsx(Text, {
56
+ color: "blue",
57
+ children: t("installKeyboard.manualInstall.link")
58
+ }),
59
+ /* @__PURE__ */ jsx(Text, {
60
+ color: "gray",
61
+ dimColor: true,
62
+ children: t("installKeyboard.manualInstall.instruction")
63
+ })
64
+ ]
65
+ })
66
+ ]
67
+ });
68
+ }
69
+
70
+ //#endregion
71
+ export { InstallKeyboard as default };
@@ -0,0 +1,246 @@
1
+ import { i as EVENT_TYPE_LABELS, n as useUserInputStore, r as useAgentContext } from "./index.mjs";
2
+ import { Box, Text, useInput, useStdout } from "ink";
3
+ import { useTranslation } from "react-i18next";
4
+ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
5
+ import { jsx, jsxs } from "react/jsx-runtime";
6
+ import { EventType } from "autoglm.js";
7
+ import Spinner from "ink-spinner";
8
+ import { ScrollView } from "ink-scroll-view";
9
+
10
+ //#region src/hooks/useEventLog.ts
11
+ function useEventLog() {
12
+ const { events, isRunning, clearEvents } = useAgentContext();
13
+ const formattedEvents = useMemo(() => {
14
+ return events.map((event) => {
15
+ const typeInfo = EVENT_TYPE_LABELS[event.type] ?? {
16
+ label: event.type.toUpperCase(),
17
+ color: "white"
18
+ };
19
+ const data = formatEventData(event);
20
+ return {
21
+ type: event.type,
22
+ label: typeInfo.label,
23
+ color: typeInfo.color,
24
+ data,
25
+ time: event.time,
26
+ deviceId: event.deviceId
27
+ };
28
+ });
29
+ }, [events]);
30
+ return {
31
+ events: formattedEvents,
32
+ latestEvent: useMemo(() => {
33
+ if (events.length === 0) return null;
34
+ return formattedEvents[formattedEvents.length - 1];
35
+ }, [events, formattedEvents]),
36
+ hasEvents: events.length > 0 || isRunning,
37
+ clear: useCallback(() => {
38
+ clearEvents();
39
+ }, [clearEvents]),
40
+ eventCount: events.length
41
+ };
42
+ }
43
+ function formatEventData(event) {
44
+ const data = event.data?.message ?? event.data;
45
+ if (typeof data === "string") return data.trim();
46
+ if (data && typeof data === "object") {
47
+ const typedData = data;
48
+ return Object.entries({
49
+ action: (v) => String(v),
50
+ start: (v) => `: [${v}]`,
51
+ end: (v) => `-> [${v}]`,
52
+ app: (v) => `: ${v}`,
53
+ element: (v) => `: [${v}]`,
54
+ text: (v) => `: ${v}`,
55
+ duration: (v) => `: ${v}s`,
56
+ result: (v) => String(v)
57
+ }).filter(([key]) => typedData[key] != null).map(([key, format]) => format(typedData[key])).join("");
58
+ }
59
+ try {
60
+ return JSON.stringify(data);
61
+ } catch {
62
+ return String(data);
63
+ }
64
+ }
65
+
66
+ //#endregion
67
+ //#region src/components/EventLog.tsx
68
+ function EventList() {
69
+ const { t } = useTranslation();
70
+ const scrollRef = useRef(null);
71
+ const { stdout } = useStdout();
72
+ const { events } = useEventLog();
73
+ const { isCommand } = useUserInputStore();
74
+ let ScrollState = /* @__PURE__ */ function(ScrollState$1) {
75
+ ScrollState$1[ScrollState$1["AUTO_SCROLL"] = 0] = "AUTO_SCROLL";
76
+ ScrollState$1[ScrollState$1["USER_SCROLLED"] = 1] = "USER_SCROLLED";
77
+ return ScrollState$1;
78
+ }({});
79
+ const [scrollState, setScrollState] = useState(ScrollState.AUTO_SCROLL);
80
+ const mergedEvents = useMemo(() => {
81
+ const result = [];
82
+ for (const event of events) {
83
+ const preIndex = result.length - 1;
84
+ const previousEvent = result[preIndex];
85
+ if (event.type === EventType.THINKING_STREAM && result.length > 0 && previousEvent.type === EventType.THINKING_STREAM) result[preIndex] = {
86
+ ...result[preIndex],
87
+ data: result[preIndex].data + event.data
88
+ };
89
+ else result.push(event);
90
+ }
91
+ return result;
92
+ }, [events]);
93
+ useEffect(() => {
94
+ const handleResize = () => scrollRef.current?.remeasure();
95
+ stdout?.on("resize", handleResize);
96
+ return () => {
97
+ stdout?.off("resize", handleResize);
98
+ };
99
+ }, [stdout]);
100
+ const checkAndUpdateScrollState = useCallback(() => {
101
+ if (!scrollRef.current) return scrollState === ScrollState.AUTO_SCROLL;
102
+ const atBottom = scrollRef.current.getScrollOffset() >= scrollRef.current.getBottomOffset() - 1;
103
+ if (atBottom && scrollState === ScrollState.USER_SCROLLED) setScrollState(ScrollState.AUTO_SCROLL);
104
+ return atBottom;
105
+ }, [scrollState]);
106
+ useInput((_input, key) => {
107
+ if (!scrollRef.current) return;
108
+ if (key.upArrow) {
109
+ scrollRef.current.scrollBy(-1);
110
+ if (!checkAndUpdateScrollState()) setScrollState(ScrollState.USER_SCROLLED);
111
+ return;
112
+ }
113
+ if (key.downArrow) {
114
+ scrollRef.current.scrollBy(1);
115
+ checkAndUpdateScrollState();
116
+ return;
117
+ }
118
+ if (key.pageUp) {
119
+ const height = scrollRef.current.getViewportHeight() || 1;
120
+ scrollRef.current.scrollBy(-height);
121
+ if (!checkAndUpdateScrollState()) setScrollState(ScrollState.USER_SCROLLED);
122
+ return;
123
+ }
124
+ if (key.pageDown) {
125
+ const height = scrollRef.current.getViewportHeight() || 1;
126
+ scrollRef.current.scrollBy(height);
127
+ checkAndUpdateScrollState();
128
+ }
129
+ }, { isActive: !isCommand });
130
+ useEffect(() => {
131
+ if (mergedEvents.length === 0) return;
132
+ const lastEvent = mergedEvents[mergedEvents.length - 1];
133
+ if (lastEvent.type === EventType.THINKING_STREAM) scrollRef.current?.remeasureItem(mergedEvents.length - 1);
134
+ if ([
135
+ EventType.TASK_COMPLETE,
136
+ EventType.ERROR,
137
+ EventType.ABORTED
138
+ ].includes(lastEvent.type)) scrollRef.current?.scrollToBottom();
139
+ else if (scrollState === ScrollState.AUTO_SCROLL) scrollRef.current?.scrollToBottom();
140
+ }, [mergedEvents]);
141
+ return /* @__PURE__ */ jsxs(Box, {
142
+ marginBottom: 1,
143
+ flexDirection: "column",
144
+ children: [/* @__PURE__ */ jsxs(Box, {
145
+ marginBottom: 1,
146
+ justifyContent: "space-between",
147
+ children: [/* @__PURE__ */ jsx(Text, {
148
+ color: "gray",
149
+ bold: true,
150
+ children: t("eventLog.activity")
151
+ }), /* @__PURE__ */ jsx(Text, {
152
+ color: "gray",
153
+ dimColor: true,
154
+ children: t("eventLog.scrollHint")
155
+ })]
156
+ }), /* @__PURE__ */ jsx(Box, {
157
+ height: 20,
158
+ width: "100%",
159
+ children: /* @__PURE__ */ jsx(ScrollView, {
160
+ ref: scrollRef,
161
+ children: mergedEvents.map((event, index) => /* @__PURE__ */ jsxs(Box, {
162
+ justifyContent: "space-between",
163
+ width: "100%",
164
+ marginBottom: 1,
165
+ alignItems: "flex-start",
166
+ children: [/* @__PURE__ */ jsxs(Box, {
167
+ flexDirection: "row",
168
+ children: [/* @__PURE__ */ jsx(Box, {
169
+ width: 13,
170
+ children: /* @__PURE__ */ jsx(Text, {
171
+ color: event.color,
172
+ bold: true,
173
+ children: `[${event.label}]`
174
+ })
175
+ }), /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(Text, {
176
+ color: "white",
177
+ children: event.data.trim()
178
+ }) })]
179
+ }), /* @__PURE__ */ jsx(Box, {
180
+ width: 16,
181
+ justifyContent: "flex-end",
182
+ children: /* @__PURE__ */ jsx(Text, {
183
+ color: "gray",
184
+ dimColor: true,
185
+ children: event.time
186
+ })
187
+ })]
188
+ }, index))
189
+ })
190
+ })]
191
+ });
192
+ }
193
+
194
+ //#endregion
195
+ //#region src/components/TaskStatus.tsx
196
+ function TaskStatus({ isRunning, currentTask }) {
197
+ const { t } = useTranslation();
198
+ if (!isRunning && !currentTask) return null;
199
+ return /* @__PURE__ */ jsxs(Box, {
200
+ marginBottom: 1,
201
+ flexDirection: "column",
202
+ children: [/* @__PURE__ */ jsxs(Box, {
203
+ gap: 2,
204
+ children: [/* @__PURE__ */ jsx(Box, {
205
+ width: 8,
206
+ children: /* @__PURE__ */ jsx(Text, {
207
+ color: "gray",
208
+ children: "STATUS:"
209
+ })
210
+ }), /* @__PURE__ */ jsxs(Text, {
211
+ color: isRunning ? "cyan" : "green",
212
+ bold: true,
213
+ children: [isRunning ? t("tasks.running") : t("tasks.idle"), isRunning && /* @__PURE__ */ jsx(Spinner, { type: "dots" })]
214
+ })]
215
+ }), currentTask && /* @__PURE__ */ jsxs(Box, {
216
+ gap: 2,
217
+ children: [/* @__PURE__ */ jsx(Box, {
218
+ width: 8,
219
+ children: /* @__PURE__ */ jsx(Text, {
220
+ color: "gray",
221
+ children: "TASK:"
222
+ })
223
+ }), /* @__PURE__ */ jsx(Text, {
224
+ color: "white",
225
+ children: currentTask
226
+ })]
227
+ })]
228
+ });
229
+ }
230
+
231
+ //#endregion
232
+ //#region src/pages/Tasks.tsx
233
+ function TaskList() {
234
+ const { isRunning, currentTask, currentDeviceId } = useAgentContext();
235
+ return /* @__PURE__ */ jsxs(Box, {
236
+ flexDirection: "column",
237
+ children: [/* @__PURE__ */ jsx(TaskStatus, {
238
+ isRunning,
239
+ currentTask,
240
+ currentDeviceId
241
+ }), /* @__PURE__ */ jsx(EventList, {})]
242
+ });
243
+ }
244
+
245
+ //#endregion
246
+ export { TaskList as default };
@@ -0,0 +1,55 @@
1
+ import { Box, Text } from "ink";
2
+ import { useTranslation } from "react-i18next";
3
+ import { jsx, jsxs } from "react/jsx-runtime";
4
+
5
+ //#region src/pages/Welcome.tsx
6
+ function Welcome() {
7
+ const { t } = useTranslation();
8
+ return /* @__PURE__ */ jsxs(Box, {
9
+ flexDirection: "column",
10
+ alignItems: "center",
11
+ marginBottom: 4,
12
+ marginTop: 2,
13
+ children: [/* @__PURE__ */ jsxs(Box, {
14
+ marginBottom: 3,
15
+ flexDirection: "column",
16
+ alignItems: "center",
17
+ children: [/* @__PURE__ */ jsx(Box, {
18
+ marginBottom: 1,
19
+ children: /* @__PURE__ */ jsx(Text, {
20
+ color: "white",
21
+ bold: true,
22
+ children: t("welcome.enterTask")
23
+ })
24
+ }), /* @__PURE__ */ jsx(Text, {
25
+ color: "gray",
26
+ dimColor: true,
27
+ children: t("welcome.example")
28
+ })]
29
+ }), /* @__PURE__ */ jsxs(Box, {
30
+ flexDirection: "column",
31
+ alignItems: "center",
32
+ gap: 1,
33
+ children: [/* @__PURE__ */ jsxs(Text, {
34
+ color: "gray",
35
+ dimColor: true,
36
+ children: [
37
+ t("welcome.enter"),
38
+ " ",
39
+ t("welcome.pressEnter")
40
+ ]
41
+ }), /* @__PURE__ */ jsxs(Text, {
42
+ color: "gray",
43
+ dimColor: true,
44
+ children: [
45
+ t("welcome.slash"),
46
+ " ",
47
+ t("welcome.typeSlash")
48
+ ]
49
+ })]
50
+ })]
51
+ });
52
+ }
53
+
54
+ //#endregion
55
+ export { Welcome as default };