plugins: rename init to execute
Alessandro committed
Mar 16, 2026 at 17:13 UTC
2a6820064ded5b35ec3027c903cb0e9b2e04bd9f
8 files changed
+81
-79
api/plugins.py
+18
-19
@@ -17,7 +17,6 @@ class Plugins(ApiHandler):
17
async def process(self, input: dict, request: Request) -> dict | Response:
18
action = input.get("action", "")
19
20
- # Accept legacy aliases during migration.
20
if action == "get_config":
21
return self._get_config(input)
22
@@ -45,11 +44,11 @@ class Plugins(ApiHandler):
44
if action == "get_doc":
45
return self._get_doc(input)
46
48
- if action == "run_init_script":
49
- return self._run_init_script(input)
47
+ if action == "run_execute_script":
48
+ return self._run_execute_script(input)
49
51
- if action == "get_init_exec":
52
- return self._get_init_exec(input)
50
+ if action == "get_execute_record":
51
+ return self._get_execute_record(input)
52
53
return Response(status=400, response=f"Unknown action: {action}")
54
@@ -275,7 +274,7 @@ class Plugins(ApiHandler):
274
return {"ok": True, "content": files.read_file(file_path), "filename": filename}
275
276
@extension.extensible
278
- def _run_init_script(self, input: dict) -> dict | Response:
277
+ def _run_execute_script(self, input: dict) -> dict | Response:
278
plugin_name = input.get("plugin_name", "")
279
if not plugin_name:
280
return Response(status=400, response="Missing plugin_name")
@@ -284,14 +283,14 @@ class Plugins(ApiHandler):
283
if not plugin_dir:
284
return Response(status=404, response="Plugin not found")
285
287
- init_script = files.get_abs_path(plugin_dir, "execute.py")
288
- if not files.exists(init_script):
286
+ execute_script = files.get_abs_path(plugin_dir, "execute.py")
287
+ if not files.exists(execute_script):
288
return Response(status=404, response="execute.py not found")
289
290
executed_at = datetime.now(timezone.utc).isoformat()
291
try:
292
result = subprocess.run(
294
- [sys.executable, init_script],
293
+ [sys.executable, execute_script],
294
stdout=subprocess.PIPE,
295
stderr=subprocess.STDOUT,
296
text=True,
@@ -307,12 +306,12 @@ class Plugins(ApiHandler):
306
exit_code = -1
307
output = f"Error: {str(e)}"
308
310
- exec_record = {"executed_at": executed_at, "exit_code": exit_code}
311
- exec_path = plugins.determine_plugin_asset_path(
312
- plugin_name, "", "", "init_exec.json"
309
+ execute_record = {"executed_at": executed_at, "exit_code": exit_code}
310
+ execute_record_path = plugins.determine_plugin_asset_path(
311
+ plugin_name, "", "", "execute_record.json"
312
)
314
- if exec_path:
315
- files.write_file(exec_path, json.dumps(exec_record))
313
+ if execute_record_path:
314
+ files.write_file(execute_record_path, json.dumps(execute_record))
315
316
return {
317
"ok": exit_code == 0,
@@ -322,17 +321,17 @@ class Plugins(ApiHandler):
321
}
322
323
@extension.extensible
325
- def _get_init_exec(self, input: dict) -> dict | Response:
324
+ def _get_execute_record(self, input: dict) -> dict | Response:
325
plugin_name = input.get("plugin_name", "")
326
if not plugin_name:
327
return Response(status=400, response="Missing plugin_name")
328
330
- exec_path = plugins.determine_plugin_asset_path(
331
- plugin_name, "", "", "init_exec.json"
329
+ execute_record_path = plugins.determine_plugin_asset_path(
330
+ plugin_name, "", "", "execute_record.json"
331
)
333
- if exec_path and files.exists(exec_path):
332
+ if execute_record_path and files.exists(execute_record_path):
333
try:
335
- data = json.loads(files.read_file(exec_path))
334
+ data = json.loads(files.read_file(execute_record_path))
335
return {"ok": True, "data": data}
336
except Exception:
337
pass
helpers/plugins.py
+3
-3
@@ -87,7 +87,7 @@ class PluginListItem(BaseModel):
87
has_config_screen: bool = False
88
has_readme: bool = False
89
has_license: bool = False
90
- has_init_script: bool = False
90
+ has_execute_script: bool = False
91
toggle_state: ToggleState = "disabled"
92
current_commit: str = ""
93
current_commit_timestamp: str = ""
@@ -162,7 +162,7 @@ def get_enhanced_plugins_list(
162
has_config_screen = files.exists(str(d / "webui" / "config.html"))
163
has_readme = files.exists(str(d / "README.md"))
164
has_license = files.exists(str(d / "LICENSE"))
165
- has_init_script = files.exists(str(d / "execute.py"))
165
+ has_execute_script = files.exists(str(d / "execute.py"))
166
toggle_state = get_toggle_state(d.name)
167
current_commit = ""
168
current_commit_timestamp = ""
@@ -187,7 +187,7 @@ def get_enhanced_plugins_list(
187
has_config_screen=has_config_screen,
188
has_readme=has_readme,
189
has_license=has_license,
190
- has_init_script=has_init_script,
190
+ has_execute_script=has_execute_script,
191
toggle_state=toggle_state,
192
current_commit=current_commit,
193
current_commit_timestamp=current_commit_timestamp,
plugins/_plugin_installer/webui/install-detail.html
+2
-2
@@ -84,9 +84,9 @@
84
<span class="icon material-symbols-outlined">gavel</span> License
85
</button>
86
</template>
87
- <template x-if="$store.pluginInstallStore.installedPluginInfo.has_init_script">
87
+ <template x-if="$store.pluginInstallStore.installedPluginInfo.has_execute_script">
88
<button type="button" class="button"
89
- @click="$store.pluginInstallStore.handleOpenInit()">
89
+ @click="$store.pluginInstallStore.handleOpenExecute()">
90
<span class="icon material-symbols-outlined">terminal</span> Script
91
</button>
92
</template>
plugins/_plugin_installer/webui/pluginInstallStore.js
+3
-3
@@ -6,7 +6,7 @@ import { toastFrontendSuccess, toastFrontendError } from "/components/notificati
6
import { showConfirmDialog } from "/js/confirmDialog.js";
7
import { store as imageViewerStore } from "/components/modals/image-viewer/image-viewer-store.js";
8
import { store as pluginListStore } from "/components/plugins/list/pluginListStore.js";
9
-import { store as pluginInitStore } from "/components/plugins/list/plugin-init-store.js";
9
+import { store as pluginExecuteStore } from "/components/plugins/list/plugin-execute-store.js";
10
11
const PLUGIN_API = "plugins/_plugin_installer/plugin_install";
12
const PER_PAGE = 20;
@@ -611,9 +611,9 @@ const model = {
611
}
612
},
613
614
- handleOpenInit() {
614
+ handleOpenExecute() {
615
if (this.installedPluginInfo) {
616
- pluginInitStore.open(this.installedPluginInfo);
616
+ pluginExecuteStore.open(this.installedPluginInfo);
617
}
618
},
619
webui/components/plugins/list/plugin-execute-modal.html
renamed
+32
-32
@@ -1,55 +1,55 @@
1
<html>
2
<head>
3
- <title>Plugin Init</title>
3
+ <title>Plugin Execute</title>
4
<script type="module">
5
- import { store } from "/components/plugins/list/plugin-init-store.js";
5
+ import { store } from "/components/plugins/list/plugin-execute-store.js";
6
</script>
7
</head>
8
<body>
9
<div x-data>
10
- <template x-if="$store.pluginInitStore">
11
- <div x-destroy="$store.pluginInitStore.cleanup()"
12
- x-create="$el.closest('.modal')?.querySelector('.modal-title') && ($el.closest('.modal').querySelector('.modal-title').textContent = 'Init: ' + $store.pluginInitStore.pluginDisplayName)"
13
- class="plugin-init-root">
10
+ <template x-if="$store.pluginExecuteStore">
11
+ <div x-destroy="$store.pluginExecuteStore.cleanup()"
12
+ x-create="$el.closest('.modal')?.querySelector('.modal-title') && ($el.closest('.modal').querySelector('.modal-title').textContent = 'Execute: ' + $store.pluginExecuteStore.pluginDisplayName)"
13
+ class="plugin-execute-root">
14
15
- <div class="plugin-init-idle"
16
- x-show="!$store.pluginInitStore.running && $store.pluginInitStore.exitCode === null && !$store.pluginInitStore.output">
15
+ <div class="plugin-execute-idle"
16
+ x-show="!$store.pluginExecuteStore.running && $store.pluginExecuteStore.exitCode === null && !$store.pluginExecuteStore.output">
17
<span class="material-symbols-outlined idle-icon">terminal</span>
18
<div class="idle-text">
19
- <span class="idle-headline">Press <strong>Run</strong> to initialize <strong x-text="$store.pluginInitStore.pluginDisplayName"></strong></span>
20
- <span class="idle-sub">This will execute the plugin's <code>execute.py</code> setup script.</span>
21
- <template x-if="$store.pluginInitStore.lastExec">
19
+ <span class="idle-headline">Press <strong>Run</strong> to execute <strong x-text="$store.pluginExecuteStore.pluginDisplayName"></strong></span>
20
+ <span class="idle-sub">This will run the plugin's <code>execute.py</code> script.</span>
21
+ <template x-if="$store.pluginExecuteStore.lastExecution">
22
<span class="last-exec-info">
23
Last run:
24
- <span x-text="new Date($store.pluginInitStore.lastExec.executed_at).toLocaleString()"></span>
24
+ <span x-text="new Date($store.pluginExecuteStore.lastExecution.executed_at).toLocaleString()"></span>
25
—
26
- <span :class="$store.pluginInitStore.lastExec.exit_code === 0 ? 'exit-ok' : 'exit-err'"
27
- x-text="$store.pluginInitStore.lastExec.exit_code === 0 ? 'succeeded' : 'failed (exit ' + $store.pluginInitStore.lastExec.exit_code + ')'">
26
+ <span :class="$store.pluginExecuteStore.lastExecution.exit_code === 0 ? 'exit-ok' : 'exit-err'"
27
+ x-text="$store.pluginExecuteStore.lastExecution.exit_code === 0 ? 'succeeded' : 'failed (exit ' + $store.pluginExecuteStore.lastExecution.exit_code + ')'">
28
</span>
29
</span>
30
</template>
31
- <template x-if="!$store.pluginInitStore.lastExec">
32
- <span class="last-exec-info never-run">Never initialized</span>
31
+ <template x-if="!$store.pluginExecuteStore.lastExecution">
32
+ <span class="last-exec-info never-run">Never executed</span>
33
</template>
34
</div>
35
</div>
36
37
- <div class="plugin-init-status" x-show="$store.pluginInitStore.running">
37
+ <div class="plugin-execute-status" x-show="$store.pluginExecuteStore.running">
38
<span class="material-symbols-outlined spin">progress_activity</span>
39
<span>Running execute.py...</span>
40
</div>
41
42
- <div class="plugin-init-exit" x-show="!$store.pluginInitStore.running && $store.pluginInitStore.exitCode !== null">
42
+ <div class="plugin-execute-exit" x-show="!$store.pluginExecuteStore.running && $store.pluginExecuteStore.exitCode !== null">
43
<span class="material-symbols-outlined"
44
- :class="$store.pluginInitStore.exitCode === 0 ? 'exit-ok' : 'exit-err'"
45
- x-text="$store.pluginInitStore.exitCode === 0 ? 'check_circle' : 'error'">
44
+ :class="$store.pluginExecuteStore.exitCode === 0 ? 'exit-ok' : 'exit-err'"
45
+ x-text="$store.pluginExecuteStore.exitCode === 0 ? 'check_circle' : 'error'">
46
</span>
47
- <span x-text="$store.pluginInitStore.exitCode === 0 ? 'Completed successfully (exit 0)' : 'Exited with code ' + $store.pluginInitStore.exitCode"></span>
47
+ <span x-text="$store.pluginExecuteStore.exitCode === 0 ? 'Completed successfully (exit 0)' : 'Exited with code ' + $store.pluginExecuteStore.exitCode"></span>
48
</div>
49
50
- <pre class="plugin-init-output"
51
- x-show="$store.pluginInitStore.output || $store.pluginInitStore.running"
52
- x-text="$store.pluginInitStore.output || ''"></pre>
50
+ <pre class="plugin-execute-output"
51
+ x-show="$store.pluginExecuteStore.output || $store.pluginExecuteStore.running"
52
+ x-text="$store.pluginExecuteStore.output || ''"></pre>
53
</div>
54
</template>
55
</div>
@@ -57,22 +57,22 @@
57
<div class="modal-footer" data-modal-footer>
58
<button class="btn btn-action footer-btn"
59
x-data
60
- :disabled="$store.pluginInitStore?.running"
61
- @click="$store.pluginInitStore?.run()">
60
+ :disabled="$store.pluginExecuteStore?.running"
61
+ @click="$store.pluginExecuteStore?.run()">
62
<span class="icon material-symbols-outlined">play_arrow</span>
63
- <span x-text="$store.pluginInitStore?.exitCode !== null || $store.pluginInitStore?.output ? 'Rerun' : 'Run'">Run</span>
63
+ <span x-text="$store.pluginExecuteStore?.exitCode !== null || $store.pluginExecuteStore?.output ? 'Rerun' : 'Run'">Run</span>
64
</button>
65
<button class="btn btn-cancel footer-btn" @click="window.closeModal?.()">Close</button>
66
</div>
67
68
<style>
69
- .plugin-init-root {
69
+ .plugin-execute-root {
70
display: flex;
71
flex-direction: column;
72
width: 100%;
73
}
74
75
- .plugin-init-idle {
75
+ .plugin-execute-idle {
76
display: flex;
77
align-items: flex-start;
78
gap: 1rem;
@@ -114,7 +114,7 @@
114
font-style: italic;
115
}
116
117
- .plugin-init-status {
117
+ .plugin-execute-status {
118
display: flex;
119
align-items: center;
120
gap: 0.5rem;
@@ -123,7 +123,7 @@
123
font-size: var(--font-size-small);
124
}
125
126
- .plugin-init-exit {
126
+ .plugin-execute-exit {
127
display: flex;
128
align-items: center;
129
gap: 0.5rem;
@@ -139,7 +139,7 @@
139
color: var(--color-error, #e74c3c);
140
}
141
142
- .plugin-init-output {
142
+ .plugin-execute-output {
143
font-family: "Courier New", Courier, monospace;
144
font-size: 0.82rem;
145
background: var(--color-bg-secondary, #1e1e1e);
webui/components/plugins/list/plugin-execute-store.js
renamed
+17
-14
@@ -11,7 +11,7 @@ const model = {
11
output: "",
12
running: false,
13
exitCode: null,
14
- lastExec: null,
14
+ lastExecution: null,
15
16
async open(plugin) {
17
if (!plugin?.name) return;
@@ -19,20 +19,20 @@ const model = {
19
this.pluginDisplayName = plugin.display_name || plugin.name;
20
this.output = "";
21
this.exitCode = null;
22
- this.lastExec = null;
23
- window.openModal?.("components/plugins/list/plugin-init-modal.html");
24
- await this.fetchLastExec();
22
+ this.lastExecution = null;
23
+ window.openModal?.("components/plugins/list/plugin-execute-modal.html");
24
+ await this.fetchLastExecution();
25
},
26
27
- async fetchLastExec() {
27
+ async fetchLastExecution() {
28
try {
29
const response = await api.callJsonApi("plugins", {
30
- action: "get_init_exec",
30
+ action: "get_execute_record",
31
plugin_name: this.pluginName,
32
});
33
- this.lastExec = response.data || null;
33
+ this.lastExecution = response.data || null;
34
} catch (e) {
35
- this.lastExec = null;
35
+ this.lastExecution = null;
36
}
37
},
38
@@ -43,22 +43,25 @@ const model = {
43
this.running = true;
44
try {
45
const response = await api.callJsonApi("plugins", {
46
- action: "run_init_script",
46
+ action: "run_execute_script",
47
plugin_name: this.pluginName,
48
});
49
this.output = response.output || "";
50
this.exitCode = response.exit_code ?? null;
51
if (response.executed_at) {
52
- this.lastExec = { executed_at: response.executed_at, exit_code: response.exit_code ?? null };
52
+ this.lastExecution = {
53
+ executed_at: response.executed_at,
54
+ exit_code: response.exit_code ?? null,
55
+ };
56
}
57
} catch (e) {
58
this.output = e.message || String(e);
59
this.exitCode = -1;
60
notificationStore.frontendError(
61
e.message || String(e),
59
- "Failed to run init script",
62
+ "Failed to run execute script",
63
3,
61
- "pluginInit",
64
+ "pluginExecute",
65
defaultPriority,
66
true,
67
);
@@ -73,8 +76,8 @@ const model = {
76
this.output = "";
77
this.running = false;
78
this.exitCode = null;
76
- this.lastExec = null;
79
+ this.lastExecution = null;
80
},
81
};
82
80
-export const store = createStore("pluginInitStore", model);
83
+export const store = createStore("pluginExecuteStore", model);
webui/components/plugins/list/plugin-list.html
+2
-2
@@ -107,11 +107,11 @@
107
<span class="icon material-symbols-outlined">settings</span> Config
108
</button>
109
</template>
110
- <template x-if="plugin.has_init_script">
110
+ <template x-if="plugin.has_execute_script">
111
<button type="button"
112
class="button"
113
title="Execute"
114
- @click="$store.pluginListStore.openPluginInit(plugin)">
114
+ @click="$store.pluginListStore.openPluginExecute(plugin)">
115
<span class="icon material-symbols-outlined">terminal</span> Execute
116
</button>
117
</template>
webui/components/plugins/list/pluginListStore.js
+4
-4
@@ -2,7 +2,7 @@ import { createStore } from "/js/AlpineStore.js";
2
import * as api from "/js/api.js";
3
import { store as pluginSettingsStore } from "/components/plugins/plugin-settings-store.js";
4
import { store as pluginToggleStore } from "/components/plugins/toggle/plugin-toggle-store.js";
5
-import { store as pluginInitStore } from "/components/plugins/list/plugin-init-store.js";
5
+import { store as pluginExecuteStore } from "/components/plugins/list/plugin-execute-store.js";
6
import { store as markdownModalStore } from "/components/modals/markdown/markdown-store.js";
7
import { callJsExtensions } from "/js/extensions.js";
8
import {
@@ -71,9 +71,9 @@ const model = {
71
window.openModal?.(`/plugins/${plugin.name}/webui/main.html`);
72
},
73
74
- openPluginInit(plugin) {
75
- if (!plugin?.name || !plugin?.has_init_script) return;
76
- pluginInitStore.open(plugin);
74
+ openPluginExecute(plugin) {
75
+ if (!plugin?.name || !plugin?.has_execute_script) return;
76
+ pluginExecuteStore.open(plugin);
77
},
78
79
async openPluginConfig(plugin) {