@symerian/symi 3.5.0 → 3.5.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/dist/build-info.json +3 -3
- package/dist/bundled/boot-md/handler.js +4 -4
- package/dist/bundled/session-memory/handler.js +4 -4
- package/dist/canvas-host/a2ui/.bundle.hash +1 -1
- package/dist/{chrome-C_I81hbq.js → chrome-B7-rO4i9.js} +4 -4
- package/dist/{chrome-BKUACyeO.js → chrome-DPjznJQ-.js} +4 -4
- package/dist/control-ui/css/revert-red-theme.md +141 -0
- package/dist/control-ui/css/style.css +5843 -0
- package/dist/control-ui/css/style.css.backup-2026-03-03-162525 +3546 -0
- package/dist/control-ui/css/style.css.backup-before-red-2026-03-03-162525 +3546 -0
- package/dist/control-ui/css/style.css.backup-before-red-theme-2026-03-03-162530 +3546 -0
- package/dist/control-ui/css/style.css.pre-2row +2165 -0
- package/dist/control-ui/css/style.css.pre-brand +1776 -0
- package/dist/control-ui/css/style.css.pre-history +1974 -0
- package/dist/control-ui/css/style.css.pre-nav +2264 -0
- package/dist/control-ui/css/style.css.pre-newsession +1898 -0
- package/dist/control-ui/css/style.css.pre-queue +2195 -0
- package/dist/control-ui/css/style.css.pre-red-prompt +2524 -0
- package/dist/control-ui/css/style.css.pre-stop +2239 -0
- package/dist/control-ui/css/style.css.pre-textarea +2184 -0
- package/dist/control-ui/css/style.css.pre-watchdog +1848 -0
- package/dist/control-ui/css/style.css.red-theme +2999 -0
- package/dist/control-ui/index.html +1049 -0
- package/dist/control-ui/js/app.js +1304 -0
- package/dist/control-ui/js/app.js.pre-2row +463 -0
- package/dist/control-ui/js/app.js.pre-heartbeat-filter +595 -0
- package/dist/control-ui/js/app.js.pre-newsession +408 -0
- package/dist/control-ui/js/app.js.pre-queue +476 -0
- package/dist/control-ui/js/app.js.pre-stop +564 -0
- package/dist/control-ui/js/app.js.pre-textarea +467 -0
- package/dist/control-ui/js/app.js.pre-watchdog +293 -0
- package/dist/control-ui/js/connections.js +438 -0
- package/dist/control-ui/js/gateway.js +233 -0
- package/dist/control-ui/js/gateway.js.pre-stop +110 -0
- package/dist/control-ui/js/history.js +732 -0
- package/dist/control-ui/js/logs.js +238 -0
- package/dist/control-ui/js/menu.js +232 -0
- package/dist/control-ui/js/menu.js.pre-nav +66 -0
- package/dist/control-ui/js/metrics.js +53 -0
- package/dist/control-ui/js/models.js +138 -0
- package/dist/control-ui/js/render.js +882 -0
- package/dist/control-ui/js/render.test.js +112 -0
- package/dist/control-ui/js/scheduling.js +461 -0
- package/dist/control-ui/js/settings.js +910 -0
- package/dist/control-ui/js/slash-autocomplete.js +168 -0
- package/dist/control-ui/js/subagents.js +560 -0
- package/dist/control-ui/js/utils.js +29 -0
- package/dist/control-ui/vendor/highlight.min.js +2518 -0
- package/dist/control-ui/vendor/marked.min.js +69 -0
- package/dist/{deliver-DyO3QD8O.js → deliver-DTRkeYm3.js} +4 -4
- package/dist/{deliver-Cjyb6h4g.js → deliver-oWGJwzFf.js} +4 -4
- package/dist/extensionAPI.js +4 -4
- package/dist/llm-slug-generator.js +4 -4
- package/dist/{manager-rvtFoeFT.js → manager-CFenq_aO.js} +1 -1
- package/dist/{manager-PTSjHNVq.js → manager-CsxTf96V.js} +1 -1
- package/dist/{pi-embedded-BPuUM-gD.js → pi-embedded-Cdub5Vs9.js} +10 -10
- package/dist/{pw-ai-BFS9ezWe.js → pw-ai-BOOB8qoi.js} +1 -1
- package/dist/{pw-ai-Cx-Ko_FL.js → pw-ai-D2pEVS5n.js} +1 -1
- package/dist/{synthesis-7UL3pCpj.js → synthesis-Be9nYyDd.js} +4 -4
- package/dist/{synthesis-fD8J2vag.js → synthesis-CBIT6Vnk.js} +4 -4
- package/dist/{unified-runner-BIiKFnNF.js → unified-runner-BVvvnjXW.js} +10 -10
- package/package.json +1 -1
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
// ── Slash command autocomplete for the prompt input ─────────────────────
|
|
2
|
+
// Fetches the chat command registry from the gateway via `chat.commands.list`
|
|
3
|
+
// and surfaces it as a dropdown when the user types `/` at the start of the
|
|
4
|
+
// prompt. Replaces the prior "you have to memorize the slash commands" UX.
|
|
5
|
+
|
|
6
|
+
(function () {
|
|
7
|
+
const promptInput = document.getElementById("prompt-input");
|
|
8
|
+
const promptRowMain = document.querySelector(".prompt-row-main");
|
|
9
|
+
if (!promptInput || !promptRowMain) {
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// Build the dropdown element once; show/hide via .open class.
|
|
14
|
+
const dropdown = document.createElement("div");
|
|
15
|
+
dropdown.className = "slash-autocomplete";
|
|
16
|
+
dropdown.id = "slash-autocomplete";
|
|
17
|
+
promptRowMain.parentElement.insertBefore(dropdown, promptRowMain);
|
|
18
|
+
|
|
19
|
+
let commands = [];
|
|
20
|
+
let filtered = [];
|
|
21
|
+
let selectedIndex = 0;
|
|
22
|
+
let isOpen = false;
|
|
23
|
+
|
|
24
|
+
// Fetch the command registry. The WebSocket handshake completes async, so
|
|
25
|
+
// we must wait for `gateway:connected` (dispatched by app.js after the
|
|
26
|
+
// gateway's connect event) before calling rpc — otherwise the rpc helper
|
|
27
|
+
// rejects with "gateway not connected" and we silently end up with an
|
|
28
|
+
// empty command list.
|
|
29
|
+
let loaded = false;
|
|
30
|
+
async function loadCommands() {
|
|
31
|
+
if (loaded) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
if (!window.gateway?.rpc) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
if (!window.gateway.ws || window.gateway.ws.readyState !== WebSocket.OPEN) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
try {
|
|
41
|
+
const result = await window.gateway.rpc("chat.commands.list", {});
|
|
42
|
+
commands = Array.isArray(result?.commands) ? result.commands : [];
|
|
43
|
+
loaded = true;
|
|
44
|
+
console.log("[slash-autocomplete] loaded", commands.length, "commands");
|
|
45
|
+
} catch (err) {
|
|
46
|
+
console.warn("[slash-autocomplete] failed to load commands:", err);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
// Try once now in case we attached after the event already fired.
|
|
50
|
+
void loadCommands();
|
|
51
|
+
// And on every connect event (covers initial connect + reconnects).
|
|
52
|
+
window.addEventListener("gateway:connected", () => {
|
|
53
|
+
void loadCommands();
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
function render() {
|
|
57
|
+
if (!isOpen || filtered.length === 0) {
|
|
58
|
+
dropdown.classList.remove("open");
|
|
59
|
+
dropdown.innerHTML = "";
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
dropdown.innerHTML = filtered
|
|
63
|
+
.slice(0, 8)
|
|
64
|
+
.map((cmd, i) => {
|
|
65
|
+
const name = cmd.nativeName ?? cmd.key;
|
|
66
|
+
const sel = i === selectedIndex ? " selected" : "";
|
|
67
|
+
const aliasText =
|
|
68
|
+
Array.isArray(cmd.textAliases) && cmd.textAliases.length > 0
|
|
69
|
+
? `<span class="slash-ac-alias">${escapeHtml(cmd.textAliases[0])}</span>`
|
|
70
|
+
: "";
|
|
71
|
+
return `<div class="slash-ac-item${sel}" data-index="${i}">
|
|
72
|
+
<span class="slash-ac-name">/${escapeHtml(name)}</span>
|
|
73
|
+
${aliasText}
|
|
74
|
+
<span class="slash-ac-desc">${escapeHtml(cmd.description ?? "")}</span>
|
|
75
|
+
</div>`;
|
|
76
|
+
})
|
|
77
|
+
.join("");
|
|
78
|
+
dropdown.classList.add("open");
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function escapeHtml(str) {
|
|
82
|
+
return String(str)
|
|
83
|
+
.replace(/&/g, "&")
|
|
84
|
+
.replace(/</g, "<")
|
|
85
|
+
.replace(/>/g, ">")
|
|
86
|
+
.replace(/"/g, """);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function refilter() {
|
|
90
|
+
const value = promptInput.value;
|
|
91
|
+
if (!value.startsWith("/")) {
|
|
92
|
+
isOpen = false;
|
|
93
|
+
render();
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
// Only the first token (no spaces) is the command query.
|
|
97
|
+
const query = value.slice(1).split(/\s/, 1)[0].toLowerCase();
|
|
98
|
+
filtered = commands.filter((cmd) => {
|
|
99
|
+
const name = (cmd.nativeName ?? cmd.key).toLowerCase();
|
|
100
|
+
if (name.startsWith(query)) {
|
|
101
|
+
return true;
|
|
102
|
+
}
|
|
103
|
+
if (Array.isArray(cmd.textAliases)) {
|
|
104
|
+
return cmd.textAliases.some((a) => a.toLowerCase().slice(1).startsWith(query));
|
|
105
|
+
}
|
|
106
|
+
return false;
|
|
107
|
+
});
|
|
108
|
+
selectedIndex = 0;
|
|
109
|
+
isOpen = filtered.length > 0;
|
|
110
|
+
render();
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function applySelection() {
|
|
114
|
+
const cmd = filtered[selectedIndex];
|
|
115
|
+
if (!cmd) {
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
const name = cmd.nativeName ?? cmd.key;
|
|
119
|
+
// Preserve any existing args after the first space.
|
|
120
|
+
const rest = promptInput.value.slice(1).split(/\s/).slice(1).join(" ");
|
|
121
|
+
promptInput.value =
|
|
122
|
+
cmd.acceptsArgs && !rest ? `/${name} ` : `/${name}${rest ? " " + rest : ""}`;
|
|
123
|
+
isOpen = false;
|
|
124
|
+
render();
|
|
125
|
+
promptInput.focus();
|
|
126
|
+
// Move caret to end.
|
|
127
|
+
promptInput.selectionStart = promptInput.selectionEnd = promptInput.value.length;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
promptInput.addEventListener("input", refilter);
|
|
131
|
+
|
|
132
|
+
promptInput.addEventListener("keydown", (e) => {
|
|
133
|
+
if (!isOpen) {
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
if (e.key === "ArrowDown") {
|
|
137
|
+
e.preventDefault();
|
|
138
|
+
selectedIndex = Math.min(selectedIndex + 1, Math.min(filtered.length, 8) - 1);
|
|
139
|
+
render();
|
|
140
|
+
} else if (e.key === "ArrowUp") {
|
|
141
|
+
e.preventDefault();
|
|
142
|
+
selectedIndex = Math.max(selectedIndex - 1, 0);
|
|
143
|
+
render();
|
|
144
|
+
} else if (e.key === "Enter" || e.key === "Tab") {
|
|
145
|
+
e.preventDefault();
|
|
146
|
+
applySelection();
|
|
147
|
+
} else if (e.key === "Escape") {
|
|
148
|
+
isOpen = false;
|
|
149
|
+
render();
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
dropdown.addEventListener("mousedown", (e) => {
|
|
154
|
+
const target = e.target.closest(".slash-ac-item");
|
|
155
|
+
if (target) {
|
|
156
|
+
e.preventDefault();
|
|
157
|
+
selectedIndex = parseInt(target.getAttribute("data-index"), 10) || 0;
|
|
158
|
+
applySelection();
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
document.addEventListener("click", (e) => {
|
|
163
|
+
if (!dropdown.contains(e.target) && e.target !== promptInput) {
|
|
164
|
+
isOpen = false;
|
|
165
|
+
render();
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
})();
|