@cremini/skillpack 1.0.9-im.5 → 1.1.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/README.md CHANGED
@@ -1,16 +1,16 @@
1
- # SkillPack.sh - Pack AI Skills into Standalone Apps
1
+ # SkillPack.sh - Pack AI Skills into Local Agents
2
2
 
3
3
  Skillpack by Cremini is built on the idea of distributed intelligence, much like cremini mushrooms that grow from a vast, interconnected mycelial network.
4
4
 
5
5
  Go to [skillpack.sh](https://skillpack.sh) to pack skills and try existing skill packs.
6
6
 
7
- One command to orchestrate [Skills](https://skills.sh), tools, mcps into a standalone app users can download and use on their own computer to address a well-defined problem or complete specific tasks!
7
+ One command orchestrates [Skills](https://skills.sh) and tools into a Local Agent that users can download and run it on their own computer to get work done. It can also connect to chat platforms like Slack or Telegram, allowing you to easily send instructions to your local agent team anytime.
8
8
 
9
9
  ```bash
10
10
  npx @cremini/skillpack create
11
11
  ```
12
12
 
13
- If skills, tools, and MCPs are like LEGO pieces, a skill pack is the master piece that assembles them into a complete solution.
13
+ If skills and tools are like LEGO pieces, a skill pack is the master piece that assembles them into a complete solution.
14
14
 
15
15
  Each Skill Pack should organize different skills to address a well-defined problem or complete specific tasks. For example, research a company by gathering information from various sources and create a PowerPoint presentation based on the findings.
16
16
 
@@ -92,7 +92,7 @@ skillpack/
92
92
  start.bat
93
93
  ```
94
94
 
95
- Then open [http://127.0.0.1:26313](http://127.0.0.1:26313), enter your API key, and start working and having fun!!!
95
+ Running start.sh will open [http://127.0.0.1:26313](http://127.0.0.1:26313) in your browser. Just enter your API key to get started and enjoy!
96
96
 
97
97
  ## Development
98
98
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@cremini/skillpack",
3
- "version": "1.0.9-im.5",
4
- "description": "Turn Skills into a Standalone App with UI",
3
+ "version": "1.1.0",
4
+ "description": "Pack AI Skills into Local Agents",
5
5
  "type": "module",
6
6
  "repository": {
7
7
  "type": "git",
@@ -51,6 +51,7 @@ export class WebAdapter {
51
51
  prompts: config.prompts || [],
52
52
  skills: config.skills || [],
53
53
  hasApiKey: !!conf.apiKey,
54
+ apiKey: conf.apiKey || "",
54
55
  provider: conf.provider || "openai",
55
56
  adapters: conf.adapters || {},
56
57
  runtimeControl: lifecycle.getRuntimeControl(),
@@ -1 +1 @@
1
- {"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/adapters/web.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/adapters/web.ts"],"names":[],"mappings":"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"}
@@ -19,12 +19,27 @@
19
19
  <p id="pack-desc">Loading...</p>
20
20
  </div>
21
21
 
22
- <div class="sidebar-section">
22
+ <div class="sidebar-actions-group">
23
+ <button id="open-chatapps-btn" class="action-btn chatapps-btn">
24
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="action-btn-icon">
25
+ <path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path>
26
+ </svg>
27
+ <span class="action-btn-label">Connect Chat Apps</span>
28
+ </button>
29
+ <button id="open-apikey-btn" class="action-btn apikey-btn">
30
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="action-btn-icon">
31
+ <path d="M21 2l-2 2m-7.61 7.61a5.5 5.5 0 1 1-7.778 7.778 5.5 5.5 0 0 1 7.777-7.777zm0 0L15.5 7.5m0 0l3 3L22 7l-3-3m-3.5 3.5L19 4"></path>
32
+ </svg>
33
+ <span class="action-btn-label">Provide Model API Key</span>
34
+ </button>
35
+ </div>
36
+
37
+ <div class="sidebar-skills-section">
23
38
  <h3>Skills</h3>
24
39
  <ul id="skills-list"></ul>
25
40
  </div>
26
41
 
27
- <div class="sidebar-section">
42
+ <div class="sidebar-settings-section">
28
43
  <button id="open-settings-btn" class="settings-trigger-btn">
29
44
  <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="btn-icon"><circle cx="12" cy="12" r="3"></circle><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path></svg>
30
45
  Settings
@@ -109,6 +124,74 @@
109
124
  </div>
110
125
  </dialog>
111
126
 
127
+ <!-- API Key Dialog -->
128
+ <dialog id="apikey-dialog" class="settings-modal compact-modal">
129
+ <div class="settings-modal-header">
130
+ <h2>Model API Key</h2>
131
+ <button id="close-apikey-btn" class="close-btn" aria-label="Close">
132
+ <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>
133
+ </button>
134
+ </div>
135
+ <div class="settings-modal-body">
136
+ <div class="settings-sections">
137
+ <div class="form-group">
138
+ <label>Provider</label>
139
+ <div class="provider-select-wrapper">
140
+ <select id="apikey-provider-select">
141
+ <option value="openai">OpenAI</option>
142
+ <option value="anthropic">Anthropic</option>
143
+ </select>
144
+ </div>
145
+ </div>
146
+ <div class="form-group">
147
+ <label>API Key</label>
148
+ <input type="password" id="apikey-input" placeholder="sk-..." class="form-input" />
149
+ <p id="apikey-status" class="status-text" style="margin-top: 8px; min-height: 18px;"></p>
150
+ </div>
151
+ </div>
152
+ </div>
153
+ <div class="settings-modal-footer">
154
+ <button id="save-apikey-btn" class="primary-btn">Save API Key</button>
155
+ </div>
156
+ </dialog>
157
+
158
+ <!-- Chat Apps Dialog -->
159
+ <dialog id="chatapps-dialog" class="settings-modal">
160
+ <div class="settings-modal-header">
161
+ <h2>Connect Chat Apps</h2>
162
+ <button id="close-chatapps-btn" class="close-btn" aria-label="Close">
163
+ <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>
164
+ </button>
165
+ </div>
166
+ <div class="settings-modal-body">
167
+ <div class="settings-sections">
168
+ <div class="settings-section">
169
+ <h3 class="section-title">Telegram</h3>
170
+ <div class="form-group">
171
+ <label>Bot Token</label>
172
+ <input type="password" id="chatapps-telegram-token" placeholder="123456:ABC-DEF..." class="form-input" />
173
+ </div>
174
+ </div>
175
+ <div class="settings-section">
176
+ <h3 class="section-title">Slack</h3>
177
+ <div class="form-group">
178
+ <label>Bot Token</label>
179
+ <input type="password" id="chatapps-slack-bot-token" placeholder="xoxb-..." class="form-input" />
180
+ </div>
181
+ <div class="form-group">
182
+ <label>App Token</label>
183
+ <input type="password" id="chatapps-slack-app-token" placeholder="xapp-..." class="form-input" />
184
+ </div>
185
+ </div>
186
+ </div>
187
+ </div>
188
+ <div class="settings-modal-footer">
189
+ <p id="chatapps-status" class="status-text"></p>
190
+ <button id="restart-chatapps-btn" class="secondary-btn" hidden>Restart Service</button>
191
+ <button id="save-chatapps-btn" class="primary-btn">Save & Connect</button>
192
+ </div>
193
+ </dialog>
194
+
112
195
  <script src="marked.min.js"></script>
113
196
  <script type="module" src="js/main.js"></script>
114
197
  </body>
@@ -0,0 +1,153 @@
1
+ /**
2
+ * API Key Dialog Module
3
+ *
4
+ * 负责 Model API Key 的配置管理。
5
+ * 独立的 Dialog,从原 SettingDialog 的 API Key 部分拆分出来。
6
+ */
7
+ import { state } from "./config.js";
8
+ import { saveConfigData } from "./api.js";
9
+
10
+ // --- DOM Elements ---
11
+ let dialog;
12
+ let openBtn;
13
+ let closeBtn;
14
+ let saveBtn;
15
+ let providerSelect;
16
+ let apiKeyInput;
17
+ let statusEl;
18
+
19
+ // --- Public API ---
20
+
21
+ export function initApiKeyDialog() {
22
+ dialog = document.getElementById("apikey-dialog");
23
+ openBtn = document.getElementById("open-apikey-btn");
24
+ closeBtn = document.getElementById("close-apikey-btn");
25
+ saveBtn = document.getElementById("save-apikey-btn");
26
+ providerSelect = document.getElementById("apikey-provider-select");
27
+ apiKeyInput = document.getElementById("apikey-input");
28
+ statusEl = document.getElementById("apikey-status");
29
+
30
+ if (!dialog) return;
31
+
32
+ if (openBtn) {
33
+ openBtn.addEventListener("click", open);
34
+ }
35
+ if (closeBtn) {
36
+ closeBtn.addEventListener("click", close);
37
+ }
38
+ if (saveBtn) {
39
+ saveBtn.addEventListener("click", handleSave);
40
+ }
41
+ if (providerSelect) {
42
+ providerSelect.addEventListener("change", updatePlaceholder);
43
+ }
44
+ }
45
+
46
+ /**
47
+ * 根据当前连接状态更新按钮外观
48
+ */
49
+ export function updateApiKeyButton() {
50
+ if (!openBtn) return;
51
+ const config = state.config;
52
+ if (config && config.hasApiKey) {
53
+ openBtn.classList.add("connected");
54
+ openBtn.querySelector(".action-btn-label").textContent = "API Key Configured";
55
+ } else {
56
+ openBtn.classList.remove("connected");
57
+ openBtn.querySelector(".action-btn-label").textContent = "Provide Model API Key";
58
+ }
59
+ }
60
+
61
+ // --- Internal Helpers ---
62
+
63
+ function open() {
64
+ populateForm();
65
+ dialog.showModal();
66
+ }
67
+
68
+ function close() {
69
+ dialog.close();
70
+ setStatus("", "");
71
+ }
72
+
73
+ function populateForm() {
74
+ const config = state.config;
75
+ if (!config) return;
76
+
77
+ // Provider
78
+ if (config.provider && providerSelect) {
79
+ providerSelect.value = config.provider;
80
+ }
81
+ updatePlaceholder();
82
+
83
+ setStatus("", "");
84
+
85
+ if (config.hasApiKey && config.apiKey) {
86
+ apiKeyInput.value = config.apiKey;
87
+ } else if (config.hasApiKey) {
88
+ apiKeyInput.value = "***************************************************";
89
+ } else {
90
+ apiKeyInput.value = "";
91
+ }
92
+ }
93
+
94
+ function updatePlaceholder() {
95
+ if (!providerSelect || !apiKeyInput) return;
96
+ const p = providerSelect.value;
97
+ if (p === "openai") apiKeyInput.placeholder = "sk-proj-...";
98
+ else if (p === "anthropic") apiKeyInput.placeholder = "sk-ant-api03-...";
99
+ else apiKeyInput.placeholder = "sk-...";
100
+ }
101
+
102
+ async function handleSave() {
103
+ const key = apiKeyInput.value.trim();
104
+ const provider = providerSelect.value;
105
+
106
+ if (!key) {
107
+ setStatus("Please enter an API key", "error");
108
+ return;
109
+ }
110
+
111
+ const updates = { provider };
112
+ if (key !== "***************************************************" && key !== state.config.apiKey) {
113
+ updates.key = key;
114
+ }
115
+
116
+ try {
117
+ saveBtn.disabled = true;
118
+ const res = await saveConfigData(updates);
119
+
120
+ state.config.provider = res.provider;
121
+ if (updates.key) {
122
+ state.config.hasApiKey = true;
123
+ state.config.apiKey = updates.key;
124
+ }
125
+
126
+ if (state.config.hasApiKey && state.config.apiKey) {
127
+ apiKeyInput.value = state.config.apiKey;
128
+ } else if (state.config.hasApiKey) {
129
+ apiKeyInput.value = "***************************************************";
130
+ } else {
131
+ apiKeyInput.value = "";
132
+ }
133
+
134
+ state.config.runtimeControl = res.runtimeControl;
135
+ state.restartRequired = !!res.requiresRestart;
136
+
137
+ setStatus("API key saved successfully", "success");
138
+ updateApiKeyButton();
139
+
140
+ // 延迟关闭让用户看到成功消息
141
+ setTimeout(() => close(), 1200);
142
+ } catch (err) {
143
+ setStatus("Save failed: " + err.message, "error");
144
+ } finally {
145
+ saveBtn.disabled = false;
146
+ }
147
+ }
148
+
149
+ function setStatus(message, status) {
150
+ if (!statusEl) return;
151
+ statusEl.textContent = message;
152
+ statusEl.className = status ? `status-text ${status}` : "status-text";
153
+ }
@@ -0,0 +1,192 @@
1
+ /**
2
+ * Chat Apps (IM Bots) Dialog Module
3
+ *
4
+ * 负责 IM Bots(Telegram / Slack)Token 的配置管理。
5
+ * 独立的 Dialog,从原 SettingDialog 的 IM Bots 部分拆分出来。
6
+ */
7
+ import { state } from "./config.js";
8
+ import { saveConfigData, restartRuntime } from "./api.js";
9
+
10
+ // --- DOM Elements ---
11
+ let dialog;
12
+ let openBtn;
13
+ let closeBtn;
14
+ let saveBtn;
15
+ let restartBtn;
16
+ let telegramTokenInput;
17
+ let slackBotTokenInput;
18
+ let slackAppTokenInput;
19
+ let statusEl;
20
+
21
+ // --- Public API ---
22
+
23
+ export function initChatAppsDialog() {
24
+ dialog = document.getElementById("chatapps-dialog");
25
+ openBtn = document.getElementById("open-chatapps-btn");
26
+ closeBtn = document.getElementById("close-chatapps-btn");
27
+ saveBtn = document.getElementById("save-chatapps-btn");
28
+ restartBtn = document.getElementById("restart-chatapps-btn");
29
+ telegramTokenInput = document.getElementById("chatapps-telegram-token");
30
+ slackBotTokenInput = document.getElementById("chatapps-slack-bot-token");
31
+ slackAppTokenInput = document.getElementById("chatapps-slack-app-token");
32
+ statusEl = document.getElementById("chatapps-status");
33
+
34
+ if (!dialog) return;
35
+
36
+ if (openBtn) {
37
+ openBtn.addEventListener("click", open);
38
+ }
39
+ if (closeBtn) {
40
+ closeBtn.addEventListener("click", close);
41
+ }
42
+ if (saveBtn) {
43
+ saveBtn.addEventListener("click", handleSave);
44
+ }
45
+ if (restartBtn) {
46
+ restartBtn.addEventListener("click", handleRestart);
47
+ }
48
+ }
49
+
50
+ /**
51
+ * 根据当前连接状态更新按钮外观
52
+ */
53
+ export function updateChatAppsButton() {
54
+ if (!openBtn) return;
55
+ const config = state.config;
56
+ const adapters = config?.adapters || {};
57
+ const hasAnyToken =
58
+ (adapters.telegram && adapters.telegram.token) ||
59
+ (adapters.slack && (adapters.slack.botToken || adapters.slack.appToken));
60
+
61
+ if (hasAnyToken) {
62
+ openBtn.classList.add("connected");
63
+ openBtn.querySelector(".action-btn-label").textContent = "Connected to Chat Apps";
64
+ } else {
65
+ openBtn.classList.remove("connected");
66
+ openBtn.querySelector(".action-btn-label").textContent = "Connect Chat Apps";
67
+ }
68
+ }
69
+
70
+ // --- Internal Helpers ---
71
+
72
+ function open() {
73
+ populateForm();
74
+ dialog.showModal();
75
+ }
76
+
77
+ function close() {
78
+ dialog.close();
79
+ setStatus("", "");
80
+ }
81
+
82
+ function populateForm() {
83
+ const config = state.config;
84
+ if (!config) return;
85
+
86
+ const adapters = config.adapters || {};
87
+
88
+ if (adapters.telegram && adapters.telegram.token) {
89
+ telegramTokenInput.value = adapters.telegram.token;
90
+ } else {
91
+ telegramTokenInput.value = "";
92
+ }
93
+
94
+ if (adapters.slack) {
95
+ slackBotTokenInput.value = adapters.slack.botToken || "";
96
+ slackAppTokenInput.value = adapters.slack.appToken || "";
97
+ } else {
98
+ slackBotTokenInput.value = "";
99
+ slackAppTokenInput.value = "";
100
+ }
101
+
102
+ // Restart required status
103
+ if (state.restartRequired) {
104
+ const canRestart = config.runtimeControl?.canManagedRestart;
105
+ setStatus(
106
+ canRestart
107
+ ? "Settings changed. Restart service to apply."
108
+ : "Settings changed. Restart the service manually to apply.",
109
+ "warning",
110
+ );
111
+ updateRestartButton(canRestart);
112
+ } else {
113
+ setStatus("", "");
114
+ updateRestartButton(false);
115
+ }
116
+ }
117
+
118
+ async function handleSave() {
119
+ const telegramToken = telegramTokenInput.value.trim();
120
+ const slackBotToken = slackBotTokenInput.value.trim();
121
+ const slackAppToken = slackAppTokenInput.value.trim();
122
+
123
+ const adapters = {};
124
+ if (telegramToken) adapters.telegram = { token: telegramToken };
125
+ if (slackBotToken || slackAppToken) {
126
+ adapters.slack = {
127
+ botToken: slackBotToken || undefined,
128
+ appToken: slackAppToken || undefined,
129
+ };
130
+ }
131
+
132
+ const updates = { adapters };
133
+
134
+ try {
135
+ saveBtn.disabled = true;
136
+ const res = await saveConfigData(updates);
137
+
138
+ state.config.adapters = res.adapters;
139
+ state.config.runtimeControl = res.runtimeControl;
140
+ state.restartRequired = !!res.requiresRestart;
141
+
142
+ if (res.requiresRestart) {
143
+ setStatus(
144
+ res.runtimeControl?.canManagedRestart
145
+ ? "Settings saved. Restart service to apply changes."
146
+ : "Settings saved. Restart the service manually to apply changes.",
147
+ "warning",
148
+ );
149
+ updateRestartButton(!!res.runtimeControl?.canManagedRestart);
150
+ } else {
151
+ setStatus("Settings saved", "success");
152
+ updateRestartButton(false);
153
+ }
154
+
155
+ updateChatAppsButton();
156
+ } catch (err) {
157
+ setStatus("Save failed: " + err.message, "error");
158
+ } finally {
159
+ saveBtn.disabled = false;
160
+ }
161
+ }
162
+
163
+ async function handleRestart() {
164
+ if (!restartBtn) return;
165
+
166
+ restartBtn.disabled = true;
167
+ if (saveBtn) saveBtn.disabled = true;
168
+ setStatus("Restarting service...", "warning");
169
+
170
+ try {
171
+ await restartRuntime();
172
+ setTimeout(() => {
173
+ window.location.reload();
174
+ }, 6000);
175
+ } catch (err) {
176
+ if (saveBtn) saveBtn.disabled = false;
177
+ restartBtn.disabled = false;
178
+ setStatus("Restart failed: " + err.message, "error");
179
+ }
180
+ }
181
+
182
+ function updateRestartButton(show) {
183
+ if (!restartBtn) return;
184
+ restartBtn.hidden = !show;
185
+ restartBtn.disabled = false;
186
+ }
187
+
188
+ function setStatus(message, status) {
189
+ if (!statusEl) return;
190
+ statusEl.textContent = message;
191
+ statusEl.className = status ? `status-text ${status}` : "status-text";
192
+ }
@@ -1,5 +1,7 @@
1
1
  import { state, loadConfig } from "./config.js";
2
2
  import { initSettings } from "./settings.js";
3
+ import { initApiKeyDialog, updateApiKeyButton } from "./api-key-dialog.js";
4
+ import { initChatAppsDialog, updateChatAppsButton } from "./chat-apps-dialog.js";
3
5
  import { initChat, showWelcome } from "./chat.js";
4
6
 
5
7
  async function init() {
@@ -39,8 +41,15 @@ async function init() {
39
41
  console.error("Initialization Failed:", err);
40
42
  }
41
43
 
44
+ // Initialize all dialog modules
42
45
  initSettings();
46
+ initApiKeyDialog();
47
+ initChatAppsDialog();
43
48
  initChat();
49
+
50
+ // Update action button states based on config
51
+ updateApiKeyButton();
52
+ updateChatAppsButton();
44
53
  }
45
54
 
46
55
  // Start application
@@ -78,14 +78,19 @@ function populateForm() {
78
78
  "warning",
79
79
  );
80
80
  updateRestartButton(true);
81
- } else if (config.hasApiKey) {
82
- setStatus("API key configured", "success");
83
- updateRestartButton(false);
84
81
  } else {
85
82
  setStatus("", "");
86
83
  updateRestartButton(false);
87
84
  }
88
85
 
86
+ if (config.hasApiKey && config.apiKey) {
87
+ apiKeyInput.value = config.apiKey;
88
+ } else if (config.hasApiKey) {
89
+ apiKeyInput.value = "***************************************************";
90
+ } else {
91
+ apiKeyInput.value = "";
92
+ }
93
+
89
94
  if (config.provider) {
90
95
  providerSelect.value = config.provider;
91
96
  }
@@ -124,19 +129,29 @@ async function handleSave() {
124
129
  }
125
130
 
126
131
  const updates = { provider, adapters };
127
- if (key) {
132
+ if (key && key !== "***************************************************" && key !== state.config.apiKey) {
128
133
  updates.key = key;
129
134
  }
130
135
 
131
136
  try {
132
137
  const res = await saveConfigData(updates);
133
- apiKeyInput.value = ""; // clear after save
134
138
 
135
139
  // Update local config
136
140
  state.config.provider = res.provider;
137
141
  state.config.adapters = res.adapters;
138
142
  state.config.runtimeControl = res.runtimeControl;
139
- if (key) state.config.hasApiKey = true;
143
+ if (updates.key) {
144
+ state.config.hasApiKey = true;
145
+ state.config.apiKey = updates.key;
146
+ }
147
+
148
+ if (state.config.hasApiKey && state.config.apiKey) {
149
+ apiKeyInput.value = state.config.apiKey;
150
+ } else if (state.config.hasApiKey) {
151
+ apiKeyInput.value = "***************************************************";
152
+ } else {
153
+ apiKeyInput.value = "";
154
+ }
140
155
  state.restartRequired = !!res.requiresRestart;
141
156
 
142
157
  if (res.requiresRestart) {
@@ -169,7 +184,7 @@ async function handleRestart() {
169
184
  await restartRuntime();
170
185
  setTimeout(() => {
171
186
  window.location.reload();
172
- }, 3000);
187
+ }, 6000);
173
188
  } catch (err) {
174
189
  if (saveBtn) saveBtn.disabled = false;
175
190
  restartBtn.disabled = false;
@@ -55,7 +55,8 @@ body {
55
55
  .sidebar-header {
56
56
  padding: 24px 20px;
57
57
  border-bottom: 1px solid var(--border-color);
58
- background: var(--bg-primary);
58
+ background: transparent;
59
+ flex-shrink: 0;
59
60
  }
60
61
 
61
62
  .sidebar-header h1 {
@@ -71,12 +72,20 @@ body {
71
72
  line-height: 1.4;
72
73
  }
73
74
 
74
- .sidebar-section {
75
+ .sidebar-settings-section {
75
76
  padding: 16px 20px;
76
- border-bottom: 1px solid var(--border-color);
77
+ border-top: 1px solid var(--border-color);
78
+ background: var(--bg-secondary);
79
+ flex-shrink: 0;
80
+ }
81
+
82
+ .sidebar-skills-section {
83
+ padding: 16px 20px;
84
+ flex: 1;
85
+ overflow-y: auto;
77
86
  }
78
87
 
79
- .sidebar-section h3 {
88
+ .sidebar-skills-section h3 {
80
89
  font-size: 11px;
81
90
  font-weight: 600;
82
91
  text-transform: uppercase;
@@ -85,23 +94,26 @@ body {
85
94
  margin-bottom: 10px;
86
95
  }
87
96
 
88
- .sidebar-section ul {
97
+ .sidebar-skills-section ul {
89
98
  list-style: none;
90
99
  }
91
100
 
92
- .sidebar-section li {
93
- padding: 8px 12px;
101
+ .sidebar-skills-section li {
102
+ padding: 12px;
94
103
  font-size: 13px;
95
104
  color: var(--text-primary);
96
105
  background: var(--bg-tertiary);
106
+ border: 1px solid transparent;
97
107
  border-radius: var(--radius-sm);
98
- margin-bottom: 6px;
108
+ margin-bottom: 8px;
99
109
  cursor: default;
100
110
  transition: all 0.2s;
101
111
  }
102
112
 
103
- .sidebar-section li:hover {
104
- background: var(--border-color);
113
+ .sidebar-skills-section li:hover {
114
+ background: var(--bg-secondary);
115
+ border-color: var(--border-color);
116
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.03);
105
117
  }
106
118
 
107
119
  .skill-name {
@@ -776,6 +788,92 @@ body {
776
788
  margin-bottom: 0;
777
789
  }
778
790
 
791
+ /* ---- Sidebar Action Buttons ---- */
792
+ .sidebar-actions-group {
793
+ padding: 24px 20px;
794
+ border-bottom: 1px solid var(--border-color);
795
+ display: flex;
796
+ flex-direction: column;
797
+ gap: 12px;
798
+ flex-shrink: 0;
799
+ }
800
+
801
+ .action-btn {
802
+ display: flex;
803
+ align-items: center;
804
+ justify-content: center;
805
+ gap: 8px;
806
+ width: 100%;
807
+ padding: 9px 16px;
808
+ border-radius: var(--radius-sm);
809
+ font-size: 14px;
810
+ font-weight: 500;
811
+ cursor: pointer;
812
+ transition: all 0.25s ease;
813
+ font-family: inherit;
814
+ }
815
+
816
+ /* Default (not connected) state — outline style */
817
+ .action-btn.chatapps-btn {
818
+ background: var(--bg-tertiary);
819
+ border: 1px solid var(--border-color);
820
+ color: var(--text-primary);
821
+ }
822
+ .action-btn.chatapps-btn:hover {
823
+ border-color: var(--accent);
824
+ background: var(--bg-secondary);
825
+ box-shadow: 0 4px 12px rgba(0,0,0,0.04);
826
+ transform: translateY(-1px);
827
+ }
828
+
829
+ /* Connected state — green filled */
830
+ .action-btn.chatapps-btn.connected {
831
+ background: var(--accent);
832
+ border: 1px solid var(--accent);
833
+ color: #fff;
834
+ opacity: 0.85;
835
+ }
836
+ .action-btn.chatapps-btn.connected:hover {
837
+ opacity: 1;
838
+ box-shadow: 0 4px 16px var(--accent-glow);
839
+ transform: translateY(-1px);
840
+ }
841
+ .action-btn.chatapps-btn.connected .action-btn-icon {
842
+ stroke: #fff;
843
+ }
844
+
845
+ /* API Key button — always outline style */
846
+ .action-btn.apikey-btn {
847
+ background: var(--bg-tertiary);
848
+ border: 1px solid var(--border-color);
849
+ color: var(--text-primary);
850
+ }
851
+ .action-btn.apikey-btn:hover {
852
+ border-color: var(--accent);
853
+ background: var(--bg-secondary);
854
+ box-shadow: 0 4px 12px rgba(0,0,0,0.04);
855
+ transform: translateY(-1px);
856
+ }
857
+
858
+ /* API Key configured state */
859
+ .action-btn.apikey-btn.connected {
860
+ border-color: var(--accent);
861
+ color: var(--accent);
862
+ background: var(--bg-secondary);
863
+ }
864
+ .action-btn.apikey-btn.connected .action-btn-icon {
865
+ stroke: var(--accent);
866
+ }
867
+
868
+ .action-btn-icon {
869
+ flex-shrink: 0;
870
+ }
871
+
872
+ /* ---- Compact Modal Variant ---- */
873
+ .compact-modal {
874
+ width: 440px;
875
+ }
876
+
779
877
  /* ---- Settings Modal ---- */
780
878
  .settings-trigger-btn {
781
879
  display: flex;
@@ -793,10 +891,7 @@ body {
793
891
  transition: all 0.2s ease;
794
892
  }
795
893
  .settings-trigger-btn:hover {
796
- background: var(--bg-secondary);
797
- border-color: var(--accent);
798
- box-shadow: 0 4px 12px rgba(0,0,0,0.03);
799
- transform: translateY(-1px);
894
+ background: #ebebeb;
800
895
  }
801
896
 
802
897
  .settings-modal {