Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
72 commits
Select commit Hold shift + click to select a range
a4819eb
feat(desktop): package an NSIS x64 installer for Windows
waleedlatif1 Oct 31, 2026
1babb21
feat(desktop): self-update Windows shells through electron-updater's …
waleedlatif1 Oct 31, 2026
3783207
feat(desktop): advertise the shell platform and gate surfaces per pla…
waleedlatif1 Oct 31, 2026
b8dfb41
feat(desktop): build a Windows File/Edit/View/Help menu
waleedlatif1 Oct 31, 2026
9fd011a
feat(desktop): full-colour Windows tray icon that opens Sim on click
waleedlatif1 Oct 31, 2026
9a4b88a
feat(desktop): Windows single-instance focus, AUMID, and native windo…
waleedlatif1 Oct 31, 2026
d0a4ec4
feat(desktop): report the app theme preference and strip the picker m…
waleedlatif1 Oct 31, 2026
41077cf
feat(desktop): serve Windows update feeds alongside macOS
waleedlatif1 Oct 31, 2026
95010d3
feat(desktop): point sim-setup and the docs at the Windows build
waleedlatif1 Oct 31, 2026
50a1ce7
feat(desktop): run the packaged smoke suite on Windows
waleedlatif1 Oct 31, 2026
87cd48d
fix(desktop): validate Windows paths lexically before touching the fi…
waleedlatif1 Oct 31, 2026
57fb0f4
ci(desktop): build, sign, and publish the Windows installer
waleedlatif1 Oct 31, 2026
261bf2c
feat(desktop): document Windows packaging, signing, and updates
waleedlatif1 Oct 31, 2026
822f048
fix(desktop): keep the committed bridge contract snapshot
waleedlatif1 Oct 31, 2026
bafbdae
fix(desktop): close Windows clipboard and file-name gaps in the agent…
waleedlatif1 Oct 31, 2026
92cf233
merge part A
waleedlatif1 Oct 31, 2026
e4c8d87
merge part B
waleedlatif1 Oct 31, 2026
9bb3c50
merge part C
waleedlatif1 Oct 31, 2026
10146e4
fix(desktop): reconcile the Windows parts after merge
waleedlatif1 Oct 31, 2026
6d1af69
test(desktop): run the desktop unit suite on Windows
waleedlatif1 Oct 31, 2026
046a793
fix(desktop): declare per-platform node-pty prebuilds as optional
waleedlatif1 Oct 31, 2026
7563f8b
ci(desktop): let the macOS callers grant the Windows job's OIDC scope
waleedlatif1 Oct 31, 2026
89ad2ea
test(desktop): give the preferences fixture a terminal-capable shell
waleedlatif1 Oct 31, 2026
bb5a1bb
docs(desktop): keep the install step's existing anchor
waleedlatif1 Oct 31, 2026
9f5991e
fix(desktop): address review on Windows gating, prereleases, and renames
waleedlatif1 Oct 31, 2026
b5a2e83
feat(desktop): ship the native local-file tools on Windows
waleedlatif1 Oct 31, 2026
420e9fc
merge Windows native file tools
waleedlatif1 Oct 31, 2026
5a87b83
feat(terminal-protocol): name Windows programs and carry each termina…
waleedlatif1 Oct 31, 2026
2e39dfe
feat(desktop): run and instrument Windows shells in the agent terminal
waleedlatif1 Oct 31, 2026
e5e376a
feat(desktop): stop a Windows terminal command by its process tree
waleedlatif1 Oct 31, 2026
386a0cd
feat(desktop): keep tmux off on Windows
waleedlatif1 Oct 31, 2026
4b6b17b
feat(desktop): ship the agent terminal on Windows
waleedlatif1 Oct 31, 2026
99d67bb
feat(desktop): send Mothership the desktop's platform and each termin…
waleedlatif1 Oct 31, 2026
ba0fbe6
docs(desktop): document the agent terminal on Windows
waleedlatif1 Oct 31, 2026
55c723b
merge Windows agent terminal
waleedlatif1 Oct 31, 2026
6fe2b11
docs(desktop): list local file tools as available on Windows
waleedlatif1 Oct 31, 2026
1f21b02
chore(mothership): sync the desktop platform and terminal shell proto…
waleedlatif1 Oct 31, 2026
954229b
refactor(desktop): drop the terminal and local-file platform gates
waleedlatif1 Oct 31, 2026
c39ccf1
fix(desktop): keep a stopped or silent terminal command from reading …
waleedlatif1 Oct 31, 2026
7c2a4a5
fix(desktop): give Git Bash its MSYS environment and Windows cwd
waleedlatif1 Oct 31, 2026
ee2aca9
feat(desktop): name a Windows program in the close-running-terminal d…
waleedlatif1 Oct 31, 2026
9c8306a
fix(desktop): run Windows terminals on the bundled ConPTY, which keep…
waleedlatif1 Oct 31, 2026
40841c9
test(desktop): keep skipping the unwritable-directory test on Windows
waleedlatif1 Oct 31, 2026
3bb88d5
fix(desktop): answer the bundled ConPTY's startup query so Windows sh…
waleedlatif1 Oct 31, 2026
9e66d97
perf(desktop): interrupt a stopped command before reading its processes
waleedlatif1 Oct 31, 2026
9dec590
perf(desktop): run Git Bash's cygpath only when the directory changes
waleedlatif1 Oct 31, 2026
6f95c59
refactor(desktop): keep node-pty's platform differences in terminal/pty
waleedlatif1 Oct 31, 2026
7fc52bf
refactor(desktop): name shell programs with terminal-protocol's progr…
waleedlatif1 Oct 31, 2026
c7a5094
refactor(desktop): read tmux support from the platform feature table
waleedlatif1 Oct 31, 2026
ff5f251
refactor(desktop): declare each IPC channel's platform feature on its…
waleedlatif1 Oct 31, 2026
2d22635
refactor(desktop): drop copyCredential's repeat of the passwordCopy gate
waleedlatif1 Oct 31, 2026
4a97d8d
refactor(desktop): restore a minimized window inside bringWindowToFront
waleedlatif1 Oct 31, 2026
2d95608
refactor(desktop): drop stagedFileName's unused platform parameter
waleedlatif1 Oct 31, 2026
ae793eb
refactor(desktop): derive win32-path's global name pattern from the s…
waleedlatif1 Oct 31, 2026
4a04693
refactor(desktop): share file identity and entry kinds across the loc…
waleedlatif1 Oct 31, 2026
19081e6
perf(desktop): classify a Windows listing's reparse points sixteen at…
waleedlatif1 Oct 31, 2026
39d8677
refactor(desktop): name the desktop platforms once in desktop-bridge
waleedlatif1 Oct 31, 2026
7d3c850
refactor(desktop): name each platform's update artifacts once in desk…
waleedlatif1 Oct 31, 2026
7efa552
refactor(desktop): read every channel's identity from one shared table
waleedlatif1 Oct 31, 2026
0a02a0e
refactor(desktop): split the application menu into shared items and p…
waleedlatif1 Oct 31, 2026
77b04be
refactor(desktop): share the update routes' error responses and drop …
waleedlatif1 Oct 31, 2026
0e142ce
perf(desktop): hand the Windows tray icon's scales over as PNG buffers
waleedlatif1 Oct 31, 2026
db4837a
refactor(desktop): upload the Windows release artifacts in one ordere…
waleedlatif1 Oct 31, 2026
40c054e
refactor(desktop): keep pty options and file type info private to the…
waleedlatif1 Oct 31, 2026
4352ba7
test(desktop): satisfy the test-pattern and unused-export audits
waleedlatif1 Oct 31, 2026
ad4ec17
test(desktop): leave the Chromium profile readers out of the Windows …
waleedlatif1 Oct 31, 2026
43c5e5c
fix(desktop): stop only the stopped command's processes on Windows
waleedlatif1 Oct 31, 2026
fb3414f
fix(desktop): answer ConPTY's startup query when it arrives split acr…
waleedlatif1 Oct 31, 2026
be091d0
fix(terminal-protocol): read each Windows shell's own escape and quoting
waleedlatif1 Oct 31, 2026
4e03097
docs(desktop): name the platform feature table's actual readers
waleedlatif1 Oct 31, 2026
3680790
fix(desktop): find a Windows command behind a shell launcher
waleedlatif1 Oct 31, 2026
9fa4316
fix(desktop): type the agent's next command only once the prompt is d…
waleedlatif1 Oct 31, 2026
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
62 changes: 48 additions & 14 deletions .github/scripts/ci-plan.gql
Original file line number Diff line number Diff line change
@@ -1,22 +1,56 @@
query($base: String!, $head: String!) {
packages { items { name path } }
affectedTasks(base: $base, head: $head, tasks: [
"test", "build", "type-check", "ci:integration", "ci:desktop-live",
"ci:e2e-scim", "ci:e2e-cli", "ci:e2e-stop-after", "ci:e2e-desktop-inbox",
"ci:e2e-browser-extension", "ci:e2e-project-files", "ci:e2e-mobile", "ci:e2e-seo"
]) {
query ($base: String!, $head: String!) {
packages {
items {
name
path
}
}
affectedTasks(
base: $base
head: $head
tasks: [
"test"
"build"
"type-check"
"ci:integration"
"ci:desktop-live"
"ci:e2e-scim"
"ci:e2e-cli"
"ci:e2e-stop-after"
"ci:e2e-desktop-inbox"
"ci:e2e-browser-extension"
"ci:e2e-project-files"
"ci:e2e-mobile"
"ci:e2e-seo"
]
) {
items {
name
fullName
package { name }
package {
name
}
reason {
__typename
... on TaskFileChanged { filePath }
... on TaskGlobalFileChanged { filePath }
... on TaskGlobalDepsChanged { filePath }
... on TaskDependencyTaskChanged { taskName packageName }
... on TaskPackageDependencyChanged { packageName }
... on TaskAllChanged { description }
... on TaskFileChanged {
filePath
}
... on TaskGlobalFileChanged {
filePath
}
... on TaskGlobalDepsChanged {
filePath
}
... on TaskDependencyTaskChanged {
taskName
packageName
}
... on TaskPackageDependencyChanged {
packageName
}
... on TaskAllChanged {
description
}
}
}
}
Expand Down
111 changes: 106 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1260,8 +1260,12 @@ jobs:
needs.desktop-signing.result == 'success' &&
needs.version.result == 'success' &&
needs.desktop-signing.outputs.configured == 'true'
# The reusable workflow's Windows job requests id-token: write for Azure
# OIDC, and GitHub checks every called job against the caller's grant at
# startup, even one this macOS call skips.
permissions:
contents: write
id-token: write
uses: ./.github/workflows/desktop-release.yml
with:
version: ${{ needs.version.outputs.version }}
Expand All @@ -1275,6 +1279,55 @@ jobs:
APPLE_API_ISSUER: ${{ secrets.APPLE_API_ISSUER }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}

# Windows desktop builds are signed with Azure Artifact Signing over GitHub
# OIDC. Gated like the macOS build: until the Azure identity and signing
# variables exist, the Windows build skips with a warning, and nothing is
# ever published unsigned. Windows jobs are separate workflow calls that no
# other job needs, so a Windows failure never blocks a macOS release; the
# update feed treats a release without latest.yml as having no Windows build.
desktop-signing-windows:
name: desktop-signing-windows
runs-on: *runner-2vcpu
timeout-minutes: 2
needs: [version, desktop-changes]
if: ${{ !cancelled() && (needs.version.outputs.is_release == 'true' || needs.desktop-changes.outputs.changed == 'true') }}
outputs:
configured: ${{ steps.check.outputs.configured }}
steps:
- name: Probe Azure signing configuration
id: check
env:
CONFIGURED: ${{ secrets.AZURE_CLIENT_ID != '' && secrets.AZURE_TENANT_ID != '' && secrets.AZURE_SUBSCRIPTION_ID != '' && vars.AZURE_SIGNING_ENDPOINT != '' && vars.AZURE_SIGNING_ACCOUNT != '' && vars.AZURE_SIGNING_PROFILE != '' && vars.AZURE_SIGNING_PUBLISHER != '' }}
run: |
echo "configured=${CONFIGURED}" >> "$GITHUB_OUTPUT"
if [ "$CONFIGURED" != "true" ]; then
echo "::warning::Windows desktop release skipped: Azure signing is not configured (secrets AZURE_CLIENT_ID, AZURE_TENANT_ID, AZURE_SUBSCRIPTION_ID; variables AZURE_SIGNING_ENDPOINT, AZURE_SIGNING_ACCOUNT, AZURE_SIGNING_PROFILE, AZURE_SIGNING_PUBLISHER)."
fi

desktop-release-windows:
name: desktop-release-windows
needs: [release, desktop-signing-windows, version]
# See desktop-release for why the implicit success() check is suppressed.
if: >-
!cancelled() &&
needs.release.result == 'success' &&
needs.desktop-signing-windows.result == 'success' &&
needs.version.result == 'success' &&
needs.desktop-signing-windows.outputs.configured == 'true'
permissions:
contents: write
id-token: write
uses: ./.github/workflows/desktop-release.yml
with:
version: ${{ needs.version.outputs.version }}
publish: true
platform: windows
secrets:
DESKTOP_RELEASE_TOKEN: ${{ secrets.DESKTOP_RELEASE_TOKEN }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}

# Per-env desktop prereleases: a dev/staging push that touches shell code
# publishes an environment-tagged GitHub prerelease to the public,
# release-only simstudioai/sim-desktop-releases repository. Keeping these
Expand All @@ -1285,15 +1338,20 @@ jobs:
name: prerelease-create
runs-on: *runner-2vcpu
timeout-minutes: 5
needs: [desktop-changes, desktop-signing]
# Requires the signing probe to have actually succeeded (not just "not
needs: [desktop-changes, desktop-signing, desktop-signing-windows]
# Requires a signing probe to have actually succeeded (not just "not
# cancelled") so a probe failure can't produce a release with no build.
# Either platform's signing is enough: each build job gates on its own.
if: >-
${{
!cancelled() &&
needs.desktop-changes.outputs.changed == 'true' &&
needs.desktop-signing.result == 'success' &&
needs.desktop-signing.outputs.configured == 'true'
(
(needs.desktop-signing.result == 'success' &&
needs.desktop-signing.outputs.configured == 'true') ||
(needs.desktop-signing-windows.result == 'success' &&
needs.desktop-signing-windows.outputs.configured == 'true')
)
}}
permissions:
contents: read
Expand Down Expand Up @@ -1355,11 +1413,19 @@ jobs:
prerelease-build:
name: prerelease-build
needs: [prerelease-create, desktop-signing]
if: >-
!cancelled() &&
needs.prerelease-create.result == 'success' &&
needs.desktop-signing.result == 'success' &&
needs.desktop-signing.outputs.configured == 'true'
# The reusable workflow declares contents: write for its stable-release
# path. GitHub cannot elevate a caller's token, even though this prerelease
# path uses the dedicated cross-repository token for its actual upload.
# id-token: write is required the same way by the Windows job (see
# desktop-release above).
permissions:
contents: write
id-token: write
uses: ./.github/workflows/desktop-release.yml
with:
version: ${{ needs.prerelease-create.outputs.version }}
Expand All @@ -1374,14 +1440,49 @@ jobs:
APPLE_API_ISSUER: ${{ secrets.APPLE_API_ISSUER }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}

# Attaches the Windows build to the same prerelease. A Windows failure never
# holds back a macOS build that succeeded (see prerelease-publish).
prerelease-build-windows:
name: prerelease-build-windows
needs: [prerelease-create, desktop-signing-windows]
Comment thread
cubic-dev-ai[bot] marked this conversation as resolved.
Resolved
if: >-
!cancelled() &&
needs.prerelease-create.result == 'success' &&
needs.desktop-signing-windows.result == 'success' &&
needs.desktop-signing-windows.outputs.configured == 'true'
permissions:
contents: write
id-token: write
uses: ./.github/workflows/desktop-release.yml
with:
version: ${{ needs.prerelease-create.outputs.version }}
publish: true
sign: true
platform: windows
secrets:
DESKTOP_RELEASE_TOKEN: ${{ secrets.DESKTOP_RELEASE_TOKEN }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}

# The draft only becomes visible to the update feed once its artifacts are
# attached — this is what makes a dev/staging push atomic from the shell's
# point of view.
prerelease-publish:
name: prerelease-publish
runs-on: *runner-2vcpu
timeout-minutes: 5
needs: [prerelease-create, prerelease-build]
needs: [prerelease-create, prerelease-build, prerelease-build-windows]
# Publishes once every configured platform has finished: the macOS build
# when Apple signing is configured, otherwise the Windows build alone.
if: >-
!cancelled() &&
needs.prerelease-create.result == 'success' &&
(
needs.prerelease-build.result == 'success' ||
(needs.prerelease-build.result == 'skipped' &&
needs.prerelease-build-windows.result == 'success')
)
permissions:
contents: read
env:
Expand Down
69 changes: 69 additions & 0 deletions .github/workflows/desktop-e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -260,3 +260,72 @@ jobs:
exit 1
fi
SIM_DESKTOP_EXECUTABLE="$EXECUTABLE" bunx playwright test e2e/packaged-smoke.spec.ts

# The Windows leg: the unit suite on Windows, then an unsigned unpacked x64
# build through the same packaged smoke suite (fuses, launch telemetry, and
# the bundled offline page).
package-smoke-windows:
name: package-smoke-windows
if: github.event_name != 'schedule'
runs-on: windows-latest
timeout-minutes: 30
defaults:
run:
shell: bash
steps:
- name: Checkout code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
with:
persist-credentials: false

- name: Setup Bun
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2
with:
bun-version: 1.4.4

- name: Setup Node
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v6
with:
node-version: 22

- name: Cache Electron downloads
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v5
with:
path: |
~/AppData/Local/electron/Cache
~/AppData/Local/electron-builder/Cache
key: desktop-downloads-${{ runner.os }}-${{ hashFiles('bun.lock') }}
restore-keys: desktop-downloads-${{ runner.os }}-

- name: Install dependencies
env:
HUSKY: '0'
run: bun install --frozen-lockfile

- name: Run desktop unit tests
working-directory: apps/desktop
run: bun run test
Comment thread
waleedlatif1 marked this conversation as resolved.
Resolved
Comment thread
waleedlatif1 marked this conversation as resolved.
Resolved

- name: Bundle and package unsigned
working-directory: apps/desktop
run: |
bun run build
bunx electron-builder --win dir --x64 --publish never -c.win.signExecutable=false

- name: Run packaged Electron smoke suite
working-directory: apps/desktop
run: |
EXECUTABLE=release/win-unpacked/Sim.exe
if [ ! -f "$EXECUTABLE" ]; then
echo "::error::Packaged app executable was not found."
exit 1
fi
SIM_DESKTOP_EXECUTABLE="$EXECUTABLE" bunx playwright test e2e/packaged-smoke.spec.ts

- name: Upload test results
if: failure()
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: desktop-package-smoke-windows-results
path: apps/desktop/test-results
retention-days: 7
Loading
Loading