@spencerboucher/switchyard 0.7.0 → 0.8.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 +1 -1
- package/dist/bridge/switchyard-terminal.js +96 -1
- package/dist/switchyard.mjs +463 -126
- package/package.json +1 -1
- package/web-dist/assets/{AutomationView-BIW_pO0M.js → AutomationView-GCthHkym.js} +2 -2
- package/web-dist/assets/{AutomationView-BIW_pO0M.js.map → AutomationView-GCthHkym.js.map} +1 -1
- package/web-dist/assets/{Badge-BiDp7NKI.js → Badge-CEMI3YyI.js} +2 -2
- package/web-dist/assets/{Badge-BiDp7NKI.js.map → Badge-CEMI3YyI.js.map} +1 -1
- package/web-dist/assets/{InteractionCard-CWxyDv81.js → InteractionCard-DaLqafmA.js} +2 -2
- package/web-dist/assets/{InteractionCard-CWxyDv81.js.map → InteractionCard-DaLqafmA.js.map} +1 -1
- package/web-dist/assets/{Menu-BDt1bxwz.js → Menu-BcKiEc6X.js} +2 -2
- package/web-dist/assets/{Menu-BDt1bxwz.js.map → Menu-BcKiEc6X.js.map} +1 -1
- package/web-dist/assets/{SegmentedControl-D-2BCZzd.js → SegmentedControl-BZPzNU08.js} +2 -2
- package/web-dist/assets/{SegmentedControl-D-2BCZzd.js.map → SegmentedControl-BZPzNU08.js.map} +1 -1
- package/web-dist/assets/{Tabs-ByiPklAw.js → Tabs-COH5EMql.js} +2 -2
- package/web-dist/assets/{Tabs-ByiPklAw.js.map → Tabs-COH5EMql.js.map} +1 -1
- package/web-dist/assets/{TextArea-BYr88SnV.js → TextArea-CeMEPZn4.js} +2 -2
- package/web-dist/assets/{TextArea-BYr88SnV.js.map → TextArea-CeMEPZn4.js.map} +1 -1
- package/web-dist/assets/{attention-Bya8XHKI.js → attention-BAdea2kA.js} +2 -2
- package/web-dist/assets/{attention-Bya8XHKI.js.map → attention-BAdea2kA.js.map} +1 -1
- package/web-dist/assets/{automations-DiXKRcnE.js → automations-DSFUzB0w.js} +2 -2
- package/web-dist/assets/{automations-DiXKRcnE.js.map → automations-DSFUzB0w.js.map} +1 -1
- package/web-dist/assets/{board-BrLaJwLJ.js → board-eQ3H8yCp.js} +2 -2
- package/web-dist/assets/{board-BrLaJwLJ.js.map → board-eQ3H8yCp.js.map} +1 -1
- package/web-dist/assets/code-D7JmYMKe.js +13 -0
- package/web-dist/assets/code-D7JmYMKe.js.map +1 -0
- package/web-dist/assets/{describe-DnvH6_fl.js → describe-C1YimBXJ.js} +2 -2
- package/web-dist/assets/{describe-DnvH6_fl.js.map → describe-C1YimBXJ.js.map} +1 -1
- package/web-dist/assets/dist-B_RpNOcK.js +56 -0
- package/web-dist/assets/dist-B_RpNOcK.js.map +1 -0
- package/web-dist/assets/{enroll-DUDpbJoB.js → enroll-1OCy5r50.js} +2 -2
- package/web-dist/assets/{enroll-DUDpbJoB.js.map → enroll-1OCy5r50.js.map} +1 -1
- package/web-dist/assets/{index-vIzH1m8u.js → index-BhpEXLav.js} +4 -4
- package/web-dist/assets/{index-vIzH1m8u.js.map → index-BhpEXLav.js.map} +1 -1
- package/web-dist/assets/index-DUeOwDZ6.css +2 -0
- package/web-dist/assets/{logic-xb-QF00E.js → logic-CBvFOyIo.js} +2 -2
- package/web-dist/assets/{logic-xb-QF00E.js.map → logic-CBvFOyIo.js.map} +1 -1
- package/web-dist/assets/{more-BP5x45cs.js → more-RjVyxPaz.js} +2 -2
- package/web-dist/assets/{more-BP5x45cs.js.map → more-RjVyxPaz.js.map} +1 -1
- package/web-dist/assets/{now--XjJC37b.js → now-CDjeFSLD.js} +2 -2
- package/web-dist/assets/{now--XjJC37b.js.map → now-CDjeFSLD.js.map} +1 -1
- package/web-dist/assets/{settings-D8T1esWq.js → settings-tH4UuIfJ.js} +2 -2
- package/web-dist/assets/{settings-D8T1esWq.js.map → settings-tH4UuIfJ.js.map} +1 -1
- package/web-dist/assets/{shared-CZ7fcu_B.js → shared-CRX6KSBm.js} +2 -2
- package/web-dist/assets/{shared-CZ7fcu_B.js.map → shared-CRX6KSBm.js.map} +1 -1
- package/web-dist/assets/states-DXozulGZ.js +2 -0
- package/web-dist/assets/states-DXozulGZ.js.map +1 -0
- package/web-dist/assets/{terminal-login-BJxV78au.js → terminal-login-CW2rE50W.js} +2 -2
- package/web-dist/assets/{terminal-login-BJxV78au.js.map → terminal-login-CW2rE50W.js.map} +1 -1
- package/web-dist/assets/{useNow-jxdoOC_1.js → useNow-C_B7JgMM.js} +2 -2
- package/web-dist/assets/{useNow-jxdoOC_1.js.map → useNow-C_B7JgMM.js.map} +1 -1
- package/web-dist/index.html +4 -4
- package/web-dist/sw.js +1 -1
- package/web-dist/assets/code-DKLO8bzz.js +0 -11
- package/web-dist/assets/code-DKLO8bzz.js.map +0 -1
- package/web-dist/assets/dist-BE_V9dwJ.js +0 -56
- package/web-dist/assets/dist-BE_V9dwJ.js.map +0 -1
- package/web-dist/assets/index-DvRcMGEe.css +0 -2
- package/web-dist/assets/states--geW2Ntl.js +0 -2
- package/web-dist/assets/states--geW2Ntl.js.map +0 -1
package/README.md
CHANGED
|
@@ -118,7 +118,7 @@ switchyard up
|
|
|
118
118
|
```sh
|
|
119
119
|
docker run -d --name switchyard -p 127.0.0.1:7400:7400 -v switchyard-data:/data \
|
|
120
120
|
-e SWITCHYARD_PUBLIC_URL=https://switchyard.example.com \
|
|
121
|
-
ghcr.io/justmytwospence/switchyard:0.
|
|
121
|
+
ghcr.io/justmytwospence/switchyard:0.8.0
|
|
122
122
|
# Single sign-on is required off localhost: see docs/auth.md
|
|
123
123
|
```
|
|
124
124
|
|
|
@@ -80,6 +80,29 @@ export default function switchyardTerminal(pi) {
|
|
|
80
80
|
if (!socketPath)
|
|
81
81
|
return;
|
|
82
82
|
let ctx = null;
|
|
83
|
+
let completer = null;
|
|
84
|
+
// Work that needs a command context (reload, plugin web views) runs inside a hidden command.
|
|
85
|
+
const internal = new Map();
|
|
86
|
+
const runInternal = (fn) => {
|
|
87
|
+
const token = randomUUID();
|
|
88
|
+
internal.set(token, fn);
|
|
89
|
+
// Without expandPromptTemplates Pi sends the text to the model instead of running the command.
|
|
90
|
+
pi.sendUserMessage(`/switchyard-internal ${token}`, { expandPromptTemplates: true });
|
|
91
|
+
};
|
|
92
|
+
try {
|
|
93
|
+
pi.registerCommand?.("switchyard-internal", {
|
|
94
|
+
description: "Used by Switchyard's web app",
|
|
95
|
+
handler: async (args, c) => {
|
|
96
|
+
const key = String(args ?? "").trim();
|
|
97
|
+
const run = internal.get(key);
|
|
98
|
+
internal.delete(key);
|
|
99
|
+
await run?.(c);
|
|
100
|
+
},
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
// an older Pi: no web views or reload
|
|
105
|
+
}
|
|
83
106
|
let remoteDialogs = false;
|
|
84
107
|
let entryCount = 0;
|
|
85
108
|
const pending = new Map();
|
|
@@ -377,6 +400,33 @@ export default function switchyardTerminal(pi) {
|
|
|
377
400
|
const name = message.slice(1).split(/\s/)[0];
|
|
378
401
|
const known = (pi.getCommands?.() ?? []).find((c) => c.name === name);
|
|
379
402
|
if (known?.source === "extension") {
|
|
403
|
+
const args = message.slice(1 + name.length).trim();
|
|
404
|
+
const probe = { version: 1, name, args, probe: true };
|
|
405
|
+
try {
|
|
406
|
+
pi.events?.emit?.("switchyard.web-command.v1", probe);
|
|
407
|
+
}
|
|
408
|
+
catch {
|
|
409
|
+
// no web view
|
|
410
|
+
}
|
|
411
|
+
if (probe.accept === true) {
|
|
412
|
+
runInternal(async (c) => {
|
|
413
|
+
const req = { version: 1, name, args, probe: false, ctx: c };
|
|
414
|
+
try {
|
|
415
|
+
pi.events.emit("switchyard.web-command.v1", req);
|
|
416
|
+
const view = await Promise.race([
|
|
417
|
+
Promise.resolve(req.view),
|
|
418
|
+
new Promise((_, rej) => setTimeout(() => rej(new Error("timed out")), 15000)),
|
|
419
|
+
]);
|
|
420
|
+
if (!view)
|
|
421
|
+
throw new Error(`/${name} returned no view`);
|
|
422
|
+
respond(id, type, { disposition: "view", view });
|
|
423
|
+
}
|
|
424
|
+
catch (e) {
|
|
425
|
+
respond(id, type, undefined, `/${name} failed: ${e?.message ?? e}`);
|
|
426
|
+
}
|
|
427
|
+
});
|
|
428
|
+
return;
|
|
429
|
+
}
|
|
380
430
|
pi.sendUserMessage(message, { expandPromptTemplates: true });
|
|
381
431
|
respond(id, type, { disposition: "handled" });
|
|
382
432
|
return;
|
|
@@ -446,10 +496,13 @@ export default function switchyardTerminal(pi) {
|
|
|
446
496
|
return;
|
|
447
497
|
case "get_commands":
|
|
448
498
|
respond(id, type, {
|
|
449
|
-
commands: (pi.getCommands?.() ?? [])
|
|
499
|
+
commands: (pi.getCommands?.() ?? [])
|
|
500
|
+
.filter((c) => c.name !== "switchyard-internal")
|
|
501
|
+
.map((c) => ({
|
|
450
502
|
name: c.name,
|
|
451
503
|
description: c.description ?? null,
|
|
452
504
|
source: c.source,
|
|
505
|
+
sourceInfo: c.sourceInfo ?? null,
|
|
453
506
|
})),
|
|
454
507
|
});
|
|
455
508
|
return;
|
|
@@ -498,6 +551,38 @@ export default function switchyardTerminal(pi) {
|
|
|
498
551
|
}
|
|
499
552
|
});
|
|
500
553
|
return;
|
|
554
|
+
case "reload":
|
|
555
|
+
if (!ctx) {
|
|
556
|
+
respond(id, type, undefined, "Session is not ready");
|
|
557
|
+
return;
|
|
558
|
+
}
|
|
559
|
+
respond(id, type);
|
|
560
|
+
runInternal((c) => c.reload());
|
|
561
|
+
return;
|
|
562
|
+
case "complete": {
|
|
563
|
+
const text = String(cmd.text ?? "");
|
|
564
|
+
if (!completer?.getSuggestions || !/^\/\S+ /.test(text) || text.includes("\n")) {
|
|
565
|
+
respond(id, type, { items: [], prefix: "" });
|
|
566
|
+
return;
|
|
567
|
+
}
|
|
568
|
+
const ac = new AbortController();
|
|
569
|
+
const timer = setTimeout(() => ac.abort(), 2000);
|
|
570
|
+
Promise.resolve(completer.getSuggestions([text], 0, text.length, { signal: ac.signal }))
|
|
571
|
+
.then((s) => respond(id, type, {
|
|
572
|
+
items: (Array.isArray(s?.items) ? s.items : [])
|
|
573
|
+
.filter((i) => typeof i?.value === "string")
|
|
574
|
+
.slice(0, 50)
|
|
575
|
+
.map((i) => ({
|
|
576
|
+
value: i.value,
|
|
577
|
+
label: typeof i.label === "string" ? i.label : i.value,
|
|
578
|
+
description: typeof i.description === "string" ? i.description : null,
|
|
579
|
+
})),
|
|
580
|
+
prefix: typeof s?.prefix === "string" ? s.prefix : "",
|
|
581
|
+
}))
|
|
582
|
+
.catch(() => respond(id, type, { items: [], prefix: "" }))
|
|
583
|
+
.finally(() => clearTimeout(timer));
|
|
584
|
+
return;
|
|
585
|
+
}
|
|
501
586
|
default:
|
|
502
587
|
respond(id, type, undefined, `Unknown command: ${type}`);
|
|
503
588
|
}
|
|
@@ -589,6 +674,16 @@ export default function switchyardTerminal(pi) {
|
|
|
589
674
|
on("session_start", (event, c) => {
|
|
590
675
|
ctx = c;
|
|
591
676
|
patchUi(c);
|
|
677
|
+
completer = null;
|
|
678
|
+
try {
|
|
679
|
+
c.ui?.addAutocompleteProvider?.((current) => {
|
|
680
|
+
completer = current;
|
|
681
|
+
return current;
|
|
682
|
+
});
|
|
683
|
+
}
|
|
684
|
+
catch {
|
|
685
|
+
// RPC or an older Pi: no completions
|
|
686
|
+
}
|
|
592
687
|
entryCount = c.sessionManager.getEntries().length;
|
|
593
688
|
const sessionId = c.sessionManager.getSessionId();
|
|
594
689
|
const sessionFile = c.sessionManager.getSessionFile() ?? null;
|