Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
c2d44a3
Unify compact subheaders and diff file navigation
juliusmarminge Jun 15, 2026
9d5e632
Tighten workspace control spacing in the header
juliusmarminge Jun 15, 2026
71ea5fa
Show disabled reasons for unavailable right panel surfaces (#3093)
juliusmarminge Jun 15, 2026
d0a7d18
[codex] Fix first browser annotation capture (#3095)
t3dotgg Jun 16, 2026
d12da19
Use `fff` for workspace search queries (#3099)
juliusmarminge Jun 16, 2026
5cd2744
[codex] Fix terminal line height for QR readability (#3096)
StiensWout Jun 16, 2026
708d538
[codex] Trace first-party relay clients (#2995)
juliusmarminge Jun 16, 2026
85fe62d
Stage fff native binaries in desktop builds (#3109)
juliusmarminge Jun 16, 2026
689a882
[codex] Add native mobile composer and markdown (#3101)
juliusmarminge Jun 16, 2026
8f9911f
Add DELETE-based MCP session termination (#3113)
juliusmarminge Jun 16, 2026
a5efb7c
Parallelize VCS status refresh and status reads (#3112)
juliusmarminge Jun 16, 2026
4b73827
fix(settings): disable auto-open of task sidebar by default (#2421)
jappyjan Jun 16, 2026
60b546c
Double-click a sidebar thread row to rename (#3064)
TheIcarusWings Jun 16, 2026
6602757
sync: merge upstream right panel search relay layer
Jun 23, 2026
7bbd621
Fix preview CI checks
Jun 24, 2026
80e6106
Fix provider diagnostics checks
Jun 24, 2026
d8df4fe
Merge branch 'sync/upstream-20260615-file-browser' into sync/upstream…
Jun 24, 2026
3107e8f
Fix provider session directory test imports
Jun 24, 2026
11a6286
Merge branch 'sync/upstream-20260615-file-browser' into sync/upstream…
Jun 24, 2026
f6bcc1c
Merge branch 'sync/upstream-20260615-file-browser' into sync/upstream…
Jun 24, 2026
4a34d31
Merge branch 'sync/upstream-20260615-file-browser' into sync/upstream…
Jun 24, 2026
8612c20
Stabilize provider registry reprobe test
Jun 24, 2026
f5ba4f6
Merge branch 'sync/upstream-20260615-file-browser' into sync/upstream…
Jun 24, 2026
f448878
Stabilize provider registry reprobe test
Jun 24, 2026
0abf592
Merge branch 'sync/upstream-20260615-file-browser' into sync/upstream…
Jun 24, 2026
a38a422
Merge branch 'sync/upstream-20260615-file-browser' into sync/upstream…
Jun 24, 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
49 changes: 49 additions & 0 deletions apps/desktop/src/preview/Manager.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,55 @@ describe("PreviewManager", () => {
),
);

effectIt.effect("keeps element picking active during subframe navigation", () =>
withManager((manager) =>
Effect.gen(function* () {
const listeners = new Map<string, (...args: unknown[]) => void>();
fromId.mockReturnValue({
id: 42,
isDestroyed: () => false,
getType: () => "webview",
getURL: () => "https://example.com",
getTitle: () => "Example",
isLoading: () => false,
isFocused: () => true,
getZoomFactor: () => 1,
setZoomFactor: vi.fn(),
on: vi.fn((event: string, listener: (...args: unknown[]) => void) => {
listeners.set(event, listener);
}),
once: vi.fn((event: string, listener: (...args: unknown[]) => void) => {
listeners.set(event, listener);
}),
off: vi.fn(),
ipc: { on: vi.fn(), off: vi.fn(), removeListener: vi.fn() },
send: webviewSend,
navigationHistory: { canGoBack: () => false, canGoForward: () => false },
setWindowOpenHandler: vi.fn(),
debugger: {
isAttached: () => false,
attach: vi.fn(),
sendCommand: vi.fn(async () => undefined),
on: vi.fn(),
off: vi.fn(),
},
} as never);

yield* manager.createTab("tab_1");
yield* manager.registerWebview("tab_1", 42);
const pick = yield* manager.pickElement("tab_1").pipe(Effect.forkChild);
yield* Effect.yieldNow;

listeners.get("did-start-navigation")?.({}, "about:blank", false, false);
yield* Effect.yieldNow;
expect(pick.pollUnsafe()).toBeUndefined();

listeners.get("did-start-navigation")?.({}, "https://example.com/next", false, true);
expect(yield* Fiber.join(pick)).toBeNull();
}),
),
);

effectIt.effect("reveals only files inside the configured browser artifact directory", () =>
withManager((manager) =>
Effect.gen(function* () {
Expand Down
9 changes: 8 additions & 1 deletion apps/desktop/src/preview/Manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1344,7 +1344,14 @@ const makeNativeOperations = Effect.fn("PreviewManager.makeOperations")(function
);
};
const onDestroyed = () => settle(null);
const onNavigated = () => settle(null);
const onNavigated = (
_event: Electron.Event,
_url: string,
_isInPlace: boolean,
isMainFrame: boolean,
) => {
if (isMainFrame) settle(null);
};
const registerPickElement = Effect.fn("PreviewManager.registerPickElement")(function* () {
yield* attempt("pickElement.register", () => {
wc.ipc.on(ELEMENT_PICKED_CHANNEL, onMessage);
Expand Down
15 changes: 14 additions & 1 deletion apps/desktop/src/window/DesktopWindow.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ function makeFakeBrowserWindow() {
once: vi.fn(),
restore: vi.fn(),
setBackgroundColor: vi.fn(),
setAutoHideCursor: vi.fn(),
setTitle: vi.fn(),
setTitleBarOverlay: vi.fn(),
show: vi.fn(),
Expand All @@ -78,6 +79,7 @@ function makeFakeBrowserWindow() {
window: window as unknown as Electron.BrowserWindow,
loadURL: window.loadURL,
openDevTools: webContents.openDevTools,
setAutoHideCursor: window.setAutoHideCursor,
webContentsListeners,
};
}
Expand Down Expand Up @@ -134,10 +136,17 @@ function makeTestLayer(input: {
readonly window: Electron.BrowserWindow;
readonly createCount: Ref.Ref<number>;
readonly mainWindow: Ref.Ref<Option.Option<Electron.BrowserWindow>>;
readonly createdWindowOptions?: Electron.BrowserWindowConstructorOptions[];
readonly openedExternalUrls?: unknown[];
}) {
const electronWindowLayer = Layer.succeed(ElectronWindow.ElectronWindow, {
create: () => Ref.update(input.createCount, (count) => count + 1).pipe(Effect.as(input.window)),
create: (options) =>
Effect.sync(() => {
input.createdWindowOptions?.push(options);
}).pipe(
Effect.andThen(Ref.update(input.createCount, (count) => count + 1)),
Effect.as(input.window),
),
main: Ref.get(input.mainWindow),
currentMainOrFirst: Ref.get(input.mainWindow),
focusedMainOrFirst: Ref.get(input.mainWindow),
Expand Down Expand Up @@ -206,10 +215,12 @@ describe("DesktopWindow", () => {
const fakeWindow = makeFakeBrowserWindow();
const createCount = yield* Ref.make(0);
const mainWindow = yield* Ref.make<Option.Option<Electron.BrowserWindow>>(Option.none());
const createdWindowOptions: Electron.BrowserWindowConstructorOptions[] = [];
const layer = makeTestLayer({
window: fakeWindow.window,
createCount,
mainWindow,
createdWindowOptions,
});

yield* Effect.gen(function* () {
Expand All @@ -219,6 +230,8 @@ describe("DesktopWindow", () => {

yield* desktopWindow.handleBackendReady;
assert.equal(yield* Ref.get(createCount), 1);
assert.isTrue(createdWindowOptions[0]?.disableAutoHideCursor);
assert.deepEqual(fakeWindow.setAutoHideCursor.mock.calls, [[false]]);
assert.deepEqual(fakeWindow.loadURL.mock.calls[0], ["http://127.0.0.1:5733/"]);
assert.equal(fakeWindow.openDevTools.mock.calls.length, 1);
}).pipe(Effect.provide(layer));
Expand Down
5 changes: 5 additions & 0 deletions apps/desktop/src/window/DesktopWindow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ const make = Effect.gen(function* () {
minHeight: 620,
show: false,
autoHideMenuBar: true,
...(environment.platform === "darwin" ? { disableAutoHideCursor: true } : {}),
backgroundColor: getInitialWindowBackgroundColor(shouldUseDarkColors),
...iconOption,
title: environment.displayName,
Expand All @@ -206,6 +207,10 @@ const make = Effect.gen(function* () {
},
});

if (environment.platform === "darwin") {
window.setAutoHideCursor(false);
}

yield* previewManager.setMainWindow(window);
window.webContents.on("will-attach-webview", (event, webPreferences, params) => {
if (
Expand Down
4 changes: 2 additions & 2 deletions apps/mobile/clerk-theme.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"neutral": "#F5F5F5",
"border": "#E5E5EA",
"ring": "#A3A3A3",
"muted": "#F5F5F5",
"muted": "#F2F2F7",
"shadow": "#000000"
},
"darkColors": {
Expand All @@ -30,7 +30,7 @@
"neutral": "#1C1C1C",
"border": "#2A2A2A",
"ring": "#525252",
"muted": "#1C1C1C",
"muted": "#0E0E0E",
"shadow": "#000000"
},
"design": {
Expand Down
20 changes: 15 additions & 5 deletions apps/mobile/global.css
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
--color-foreground: #262626;
--color-foreground-secondary: #525252;
--color-foreground-muted: #737373;
--color-foreground-tertiary: #a3a3a3;
--color-foreground-tertiary: #8e8e93;

/* Borders & separators */
--color-border: rgba(0, 0, 0, 0.08);
Expand All @@ -28,6 +28,9 @@
/* Subtle backgrounds (badges, pills, overlays) */
--color-subtle: rgba(0, 0, 0, 0.04);
--color-subtle-strong: rgba(0, 0, 0, 0.08);
--color-inline-skill-background: rgba(217, 70, 239, 0.12);
--color-inline-skill-border: rgba(217, 70, 239, 0.25);
--color-inline-skill-foreground: #a21caf;

/* Primary action */
--color-primary: #262626;
Expand Down Expand Up @@ -58,6 +61,8 @@
/* Header / glass chrome */
--color-header: rgba(255, 255, 255, 0.97);
--color-header-border: rgba(0, 0, 0, 0.06);
--color-glass-surface: rgba(255, 255, 255, 0.72);
--color-glass-tint: rgba(255, 255, 255, 0.18);

/* StatusBar */
--color-status-bar: #f2f2f7;
Expand Down Expand Up @@ -105,8 +110,8 @@
/* Text */
--color-foreground: #f5f5f5;
--color-foreground-secondary: #a3a3a3;
--color-foreground-muted: #737373;
--color-foreground-tertiary: #525252;
--color-foreground-muted: #8e8e93;
--color-foreground-tertiary: #636366;

/* Borders & separators */
--color-border: rgba(255, 255, 255, 0.06);
Expand All @@ -116,6 +121,9 @@
/* Subtle backgrounds (badges, pills, overlays) */
--color-subtle: rgba(255, 255, 255, 0.04);
--color-subtle-strong: rgba(255, 255, 255, 0.08);
--color-inline-skill-background: rgba(217, 70, 239, 0.12);
--color-inline-skill-border: rgba(217, 70, 239, 0.25);
--color-inline-skill-foreground: #f0abfc;

/* Primary action */
--color-primary: #f5f5f5;
Expand All @@ -136,16 +144,18 @@
/* Inputs */
--color-input: #141414;
--color-input-border: rgba(255, 255, 255, 0.08);
--color-placeholder: #737373;
--color-placeholder: #8e8e93;

/* Icons */
--color-icon: #f5f5f5;
--color-icon-muted: #a3a3a3;
--color-icon-subtle: #737373;
--color-icon-subtle: #8e8e93;

/* Header / glass chrome */
--color-header: rgba(10, 10, 10, 0.97);
--color-header-border: rgba(255, 255, 255, 0.06);
--color-glass-surface: rgba(23, 23, 23, 0.78);
--color-glass-tint: rgba(23, 23, 23, 0.24);

/* StatusBar */
--color-status-bar: #0a0a0a;
Expand Down
21 changes: 21 additions & 0 deletions apps/mobile/modules/t3-composer-editor/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
The MIT License (MIT)

Copyright (c) 2015-present 650 Industries, Inc. (aka Expo)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"platforms": ["apple"],
"apple": {
"modules": ["T3ComposerEditorModule"]
}
Comment on lines +1 to +5

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Add package metadata for the composer module

This new local Expo module is consumed by the iOS composer via requireNativeView("T3ComposerEditor"), but the module directory only adds expo-module.config.json/podspec files and no package.json metadata. Expo autolinking expects the module config to live next to a package manifest, so iOS prebuild will not discover/register T3ComposerEditorModule; mounting the composer will then fail with a missing native view. Add the local module package metadata (and app dependency/podspec path as needed) so it is autolinked.

Useful? React with 👍 / 👎.

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
Pod::Spec.new do |s|
s.name = 'T3ComposerEditor'
s.version = '1.0.0'
s.summary = 'Native attributed composer editor for T3 Code mobile.'
s.description = 'UIKit-backed rich text composer with atomic skill and file tokens.'
s.author = 'T3 Tools'
s.homepage = 'https://t3tools.com'
s.platforms = {
:ios => '16.4',
}
s.source = { :path => '.' }
s.static_framework = true

s.dependency 'ExpoModulesCore'
# Swift/Objective-C compatibility
s.pod_target_xcconfig = {
'DEFINES_MODULE' => 'YES',
}

s.source_files = "**/*.{h,m,mm,swift,hpp,cpp}"
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import ExpoModulesCore

public class T3ComposerEditorModule: Module {
public func definition() -> ModuleDefinition {
Name("T3ComposerEditor")

View(T3ComposerEditorView.self) {
Prop("value") { (view: T3ComposerEditorView, value: String) in
view.setValue(value)
}
Prop("tokensJson") { (view: T3ComposerEditorView, tokensJson: String) in
view.setTokensJson(tokensJson)
}
Prop("selectionJson") { (view: T3ComposerEditorView, selectionJson: String) in
view.setSelectionJson(selectionJson)
}
Prop("themeJson") { (view: T3ComposerEditorView, themeJson: String) in
view.setThemeJson(themeJson)
}
Prop("placeholder") { (view: T3ComposerEditorView, placeholder: String) in
view.setPlaceholder(placeholder)
}
Prop("fontFamily") { (view: T3ComposerEditorView, fontFamily: String) in
view.setFontFamily(fontFamily)
}
Prop("fontSize") { (view: T3ComposerEditorView, fontSize: Double) in
view.setFontSize(CGFloat(fontSize))
}
Prop("lineHeight") { (view: T3ComposerEditorView, lineHeight: Double) in
view.setLineHeight(CGFloat(lineHeight))
}
Prop("contentInsetVertical") { (view: T3ComposerEditorView, contentInsetVertical: Double) in
view.setContentInsetVertical(CGFloat(contentInsetVertical))
}
Prop("editable") { (view: T3ComposerEditorView, editable: Bool) in
view.setEditable(editable)
}
Prop("scrollEnabled") { (view: T3ComposerEditorView, scrollEnabled: Bool) in
view.setScrollEnabled(scrollEnabled)
}
Prop("autoFocus") { (view: T3ComposerEditorView, autoFocus: Bool) in
view.setAutoFocus(autoFocus)
}
Prop("autoCorrect") { (view: T3ComposerEditorView, autoCorrect: Bool) in
view.setAutoCorrect(autoCorrect)
}
Prop("spellCheck") { (view: T3ComposerEditorView, spellCheck: Bool) in
view.setSpellCheck(spellCheck)
}

Events(
"onComposerChange",
"onComposerSelectionChange",
"onComposerFocus",
"onComposerBlur",
"onComposerPasteImages",
"onComposerContentSizeChange"
)

AsyncFunction("focus") { (view: T3ComposerEditorView) in
view.focusEditor()
}
AsyncFunction("blur") { (view: T3ComposerEditorView) in
view.blurEditor()
}
AsyncFunction("setSelection") { (view: T3ComposerEditorView, start: Int, end: Int) in
view.setSelection(start: start, end: end)
}
}
}
}
Loading
Loading