impel-cli 0.20.25 → 0.20.26
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/RELEASE_NOTES.md +9 -0
- package/package.json +1 -1
- package/src/apps.js +1 -1
- package/src/desktopTasks.js +29 -56
package/RELEASE_NOTES.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# Release notes
|
|
2
2
|
|
|
3
|
+
## 0.20.26 — Native task-board navigation
|
|
4
|
+
|
|
5
|
+
- Embeds Tasks in each managed desktop app's content view instead of a
|
|
6
|
+
separate always-on-top window, so selecting another sidebar destination
|
|
7
|
+
reliably dismisses the tenant board and completes the vendor navigation.
|
|
8
|
+
- Removes the redundant desktop frame around the MCP App so the task-board
|
|
9
|
+
toolbar and workspace occupy the complete host content surface.
|
|
10
|
+
- Rebuilds existing managed bundles onto the corrected embedded-view contract.
|
|
11
|
+
|
|
3
12
|
## 0.20.25 — Embedded tenant task boards
|
|
4
13
|
|
|
5
14
|
- Adds a persistent Tasks destination to the exact managed Claude and
|
package/package.json
CHANGED
package/src/apps.js
CHANGED
|
@@ -301,7 +301,7 @@ export const CURRENT_CONFIG_VERSION = 32;
|
|
|
301
301
|
// — which is what made every `impel update` re-trigger macOS permission
|
|
302
302
|
// prompts. Bump this ONLY when a code change alters the bytes of a built
|
|
303
303
|
// bundle; leave it alone for changes that don't touch bundle contents.
|
|
304
|
-
export const BUNDLE_BUILD_FINGERPRINT = "bundle-2026-08-08.
|
|
304
|
+
export const BUNDLE_BUILD_FINGERPRINT = "bundle-2026-08-08.2";
|
|
305
305
|
|
|
306
306
|
/** Parse the tenant's install manifest, or null when absent/corrupt. */
|
|
307
307
|
export function readTenantManifest(homeDir = os.homedir(), tenantId = null) {
|
package/src/desktopTasks.js
CHANGED
|
@@ -254,7 +254,7 @@ const NAVIGATION_SOURCE = String.raw`(() => {
|
|
|
254
254
|
const sidebar = findSidebar();
|
|
255
255
|
if (!sidebar || !(event.target instanceof Node) || !sidebar.contains(event.target)) return;
|
|
256
256
|
select(false);
|
|
257
|
-
signal("hide");
|
|
257
|
+
setTimeout(() => signal("hide"), 0);
|
|
258
258
|
};
|
|
259
259
|
const onResize = () => {
|
|
260
260
|
if (active) signal("layout");
|
|
@@ -480,11 +480,12 @@ if (
|
|
|
480
480
|
const {
|
|
481
481
|
app,
|
|
482
482
|
BrowserWindow,
|
|
483
|
+
WebContentsView,
|
|
483
484
|
ipcMain,
|
|
484
485
|
shell,
|
|
485
486
|
webContents: electronWebContents,
|
|
486
487
|
} = electron;
|
|
487
|
-
if (!app || !BrowserWindow || !ipcMain || !electronWebContents) {
|
|
488
|
+
if (!app || !BrowserWindow || !WebContentsView || !ipcMain || !electronWebContents) {
|
|
488
489
|
record("unsupported-electron-surface");
|
|
489
490
|
return;
|
|
490
491
|
}
|
|
@@ -540,16 +541,7 @@ if (
|
|
|
540
541
|
const createView = (window) => {
|
|
541
542
|
const state = stateFor(window);
|
|
542
543
|
if (state.view && !state.view.webContents.isDestroyed()) return state;
|
|
543
|
-
const view =
|
|
544
|
-
frame: false,
|
|
545
|
-
show: false,
|
|
546
|
-
resizable: false,
|
|
547
|
-
movable: false,
|
|
548
|
-
minimizable: false,
|
|
549
|
-
maximizable: false,
|
|
550
|
-
fullscreenable: false,
|
|
551
|
-
skipTaskbar: true,
|
|
552
|
-
backgroundColor: "#181818",
|
|
544
|
+
const view = new WebContentsView({
|
|
553
545
|
webPreferences: {
|
|
554
546
|
preload: viewPreload,
|
|
555
547
|
contextIsolation: true,
|
|
@@ -558,7 +550,9 @@ if (
|
|
|
558
550
|
spellcheck: false,
|
|
559
551
|
},
|
|
560
552
|
});
|
|
561
|
-
|
|
553
|
+
window.contentView.addChildView(view);
|
|
554
|
+
view.setVisible(false);
|
|
555
|
+
view.setBackgroundColor("#181818");
|
|
562
556
|
allowedViewContents.add(view.webContents);
|
|
563
557
|
internalViewContents.add(view.webContents);
|
|
564
558
|
view.webContents.setWindowOpenHandler(() => ({ action: "deny" }));
|
|
@@ -568,63 +562,45 @@ if (
|
|
|
568
562
|
view.webContents.on("destroyed", () => {
|
|
569
563
|
allowedViewContents.delete(view.webContents);
|
|
570
564
|
internalViewContents.delete(view.webContents);
|
|
571
|
-
|
|
572
|
-
view.on("closed", () => {
|
|
565
|
+
try { window.contentView.removeChildView(view); } catch {}
|
|
573
566
|
if (state.view === view) state.view = null;
|
|
574
567
|
});
|
|
575
|
-
view.on("blur", () => setTimeout(() => {
|
|
576
|
-
const focused = BrowserWindow.getFocusedWindow();
|
|
577
|
-
if (focused === window || focused === state.nativeNav || focused === state.view) return;
|
|
578
|
-
state.visible = false;
|
|
579
|
-
state.view?.hide();
|
|
580
|
-
state.nativeNav?.hide();
|
|
581
|
-
}, 100));
|
|
582
568
|
view.webContents.loadURL(hostUrl).catch((error) => record("view-load-failed", error));
|
|
583
569
|
state.view = view;
|
|
584
570
|
return state;
|
|
585
571
|
};
|
|
586
572
|
|
|
587
|
-
const screenBounds = (window, bounds) => {
|
|
588
|
-
const content = window.getContentBounds();
|
|
589
|
-
return {
|
|
590
|
-
x: content.x + bounds.x,
|
|
591
|
-
y: content.y + bounds.y,
|
|
592
|
-
width: bounds.width,
|
|
593
|
-
height: bounds.height,
|
|
594
|
-
};
|
|
595
|
-
};
|
|
596
|
-
|
|
597
573
|
const show = (window, bounds) => {
|
|
598
574
|
const state = createView(window);
|
|
599
575
|
state.bounds = bounds;
|
|
600
576
|
state.visible = true;
|
|
601
|
-
state.view.setBounds(
|
|
602
|
-
state.view.
|
|
603
|
-
state.view.focus();
|
|
577
|
+
state.view.setBounds(bounds);
|
|
578
|
+
state.view.setVisible(true);
|
|
579
|
+
state.view.webContents.focus();
|
|
604
580
|
const boardStatus = () => ({
|
|
605
581
|
parentBounds: window.getBounds(),
|
|
606
582
|
parentContentBounds: window.getContentBounds(),
|
|
607
583
|
boardBounds: state.view.getBounds(),
|
|
608
|
-
boardVisible: state.
|
|
609
|
-
boardFocused: state.view.isFocused(),
|
|
584
|
+
boardVisible: state.visible,
|
|
585
|
+
boardFocused: state.view.webContents.isFocused(),
|
|
610
586
|
});
|
|
611
587
|
record("board-shown", JSON.stringify(boardStatus()));
|
|
612
588
|
setTimeout(() => {
|
|
613
|
-
if (state.view && !state.view.isDestroyed()) record("board-visible-check", JSON.stringify(boardStatus()));
|
|
589
|
+
if (state.view && !state.view.webContents.isDestroyed()) record("board-visible-check", JSON.stringify(boardStatus()));
|
|
614
590
|
}, 2000);
|
|
615
591
|
};
|
|
616
592
|
const hide = (window) => {
|
|
617
593
|
const state = windows.get(window.id);
|
|
618
594
|
if (!state) return;
|
|
619
595
|
state.visible = false;
|
|
620
|
-
state.view?.
|
|
596
|
+
state.view?.setVisible(false);
|
|
621
597
|
window.webContents.focus();
|
|
622
598
|
};
|
|
623
599
|
|
|
624
600
|
const layoutBoard = (window) => {
|
|
625
601
|
const state = windows.get(window.id);
|
|
626
|
-
if (!state?.visible || !state.view || !state.bounds || state.view.isDestroyed()) return;
|
|
627
|
-
state.view.setBounds(
|
|
602
|
+
if (!state?.visible || !state.view || !state.bounds || state.view.webContents.isDestroyed()) return;
|
|
603
|
+
state.view.setBounds(state.bounds);
|
|
628
604
|
};
|
|
629
605
|
|
|
630
606
|
const nativeBoardBounds = (window) => {
|
|
@@ -800,24 +776,24 @@ if (
|
|
|
800
776
|
state.nativeNav.showInactive();
|
|
801
777
|
state.nativeNav.moveTop();
|
|
802
778
|
}
|
|
803
|
-
if (state?.visible && state.view && !state.view.isDestroyed()) state.view.
|
|
779
|
+
if (state?.visible && state.view && !state.view.webContents.isDestroyed()) state.view.setVisible(true);
|
|
804
780
|
});
|
|
805
781
|
window.on("blur", () => setTimeout(() => {
|
|
806
782
|
const state = windows.get(window.id);
|
|
807
783
|
const focused = BrowserWindow.getFocusedWindow();
|
|
808
|
-
if (focused === state?.nativeNav
|
|
784
|
+
if (focused === state?.nativeNav) return;
|
|
809
785
|
state?.nativeNav?.hide();
|
|
810
|
-
state?.view?.
|
|
786
|
+
state?.view?.setVisible(false);
|
|
811
787
|
}, 1000));
|
|
812
788
|
window.on("minimize", () => {
|
|
813
789
|
const state = windows.get(window.id);
|
|
814
790
|
state?.nativeNav?.hide();
|
|
815
|
-
state?.view?.
|
|
791
|
+
state?.view?.setVisible(false);
|
|
816
792
|
});
|
|
817
793
|
window.on("restore", () => {
|
|
818
794
|
const state = windows.get(window.id);
|
|
819
795
|
state?.nativeNav?.showInactive();
|
|
820
|
-
if (state?.visible) state.view?.
|
|
796
|
+
if (state?.visible) state.view?.setVisible(true);
|
|
821
797
|
});
|
|
822
798
|
window.on("closed", () => {
|
|
823
799
|
const state = windows.get(window.id);
|
|
@@ -830,7 +806,8 @@ if (
|
|
|
830
806
|
if (state.nativeNav) nativeNavOwners.delete(state.nativeNav.webContents);
|
|
831
807
|
try {
|
|
832
808
|
if (state.view) {
|
|
833
|
-
state.view
|
|
809
|
+
window.contentView.removeChildView(state.view);
|
|
810
|
+
state.view.webContents.close();
|
|
834
811
|
}
|
|
835
812
|
if (state.nativeNav) {
|
|
836
813
|
state.nativeNav.destroy();
|
|
@@ -900,7 +877,7 @@ if (
|
|
|
900
877
|
if (focused && (windows.has(focused.id) || internalViewContents.has(focused.webContents))) return;
|
|
901
878
|
for (const state of windows.values()) {
|
|
902
879
|
state.nativeNav?.hide();
|
|
903
|
-
state.view?.
|
|
880
|
+
state.view?.setVisible(false);
|
|
904
881
|
}
|
|
905
882
|
};
|
|
906
883
|
|
|
@@ -949,19 +926,13 @@ export function desktopTasksHostHtml() {
|
|
|
949
926
|
:root { color-scheme: light dark; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; }
|
|
950
927
|
* { box-sizing: border-box; }
|
|
951
928
|
html, body { width: 100%; height: 100%; margin: 0; overflow: hidden; background: Canvas; color: CanvasText; }
|
|
952
|
-
body { display: grid; grid-template-rows:
|
|
953
|
-
header { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 0 10px 0 14px; border-bottom: 1px solid color-mix(in srgb, CanvasText 12%, transparent); }
|
|
954
|
-
header strong { font-size: 13px; font-weight: 600; }
|
|
955
|
-
button { border: 0; border-radius: 7px; padding: 5px 9px; background: color-mix(in srgb, CanvasText 8%, Canvas); color: CanvasText; font: inherit; cursor: pointer; }
|
|
956
|
-
button:hover { background: color-mix(in srgb, CanvasText 13%, Canvas); }
|
|
957
|
-
button:focus-visible { outline: 2px solid #7c8cff; outline-offset: 2px; }
|
|
929
|
+
body { display: grid; grid-template-rows: minmax(0, 1fr); }
|
|
958
930
|
iframe { width: 100%; height: 100%; border: 0; background: Canvas; }
|
|
959
931
|
#status { display: grid; place-items: center; padding: 24px; color: color-mix(in srgb, CanvasText 65%, transparent); text-align: center; }
|
|
960
932
|
#status[hidden] { display: none; }
|
|
961
933
|
</style>
|
|
962
934
|
</head>
|
|
963
935
|
<body>
|
|
964
|
-
<header><strong>Tasks</strong><button id="close" type="button" aria-label="Close Tasks">Close</button></header>
|
|
965
936
|
<div id="status" role="status">Loading Impel Tasks…</div>
|
|
966
937
|
<iframe id="widget" title="Impel Tasks" sandbox="allow-scripts allow-forms" hidden></iframe>
|
|
967
938
|
<script>
|
|
@@ -1024,7 +995,9 @@ export function desktopTasksHostHtml() {
|
|
|
1024
995
|
}
|
|
1025
996
|
});
|
|
1026
997
|
|
|
1027
|
-
|
|
998
|
+
window.addEventListener("keydown", (event) => {
|
|
999
|
+
if (event.key === "Escape") bridge.close();
|
|
1000
|
+
});
|
|
1028
1001
|
Promise.all([
|
|
1029
1002
|
bridge.rpc({ method: "resources/read", params: { uri: ${JSON.stringify(DESKTOP_TASKS_RESOURCE_URI)} } }),
|
|
1030
1003
|
bridge.rpc({ method: "tools/call", params: { name: "show_tasks", arguments: { scope: "visible", limit: 50 } } }),
|