@jixo/cli 0.23.3 → 0.23.4
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/assets/bundle/google-aistudio.browser.js +206 -0
- package/assets/bundle/google-aistudio.node.js +1192 -0
- package/bundle/index.js +35 -35
- package/package.json +1 -1
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
let rootDirHandle;
|
|
2
|
+
const prepareDirHandle = async () => {
|
|
3
|
+
if (rootDirHandle) return rootDirHandle;
|
|
4
|
+
const ti = setTimeout(() => {
|
|
5
|
+
console.log("%c等待用户动作: 请选择一个文件夹,用来作为内容导入导出的协作目录.", styles.info);
|
|
6
|
+
}, 100);
|
|
7
|
+
try {
|
|
8
|
+
rootDirHandle = await window.showDirectoryPicker({ mode: "readwrite" });
|
|
9
|
+
console.log(`%c✅ 根文件夹已选择: %c${rootDirHandle.name}`, styles.success, styles.code);
|
|
10
|
+
return rootDirHandle;
|
|
11
|
+
} catch (e) {
|
|
12
|
+
clearTimeout(ti);
|
|
13
|
+
if (e instanceof Error) {
|
|
14
|
+
if (e.name === "SecurityError" || e.name === "NotAllowedError") {
|
|
15
|
+
console.log("%c请将鼠标聚焦到窗口视图中", styles.info);
|
|
16
|
+
await delay(1e3);
|
|
17
|
+
return prepareDirHandle();
|
|
18
|
+
}
|
|
19
|
+
if (e.name === "AbortError") throw new DOMException("用户取消了文件夹选择", "AbortError");
|
|
20
|
+
}
|
|
21
|
+
throw e;
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
const styles = {
|
|
25
|
+
header: "color: #4CAF50; font-size: 18px; font-weight: bold; border-bottom: 2px solid #4CAF50; padding-bottom: 5px;",
|
|
26
|
+
info: "color: #2196F3; font-style: italic;",
|
|
27
|
+
success: "color: #8BC34A; font-weight: bold;",
|
|
28
|
+
error: "color: #F44336; font-weight: bold;",
|
|
29
|
+
code: "background-color: #f0f0f0; color: #333; padding: 2px 4px; border-radius: 3px; font-family: monospace;",
|
|
30
|
+
warn: "color: #FFC107;"
|
|
31
|
+
};
|
|
32
|
+
const arrayFromAsync = async (iter) => {
|
|
33
|
+
const arr = [];
|
|
34
|
+
for await (const item of iter) arr.push(item);
|
|
35
|
+
return arr;
|
|
36
|
+
};
|
|
37
|
+
const getTargetNamespace = () => location.pathname.split("/").at(-1);
|
|
38
|
+
const delay = (ms) => new Promise((cb) => setTimeout(cb, ms));
|
|
39
|
+
const aFollowedByB = (el, aSelector, bSelector, cb) => {
|
|
40
|
+
const run = () => {
|
|
41
|
+
console.log("QAQ", el);
|
|
42
|
+
for (const bEle of el.querySelectorAll(`:scope > ${aSelector} + ${bSelector}`)) {
|
|
43
|
+
const aEle = bEle.previousElementSibling;
|
|
44
|
+
cb(aEle, bEle);
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
const mo = new MutationObserver(run);
|
|
48
|
+
mo.observe(el, { childList: true });
|
|
49
|
+
run();
|
|
50
|
+
return () => mo.disconnect();
|
|
51
|
+
};
|
|
52
|
+
const $ = document.querySelector.bind(document);
|
|
53
|
+
const $$ = document.querySelectorAll.bind(document);
|
|
54
|
+
const fillFunctionCall = async () => {
|
|
55
|
+
const rootDirHandle$1 = await prepareDirHandle();
|
|
56
|
+
const targetName = getTargetNamespace();
|
|
57
|
+
const keys = await arrayFromAsync(rootDirHandle$1.keys());
|
|
58
|
+
const callTaskname = keys.find((key) => key.endsWith(".function_call.json") && key.startsWith(targetName));
|
|
59
|
+
if (!callTaskname) return;
|
|
60
|
+
const taskFileHandle = await rootDirHandle$1.getFileHandle(callTaskname);
|
|
61
|
+
const taskFile = await taskFileHandle.getFile();
|
|
62
|
+
const taskResponse = JSON.parse(await taskFile.text());
|
|
63
|
+
if (!taskResponse.output) return;
|
|
64
|
+
const scrollToBottom = async () => {
|
|
65
|
+
const chatContainerEle = document.querySelector("ms-autoscroll-container");
|
|
66
|
+
if (chatContainerEle) chatContainerEle.scrollTo({
|
|
67
|
+
top: chatContainerEle.scrollHeight - chatContainerEle.clientHeight,
|
|
68
|
+
behavior: "smooth"
|
|
69
|
+
});
|
|
70
|
+
await delay(1e3);
|
|
71
|
+
};
|
|
72
|
+
const findFunctionCallResponseTextareaEle = () => document.querySelector("textarea[placeholder=\"Enter function response\"]");
|
|
73
|
+
const waitFunctionCallResponseTextareaEle = async () => {
|
|
74
|
+
while (true) {
|
|
75
|
+
const ele = findFunctionCallResponseTextareaEle();
|
|
76
|
+
if (ele) return ele;
|
|
77
|
+
await scrollToBottom();
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
const textareaEle = await waitFunctionCallResponseTextareaEle();
|
|
81
|
+
if (textareaEle.disabled) return;
|
|
82
|
+
textareaEle.value = JSON.stringify(taskResponse.output, null, 2);
|
|
83
|
+
textareaEle.dispatchEvent(new Event("input"));
|
|
84
|
+
await delay(150);
|
|
85
|
+
const findFunctionCallResponseButtonEle = () => document.querySelector(`button[mattooltip="Send response"]`);
|
|
86
|
+
const waitFunctionCallResponseButtonEle = async () => {
|
|
87
|
+
while (true) {
|
|
88
|
+
const ele = findFunctionCallResponseButtonEle();
|
|
89
|
+
if (ele) return ele;
|
|
90
|
+
await scrollToBottom();
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
const buttonEle = await waitFunctionCallResponseButtonEle();
|
|
94
|
+
buttonEle.click();
|
|
95
|
+
await rootDirHandle$1.removeEntry(callTaskname);
|
|
96
|
+
};
|
|
97
|
+
const syncInput = async (fps = 2) => {
|
|
98
|
+
(async () => {
|
|
99
|
+
while (true) {
|
|
100
|
+
await fillFunctionCall();
|
|
101
|
+
await delay(1e3 / fps);
|
|
102
|
+
}
|
|
103
|
+
})();
|
|
104
|
+
};
|
|
105
|
+
const syncOutput = () => {
|
|
106
|
+
const styleEle = document.createElement("style");
|
|
107
|
+
const headEle = $("head");
|
|
108
|
+
const css = String.raw;
|
|
109
|
+
styleEle.innerText = css`
|
|
110
|
+
.cdk-global-overlay-wrapper:has(.get-code-dialog) {
|
|
111
|
+
display: none;
|
|
112
|
+
}
|
|
113
|
+
button[aria-label="Get code"] {
|
|
114
|
+
pointer-events: none;
|
|
115
|
+
}
|
|
116
|
+
`.replaceAll("\n", "");
|
|
117
|
+
headEle.appendChild(styleEle);
|
|
118
|
+
const findCdkOverlayContainer = () => $(".cdk-overlay-container");
|
|
119
|
+
const cdkOverlayTaskId = Symbol.for("cdk-overlay-style-hooks");
|
|
120
|
+
if (!window[cdkOverlayTaskId]) {
|
|
121
|
+
let cdkOverlayContainer;
|
|
122
|
+
let off = () => {};
|
|
123
|
+
window[cdkOverlayTaskId] = setInterval(() => {
|
|
124
|
+
const newCdkOverlayContainer = findCdkOverlayContainer();
|
|
125
|
+
if (newCdkOverlayContainer !== cdkOverlayContainer && newCdkOverlayContainer) {
|
|
126
|
+
off();
|
|
127
|
+
off = aFollowedByB(cdkOverlayContainer = newCdkOverlayContainer, ".cdk-overlay-backdrop", ".cdk-global-overlay-wrapper:has(.get-code-dialog)", (cdkOverlayBackdropEle) => {
|
|
128
|
+
if (cdkOverlayBackdropEle.style.display !== "none") {
|
|
129
|
+
console.log("%c隐藏遮罩元素", styles.warn, cdkOverlayBackdropEle);
|
|
130
|
+
cdkOverlayBackdropEle.style.display = "none";
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
}, 1e3);
|
|
135
|
+
}
|
|
136
|
+
const findMustacheKey = () => {
|
|
137
|
+
for (const key in default_MakerSuite) {
|
|
138
|
+
const render = default_MakerSuite[key]?.render;
|
|
139
|
+
if (render && typeof render === "function") return key;
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
const waitMustacheKey = async () => {
|
|
143
|
+
while (true) {
|
|
144
|
+
const key = findMustacheKey();
|
|
145
|
+
if (key) return key;
|
|
146
|
+
await new Promise((c) => setTimeout(c, 200));
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
async function startInject() {
|
|
150
|
+
const key = await waitMustacheKey();
|
|
151
|
+
const _render = default_MakerSuite[key].render;
|
|
152
|
+
default_MakerSuite[key].render = (...args) => {
|
|
153
|
+
const b = args[1];
|
|
154
|
+
runFileCreation(b);
|
|
155
|
+
return "";
|
|
156
|
+
};
|
|
157
|
+
const findInput = () => $(`textarea[aria-label="Start typing a prompt"]`);
|
|
158
|
+
findInput()?.dispatchEvent(new Event("input"));
|
|
159
|
+
}
|
|
160
|
+
if (!$(".cdk-overlay-container:has(.get-code-dialog)")) {
|
|
161
|
+
const findBtn = () => $(`button[aria-label="Get code"]`);
|
|
162
|
+
const waitBtn = async () => {
|
|
163
|
+
while (true) {
|
|
164
|
+
const btn = findBtn();
|
|
165
|
+
if (btn) return btn;
|
|
166
|
+
await delay(200);
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
waitBtn().then((getCodeButtonEle) => {
|
|
170
|
+
getCodeButtonEle.click();
|
|
171
|
+
requestAnimationFrame(startInject);
|
|
172
|
+
});
|
|
173
|
+
} else startInject();
|
|
174
|
+
};
|
|
175
|
+
let writting = false;
|
|
176
|
+
async function runFileCreation(b, targetFilename = getTargetNamespace() + ".contents.json") {
|
|
177
|
+
if (writting) return;
|
|
178
|
+
writting = true;
|
|
179
|
+
try {
|
|
180
|
+
const rootDirHandle$1 = await prepareDirHandle();
|
|
181
|
+
if (!rootDirHandle$1) return;
|
|
182
|
+
const fileHandle = await rootDirHandle$1.getFileHandle(targetFilename, { create: true });
|
|
183
|
+
const writable = await fileHandle.createWritable();
|
|
184
|
+
console.log("%c - 创建可写流成功。", styles.info);
|
|
185
|
+
await writable.write(JSON.stringify(b));
|
|
186
|
+
console.log("%c - 数据写入中...", styles.info);
|
|
187
|
+
await writable.close();
|
|
188
|
+
console.log(`%c - ✅ 文件写入并关闭成功: %c${targetFilename}`, styles.success, styles.code);
|
|
189
|
+
} catch (error) {
|
|
190
|
+
if (error instanceof Error && error.name === "AbortError") console.warn("%c⚠️ 用户取消了文件夹选择操作。流程已中止。", styles.warn);
|
|
191
|
+
else console.error("%c❌ 发生意外错误:", styles.error, error);
|
|
192
|
+
} finally {
|
|
193
|
+
writting = false;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
(async () => {
|
|
197
|
+
const aborted = await prepareDirHandle().then(() => false, (e) => {
|
|
198
|
+
if (e instanceof Error && e.name === "AbortError") return true;
|
|
199
|
+
});
|
|
200
|
+
if (aborted) {
|
|
201
|
+
console.warn("用户取消了脚本运行");
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
syncOutput();
|
|
205
|
+
syncInput();
|
|
206
|
+
})();
|