@hyperdreamer/pi-webui 1.14.0 → 1.15.0
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/dist/client/assets/{CodeViewer-BEbclxBf.js → CodeViewer-BGClPFoI.js} +1 -1
- package/dist/client/assets/{UnifiedDiffViewer-DXWhrIST.js → UnifiedDiffViewer-I9Fc0TRx.js} +1 -1
- package/dist/client/assets/{index-2EIg2vwJ.js → index-DEhtRZU8.js} +56 -56
- package/dist/client/index.html +1 -1
- package/dist/pi-webui-plugins/workspace-tasks/config.js +79 -0
- package/dist/pi-webui-plugins/workspace-tasks/tasksPanelElement.js +926 -142
- package/dist/pi-webui-plugins/workspace-tasks/workspaceTasksClient.js +204 -9
- package/dist/server/sessions/piSessionService.js +22 -12
- package/dist/server/sessions/piSessionService.js.map +1 -1
- package/dist/server/sessions/sessionCommandService.js +38 -0
- package/dist/server/sessions/sessionCommandService.js.map +1 -1
- package/docs/plugins.md +42 -2
- package/package.json +1 -1
package/dist/client/index.html
CHANGED
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
html, body { margin: 0; height: 100%; overflow: hidden; background: var(--pi-bg); color: var(--pi-text); }
|
|
55
55
|
body { min-height: 100dvh; }
|
|
56
56
|
</style>
|
|
57
|
-
<script type="module" crossorigin src="./assets/index-
|
|
57
|
+
<script type="module" crossorigin src="./assets/index-DEhtRZU8.js"></script>
|
|
58
58
|
<link rel="modulepreload" crossorigin href="./assets/vendor-editor-core-vyMPzMNA.js">
|
|
59
59
|
<link rel="modulepreload" crossorigin href="./assets/vendor-editor-languages-DlEQaRIv.js">
|
|
60
60
|
<link rel="modulepreload" crossorigin href="./assets/vendor-terminal-D8k4UKM2.js">
|
|
@@ -2,6 +2,80 @@
|
|
|
2
2
|
export const TASKS_CONFIG_PATH = ".pi-webui/tasks.json";
|
|
3
3
|
export const TASKS_CONFIG_VERSION = 1;
|
|
4
4
|
const taskIdPattern = /^[a-z][a-z0-9.-]*$/u;
|
|
5
|
+
export const emptyWorkspaceTasksConfig = {
|
|
6
|
+
version: TASKS_CONFIG_VERSION,
|
|
7
|
+
tasks: [],
|
|
8
|
+
};
|
|
9
|
+
export function suggestWorkspaceTaskId(title) {
|
|
10
|
+
const id = title.toLowerCase().replace(/[^a-z0-9]+/gu, "-").replace(/^-+|-+$/gu, "");
|
|
11
|
+
if (id === "")
|
|
12
|
+
return "task";
|
|
13
|
+
return /^\d/u.test(id) ? `task-${id}` : id;
|
|
14
|
+
}
|
|
15
|
+
export function validateAndNormalizeDraft(draft, existingTasks, originalIndex) {
|
|
16
|
+
const id = draft.id.trim();
|
|
17
|
+
const title = draft.title.trim();
|
|
18
|
+
const description = draft.description.trim();
|
|
19
|
+
const group = draft.group.trim();
|
|
20
|
+
const errors = {};
|
|
21
|
+
if (id === "") {
|
|
22
|
+
errors.id = "ID is required.";
|
|
23
|
+
}
|
|
24
|
+
else if (!taskIdPattern.test(id)) {
|
|
25
|
+
errors.id = `ID must match ${taskIdPattern.source}.`;
|
|
26
|
+
}
|
|
27
|
+
else if (existingTasks.some((task, index) => index !== originalIndex && task.id === id)) {
|
|
28
|
+
errors.id = `Task ID "${id}" already exists.`;
|
|
29
|
+
}
|
|
30
|
+
if (title === "")
|
|
31
|
+
errors.title = "Title is required.";
|
|
32
|
+
if (draft.command.trim() === "")
|
|
33
|
+
errors.command = "Command script is required.";
|
|
34
|
+
if (Object.keys(errors).length > 0)
|
|
35
|
+
return { ok: false, errors };
|
|
36
|
+
return {
|
|
37
|
+
ok: true,
|
|
38
|
+
task: {
|
|
39
|
+
id,
|
|
40
|
+
title,
|
|
41
|
+
command: draft.command,
|
|
42
|
+
...(description === "" ? {} : { description }),
|
|
43
|
+
...(group === "" ? {} : { group }),
|
|
44
|
+
confirm: draft.confirm,
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
export function appendWorkspaceTask(config, task) {
|
|
49
|
+
return { version: config.version, tasks: [...config.tasks, task] };
|
|
50
|
+
}
|
|
51
|
+
export function replaceWorkspaceTaskAt(config, index, task) {
|
|
52
|
+
assertWorkspaceTaskIndex(config, index);
|
|
53
|
+
return {
|
|
54
|
+
version: config.version,
|
|
55
|
+
tasks: [...config.tasks.slice(0, index), task, ...config.tasks.slice(index + 1)],
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
export function removeWorkspaceTaskAt(config, index) {
|
|
59
|
+
assertWorkspaceTaskIndex(config, index);
|
|
60
|
+
return {
|
|
61
|
+
version: config.version,
|
|
62
|
+
tasks: [...config.tasks.slice(0, index), ...config.tasks.slice(index + 1)],
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
export function serializeWorkspaceTasksConfig(config) {
|
|
66
|
+
const canonicalConfig = {
|
|
67
|
+
version: config.version,
|
|
68
|
+
tasks: config.tasks.map((task) => ({
|
|
69
|
+
id: task.id,
|
|
70
|
+
title: task.title,
|
|
71
|
+
command: task.command,
|
|
72
|
+
...(task.description === undefined ? {} : { description: task.description }),
|
|
73
|
+
...(task.group === undefined ? {} : { group: task.group }),
|
|
74
|
+
confirm: task.confirm,
|
|
75
|
+
})),
|
|
76
|
+
};
|
|
77
|
+
return `${JSON.stringify(canonicalConfig, null, 2)}\n`;
|
|
78
|
+
}
|
|
5
79
|
export function parseTasksConfigText(text) {
|
|
6
80
|
let parsed;
|
|
7
81
|
try {
|
|
@@ -83,6 +157,11 @@ function optionalNonEmptyString(record, key, label) {
|
|
|
83
157
|
return invalid(`${label} ${key} must be a non-empty string when provided`);
|
|
84
158
|
return { ok: true, value };
|
|
85
159
|
}
|
|
160
|
+
function assertWorkspaceTaskIndex(config, index) {
|
|
161
|
+
if (!Number.isInteger(index) || index < 0 || index >= config.tasks.length) {
|
|
162
|
+
throw new RangeError(`Task index ${String(index)} is out of range`);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
86
165
|
function invalid(error) {
|
|
87
166
|
return { ok: false, error };
|
|
88
167
|
}
|