Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,29 @@
# Changelog

## 2.1.2, 2026-07-18

### Neu

- Native Linux-Titelleiste mit Minimieren, Maximieren und Schließen
- Abgesicherter Fenster-Patch für bestehende und neu aufgebaute Laufzeiten
- Sofortige Inhaltsanpassung beim Maximieren und Ändern der Fenstergröße
- Nutzbare Mindestgröße von 900 × 650 Pixeln für normale Kimi-Fenster

### Geändert

- Der native Aufbau aktiviert die Linux-Systemdekoration nach dem Entpacken der Kimi-Anwendung
- Die Inhaltsgröße wird sofort, im nächsten Ereigniszyklus und nach Abschluss der Größenänderung synchronisiert

### Behoben

- Fehlende Fensterknöpfe unter Linux
- Verzögerte oder unvollständige Inhaltsanpassung nach Maximieren und manueller Größenänderung
- Unbrauchbar kleines Zusammenschieben der normalen Kimi-Fenster

### Entfernt

- Keine Änderungen

## 2.1.1, 2026-07-18

### Neu
Expand Down
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,17 @@ Bei jeder vollständigen Installation wird die aktuell von Moonshot AI angeboten
- Start über das Programmmenü und als systemd-Benutzerdienst
- Sicheres Update-Skript mit Versionsprüfung und atomarem Austausch
- Kimi K3 über die aktuelle Kimi-Work-Modellauswahl
- Native Linux-Fensterknöpfe für Minimieren, Maximieren und Schließen
- Sofortige Inhaltsanpassung beim Maximieren und Ändern der Fenstergröße
- Mindestgröße von 900 × 650 Pixeln für normale Kimi-Fenster

## Unterstützter Stand

| Komponente | Version |
| --- | --- |
| Kimi Work | 3.1.2 |
| Kimi-Modell | Kimi K3 verfügbar |
| Kimi Work Linux | 2.1.1 |
| Kimi Work Linux | 2.1.2 |
| Electron | 41.7.2 |
| Kimi Node-Laufzeit | 24.15.0 |
| Plattform | Linux x86_64 mit glibc und systemd |
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "kimi-work-linux",
"version": "2.1.1",
"version": "2.1.2",
"private": true,
"description": "Unofficial native Linux runtime for Kimi Work",
"license": "MIT",
Expand Down
166 changes: 166 additions & 0 deletions scripts/native-setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,17 @@ OFFICIAL_DOWNLOAD_URL='https://appsupport.moonshot.cn/api/app/pkg/latest/windows
NODE_VERSION='v24.15.0'
NODE_ARCHIVE_NAME="node-${NODE_VERSION}-linux-x64.tar.gz"
NODE_ARCHIVE_SHA='44836872d9aec49f1e6b52a9a922872db9a2b02d235a616a5681b6a85fec8d89'
PATCH_ONLY=false

# Erlaubt eine abgesicherte Aktualisierung der vorhandenen Fensterintegration.
if [[ "${1:-}" == '--patch-linux-window-only' ]]; then
PATCH_ONLY=true
shift
fi
[[ "$#" -eq 0 ]] || {
printf 'Fehler: Unbekanntes Argument: %s\n' "$1" >&2
exit 64
}

# Gibt Fehler vollständig aus und beendet den Aufbau.
fail() {
Expand All @@ -34,6 +45,160 @@ cleanup() {
}
trap cleanup EXIT

# Aktiviert die native Titelleiste und synchronisiert den Inhalt mit der Fenstergröße.
patch_linux_window() {
local app_archive="$1"
local patch_dir="${temporary_dir}/linux-window"
local source_dir="${patch_dir}/source"
local main_process_file="${source_dir}/out/main/index.js"
local patched_archive="${patch_dir}/app.asar"

[[ -f "$app_archive" ]] || fail "Das Kimi Anwendungsarchiv fehlt: ${app_archive}"
rm -rf -- "$patch_dir"
mkdir -p "$source_dir"
"${PROJECT_DIR}/node_modules/.bin/asar" extract "$app_archive" "$source_dir"
[[ -f "$main_process_file" ]] || fail 'Der Kimi Hauptprozess für die Fensteranpassung fehlt.'

# Ersetzt ausschließlich die in Kimi 3.1.2 geprüften Fensteroptionen und Ereignisse.
node - "$main_process_file" <<'NODE'
const fs = require('fs')

const mainProcessFile = process.argv[2]
let patched = fs.readFileSync(mainProcessFile, 'utf8')
const count = (text, value) => text.split(value).length - 1

const titlebarOriginal =
'titleBarStyle: process.platform === "darwin" ? "hiddenInset" : "hidden",'
const titlebarReplacement =
'titleBarStyle: process.platform === "darwin" ? "hiddenInset" : process.platform === "linux" ? "default" : "hidden",'
const titlebarOriginalCount = count(patched, titlebarOriginal)
const titlebarReplacementCount = count(patched, titlebarReplacement)

if (titlebarOriginalCount === 2 && titlebarReplacementCount === 0) {
patched = patched.split(titlebarOriginal).join(titlebarReplacement)
} else if (titlebarOriginalCount !== 0 || titlebarReplacementCount !== 2) {
process.stderr.write(
`Fehler: Unerwartete Kimi Titelleistenkonfiguration. Original: ${titlebarOriginalCount}, Linux: ${titlebarReplacementCount}.\n`,
)
process.exit(1)
}

const resizeOriginal = ` setupResizeHandler() {
if (!this.baseWindow) {
return;
}
this.baseWindow.on("resized", () => {
this.contentSurface.updateViewBounds();
this.kimiAgentBrowser.syncVisibility();
});
this.baseWindow.on("resize", () => {
this.contentSurface.updateViewBounds();
this.kimiAgentBrowser.syncVisibility();
});
}`
const resizeReplacement = ` setupResizeHandler() {
if (!this.baseWindow) {
return;
}
let resizeRefreshPending = false;
let resizeSettleTimer;
const refreshContentBounds = () => {
if (!this.baseWindow) {
return;
}
this.contentSurface.updateViewBounds();
this.kimiAgentBrowser.syncVisibility();
};
const scheduleContentBoundsRefresh = () => {
refreshContentBounds();
if (!resizeRefreshPending) {
resizeRefreshPending = true;
setImmediate(() => {
resizeRefreshPending = false;
refreshContentBounds();
});
}
if (resizeSettleTimer) {
clearTimeout(resizeSettleTimer);
}
resizeSettleTimer = setTimeout(() => {
resizeSettleTimer = void 0;
refreshContentBounds();
}, 80);
};
for (const eventName of [
"resize",
"resized",
"maximize",
"unmaximize",
"restore",
"enter-full-screen",
"leave-full-screen"
]) {
this.baseWindow.on(eventName, scheduleContentBoundsRefresh);
}
}`
const resizeOriginalCount = count(patched, resizeOriginal)
const resizeReplacementCount = count(patched, resizeReplacement)

if (resizeOriginalCount === 1 && resizeReplacementCount === 0) {
patched = patched.replace(resizeOriginal, resizeReplacement)
} else if (resizeOriginalCount !== 0 || resizeReplacementCount !== 1) {
process.stderr.write(
`Fehler: Unerwartete Kimi Größenlogik. Original: ${resizeOriginalCount}, Linux: ${resizeReplacementCount}.\n`,
)
process.exit(1)
}

const minimumSizeOriginal = ` minWidth: 400,
minHeight: 600,`
const minimumSizeReplacement = ` minWidth: process.platform === "linux" ? 900 : 400,
minHeight: process.platform === "linux" ? 650 : 600,`
const minimumSizeOriginalCount = count(patched, minimumSizeOriginal)
const minimumSizeReplacementCount = count(patched, minimumSizeReplacement)

if (minimumSizeOriginalCount === 2 && minimumSizeReplacementCount === 0) {
patched = patched.split(minimumSizeOriginal).join(minimumSizeReplacement)
} else if (minimumSizeOriginalCount !== 0 || minimumSizeReplacementCount !== 2) {
process.stderr.write(
`Fehler: Unerwartete Kimi Mindestgröße. Original: ${minimumSizeOriginalCount}, Linux: ${minimumSizeReplacementCount}.\n`,
)
process.exit(1)
}

if (
count(patched, titlebarReplacement) !== 2 ||
count(patched, titlebarOriginal) !== 0 ||
count(patched, resizeReplacement) !== 1 ||
count(patched, resizeOriginal) !== 0 ||
count(patched, minimumSizeReplacement) !== 2 ||
count(patched, minimumSizeOriginal) !== 0
) {
process.stderr.write('Fehler: Die Linux Fensteranpassung konnte nicht eindeutig geprüft werden.\n')
process.exit(1)
}

fs.writeFileSync(mainProcessFile, patched)
process.stdout.write('Die native Linux Titelleiste, Größenanpassung und Mindestgröße wurden aktiviert.\n')
NODE

"${PROJECT_DIR}/node_modules/.bin/asar" pack "$source_dir" "$patched_archive"
"${PROJECT_DIR}/node_modules/.bin/asar" list "$patched_archive" \
| grep -qx '/out/main/index.js' \
|| fail 'Das neu gepackte Kimi Archiv enthält keinen Hauptprozess.'
install -m 0644 "$patched_archive" "${app_archive}.tmp"
mv "${app_archive}.tmp" "$app_archive"
}

# Passt auf ausdrücklichen internen Aufruf nur die vorhandene Laufzeit an.
if [[ "$PATCH_ONLY" == true ]]; then
systemctl --user is-active --quiet kimi-work-native.service \
&& fail 'Kimi Work muss vor der Fensteranpassung beendet werden.'
patch_linux_window "${APP_DIR}/resources/app.asar"
printf '%s\n' 'Die vorhandene Kimi Linux Laufzeit wurde erfolgreich angepasst.'
exit 0
fi

# Lädt das unveränderte aktuelle Kimi Originalpaket herunter.
mkdir -p "$CACHE_DIR"
installer_path="${CACHE_DIR}/kimi-work-latest.exe"
Expand Down Expand Up @@ -70,6 +235,7 @@ new_app_dir="${temporary_dir}/app"
cp -a "${PROJECT_DIR}/node_modules/electron/dist" "$new_app_dir"
mv "${new_app_dir}/electron" "${new_app_dir}/kimi-desktop"
install -m 0644 "${official_dir}/resources/app.asar" "${new_app_dir}/resources/app.asar"
patch_linux_window "${new_app_dir}/resources/app.asar"
resource_dir="${new_app_dir}/resources/resources"
mkdir -p "${resource_dir}/runtime" "${resource_dir}/skills"

Expand Down
Loading