pinokiod 7.2.18 → 7.3.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.
- package/Dockerfile +2 -0
- package/kernel/api/index.js +13 -179
- package/kernel/api/process/index.js +44 -99
- package/kernel/bin/conda-pins.js +53 -0
- package/kernel/bin/conda.js +35 -6
- package/kernel/bin/huggingface.js +1 -1
- package/kernel/bin/index.js +15 -2
- package/kernel/environment.js +11 -205
- package/kernel/git.js +13 -0
- package/kernel/index.js +1 -64
- package/kernel/plugin.js +58 -6
- package/kernel/prototype.js +0 -4
- package/kernel/shell.js +2 -23
- package/kernel/util.js +0 -60
- package/package.json +1 -1
- package/server/index.js +171 -229
- package/server/lib/content_validation.js +33 -47
- package/server/public/common.js +29 -103
- package/server/public/create-launcher.js +31 -4
- package/server/public/electron.css +6 -0
- package/server/public/style.css +0 -337
- package/server/public/task-launcher.css +3 -11
- package/server/public/task-launcher.js +32 -5
- package/server/public/universal-launcher.js +26 -3
- package/server/socket.js +11 -22
- package/server/views/app.ejs +30 -167
- package/server/views/d.ejs +35 -33
- package/server/views/editor.ejs +4 -25
- package/server/views/partials/main_sidebar.ejs +0 -1
- package/server/views/partials/menu.ejs +1 -1
- package/server/views/pre.ejs +1 -1
- package/server/views/shell.ejs +3 -11
- package/server/views/task_launch.ejs +10 -10
- package/server/views/terminal.ejs +5 -34
- package/spec/INSTRUCTION_SYNC.md +5 -5
- package/kernel/agent_instructions.js +0 -166
- package/kernel/api/shell_run_template.js +0 -273
- package/kernel/api/uri/index.js +0 -51
- package/kernel/plugin_sources.js +0 -289
- package/kernel/watch/context.js +0 -42
- package/kernel/watch/drivers/fs.js +0 -71
- package/kernel/watch/drivers/poll.js +0 -33
- package/kernel/watch/index.js +0 -185
- package/server/features/index.js +0 -13
- package/server/features/notes/index.js +0 -41
- package/server/features/notes/parser.js +0 -174
- package/server/features/notes/public/notes.css +0 -955
- package/server/features/notes/public/notes.js +0 -1149
- package/server/features/notes/registry_import.js +0 -412
- package/server/features/notes/routes.js +0 -156
- package/server/features/notes/service.js +0 -326
- package/server/features/notes/watcher.js +0 -74
- package/server/lib/workspace_catalog.js +0 -151
- package/server/lib/workspace_runtime.js +0 -390
- package/server/public/tasker.css +0 -336
- package/server/public/tasker.js +0 -407
- package/server/routes/workspaces.js +0 -44
- package/server/views/partials/workspace_row.ejs +0 -61
- package/server/views/tasker.ejs +0 -40
- package/server/views/workspaces.ejs +0 -813
- package/system/plugin/antigravity/antigravity.png +0 -0
- package/system/plugin/antigravity/pinokio.js +0 -35
- package/system/plugin/claude/claude.png +0 -0
- package/system/plugin/claude/pinokio.js +0 -61
- package/system/plugin/claude-auto/claude.png +0 -0
- package/system/plugin/claude-auto/pinokio.js +0 -72
- package/system/plugin/claude-desktop/icon.jpeg +0 -0
- package/system/plugin/claude-desktop/pinokio.js +0 -37
- package/system/plugin/codex/openai.webp +0 -0
- package/system/plugin/codex/pinokio.js +0 -56
- package/system/plugin/codex-auto/openai.webp +0 -0
- package/system/plugin/codex-auto/pinokio.js +0 -63
- package/system/plugin/codex-desktop/icon.png +0 -0
- package/system/plugin/codex-desktop/pinokio.js +0 -37
- package/system/plugin/crush/crush.png +0 -0
- package/system/plugin/crush/pinokio.js +0 -29
- package/system/plugin/cursor/cursor.jpeg +0 -0
- package/system/plugin/cursor/pinokio.js +0 -37
- package/system/plugin/gemini/gemini.jpeg +0 -0
- package/system/plugin/gemini/pinokio.js +0 -38
- package/system/plugin/gemini-auto/gemini.jpeg +0 -0
- package/system/plugin/gemini-auto/pinokio.js +0 -41
- package/system/plugin/qwen/pinokio.js +0 -48
- package/system/plugin/qwen/qwen.png +0 -0
- package/system/plugin/vscode/pinokio.js +0 -34
- package/system/plugin/vscode/vscode.png +0 -0
- package/system/plugin/windsurf/pinokio.js +0 -37
- package/system/plugin/windsurf/windsurf.png +0 -0
- package/test/plugin-sources.test.js +0 -45
package/server/public/tasker.js
DELETED
|
@@ -1,407 +0,0 @@
|
|
|
1
|
-
(function(window, document) {
|
|
2
|
-
"use strict";
|
|
3
|
-
|
|
4
|
-
const VARIABLE_FILTER_KEYS = new Set([
|
|
5
|
-
"var",
|
|
6
|
-
"vars",
|
|
7
|
-
"variable",
|
|
8
|
-
"variables",
|
|
9
|
-
"require",
|
|
10
|
-
"requires"
|
|
11
|
-
]);
|
|
12
|
-
const PASSTHROUGH_KEYS = new Set([
|
|
13
|
-
"tool",
|
|
14
|
-
"folderName"
|
|
15
|
-
]);
|
|
16
|
-
const TASK_INPUT_NAME_PATTERN = /^[a-zA-Z0-9_][a-zA-Z0-9_.-]*$/;
|
|
17
|
-
|
|
18
|
-
function normalizeText(value) {
|
|
19
|
-
return String(value || "").replace(/\s+/g, " ").trim();
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
function normalizeTaskInputName(value) {
|
|
23
|
-
const normalized = String(value || "").trim();
|
|
24
|
-
return TASK_INPUT_NAME_PATTERN.test(normalized) ? normalized : "";
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function splitVariableList(value) {
|
|
28
|
-
return String(value || "")
|
|
29
|
-
.split(/[,\s]+/)
|
|
30
|
-
.map(normalizeTaskInputName)
|
|
31
|
-
.filter(Boolean);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
function getRequiredVariables(params) {
|
|
35
|
-
const variables = new Set();
|
|
36
|
-
VARIABLE_FILTER_KEYS.forEach((key) => {
|
|
37
|
-
params.getAll(key).forEach((value) => {
|
|
38
|
-
splitVariableList(value).forEach((name) => variables.add(name));
|
|
39
|
-
});
|
|
40
|
-
});
|
|
41
|
-
return Array.from(variables);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
function getInitialSearchQuery(params) {
|
|
45
|
-
return (params.get("q") || params.get("search") || "").trim();
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
function getTemplateVariableNames(template) {
|
|
49
|
-
const names = new Set();
|
|
50
|
-
const regex = /{{\s*([a-zA-Z0-9_][a-zA-Z0-9_.-]*)\s*}}/g;
|
|
51
|
-
let match;
|
|
52
|
-
while ((match = regex.exec(String(template || ""))) !== null) {
|
|
53
|
-
names.add(match[1]);
|
|
54
|
-
}
|
|
55
|
-
return Array.from(names);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
function getTaskVariableSet(task) {
|
|
59
|
-
const names = new Set();
|
|
60
|
-
const inputs = Array.isArray(task && task.inputs) ? task.inputs : [];
|
|
61
|
-
inputs.forEach((input) => {
|
|
62
|
-
const name = normalizeTaskInputName(input && input.name);
|
|
63
|
-
if (name) {
|
|
64
|
-
names.add(name);
|
|
65
|
-
}
|
|
66
|
-
});
|
|
67
|
-
getTemplateVariableNames(task && task.template).forEach((name) => {
|
|
68
|
-
names.add(name);
|
|
69
|
-
});
|
|
70
|
-
return names;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
function taskMatchesRequiredVariables(task, requiredVariables) {
|
|
74
|
-
if (!requiredVariables.length) {
|
|
75
|
-
return true;
|
|
76
|
-
}
|
|
77
|
-
const taskVariables = getTaskVariableSet(task);
|
|
78
|
-
return requiredVariables.every((name) => taskVariables.has(name));
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
function formatTaskTemplateSummary(task) {
|
|
82
|
-
const preview = normalizeText((task && (task.template || task.description)) || "");
|
|
83
|
-
if (!preview) {
|
|
84
|
-
return "Task";
|
|
85
|
-
}
|
|
86
|
-
return preview.length > 150 ? `${preview.slice(0, 147).trimEnd()}...` : preview;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
function formatRecentUsage(value) {
|
|
90
|
-
const timestamp = Date.parse(typeof value === "string" ? value : "");
|
|
91
|
-
if (!Number.isFinite(timestamp)) {
|
|
92
|
-
return "";
|
|
93
|
-
}
|
|
94
|
-
const diffMs = Math.max(0, Date.now() - timestamp);
|
|
95
|
-
const dayMs = 24 * 60 * 60 * 1000;
|
|
96
|
-
const diffDays = Math.floor(diffMs / dayMs);
|
|
97
|
-
if (diffDays === 0) return "Used today";
|
|
98
|
-
if (diffDays === 1) return "Used yesterday";
|
|
99
|
-
if (diffDays < 7) return `Used ${diffDays}d ago`;
|
|
100
|
-
if (diffDays < 30) return `Used ${Math.floor(diffDays / 7)}w ago`;
|
|
101
|
-
if (diffDays < 365) return `Used ${Math.floor(diffDays / 30)}mo ago`;
|
|
102
|
-
return `Used ${Math.floor(diffDays / 365)}y ago`;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
function getTaskHref(task, params) {
|
|
106
|
-
const id = task && typeof task.id === "string" ? task.id.trim() : "";
|
|
107
|
-
if (!id) {
|
|
108
|
-
return "/tasks";
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
const taskVariables = getTaskVariableSet(task);
|
|
112
|
-
const url = new URL("/task", window.location.origin);
|
|
113
|
-
url.searchParams.set("id", id);
|
|
114
|
-
|
|
115
|
-
params.forEach((value, key) => {
|
|
116
|
-
if (key.startsWith("input.")) {
|
|
117
|
-
const inputName = normalizeTaskInputName(key.slice("input.".length));
|
|
118
|
-
if (inputName && taskVariables.has(inputName)) {
|
|
119
|
-
url.searchParams.set(`input.${inputName}`, value);
|
|
120
|
-
}
|
|
121
|
-
return;
|
|
122
|
-
}
|
|
123
|
-
if (PASSTHROUGH_KEYS.has(key) && value) {
|
|
124
|
-
url.searchParams.set(key, value);
|
|
125
|
-
}
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
return `${url.pathname}${url.search}`;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
function getSearchText(task) {
|
|
132
|
-
const inputs = Array.isArray(task && task.inputs) ? task.inputs : [];
|
|
133
|
-
return [
|
|
134
|
-
task && task.id,
|
|
135
|
-
task && task.ref,
|
|
136
|
-
task && task.title,
|
|
137
|
-
task && task.description,
|
|
138
|
-
task && task.template,
|
|
139
|
-
task && task.path,
|
|
140
|
-
task && task.target,
|
|
141
|
-
...inputs.flatMap((input) => [
|
|
142
|
-
input && input.name,
|
|
143
|
-
input && input.label
|
|
144
|
-
])
|
|
145
|
-
].filter(Boolean).join(" ").toLowerCase();
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
function createTaskRow(task, params) {
|
|
149
|
-
const row = document.createElement("a");
|
|
150
|
-
row.className = "tasker-row";
|
|
151
|
-
row.href = getTaskHref(task, params);
|
|
152
|
-
row.tabIndex = -1;
|
|
153
|
-
|
|
154
|
-
const icon = document.createElement("span");
|
|
155
|
-
icon.className = "tasker-row-icon";
|
|
156
|
-
icon.setAttribute("aria-hidden", "true");
|
|
157
|
-
const iconGlyph = document.createElement("i");
|
|
158
|
-
iconGlyph.className = "fa-solid fa-bookmark";
|
|
159
|
-
icon.appendChild(iconGlyph);
|
|
160
|
-
row.appendChild(icon);
|
|
161
|
-
|
|
162
|
-
const copy = document.createElement("span");
|
|
163
|
-
copy.className = "tasker-row-copy";
|
|
164
|
-
|
|
165
|
-
const label = document.createElement("span");
|
|
166
|
-
label.className = "tasker-row-label";
|
|
167
|
-
label.textContent = (task && (task.title || task.id)) || "Untitled task";
|
|
168
|
-
copy.appendChild(label);
|
|
169
|
-
|
|
170
|
-
const meta = document.createElement("span");
|
|
171
|
-
meta.className = "tasker-row-meta";
|
|
172
|
-
const metaBits = [formatTaskTemplateSummary(task)];
|
|
173
|
-
const inputs = Array.isArray(task && task.inputs) ? task.inputs : [];
|
|
174
|
-
if (inputs.length > 0) {
|
|
175
|
-
metaBits.push(`${inputs.length} input${inputs.length === 1 ? "" : "s"}`);
|
|
176
|
-
}
|
|
177
|
-
const usage = formatRecentUsage(task && task.last_used_at);
|
|
178
|
-
if (usage) {
|
|
179
|
-
metaBits.push(usage);
|
|
180
|
-
}
|
|
181
|
-
meta.textContent = metaBits.filter(Boolean).join(" - ");
|
|
182
|
-
copy.appendChild(meta);
|
|
183
|
-
|
|
184
|
-
row.appendChild(copy);
|
|
185
|
-
|
|
186
|
-
const hint = document.createElement("span");
|
|
187
|
-
hint.className = "tasker-row-hint";
|
|
188
|
-
hint.setAttribute("aria-hidden", "true");
|
|
189
|
-
const hintGlyph = document.createElement("i");
|
|
190
|
-
hintGlyph.className = "fa-solid fa-chevron-right";
|
|
191
|
-
hint.appendChild(hintGlyph);
|
|
192
|
-
row.appendChild(hint);
|
|
193
|
-
|
|
194
|
-
return row;
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
function initTasker() {
|
|
198
|
-
const root = document.querySelector("[data-tasker]");
|
|
199
|
-
if (!root) {
|
|
200
|
-
return;
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
const searchInput = root.querySelector("[data-tasker-search]");
|
|
204
|
-
const clearButton = root.querySelector("[data-tasker-clear]");
|
|
205
|
-
const status = root.querySelector("[data-tasker-status]");
|
|
206
|
-
const list = root.querySelector("[data-tasker-list]");
|
|
207
|
-
const empty = root.querySelector("[data-tasker-empty]");
|
|
208
|
-
const params = new URLSearchParams(window.location.search);
|
|
209
|
-
const requiredVariables = getRequiredVariables(params);
|
|
210
|
-
const initialSearchQuery = getInitialSearchQuery(params);
|
|
211
|
-
let tasks = [];
|
|
212
|
-
let sourceTaskCount = 0;
|
|
213
|
-
let visibleTasks = [];
|
|
214
|
-
let selectedIndex = -1;
|
|
215
|
-
let loading = true;
|
|
216
|
-
let error = "";
|
|
217
|
-
|
|
218
|
-
if (searchInput && initialSearchQuery) {
|
|
219
|
-
searchInput.value = initialSearchQuery;
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
function syncSelectedRow() {
|
|
223
|
-
if (!list) {
|
|
224
|
-
return;
|
|
225
|
-
}
|
|
226
|
-
const rows = Array.from(list.querySelectorAll(".tasker-row"));
|
|
227
|
-
rows.forEach((row, index) => {
|
|
228
|
-
const selected = index === selectedIndex;
|
|
229
|
-
row.classList.toggle("selected", selected);
|
|
230
|
-
row.setAttribute("aria-selected", selected ? "true" : "false");
|
|
231
|
-
if (selected) {
|
|
232
|
-
row.scrollIntoView({
|
|
233
|
-
block: "nearest"
|
|
234
|
-
});
|
|
235
|
-
}
|
|
236
|
-
});
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
function selectResult(index) {
|
|
240
|
-
if (!visibleTasks.length) {
|
|
241
|
-
selectedIndex = -1;
|
|
242
|
-
syncSelectedRow();
|
|
243
|
-
return;
|
|
244
|
-
}
|
|
245
|
-
const max = visibleTasks.length - 1;
|
|
246
|
-
selectedIndex = Math.max(0, Math.min(index, max));
|
|
247
|
-
syncSelectedRow();
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
function moveSelection(delta) {
|
|
251
|
-
if (!visibleTasks.length) {
|
|
252
|
-
return;
|
|
253
|
-
}
|
|
254
|
-
if (selectedIndex < 0) {
|
|
255
|
-
selectResult(delta > 0 ? 0 : visibleTasks.length - 1);
|
|
256
|
-
return;
|
|
257
|
-
}
|
|
258
|
-
const nextIndex = (selectedIndex + delta + visibleTasks.length) % visibleTasks.length;
|
|
259
|
-
selectResult(nextIndex);
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
function openSelectedResult() {
|
|
263
|
-
if (!visibleTasks.length || selectedIndex < 0) {
|
|
264
|
-
return;
|
|
265
|
-
}
|
|
266
|
-
const row = list ? list.querySelectorAll(".tasker-row")[selectedIndex] : null;
|
|
267
|
-
const href = row ? row.getAttribute("href") : "";
|
|
268
|
-
if (href) {
|
|
269
|
-
window.location.href = href;
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
function setStatus(copy) {
|
|
274
|
-
if (status) {
|
|
275
|
-
status.textContent = copy || "";
|
|
276
|
-
status.hidden = !copy;
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
function render() {
|
|
281
|
-
if (!list || !empty || !searchInput) {
|
|
282
|
-
return;
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
const query = searchInput.value.trim().toLowerCase();
|
|
286
|
-
visibleTasks = query
|
|
287
|
-
? tasks.filter((task) => getSearchText(task).includes(query))
|
|
288
|
-
: tasks.slice();
|
|
289
|
-
if (visibleTasks.length) {
|
|
290
|
-
selectedIndex = selectedIndex < 0 ? 0 : Math.min(selectedIndex, visibleTasks.length - 1);
|
|
291
|
-
} else {
|
|
292
|
-
selectedIndex = -1;
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
list.innerHTML = "";
|
|
296
|
-
visibleTasks.forEach((task, index) => {
|
|
297
|
-
const row = createTaskRow(task, params);
|
|
298
|
-
row.addEventListener("mouseenter", () => {
|
|
299
|
-
selectedIndex = index;
|
|
300
|
-
syncSelectedRow();
|
|
301
|
-
});
|
|
302
|
-
list.appendChild(row);
|
|
303
|
-
});
|
|
304
|
-
syncSelectedRow();
|
|
305
|
-
|
|
306
|
-
const hasRows = visibleTasks.length > 0;
|
|
307
|
-
list.hidden = !hasRows;
|
|
308
|
-
empty.hidden = hasRows || loading || Boolean(error);
|
|
309
|
-
|
|
310
|
-
if (clearButton) {
|
|
311
|
-
clearButton.hidden = !query;
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
if (loading) {
|
|
315
|
-
setStatus("Loading tasks...");
|
|
316
|
-
} else if (error) {
|
|
317
|
-
setStatus(error);
|
|
318
|
-
} else if (!tasks.length) {
|
|
319
|
-
setStatus("");
|
|
320
|
-
empty.hidden = false;
|
|
321
|
-
empty.textContent = requiredVariables.length && sourceTaskCount
|
|
322
|
-
? `No tasks match ${requiredVariables.join(", ")}.`
|
|
323
|
-
: "No saved tasks yet.";
|
|
324
|
-
} else if (query && !hasRows) {
|
|
325
|
-
setStatus("");
|
|
326
|
-
empty.hidden = false;
|
|
327
|
-
empty.textContent = "No tasks match this search.";
|
|
328
|
-
} else {
|
|
329
|
-
const noun = visibleTasks.length === 1 ? "task" : "tasks";
|
|
330
|
-
setStatus(`${visibleTasks.length} ${noun}`);
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
async function loadTasks() {
|
|
335
|
-
loading = true;
|
|
336
|
-
error = "";
|
|
337
|
-
render();
|
|
338
|
-
try {
|
|
339
|
-
const response = await fetch("/api/tasks", {
|
|
340
|
-
cache: "no-store"
|
|
341
|
-
});
|
|
342
|
-
const payload = await response.json().catch(() => null);
|
|
343
|
-
if (!response.ok || !payload || !Array.isArray(payload.items)) {
|
|
344
|
-
throw new Error("Failed to load tasks.");
|
|
345
|
-
}
|
|
346
|
-
sourceTaskCount = payload.items.length;
|
|
347
|
-
tasks = payload.items.filter((task) => taskMatchesRequiredVariables(task, requiredVariables));
|
|
348
|
-
} catch (loadError) {
|
|
349
|
-
tasks = [];
|
|
350
|
-
sourceTaskCount = 0;
|
|
351
|
-
error = loadError && loadError.message ? loadError.message : "Failed to load tasks.";
|
|
352
|
-
} finally {
|
|
353
|
-
loading = false;
|
|
354
|
-
render();
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
if (searchInput) {
|
|
359
|
-
searchInput.addEventListener("input", render);
|
|
360
|
-
searchInput.addEventListener("keydown", (event) => {
|
|
361
|
-
if (event.key === "ArrowDown") {
|
|
362
|
-
event.preventDefault();
|
|
363
|
-
moveSelection(1);
|
|
364
|
-
return;
|
|
365
|
-
}
|
|
366
|
-
if (event.key === "ArrowUp") {
|
|
367
|
-
event.preventDefault();
|
|
368
|
-
moveSelection(-1);
|
|
369
|
-
return;
|
|
370
|
-
}
|
|
371
|
-
if (event.key === "Enter") {
|
|
372
|
-
event.preventDefault();
|
|
373
|
-
openSelectedResult();
|
|
374
|
-
return;
|
|
375
|
-
}
|
|
376
|
-
if (event.key === "Home" && (event.metaKey || event.ctrlKey)) {
|
|
377
|
-
event.preventDefault();
|
|
378
|
-
selectResult(0);
|
|
379
|
-
return;
|
|
380
|
-
}
|
|
381
|
-
if (event.key === "End" && (event.metaKey || event.ctrlKey)) {
|
|
382
|
-
event.preventDefault();
|
|
383
|
-
selectResult(visibleTasks.length - 1);
|
|
384
|
-
}
|
|
385
|
-
});
|
|
386
|
-
window.requestAnimationFrame(() => {
|
|
387
|
-
searchInput.focus();
|
|
388
|
-
searchInput.select();
|
|
389
|
-
});
|
|
390
|
-
}
|
|
391
|
-
if (clearButton && searchInput) {
|
|
392
|
-
clearButton.addEventListener("click", () => {
|
|
393
|
-
searchInput.value = "";
|
|
394
|
-
render();
|
|
395
|
-
searchInput.focus();
|
|
396
|
-
});
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
loadTasks();
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
if (document.readyState === "loading") {
|
|
403
|
-
document.addEventListener("DOMContentLoaded", initTasker, { once: true });
|
|
404
|
-
} else {
|
|
405
|
-
initTasker();
|
|
406
|
-
}
|
|
407
|
-
})(window, document);
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
const express = require("express")
|
|
2
|
-
|
|
3
|
-
function registerWorkspacesRoutes(app, options = {}) {
|
|
4
|
-
const {
|
|
5
|
-
workspaceCatalog,
|
|
6
|
-
composePeerAccessPayload,
|
|
7
|
-
getTheme,
|
|
8
|
-
getPeers,
|
|
9
|
-
getCurrentHost,
|
|
10
|
-
getPortal,
|
|
11
|
-
} = options
|
|
12
|
-
|
|
13
|
-
if (!workspaceCatalog) {
|
|
14
|
-
throw new Error("workspaceCatalog is required")
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const router = express.Router()
|
|
18
|
-
|
|
19
|
-
router.get("/workspaces", async (req, res, next) => {
|
|
20
|
-
try {
|
|
21
|
-
const catalog = await workspaceCatalog.list({ sort: req.query.sort })
|
|
22
|
-
res.render("workspaces", {
|
|
23
|
-
title: "Workspaces",
|
|
24
|
-
sidebarSelected: "workspaces",
|
|
25
|
-
workspaceCatalog: catalog,
|
|
26
|
-
theme: getTheme ? getTheme(req) : null,
|
|
27
|
-
peers: getPeers ? getPeers() : [],
|
|
28
|
-
currentHost: getCurrentHost ? getCurrentHost(req) : null,
|
|
29
|
-
portal: getPortal ? getPortal(req) : null,
|
|
30
|
-
peerAccess: composePeerAccessPayload ? composePeerAccessPayload(req) : null,
|
|
31
|
-
})
|
|
32
|
-
} catch (err) {
|
|
33
|
-
next(err)
|
|
34
|
-
}
|
|
35
|
-
})
|
|
36
|
-
|
|
37
|
-
router.get("/activity", (req, res) => {
|
|
38
|
-
res.redirect("/workspaces")
|
|
39
|
-
})
|
|
40
|
-
|
|
41
|
-
app.use(router)
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
module.exports = registerWorkspacesRoutes
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
<%
|
|
2
|
-
const shellCount = workspace.counts && Number.isFinite(workspace.counts.shells) ? workspace.counts.shells : 0;
|
|
3
|
-
const scriptCount = workspace.counts && Number.isFinite(workspace.counts.scripts) ? workspace.counts.scripts : 0;
|
|
4
|
-
const noteCount = workspace.counts && Number.isFinite(workspace.counts.notes) ? workspace.counts.notes : 0;
|
|
5
|
-
const shellTitles = Array.isArray(workspace.shells) ? workspace.shells.map((shell) => shell.title || shell.id || "").join(" ") : "";
|
|
6
|
-
const scriptTitles = Array.isArray(workspace.scripts) ? workspace.scripts.map((script) => script.title || script.id || "").join(" ") : "";
|
|
7
|
-
const note = workspace.note || null;
|
|
8
|
-
const noteId = note && note.id ? note.id : `note-${index}`;
|
|
9
|
-
const searchText = [workspace.name, workspace.cwd, shellTitles, scriptTitles, note && note.title].filter(Boolean).join(" ");
|
|
10
|
-
const modifiedLabel = dateLabel(workspace.modifiedAt);
|
|
11
|
-
const details = [];
|
|
12
|
-
if (shellCount > 0) details.push(plural(shellCount, "terminal"));
|
|
13
|
-
if (scriptCount > 0) details.push(plural(scriptCount, "script"));
|
|
14
|
-
if (noteCount > 0) details.push(noteCount === 1 ? "Note ready" : plural(noteCount, "note"));
|
|
15
|
-
if (modifiedLabel) details.push(modifiedLabel);
|
|
16
|
-
%>
|
|
17
|
-
<div
|
|
18
|
-
class="workspace-card workspace-line line align-top"
|
|
19
|
-
data-cwd="<%= workspace.cwd %>"
|
|
20
|
-
data-name="<%= workspace.name %>"
|
|
21
|
-
data-index="<%= index %>"
|
|
22
|
-
data-launch-count-total="<%= workspace.usageCount || 0 %>"
|
|
23
|
-
data-last-launch-at="<%= workspace.lastOpenedAt || workspace.modifiedAt || "" %>"
|
|
24
|
-
data-search="<%= searchText %>"
|
|
25
|
-
>
|
|
26
|
-
<h3>
|
|
27
|
-
<div class="workspace-icon item-icon">
|
|
28
|
-
<i class="fa-solid <%= workspace.running ? "fa-folder-open" : "fa-folder" %>" aria-hidden="true"></i>
|
|
29
|
-
</div>
|
|
30
|
-
<div class="col">
|
|
31
|
-
<div class="title">
|
|
32
|
-
<i class="fa-solid fa-circle" aria-hidden="true"></i>
|
|
33
|
-
<span><%= workspace.name || "Workspace" %></span>
|
|
34
|
-
</div>
|
|
35
|
-
<div class="uri"><%= workspace.cwd %></div>
|
|
36
|
-
<% if (details.length) { %>
|
|
37
|
-
<div class="description"><%= details.join(" / ") %></div>
|
|
38
|
-
<% } %>
|
|
39
|
-
<div class="menu-btns">
|
|
40
|
-
<% if (workspace.primaryUrl && shellCount === 1) { %>
|
|
41
|
-
<a class="btn" href="<%= workspace.primaryUrl %>" title="Open terminal"><i class="fa-solid fa-terminal" aria-hidden="true"></i> Terminal</a>
|
|
42
|
-
<% } else if (shellCount > 1) { %>
|
|
43
|
-
<button class="btn" type="button" data-open-workspace="<%= workspace.cwd %>" data-workspace-modal-mode="terminals" title="Open terminals"><i class="fa-solid fa-terminal" aria-hidden="true"></i> Terminals</button>
|
|
44
|
-
<% } %>
|
|
45
|
-
<% if (workspace.launchUrl) { %>
|
|
46
|
-
<button class="btn" type="button" data-open-workspace="<%= workspace.cwd %>" data-workspace-modal-mode="session" title="Start session"><i class="fa-solid fa-play" aria-hidden="true"></i> Start</button>
|
|
47
|
-
<% } %>
|
|
48
|
-
<button class="btn" type="button" data-open-path="<%= workspace.cwd %>" title="Open folder"><i class="fa-solid fa-folder-open" aria-hidden="true"></i> Folder</button>
|
|
49
|
-
<% if (note && note.notePath) { %>
|
|
50
|
-
<button class="btn" type="button" data-open-path="<%= note.notePath %>" title="Open note"><i class="fa-solid fa-file-lines" aria-hidden="true"></i> Note</button>
|
|
51
|
-
<% if (note.excerpt) { %>
|
|
52
|
-
<button class="btn" type="button" data-preview-toggle="<%= noteId %>"><i class="fa-solid fa-eye" aria-hidden="true"></i> Preview</button>
|
|
53
|
-
<% } %>
|
|
54
|
-
<% } %>
|
|
55
|
-
</div>
|
|
56
|
-
<% if (note && note.excerpt) { %>
|
|
57
|
-
<div class="workspace-note-preview" data-preview-panel="<%= noteId %>" hidden><%= note.excerpt %></div>
|
|
58
|
-
<% } %>
|
|
59
|
-
</div>
|
|
60
|
-
</h3>
|
|
61
|
-
</div>
|
package/server/views/tasker.ejs
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
<!doctype html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="utf-8">
|
|
5
|
-
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
|
-
<title>Tasker</title>
|
|
7
|
-
<link href="/css/fontawesome.min.css" rel="stylesheet">
|
|
8
|
-
<link href="/css/solid.min.css" rel="stylesheet">
|
|
9
|
-
<link href="/css/brands.min.css" rel="stylesheet">
|
|
10
|
-
<link href="/noty.css" rel="stylesheet">
|
|
11
|
-
<link href="/style.css" rel="stylesheet">
|
|
12
|
-
<link href="/universal-launcher.css" rel="stylesheet">
|
|
13
|
-
<link href="/tasker.css" rel="stylesheet">
|
|
14
|
-
<script src="/tasker.js" defer></script>
|
|
15
|
-
<% if (agent === "electron") { %>
|
|
16
|
-
<link href="/electron.css" rel="stylesheet"/>
|
|
17
|
-
<% } %>
|
|
18
|
-
</head>
|
|
19
|
-
<body class="<%= theme %> tasker-page" data-agent="<%= agent %>">
|
|
20
|
-
<%- include('partials/app_navheader', { agent }) %>
|
|
21
|
-
<main class="tasker-main" aria-label="Tasker">
|
|
22
|
-
<section class="tasker-panel" data-tasker>
|
|
23
|
-
<div class="tasker-search-wrap">
|
|
24
|
-
<div class="tasker-search-field">
|
|
25
|
-
<i class="fa-solid fa-magnifying-glass" aria-hidden="true"></i>
|
|
26
|
-
<input class="tasker-search-input" type="search" aria-label="Search tasks" placeholder="Search tasks" autocomplete="off" spellcheck="false" data-tasker-search>
|
|
27
|
-
<button class="tasker-search-clear" type="button" aria-label="Clear search" data-tasker-clear hidden>
|
|
28
|
-
<i class="fa-solid fa-xmark" aria-hidden="true"></i>
|
|
29
|
-
</button>
|
|
30
|
-
</div>
|
|
31
|
-
</div>
|
|
32
|
-
|
|
33
|
-
<div class="tasker-status" role="status" data-tasker-status>Loading tasks...</div>
|
|
34
|
-
<div class="tasker-list" data-tasker-list hidden></div>
|
|
35
|
-
<div class="tasker-empty" data-tasker-empty hidden>No tasks found.</div>
|
|
36
|
-
</section>
|
|
37
|
-
</main>
|
|
38
|
-
<%- include('partials/app_common_scripts') %>
|
|
39
|
-
</body>
|
|
40
|
-
</html>
|