pi-sdk-web 0.3.2 → 0.3.4
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/server.js +14 -0
- package/dist/static/app.js +81 -42
- package/package.json +1 -1
package/dist/server.js
CHANGED
|
@@ -278,6 +278,7 @@ export class PiWebServer {
|
|
|
278
278
|
cwd: this.formatCwd(this.session.sessionManager.getCwd()),
|
|
279
279
|
gitBranch: this.getGitBranch(this.session.sessionManager.getCwd()),
|
|
280
280
|
commands: this.getCommands(),
|
|
281
|
+
tools: this.getActiveTools(),
|
|
281
282
|
};
|
|
282
283
|
try {
|
|
283
284
|
state.sessionStats = this.session.getSessionStats();
|
|
@@ -352,6 +353,19 @@ export class PiWebServer {
|
|
|
352
353
|
return [];
|
|
353
354
|
}
|
|
354
355
|
}
|
|
356
|
+
/** Tools currently exposed to the LLM (name + description). */
|
|
357
|
+
getActiveTools() {
|
|
358
|
+
try {
|
|
359
|
+
const active = new Set(this.session.getActiveToolNames());
|
|
360
|
+
return this.session
|
|
361
|
+
.getAllTools()
|
|
362
|
+
.filter((t) => active.has(t.name))
|
|
363
|
+
.map((t) => ({ name: t.name, description: t.description }));
|
|
364
|
+
}
|
|
365
|
+
catch {
|
|
366
|
+
return [];
|
|
367
|
+
}
|
|
368
|
+
}
|
|
355
369
|
handleClientMessage(ws, raw) {
|
|
356
370
|
let data;
|
|
357
371
|
try {
|
package/dist/static/app.js
CHANGED
|
@@ -208,7 +208,7 @@ class PiWebClient {
|
|
|
208
208
|
}
|
|
209
209
|
|
|
210
210
|
// Loaded resources
|
|
211
|
-
this.renderLoadedResources(state.commands);
|
|
211
|
+
this.renderLoadedResources(state.commands, state.tools);
|
|
212
212
|
|
|
213
213
|
// First footer line: pwd (branch) • session name
|
|
214
214
|
const pwd = state.cwd || '';
|
|
@@ -220,56 +220,81 @@ class PiWebClient {
|
|
|
220
220
|
this.renderStats(state.sessionStats, state);
|
|
221
221
|
}
|
|
222
222
|
|
|
223
|
-
renderLoadedResources(commands) {
|
|
223
|
+
renderLoadedResources(commands, tools) {
|
|
224
224
|
if (!this.loadedResourcesEl) return;
|
|
225
|
-
|
|
226
|
-
this.loadedResourcesEl.innerHTML = '';
|
|
227
|
-
return;
|
|
228
|
-
}
|
|
225
|
+
this.loadedResourcesEl.innerHTML = '';
|
|
229
226
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
const
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
227
|
+
// Loaded Resources block (Skills/Prompts/Extensions)
|
|
228
|
+
if (commands && commands.length > 0) {
|
|
229
|
+
const groups = { skill: [], prompt: [], extension: [] };
|
|
230
|
+
for (const cmd of commands) {
|
|
231
|
+
const source = cmd.source;
|
|
232
|
+
if (source === 'skill') groups.skill.push(cmd);
|
|
233
|
+
else if (source === 'prompt') groups.prompt.push(cmd);
|
|
234
|
+
else groups.extension.push(cmd);
|
|
235
|
+
}
|
|
237
236
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
237
|
+
const div = document.createElement('div');
|
|
238
|
+
div.className = 'resources-block';
|
|
239
|
+
div.dataset.expanded = 'false';
|
|
241
240
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
241
|
+
const header = document.createElement('div');
|
|
242
|
+
header.className = 'resources-header';
|
|
243
|
+
header.textContent = 'Loaded Resources (click to expand)';
|
|
245
244
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
245
|
+
const body = document.createElement('div');
|
|
246
|
+
body.className = 'resources-body';
|
|
247
|
+
body.style.display = 'none';
|
|
249
248
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
249
|
+
const sections = [];
|
|
250
|
+
if (groups.skill.length > 0) {
|
|
251
|
+
sections.push(this.resourceSection('Skills', groups.skill.map((c) => c.name)));
|
|
252
|
+
}
|
|
253
|
+
if (groups.prompt.length > 0) {
|
|
254
|
+
sections.push(this.resourceSection('Prompts', groups.prompt.map((c) => c.name)));
|
|
255
|
+
}
|
|
256
|
+
if (groups.extension.length > 0) {
|
|
257
|
+
sections.push(this.resourceSection('Extensions', groups.extension.map((c) => c.name)));
|
|
258
|
+
}
|
|
259
|
+
body.innerHTML = sections.join('');
|
|
260
|
+
|
|
261
|
+
div.appendChild(header);
|
|
262
|
+
div.appendChild(body);
|
|
263
|
+
div.addEventListener('click', () => {
|
|
264
|
+
const expanded = div.dataset.expanded === 'true';
|
|
265
|
+
div.dataset.expanded = expanded ? 'false' : 'true';
|
|
266
|
+
body.style.display = expanded ? 'none' : 'block';
|
|
267
|
+
header.textContent = expanded ? 'Loaded Resources (click to expand)' : 'Loaded Resources (click to collapse)';
|
|
268
|
+
});
|
|
269
|
+
this.loadedResourcesEl.appendChild(div);
|
|
259
270
|
}
|
|
260
|
-
body.innerHTML = sections.join('');
|
|
261
271
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
div.dataset.expanded =
|
|
267
|
-
|
|
268
|
-
header.textContent = expanded ? 'Loaded Resources (click to expand)' : 'Loaded Resources (click to collapse)';
|
|
269
|
-
});
|
|
272
|
+
// Separate Tools block below Loaded Resources (web enhancement)
|
|
273
|
+
if (tools && tools.length > 0) {
|
|
274
|
+
const div = document.createElement('div');
|
|
275
|
+
div.className = 'resources-block';
|
|
276
|
+
div.dataset.expanded = 'false';
|
|
277
|
+
div.style.marginTop = '6px';
|
|
270
278
|
|
|
271
|
-
|
|
272
|
-
|
|
279
|
+
const header = document.createElement('div');
|
|
280
|
+
header.className = 'resources-header';
|
|
281
|
+
header.textContent = 'Tools (click to expand)';
|
|
282
|
+
|
|
283
|
+
const body = document.createElement('div');
|
|
284
|
+
body.className = 'resources-body';
|
|
285
|
+
body.style.display = 'none';
|
|
286
|
+
body.innerHTML = this.resourceSection('', tools.map((t) => t.name));
|
|
287
|
+
|
|
288
|
+
div.appendChild(header);
|
|
289
|
+
div.appendChild(body);
|
|
290
|
+
div.addEventListener('click', () => {
|
|
291
|
+
const expanded = div.dataset.expanded === 'true';
|
|
292
|
+
div.dataset.expanded = expanded ? 'false' : 'true';
|
|
293
|
+
body.style.display = expanded ? 'none' : 'block';
|
|
294
|
+
header.textContent = expanded ? 'Tools (click to expand)' : 'Tools (click to collapse)';
|
|
295
|
+
});
|
|
296
|
+
this.loadedResourcesEl.appendChild(div);
|
|
297
|
+
}
|
|
273
298
|
}
|
|
274
299
|
|
|
275
300
|
resourceSection(name, items) {
|
|
@@ -804,12 +829,14 @@ class PiWebClient {
|
|
|
804
829
|
const widgetsEl = document.getElementById('widgets');
|
|
805
830
|
if (!widgetsEl) return;
|
|
806
831
|
const key = req.widgetKey || 'widget';
|
|
832
|
+
const wasAtBottom = this.wasAtBottom();
|
|
807
833
|
|
|
808
834
|
if (req.widgetLines === undefined || req.widgetLines === null) {
|
|
809
835
|
// Clear this widget
|
|
810
836
|
const el = widgetsEl.querySelector(`[data-widget-key="${CSS.escape(key)}"]`);
|
|
811
837
|
if (el) el.remove();
|
|
812
838
|
if (widgetsEl.children.length === 0) widgetsEl.style.display = 'none';
|
|
839
|
+
if (wasAtBottom) this.scrollToBottom();
|
|
813
840
|
return;
|
|
814
841
|
}
|
|
815
842
|
|
|
@@ -829,6 +856,8 @@ class PiWebClient {
|
|
|
829
856
|
el.querySelector('.widget-title').textContent = key;
|
|
830
857
|
el.querySelector('.widget-body').textContent = (req.widgetLines || []).join('\n');
|
|
831
858
|
widgetsEl.style.display = 'block';
|
|
859
|
+
// Layout change: keep pinned to bottom if already there
|
|
860
|
+
if (wasAtBottom) this.scrollToBottom();
|
|
832
861
|
}
|
|
833
862
|
|
|
834
863
|
// ------------------------------------------------------------------
|
|
@@ -1401,18 +1430,28 @@ class PiWebClient {
|
|
|
1401
1430
|
renderStatusItem(req) {
|
|
1402
1431
|
const el = document.getElementById('ext-status');
|
|
1403
1432
|
if (!el) return;
|
|
1433
|
+
const wasAtBottom = this.wasAtBottom();
|
|
1404
1434
|
if (req.statusText === undefined || req.statusText === null) {
|
|
1405
1435
|
delete this.extStatus[req.statusKey];
|
|
1406
1436
|
} else {
|
|
1407
1437
|
this.extStatus[req.statusKey] = req.statusText;
|
|
1408
1438
|
}
|
|
1409
1439
|
this.updateExtStatusDisplay();
|
|
1440
|
+
if (wasAtBottom) this.scrollToBottom();
|
|
1410
1441
|
}
|
|
1411
1442
|
|
|
1412
1443
|
applyExtStatusSnapshot(snapshot) {
|
|
1413
1444
|
if (!snapshot) return;
|
|
1445
|
+
const wasAtBottom = this.wasAtBottom();
|
|
1414
1446
|
this.extStatus = Object.assign({}, snapshot);
|
|
1415
1447
|
this.updateExtStatusDisplay();
|
|
1448
|
+
if (wasAtBottom) this.scrollToBottom();
|
|
1449
|
+
}
|
|
1450
|
+
|
|
1451
|
+
/** Whether the view is currently pinned to the bottom (before layout changes). */
|
|
1452
|
+
wasAtBottom() {
|
|
1453
|
+
const scroller = document.getElementById('scroll-view');
|
|
1454
|
+
return !!scroller && scroller.scrollTop + scroller.clientHeight >= scroller.scrollHeight - 2;
|
|
1416
1455
|
}
|
|
1417
1456
|
|
|
1418
1457
|
updateExtStatusDisplay() {
|