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
c779d52
feat: add Sentry error tracking (#287)
jmaxdev Apr 29, 2026
1bb0749
Revert "feat: add Sentry error tracking (#287)" (#291)
jmaxdev Apr 29, 2026
c3cb5a8
feat: cloud AI streaming for OpenAI / Anthropic / Gemini / OpenRouter…
matiaspalmac Apr 29, 2026
e6e3b36
feat: store cloud AI provider keys in OS keychain (#294)
matiaspalmac Apr 29, 2026
9207f5e
feat: cloud AI tool calling and agent mode for OpenAI / Anthropic / G…
matiaspalmac Apr 29, 2026
f7d6531
feat: detach bottom panel into a floating window (#296)
matiaspalmac Apr 29, 2026
97c4c43
feat: cross-window chat history sync between main and floating window…
matiaspalmac Apr 29, 2026
86a6067
feat: JSON Crack-style graph view for .json files (#298)
matiaspalmac Apr 29, 2026
285a668
feat: drag-to-reorder rows in .env and package.json visual editors (#…
matiaspalmac Apr 29, 2026
61b47a9
feat: open another workspace in a new window via Ctrl+Shift+N (#300)
matiaspalmac Apr 29, 2026
3c3f936
Sentry telemetry (#292)
jmaxdev Apr 29, 2026
bf9f325
fix(desktop): avoid Tauri state TypeId collision between Ollama and C…
matiaspalmac Apr 29, 2026
c75ec25
fix(desktop): use crypto.getRandomValues fallback for WINDOW_SESSION_…
matiaspalmac Apr 30, 2026
feb4c00
feat: implement core UI components, localization hooks, and agent con…
jmaxdev May 1, 2026
8b9d495
Improvement: Add Discord RPC
jmaxdev May 1, 2026
7be4bd4
add: Included colavorative features using discord (beta)
jmaxdev May 1, 2026
896b1e8
feat: implement agent architecture with context providers, workspace …
jmaxdev May 1, 2026
94d0ea1
feat: implement StatusBar and TitleBar components with integrated col…
jmaxdev May 1, 2026
6298be1
feat: implement CollaborationContext for Yjs-based real-time sessions…
jmaxdev May 1, 2026
3e71a46
feat: implement CollaborationContext for Yjs-based real-time syncing …
jmaxdev May 1, 2026
105c40d
feat: implement Status Bar and Tab Bar components with collaboration …
jmaxdev May 1, 2026
da7d3d9
feat: add real-time collaboration support via Yjs and WebRTC with sta…
jmaxdev May 1, 2026
70b97eb
chore: increment version
jmaxdev May 1, 2026
9f45ed2
fix: fixed wrong version
jmaxdev May 1, 2026
1714577
Merge branch 'main' into dev
jmaxdev May 1, 2026
14624f9
feat: implement backend support for workspace synchronization, Discor…
jmaxdev May 1, 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
2 changes: 1 addition & 1 deletion apps/desktop/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@trixty/desktop",
"version": "1.0.14",
"version": "1.1.5",
"private": true,
"scripts": {
"dev": "next dev",
Expand Down
3 changes: 1 addition & 2 deletions apps/desktop/src-tauri/src/discord_rpc.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use serde::{Deserialize, Serialize};
use serde_json::{json, Value};
use std::env;
use std::path::PathBuf;

use tokio::io::{AsyncReadExt, AsyncWriteExt};
#[cfg(unix)]
use tokio::net::UnixStream;
Expand Down
2 changes: 1 addition & 1 deletion apps/desktop/src-tauri/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ mod http;
mod pty;
mod discord_rpc;

use cli::CliWorkspace;

use error::redact_user_paths;

mod extensions;
Expand Down
7 changes: 3 additions & 4 deletions apps/desktop/src/api/builtin.l10n.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1004,6 +1004,9 @@ export function registerBuiltinTranslations() {
'agent.configuration.loadonstartup_warning': 'Aviso: Esto puede provocar ralentización del sistema y hacer que Trixty tarde más en cargar mientras el modelo se sube a la memoria.',
'agent.configuration.loadonstartup_ping_desc': 'Trixty enviará una señal en segundo plano para cargar los modelos al iniciar la aplicación.',
'agent.configuration.keepalive_unit': 'minutos',
'agent.configuration.ai_agent_suffix': 'Agente de IA',
'agent.configuration.time_m': '{n}m',
'agent.configuration.time_h': '{n}h',
'agent.configuration.provider_keys_label': 'Permitir Claves de Proveedor',
'agent.configuration.provider_keys_desc': 'Desbloquea proveedores en la nube (OpenAI, Anthropic, Gemini, OpenRouter) en el encabezado del chat y revela el submenú Claves de Proveedor donde guardas las credenciales API.',
'agent.configuration.inline_suggestions_label': 'Sugerencias de código en línea',
Expand Down Expand Up @@ -1033,10 +1036,6 @@ export function registerBuiltinTranslations() {
'settings.about.logo_alt': 'Logo de Trixty',
'settings.general.exclude_title_part1': 'Archivos: ',
'settings.general.exclude_title_part2': 'Excluir',
'agent.configuration.keepalive_unit': 'minutos',
'agent.configuration.ai_agent_suffix': 'Agente de IA',
'agent.configuration.time_m': '{n}m',
'agent.configuration.time_h': '{n}h',
'onboarding.language.en_native': 'Inglés (EE. UU.)',
'onboarding.language.es_native': 'Español',
});
Expand Down
4 changes: 2 additions & 2 deletions apps/desktop/src/components/StatusBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@
const StatusBar: React.FC = () => {
const { currentFile } = useFiles();
const {
setSidebarOpen,

Check failure on line 23 in apps/desktop/src/components/StatusBar.tsx

View workflow job for this annotation

GitHub Actions / quality

'setSidebarOpen' is assigned a value but never used
setRightPanelOpen,

Check failure on line 24 in apps/desktop/src/components/StatusBar.tsx

View workflow job for this annotation

GitHub Actions / quality

'setRightPanelOpen' is assigned a value but never used
setBottomPanelOpen,

Check failure on line 25 in apps/desktop/src/components/StatusBar.tsx

View workflow job for this annotation

GitHub Actions / quality

'setBottomPanelOpen' is assigned a value but never used
} = useUI();
const { rootPath } = useWorkspace();
const { t } = useL10n();
Expand Down Expand Up @@ -89,8 +89,8 @@
.filter(u => u.user && u.user.clientId !== (provider?.awareness?.clientID))
.map((u, i) => (
<div key={i} className="flex items-center gap-2 px-1.5 py-1 rounded hover:bg-white/5 transition-colors">
<div className="w-1.5 h-1.5 rounded-full" style={{ backgroundColor: u.user.color }} />
<span className="text-[11px] text-[#bbb]">{u.user.name}</span>
<div className="w-1.5 h-1.5 rounded-full" style={{ backgroundColor: u.user?.color }} />
<span className="text-[11px] text-[#bbb]">{u.user?.name}</span>
</div>
))}
</div>
Expand Down
4 changes: 2 additions & 2 deletions apps/desktop/src/components/TabBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,8 @@ const TabBar: React.FC = () => {
className="flex bg-surface-1 h-[36px] overflow-x-auto scrollbar-none border-b border-border-subtle shrink-0"
>
{openFiles.map((file) => {
const isActive = currentFile &&
file.path.replace(/\\/g, "/").toLowerCase() === currentFile.path.replace(/\\/g, "/").toLowerCase();
const isActive = !!(currentFile &&
file.path.replace(/\\/g, "/").toLowerCase() === currentFile.path.replace(/\\/g, "/").toLowerCase());
return (
<div
key={file.path}
Expand Down
22 changes: 17 additions & 5 deletions apps/desktop/src/context/CollaborationContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,23 @@ import { useSettings } from "@/context/SettingsContext";
import * as Y from "yjs";
import { WebrtcProvider } from "y-webrtc";

export interface CollaborationUser {
name: string;
color: string;
clientId: number;
currentFile?: string | null;
}

export interface AwarenessState {
user?: CollaborationUser;
}


interface CollaborationContextType {
isCollaborating: boolean;
role: "host" | "guest" | null;
joinSecret: string | null;
activeUsers: any[];
activeUsers: AwarenessState[];
ydoc: Y.Doc;
provider: WebrtcProvider | null;
acceptJoin: (userId: string) => Promise<void>;
Expand All @@ -28,7 +40,7 @@ export function CollaborationProvider({ children }: { children: React.ReactNode
const [isCollaborating, setIsCollaborating] = useState(false);
const [role, setRole] = useState<"host" | "guest" | null>(null);
const [joinSecret, setJoinSecret] = useState<string | null>(null);
const [activeUsers, setActiveUsers] = useState<any[]>([]);
const [activeUsers, setActiveUsers] = useState<AwarenessState[]>([]);
const { systemSettings } = useSettings();

const ydoc = useMemo(() => new Y.Doc(), []);
Expand Down Expand Up @@ -65,7 +77,7 @@ export function CollaborationProvider({ children }: { children: React.ReactNode
});

// Listen for Discord RPC events
const unlisten = listen("discord-rpc-event", (event: any) => {
const unlisten = listen("discord-rpc-event", (event: { payload: any }) => {
const { evt, data } = event.payload;
if (evt === "ACTIVITY_JOIN_REQUEST") {
const { user } = data;
Expand Down Expand Up @@ -135,7 +147,7 @@ export function CollaborationProvider({ children }: { children: React.ReactNode
try {
await invoke("accept_discord_join_request", { userId });
toast.success("Accepted join request");
} catch (err) {
} catch {
toast.error("Failed to accept join request");
}
};
Expand All @@ -144,7 +156,7 @@ export function CollaborationProvider({ children }: { children: React.ReactNode
try {
await invoke("reject_discord_join_request", { userId });
toast.info("Rejected join request");
} catch (err) {
} catch {
toast.error("Failed to reject join request");
}
};
Expand Down
10 changes: 5 additions & 5 deletions apps/desktop/src/hooks/useWorkspaceSync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useEffect, useCallback } from "react";
import { invoke } from "@tauri-apps/api/core";
import { useCollaboration } from "@/context/CollaborationContext";
import { useWorkspace } from "@/context/WorkspaceContext";
import { useSettings } from "@/context/SettingsContext";

import * as Y from "yjs";

interface FileEntry {
Expand All @@ -15,9 +15,9 @@ interface FileEntry {
export function useWorkspaceSync() {
const { isCollaborating, role, ydoc } = useCollaboration();
const { rootPath } = useWorkspace();
const { systemSettings } = useSettings();

const syncDirectory = useCallback(async (path: string, map: Y.Map<any>) => {

const syncDirectory = useCallback(async (path: string, map: Y.Map<unknown>) => {
try {
const data = await invoke<FileEntry[]>("read_directory", { path });

Expand Down Expand Up @@ -46,14 +46,14 @@ export function useWorkspaceSync() {
syncDirectory(rootPath, workspaceMap);

// Listen for file requests from guests
const requestObserver = async (event: any) => {
const requestObserver = async (event: Y.YMapEvent<unknown>) => {
for (const [path, action] of event.keys) {
if (action.action === "add" || action.action === "update") {
const req = fileRequests.get(path);
if (!req) continue;

try {
const content = await invoke<string>("read_file", { path }, { silent: true });
const content = await invoke<string>("read_file", { path });
const sharedText = ydoc.getText(`file:${path}`);

// Only populate if empty to avoid overwriting current edits
Expand Down
Loading