pinokiod 7.3.0 → 7.3.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/kernel/api/github/index.js +444 -0
- package/kernel/api/index.js +199 -11
- package/kernel/api/process/index.js +124 -44
- package/kernel/api/shell_run_template.js +273 -0
- package/kernel/api/uri/index.js +51 -0
- package/kernel/bin/{conda-python.js → conda-pins.js} +23 -0
- package/kernel/bin/conda.js +15 -5
- package/kernel/bin/git.js +9 -10
- package/kernel/bin/huggingface.js +1 -1
- package/kernel/bin/index.js +5 -2
- package/kernel/bin/zip.js +9 -1
- package/kernel/connect/providers/github/README.md +5 -4
- package/kernel/environment.js +195 -92
- package/kernel/git.js +98 -19
- package/kernel/gitconfig_template +7 -0
- package/kernel/gpu/amd.js +72 -0
- package/kernel/gpu/apple.js +8 -0
- package/kernel/gpu/common.js +12 -0
- package/kernel/gpu/intel.js +47 -0
- package/kernel/gpu/nvidia.js +8 -0
- package/kernel/index.js +11 -1
- package/kernel/managed_skills.js +871 -0
- package/kernel/plugin.js +6 -58
- package/kernel/plugin_sources.js +316 -0
- package/kernel/resource_usage/gpu.js +349 -0
- package/kernel/resource_usage/index.js +322 -0
- package/kernel/resource_usage/macos_footprint.js +197 -0
- package/kernel/resource_usage/preferences.js +92 -0
- package/kernel/resource_usage/process_tree.js +303 -0
- package/kernel/scripts/git/create +4 -4
- package/kernel/scripts/git/fork +7 -8
- package/kernel/shell.js +23 -2
- package/kernel/shells.js +41 -0
- package/kernel/sysinfo.js +62 -9
- package/kernel/util.js +60 -0
- package/package.json +1 -1
- package/server/index.js +984 -156
- package/server/lib/app_log_report.js +543 -0
- package/server/lib/content_validation.js +55 -33
- package/server/lib/launcher_instruction_bootstrap.js +4 -96
- package/server/lib/terminal_session_helpers.js +0 -3
- package/server/public/common.js +77 -31
- package/server/public/create-launcher.js +4 -32
- package/server/public/logs.js +1428 -0
- package/server/public/nav.js +7 -0
- package/server/public/plugin-detail.js +93 -10
- package/server/public/privacy_filter_worker.js +391 -0
- package/server/public/style.css +1104 -154
- package/server/public/task-launcher.js +8 -29
- package/server/public/universal-launcher.css +8 -6
- package/server/public/universal-launcher.js +3 -27
- package/server/routes/apps.js +195 -1
- package/server/views/app.ejs +3041 -717
- package/server/views/autolaunch.ejs +917 -0
- package/server/views/bootstrap.ejs +7 -1
- package/server/views/d.ejs +408 -65
- package/server/views/editor.ejs +85 -19
- package/server/views/index.ejs +661 -111
- package/server/views/init/index.ejs +1 -1
- package/server/views/install.ejs +1 -1
- package/server/views/logs.ejs +164 -86
- package/server/views/net.ejs +7 -1
- package/server/views/partials/d_terminal_column.ejs +2 -2
- package/server/views/partials/d_terminal_options.ejs +0 -8
- package/server/views/partials/fs_status.ejs +47 -0
- package/server/views/partials/home_action_modal.ejs +86 -0
- package/server/views/partials/home_run_menu.ejs +87 -0
- package/server/views/partials/main_sidebar.ejs +2 -0
- package/server/views/partials/menu.ejs +1 -1
- package/server/views/plugin_detail.ejs +19 -4
- package/server/views/plugins.ejs +201 -3
- package/server/views/pre.ejs +1 -1
- package/server/views/pro.ejs +1 -1
- package/server/views/shell.ejs +40 -18
- package/server/views/skills.ejs +506 -0
- package/server/views/terminal.ejs +45 -19
- package/spec/INSTRUCTION_SYNC.md +20 -10
- package/system/plugin/antigravity-cli/antigravity.png +0 -0
- package/system/plugin/antigravity-cli/common.js +155 -0
- package/system/plugin/antigravity-cli/install.js +272 -0
- package/system/plugin/antigravity-cli/pinokio.js +13 -0
- package/system/plugin/antigravity-cli-auto/antigravity.png +0 -0
- package/system/plugin/antigravity-cli-auto/pinokio.js +13 -0
- package/system/plugin/claude/claude.png +0 -0
- package/system/plugin/claude/pinokio.js +47 -0
- package/system/plugin/claude-auto/claude.png +0 -0
- package/system/plugin/claude-auto/pinokio.js +58 -0
- package/system/plugin/claude-desktop/icon.jpeg +0 -0
- package/system/plugin/claude-desktop/pinokio.js +23 -0
- package/system/plugin/codex/openai.webp +0 -0
- package/system/plugin/codex/pinokio.js +42 -0
- package/system/plugin/codex-auto/openai.webp +0 -0
- package/system/plugin/codex-auto/pinokio.js +49 -0
- package/system/plugin/codex-desktop/icon.png +0 -0
- package/system/plugin/codex-desktop/pinokio.js +23 -0
- package/system/plugin/crush/crush.png +0 -0
- package/system/plugin/crush/pinokio.js +15 -0
- package/system/plugin/cursor/cursor.jpeg +0 -0
- package/system/plugin/cursor/pinokio.js +23 -0
- package/system/plugin/qwen/pinokio.js +34 -0
- package/system/plugin/qwen/qwen.png +0 -0
- package/system/plugin/vscode/pinokio.js +20 -0
- package/system/plugin/vscode/vscode.png +0 -0
- package/system/plugin/windsurf/pinokio.js +23 -0
- package/system/plugin/windsurf/windsurf.png +0 -0
- package/test/antigravity-cli-plugin.test.js +185 -0
- package/test/app-api.test.js +239 -0
- package/test/app-log-report.test.js +67 -0
- package/test/environment-cache-preflight.test.js +98 -0
- package/test/git-bin.test.js +59 -0
- package/test/git-defaults.test.js +97 -0
- package/test/github-api.test.js +158 -0
- package/test/github-connection.test.js +117 -0
- package/test/huggingface-bin.test.js +25 -0
- package/test/managed-skills.test.js +351 -0
- package/test/plugin-action-functions.test.js +337 -0
- package/test/plugin-dev-iframe.test.js +17 -0
- package/test/plugin-sources.test.js +203 -0
- package/test/privacy-filter-worker-heuristics.test.js +69 -0
- package/test/process-wait.test.js +169 -0
- package/test/script-api.test.js +97 -0
- package/test/shell-api.test.js +134 -0
- package/test/shell-run-template.test.js +209 -0
- package/test/storage-api.test.js +137 -0
- package/test/uri-api.test.js +100 -0
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
"use strict"
|
|
2
2
|
|
|
3
|
+
const ManagedSkills = require("../../kernel/managed_skills")
|
|
4
|
+
|
|
3
5
|
const LAUNCHER_AGENT_FILES = [
|
|
4
6
|
"AGENTS.md",
|
|
5
7
|
"CLAUDE.md",
|
|
@@ -34,107 +36,13 @@ const LAUNCHER_FOLDER_CONTEXT_PREAMBLE = [
|
|
|
34
36
|
"3. If they conflict, follow `REQUEST.md` for the current run while preserving the broader intent in `SPEC.md`."
|
|
35
37
|
].join("\n")
|
|
36
38
|
|
|
37
|
-
const parseSimpleFrontmatter = (content) => {
|
|
38
|
-
const normalized = String(content || "").replace(/\r\n/g, "\n")
|
|
39
|
-
if (!normalized.startsWith("---\n")) {
|
|
40
|
-
return {
|
|
41
|
-
frontmatter: null,
|
|
42
|
-
bodyWithoutFrontmatter: normalized.trim()
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
const end = normalized.indexOf("\n---\n", 4)
|
|
46
|
-
if (end === -1) {
|
|
47
|
-
return {
|
|
48
|
-
frontmatter: null,
|
|
49
|
-
bodyWithoutFrontmatter: normalized.trim()
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
return {
|
|
53
|
-
frontmatter: normalized.slice(4, end),
|
|
54
|
-
bodyWithoutFrontmatter: normalized.slice(end + 5).trim()
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
39
|
const createLauncherInstructionBootstrap = ({ kernel, fs, path, os }) => {
|
|
59
|
-
const getSkillRoots = () => {
|
|
60
|
-
const roots = []
|
|
61
|
-
const seen = new Set()
|
|
62
|
-
const addRoot = (target) => {
|
|
63
|
-
if (typeof target !== "string" || !target.trim()) {
|
|
64
|
-
return
|
|
65
|
-
}
|
|
66
|
-
const resolved = path.resolve(target)
|
|
67
|
-
if (seen.has(resolved)) {
|
|
68
|
-
return
|
|
69
|
-
}
|
|
70
|
-
seen.add(resolved)
|
|
71
|
-
roots.push(resolved)
|
|
72
|
-
}
|
|
73
|
-
const home = os.homedir()
|
|
74
|
-
addRoot(path.join(home, ".agents", "skills"))
|
|
75
|
-
addRoot(path.join(home, ".agent", "skills"))
|
|
76
|
-
addRoot(path.join(home, ".codex", "skills"))
|
|
77
|
-
addRoot(path.join(home, ".claude", "skills"))
|
|
78
|
-
addRoot(path.join(home, ".gemini", "skills"))
|
|
79
|
-
addRoot(path.join(home, ".config", "gemini", "skills"))
|
|
80
|
-
addRoot(path.join(home, ".openclaw", "skills"))
|
|
81
|
-
if (kernel && typeof kernel.path === "function") {
|
|
82
|
-
addRoot(kernel.path("skills"))
|
|
83
|
-
}
|
|
84
|
-
return roots
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
const readFileIfExists = async (filepath) => {
|
|
88
|
-
if (typeof filepath !== "string" || !filepath.trim()) {
|
|
89
|
-
return ""
|
|
90
|
-
}
|
|
91
|
-
try {
|
|
92
|
-
return await fs.promises.readFile(filepath, "utf8")
|
|
93
|
-
} catch (error) {
|
|
94
|
-
if (error && error.code === "ENOENT") {
|
|
95
|
-
return ""
|
|
96
|
-
}
|
|
97
|
-
throw error
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
const resolveSkillBody = async (skillName, fallbackResolver) => {
|
|
102
|
-
const normalizedName = typeof skillName === "string" ? skillName.trim() : ""
|
|
103
|
-
if (!normalizedName) {
|
|
104
|
-
return ""
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
const roots = getSkillRoots()
|
|
108
|
-
for (let i = 0; i < roots.length; i++) {
|
|
109
|
-
const skillPath = path.resolve(roots[i], normalizedName, "SKILL.md")
|
|
110
|
-
const contents = await readFileIfExists(skillPath)
|
|
111
|
-
if (contents.trim()) {
|
|
112
|
-
return parseSimpleFrontmatter(contents).bodyWithoutFrontmatter
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
if (typeof fallbackResolver === "function") {
|
|
117
|
-
const fallback = await fallbackResolver()
|
|
118
|
-
if (typeof fallback === "string" && fallback.trim()) {
|
|
119
|
-
return parseSimpleFrontmatter(fallback).bodyWithoutFrontmatter
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
return ""
|
|
123
|
-
}
|
|
124
|
-
|
|
125
40
|
const resolvePinokioBody = async () => {
|
|
126
|
-
return
|
|
127
|
-
return readFileIfExists(path.resolve(__dirname, "../../prototype/system/SKILL_PINOKIO.md"))
|
|
128
|
-
})
|
|
41
|
+
return ManagedSkills.readEnabledManagedSkillBody(kernel, "pinokio").catch(() => "")
|
|
129
42
|
}
|
|
130
43
|
|
|
131
44
|
const resolveGepetoBody = async () => {
|
|
132
|
-
return
|
|
133
|
-
if (!kernel || !kernel.homedir) {
|
|
134
|
-
return ""
|
|
135
|
-
}
|
|
136
|
-
return readFileIfExists(path.resolve(kernel.homedir, "AGENTS.md"))
|
|
137
|
-
})
|
|
45
|
+
return ManagedSkills.readEnabledManagedSkillBody(kernel, "gepeto").catch(() => "")
|
|
138
46
|
}
|
|
139
47
|
|
|
140
48
|
const buildLauncherInstructionBody = async () => {
|
|
@@ -333,9 +333,6 @@ const createTerminalSessionHelpers = ({ kernel, fs, path, os, crypto }) => {
|
|
|
333
333
|
addRoot(path.join(home, ".gemini", "skills"))
|
|
334
334
|
addRoot(path.join(home, ".config", "gemini", "skills"))
|
|
335
335
|
addRoot(path.join(home, ".openclaw", "skills"))
|
|
336
|
-
if (kernel && kernel.homedir) {
|
|
337
|
-
addRoot(kernel.path("skills"))
|
|
338
|
-
}
|
|
339
336
|
return roots
|
|
340
337
|
}
|
|
341
338
|
|
package/server/public/common.js
CHANGED
|
@@ -104,6 +104,79 @@ function createMinimalLoadingSwal () {
|
|
|
104
104
|
});
|
|
105
105
|
return close;
|
|
106
106
|
}
|
|
107
|
+
|
|
108
|
+
const PINOKIO_WAIT_FOOTER_ID = 'pinokio-process-wait-footer-status'
|
|
109
|
+
|
|
110
|
+
function escapePinokioStatusHtml(value) {
|
|
111
|
+
return String(value == null ? '' : value)
|
|
112
|
+
.replace(/&/g, '&')
|
|
113
|
+
.replace(/</g, '<')
|
|
114
|
+
.replace(/>/g, '>')
|
|
115
|
+
.replace(/"/g, '"')
|
|
116
|
+
.replace(/'/g, ''')
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function ensurePinokioWaitFooterStatus() {
|
|
120
|
+
let status = document.getElementById(PINOKIO_WAIT_FOOTER_ID)
|
|
121
|
+
if (status) {
|
|
122
|
+
return status
|
|
123
|
+
}
|
|
124
|
+
status = document.createElement('div')
|
|
125
|
+
status.id = PINOKIO_WAIT_FOOTER_ID
|
|
126
|
+
status.className = 'pinokio-install-inline-status pinokio-process-wait-footer-status'
|
|
127
|
+
status.hidden = true
|
|
128
|
+
status.setAttribute('aria-live', 'polite')
|
|
129
|
+
|
|
130
|
+
const anchor = document.querySelector('.terminal-container')
|
|
131
|
+
|| document.querySelector('main')
|
|
132
|
+
|| document.querySelector('#terminal')?.parentElement
|
|
133
|
+
|| document.querySelector('footer')
|
|
134
|
+
|| document.body
|
|
135
|
+
|
|
136
|
+
if (anchor && anchor !== document.body) {
|
|
137
|
+
anchor.insertAdjacentElement('afterend', status)
|
|
138
|
+
} else {
|
|
139
|
+
document.body.appendChild(status)
|
|
140
|
+
}
|
|
141
|
+
return status
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function showPinokioWaitFooterStatus(data = {}) {
|
|
145
|
+
const title = data.title || 'Waiting'
|
|
146
|
+
const description = data.description || data.message || ''
|
|
147
|
+
const status = ensurePinokioWaitFooterStatus()
|
|
148
|
+
status.className = 'pinokio-install-inline-status pinokio-process-wait-footer-status is-progress'
|
|
149
|
+
status.innerHTML = `
|
|
150
|
+
<div class="pinokio-install-inline-status-shell">
|
|
151
|
+
<span class="pinokio-install-inline-status-icon" aria-hidden="true">
|
|
152
|
+
<i class="fa-solid fa-circle-notch fa-spin"></i>
|
|
153
|
+
</span>
|
|
154
|
+
<div class="pinokio-install-inline-status-copy">
|
|
155
|
+
<div class="pinokio-install-inline-status-title">${escapePinokioStatusHtml(title)}</div>
|
|
156
|
+
${description ? `<div class="pinokio-install-inline-status-detail">${escapePinokioStatusHtml(description)}</div>` : ''}
|
|
157
|
+
</div>
|
|
158
|
+
</div>
|
|
159
|
+
`
|
|
160
|
+
status.hidden = false
|
|
161
|
+
document.body.classList.add('pinokio-install-status-visible')
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function hidePinokioWaitFooterStatus() {
|
|
165
|
+
const status = document.getElementById(PINOKIO_WAIT_FOOTER_ID)
|
|
166
|
+
if (!status) {
|
|
167
|
+
return
|
|
168
|
+
}
|
|
169
|
+
status.hidden = true
|
|
170
|
+
status.innerHTML = ''
|
|
171
|
+
document.body.classList.remove('pinokio-install-status-visible')
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
if (typeof window !== 'undefined') {
|
|
175
|
+
window.PinokioWaitFooterStatus = {
|
|
176
|
+
show: showPinokioWaitFooterStatus,
|
|
177
|
+
hide: hidePinokioWaitFooterStatus
|
|
178
|
+
}
|
|
179
|
+
}
|
|
107
180
|
function check_ready (targetUrl = null, options = {}) {
|
|
108
181
|
createLauncherDebugLog('check_ready start');
|
|
109
182
|
return fetch("/pinokio/requirements_ready").then((res) => {
|
|
@@ -3482,33 +3555,6 @@ document.addEventListener("DOMContentLoaded", () => {
|
|
|
3482
3555
|
tools: null,
|
|
3483
3556
|
toolsPromise: null
|
|
3484
3557
|
};
|
|
3485
|
-
const ASK_AI_FALLBACK_TOOLS = [
|
|
3486
|
-
{
|
|
3487
|
-
value: 'claude',
|
|
3488
|
-
label: 'Claude Code',
|
|
3489
|
-
iconSrc: '/asset/plugin/code/claude/claude.png',
|
|
3490
|
-
href: '/run/plugin/code/claude/pinokio.js',
|
|
3491
|
-
category: 'CLI',
|
|
3492
|
-
isDefault: true
|
|
3493
|
-
},
|
|
3494
|
-
{
|
|
3495
|
-
value: 'codex',
|
|
3496
|
-
label: 'OpenAI Codex',
|
|
3497
|
-
iconSrc: '/asset/plugin/code/codex/openai.webp',
|
|
3498
|
-
href: '/run/plugin/code/codex/pinokio.js',
|
|
3499
|
-
category: 'CLI',
|
|
3500
|
-
isDefault: false
|
|
3501
|
-
},
|
|
3502
|
-
{
|
|
3503
|
-
value: 'gemini',
|
|
3504
|
-
label: 'Google Gemini CLI',
|
|
3505
|
-
iconSrc: '/asset/plugin/code/gemini/gemini.jpeg',
|
|
3506
|
-
href: '/run/plugin/code/gemini/pinokio.js',
|
|
3507
|
-
category: 'CLI',
|
|
3508
|
-
isDefault: false
|
|
3509
|
-
}
|
|
3510
|
-
];
|
|
3511
|
-
|
|
3512
3558
|
initializeUniversalLauncherIntegration();
|
|
3513
3559
|
initializeCreateLauncherIntegration();
|
|
3514
3560
|
|
|
@@ -3920,6 +3966,7 @@ document.addEventListener("DOMContentLoaded", () => {
|
|
|
3920
3966
|
return typeof pathname === 'string'
|
|
3921
3967
|
&& (
|
|
3922
3968
|
pathname.startsWith('/run/plugin/')
|
|
3969
|
+
|| pathname.startsWith('/pinokio/run/plugin/')
|
|
3923
3970
|
|| (pathname.startsWith('/run/api/') && /\/pinokio\.js$/i.test(pathname))
|
|
3924
3971
|
);
|
|
3925
3972
|
}
|
|
@@ -4010,12 +4057,11 @@ document.addEventListener("DOMContentLoaded", () => {
|
|
|
4010
4057
|
return res.json();
|
|
4011
4058
|
})
|
|
4012
4059
|
.then((payload) => {
|
|
4013
|
-
|
|
4014
|
-
return mapped.length > 0 ? mapped : ASK_AI_FALLBACK_TOOLS.slice();
|
|
4060
|
+
return mapPluginMenuToAskAiTools(payload && Array.isArray(payload.menu) ? payload.menu : []);
|
|
4015
4061
|
})
|
|
4016
4062
|
.catch((error) => {
|
|
4017
|
-
console.warn('Failed to load Ask AI plugins
|
|
4018
|
-
return
|
|
4063
|
+
console.warn('Failed to load Ask AI plugins', error);
|
|
4064
|
+
return [];
|
|
4019
4065
|
})
|
|
4020
4066
|
.finally(() => {
|
|
4021
4067
|
askAiState.toolsPromise = null;
|
|
@@ -5,33 +5,6 @@
|
|
|
5
5
|
return;
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
-
const FALLBACK_TOOLS = [
|
|
9
|
-
{
|
|
10
|
-
value: 'claude',
|
|
11
|
-
label: 'Claude Code',
|
|
12
|
-
iconSrc: '/asset/plugin/code/claude/claude.png',
|
|
13
|
-
isDefault: true,
|
|
14
|
-
href: '/run/plugin/code/claude/pinokio.js',
|
|
15
|
-
category: 'CLI',
|
|
16
|
-
},
|
|
17
|
-
{
|
|
18
|
-
value: 'codex',
|
|
19
|
-
label: 'OpenAI Codex',
|
|
20
|
-
iconSrc: '/asset/plugin/code/codex/openai.webp',
|
|
21
|
-
isDefault: false,
|
|
22
|
-
href: '/run/plugin/code/codex/pinokio.js',
|
|
23
|
-
category: 'CLI',
|
|
24
|
-
},
|
|
25
|
-
{
|
|
26
|
-
value: 'gemini',
|
|
27
|
-
label: 'Google Gemini CLI',
|
|
28
|
-
iconSrc: '/asset/plugin/code/gemini/gemini.jpeg',
|
|
29
|
-
isDefault: false,
|
|
30
|
-
href: '/run/plugin/code/gemini/pinokio.js',
|
|
31
|
-
category: 'CLI',
|
|
32
|
-
},
|
|
33
|
-
];
|
|
34
|
-
|
|
35
8
|
const CATEGORY_ORDER = ['CLI', 'IDE'];
|
|
36
9
|
const MODAL_VARIANTS = {
|
|
37
10
|
CREATE: 'create',
|
|
@@ -83,7 +56,7 @@
|
|
|
83
56
|
|
|
84
57
|
let value = '';
|
|
85
58
|
if (href) {
|
|
86
|
-
// Normalize href to a plugin-relative path for the backend (e.g.,
|
|
59
|
+
// Normalize href to a plugin-relative path for the backend (e.g., pinokio/run/plugin/codex)
|
|
87
60
|
const normalized = href.replace(/^\/run/, '').replace(/^\/+/, '');
|
|
88
61
|
const parts = normalized.split('/').filter(Boolean);
|
|
89
62
|
// Expect /plugin/<path...>/pinokio.js -> want <path...>
|
|
@@ -138,12 +111,11 @@
|
|
|
138
111
|
})
|
|
139
112
|
.then((data) => {
|
|
140
113
|
const menu = data && Array.isArray(data.menu) ? data.menu : [];
|
|
141
|
-
|
|
142
|
-
return tools.length > 0 ? tools : FALLBACK_TOOLS.slice();
|
|
114
|
+
return mapPluginMenuToCreateLauncherTools(menu);
|
|
143
115
|
})
|
|
144
116
|
.catch((error) => {
|
|
145
|
-
console.warn('
|
|
146
|
-
return
|
|
117
|
+
console.warn('Failed to load plugins for create launcher modal', error);
|
|
118
|
+
return [];
|
|
147
119
|
})
|
|
148
120
|
.finally(() => {
|
|
149
121
|
loadingTools = null;
|