* feat: shell controller, TabStage, layout and theme plugins with repair view

* feat: move the classic layout into its own bundled plugin

* feat: move color themes into a bundled themes plugin

* fix: plugin tests and type checks work with a linked sdk

* fix: home tab, layout switch and missing layout fallbacks for looks

* chore: add classic layout and themes to the readme

* chore: drop example plugin links from the plugin guide

* feat: plugin filters by type, paged browse, hide plugins needing newer termix

* feat: move desktop, status, import, audit and branding features into plugins

* feat: host lock api so a plugin can load hosts from a config file (#1581)

* chore: add hosts config to the plugin table

* feat: login policy hook for plugins and optional https redirect (#1584)

* chore: add login security to the plugin table

* feat: api key socket tickets so a master can open remote sessions (#1654)

* feat: sync moves to a plugin, desktop gets multiple accounts (#1580, #1654)

* chore: add sync to the plugin table

* feat: move the sync screens and wizard out of core into the plugin (#1580)

* fix: add a neutral linked desktop hook for plugins (#1580)

* fix: show the linked account's name and admin flag in the app (#1580)

* feat: ssh transport providers, core ssh relay and plugin folders api

* feat: support FIDO2 security keys through ssh agent

* feat: add companion panels beside host tabs

* feat: mTLS client certificates for desktop server links

* feat: native web view for plugins in the desktop app

* fix: detect the desktop link window by Electron's default user agent

Fixes #1675

* fix: changelog for desktop link fix

* fix: keep text primary keys in the plugin data export

* fix: ship sharp binaries for Windows arm64 builds

* feat: client cert on the sync link types (sdk 1.0.18)

* chore: update translations

* feat: themed title bar for the desktop app (#1690)

* chore: changelog for the themed title bar

* fix: draw the title bar in the sidebar color

* feat: per host layout for the terminal panel bar

* chore: sdk 1.0.19 for the panel bar layout

* chore: bundle all 43 plugins for 26.10.3

* chore: update translations

---------

Co-authored-by: SirHephaistos <60616553+SirHephaistos@users.noreply.github.com>
Co-authored-by: Giovanny Aranda <garanda21@gmail.com>
This commit is contained in:
authored and GitHub committed 2026-10-20 16:03:29 -05:00
1 parent aff29a9581
commit a89ccc6b07
577 files changed
+76479 -101831

No files matched your search

+95
View File
@@ -276,6 +276,33 @@ describe("pinsFromIndex", () => {
expect(pins[0]).not.toHaveProperty("onboarding");
});
it("pins a release kept in gated", () => {
const pins = pinsFromIndex(
{
plugins: [
{
id: "look",
versions: [],
gated: [
{
version: "1.1.0-beta.1",
url: "https://example.test/look-1.1.0-beta.1.tmxplug",
sha256: "d".repeat(64),
},
{
version: "1.0.0",
url: "https://example.test/look-1.0.0.tmxplug",
sha256: "e".repeat(64),
},
],
},
],
},
null,
);
expect(pins[0].url).toBe("https://example.test/look-1.0.0.tmxplug");
});
it("pins only the ids asked for", () => {
expect(pinsFromIndex(index, ["beta"]).map((pin) => pin.id)).toEqual([
"beta",
@@ -416,3 +443,71 @@ describe("rebuilding local plugins", () => {
expect(run.sort()).toEqual(["a", "b"]);
});
});
describe("default look", () => {
const entry = { source: "tmxplug", path: "a", sha256: SHA };
it("reads the defaultLook flag and refuses anything but a boolean", () => {
const { plugins, problems } = parseBundledPlugins({
plugins: [
{ ...entry, id: "look", defaultLook: true },
{ ...entry, id: "plain" },
{ ...entry, id: "odd", defaultLook: "yes" },
],
});
expect(problems).toEqual(["odd defaultLook must be a boolean"]);
expect(
plugins.map((p: { id: string; defaultLook: boolean }) => [
p.id,
p.defaultLook,
]),
).toEqual([
["look", true],
["plain", false],
]);
});
it("carries it into the bundled index and through a re-pin", () => {
expect(
buildBundledIndex(
[
{ id: "look", onboarding: null, defaultLook: true },
{ id: "plain", onboarding: null, defaultLook: false },
],
["look", "plain"],
),
).toEqual({ version: 1, plugins: { look: { defaultLook: true } } });
const index = {
plugins: [
{
id: "look",
versions: [
{ version: "1.0.0", url: "https://x/l.tmxplug", sha256: SHA },
],
},
],
};
expect(
pinsFromIndex(index, null, [{ id: "look", defaultLook: true }])[0],
).toMatchObject({ id: "look", defaultLook: true });
});
it("copies a local build's theme files", () => {
const repo = tempDir();
fs.mkdirSync(path.join(repo, "dist"), { recursive: true });
fs.mkdirSync(path.join(repo, "themes"), { recursive: true });
fs.writeFileSync(path.join(repo, "dist", "backend.js"), "export {}");
fs.writeFileSync(path.join(repo, "themes", "paper.css"), ".paper{}");
fs.writeFileSync(
path.join(repo, "manifest.json"),
JSON.stringify({
id: "inks",
contributes: { themes: [{ id: "paper", css: "themes/paper.css" }] },
}),
);
const out = path.join(tempDir(), "inks");
copyLocalBuild(repo, out);
expect(fs.existsSync(path.join(out, "themes", "paper.css"))).toBe(true);
});
});