pi-sdk-web 0.4.0 → 0.4.2
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/pi-bin/server/__pycache__/rpc_client.cpython-313.pyc +0 -0
- package/dist/pi-bin/server/__pycache__/websocket.cpython-313.pyc +0 -0
- package/dist/pi-bin/server/server.py +17 -1
- package/dist/server.js +7 -0
- package/dist/static/app.js +37 -18
- package/dist/static/style.css +13 -0
- package/package.json +1 -1
|
Binary file
|
|
Binary file
|
|
@@ -28,7 +28,23 @@ from rpc_client import RpcClient, RpcCommands
|
|
|
28
28
|
from websocket import WebSocketConnection, WebSocketServer
|
|
29
29
|
|
|
30
30
|
DEFAULT_PORT = 4080
|
|
31
|
-
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _resolve_static_dir() -> Path:
|
|
34
|
+
"""Find the static/ directory: the repo layout keeps it next to the
|
|
35
|
+
project root (server.py's parent.parent), while the npm package layout
|
|
36
|
+
ships it at dist/static (server.py lives at dist/pi-bin/server/). Search
|
|
37
|
+
upward so both layouts resolve."""
|
|
38
|
+
d = Path(__file__).resolve().parent
|
|
39
|
+
for _ in range(4):
|
|
40
|
+
candidate = d / "static"
|
|
41
|
+
if candidate.is_dir():
|
|
42
|
+
return candidate
|
|
43
|
+
d = d.parent
|
|
44
|
+
return Path(__file__).resolve().parent / "static"
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
STATIC_DIR = _resolve_static_dir()
|
|
32
48
|
|
|
33
49
|
|
|
34
50
|
class Peripheral:
|
package/dist/server.js
CHANGED
|
@@ -530,11 +530,13 @@ export class PiWebServer {
|
|
|
530
530
|
case "set_scoped_models": {
|
|
531
531
|
const models = Array.isArray(data.models) ? data.models : [];
|
|
532
532
|
const resolved = [];
|
|
533
|
+
const enabledIds = [];
|
|
533
534
|
for (const m of models) {
|
|
534
535
|
const provider = m.provider;
|
|
535
536
|
const modelId = m.modelId;
|
|
536
537
|
if (!provider || !modelId)
|
|
537
538
|
continue;
|
|
539
|
+
enabledIds.push(`${provider}/${modelId}`);
|
|
538
540
|
const model = this.session.modelRuntime
|
|
539
541
|
.getAvailableSnapshot()
|
|
540
542
|
.find((x) => x.provider === provider && x.id === modelId);
|
|
@@ -542,6 +544,11 @@ export class PiWebServer {
|
|
|
542
544
|
resolved.push({ model, thinkingLevel: m.thinkingLevel });
|
|
543
545
|
}
|
|
544
546
|
this.session.setScopedModels(resolved);
|
|
547
|
+
// Persist only on explicit save (TUI Ctrl+S onPersist); toggling is
|
|
548
|
+
// session-only (onChange) and must not rewrite settings.json.
|
|
549
|
+
if (data.persist === true) {
|
|
550
|
+
this.session.settingsManager.setEnabledModels(enabledIds.length > 0 ? enabledIds : undefined);
|
|
551
|
+
}
|
|
545
552
|
this.broadcastState();
|
|
546
553
|
break;
|
|
547
554
|
}
|
package/dist/static/app.js
CHANGED
|
@@ -1872,6 +1872,7 @@ class PiWebClient {
|
|
|
1872
1872
|
this.scopedModelsAll = [];
|
|
1873
1873
|
this.scopedModelsSelected = new Set();
|
|
1874
1874
|
this.scopedModelsData = null;
|
|
1875
|
+
this.scopedModelsSaved = true;
|
|
1875
1876
|
this.modalList.innerHTML = '<div class="modal-message">Loading models...</div>';
|
|
1876
1877
|
this.send({ type: 'get_scoped_models' });
|
|
1877
1878
|
}
|
|
@@ -1910,11 +1911,13 @@ class PiWebClient {
|
|
|
1910
1911
|
})
|
|
1911
1912
|
.join('');
|
|
1912
1913
|
this.modalList.innerHTML =
|
|
1913
|
-
rows +
|
|
1914
1914
|
`<div class="modal-actions">
|
|
1915
|
-
<button class="modal-btn ok-btn">
|
|
1915
|
+
<button class="modal-btn ok-btn">Save</button>
|
|
1916
1916
|
<button class="modal-btn cancel-btn">Cancel</button>
|
|
1917
|
-
|
|
1917
|
+
<span class="modal-hint"></span>
|
|
1918
|
+
</div>` +
|
|
1919
|
+
rows;
|
|
1920
|
+
this.updateScopedUnsavedHint();
|
|
1918
1921
|
this.modalList.querySelectorAll('.scoped-model').forEach((el) => {
|
|
1919
1922
|
el.addEventListener('click', () => {
|
|
1920
1923
|
const key = el.dataset.key;
|
|
@@ -1923,26 +1926,14 @@ class PiWebClient {
|
|
|
1923
1926
|
const checked = this.scopedModelsSelected.has(key);
|
|
1924
1927
|
el.classList.toggle('selected', checked);
|
|
1925
1928
|
el.querySelector('.modal-check').textContent = checked ? '☑' : '☐';
|
|
1929
|
+
// TUI onChange: apply to session (memory, persist=false); Save persists.
|
|
1930
|
+
this.applyScopedModels(false);
|
|
1926
1931
|
});
|
|
1927
1932
|
});
|
|
1928
1933
|
const okBtn = this.modalList.querySelector('.ok-btn');
|
|
1929
1934
|
if (okBtn) {
|
|
1930
1935
|
okBtn.addEventListener('click', () => {
|
|
1931
|
-
|
|
1932
|
-
for (const m of this.scopedModelsAll || []) {
|
|
1933
|
-
const key = `${m.provider}/${m.id}`;
|
|
1934
|
-
if (this.scopedModelsSelected.has(key)) {
|
|
1935
|
-
const scopedInfo = (this.scopedModelsData?.scoped || []).find(
|
|
1936
|
-
(s) => `${s.provider}/${s.id}` === key,
|
|
1937
|
-
);
|
|
1938
|
-
models.push({
|
|
1939
|
-
provider: m.provider,
|
|
1940
|
-
modelId: m.id,
|
|
1941
|
-
thinkingLevel: scopedInfo?.thinkingLevel,
|
|
1942
|
-
});
|
|
1943
|
-
}
|
|
1944
|
-
}
|
|
1945
|
-
this.send({ type: 'set_scoped_models', models });
|
|
1936
|
+
this.applyScopedModels(true);
|
|
1946
1937
|
this.closeModal();
|
|
1947
1938
|
});
|
|
1948
1939
|
}
|
|
@@ -1950,6 +1941,34 @@ class PiWebClient {
|
|
|
1950
1941
|
if (cancelBtn) cancelBtn.addEventListener('click', () => this.closeModal());
|
|
1951
1942
|
}
|
|
1952
1943
|
|
|
1944
|
+
/** Send the current selection to the server (persist=false = memory only). */
|
|
1945
|
+
applyScopedModels(persist) {
|
|
1946
|
+
const models = [];
|
|
1947
|
+
for (const m of this.scopedModelsAll || []) {
|
|
1948
|
+
const key = `${m.provider}/${m.id}`;
|
|
1949
|
+
if (this.scopedModelsSelected.has(key)) {
|
|
1950
|
+
const scopedInfo = (this.scopedModelsData?.scoped || []).find(
|
|
1951
|
+
(s) => `${s.provider}/${s.id}` === key,
|
|
1952
|
+
);
|
|
1953
|
+
models.push({
|
|
1954
|
+
provider: m.provider,
|
|
1955
|
+
modelId: m.id,
|
|
1956
|
+
thinkingLevel: scopedInfo?.thinkingLevel,
|
|
1957
|
+
});
|
|
1958
|
+
}
|
|
1959
|
+
}
|
|
1960
|
+
this.send({ type: 'set_scoped_models', models, persist: persist });
|
|
1961
|
+
this.scopedModelsSaved = persist;
|
|
1962
|
+
this.updateScopedUnsavedHint();
|
|
1963
|
+
}
|
|
1964
|
+
|
|
1965
|
+
updateScopedUnsavedHint() {
|
|
1966
|
+
const hint = this.modalList.querySelector('.modal-hint');
|
|
1967
|
+
if (!hint) return;
|
|
1968
|
+
hint.textContent = this.scopedModelsSaved ? '' : ' (unsaved)';
|
|
1969
|
+
hint.className = this.scopedModelsSaved ? 'modal-hint' : 'modal-hint unsaved';
|
|
1970
|
+
}
|
|
1971
|
+
|
|
1953
1972
|
// ------------------------------------------------------------------
|
|
1954
1973
|
// Slash command menu
|
|
1955
1974
|
// ------------------------------------------------------------------
|
package/dist/static/style.css
CHANGED
|
@@ -859,6 +859,19 @@ body {
|
|
|
859
859
|
gap: 8px;
|
|
860
860
|
justify-content: flex-end;
|
|
861
861
|
margin-top: 10px;
|
|
862
|
+
margin-bottom: 10px;
|
|
863
|
+
align-items: center;
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
.modal-hint {
|
|
867
|
+
font-size: 12px;
|
|
868
|
+
color: var(--dim);
|
|
869
|
+
margin-left: auto;
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
.modal-hint.unsaved {
|
|
873
|
+
color: var(--warning);
|
|
874
|
+
font-weight: 600;
|
|
862
875
|
}
|
|
863
876
|
|
|
864
877
|
.modal-btn {
|