🎉 Initial commit: PiAgentUI — AI Agent Desktop & Web UI
Build & Push Frontend Docker Image / build-and-push (push) Canceled after 0s
Build Validation / validate (push) Canceled after 6s
Build & Push Backend Docker Image / build-and-push (push) Failing after 10m10s
Build & Push Gateway Docker Image / build-and-push (push) Failing after 10m9s
Build & Push Frontend Docker Image / build-and-push (push) Canceled after 0s
Build Validation / validate (push) Canceled after 6s
Build & Push Backend Docker Image / build-and-push (push) Failing after 10m10s
Build & Push Gateway Docker Image / build-and-push (push) Failing after 10m9s
A professional workspace for AI coding agents with: - Real-time streaming chat with SSE - Session management (fork, clone, tree navigation) - MCP tools browser & metadata panel - Skills browser (global, project, package sources) - Voice input & STT provider configuration - Integrated terminal & file explorer - Model selector with capability metadata - Keyboard-first UI with command palette - 8 languages (en, pt-BR, es, ja, zh-CN, ar, bn, hi) - Tauri 2 desktop app - React 19 + TypeScript + Vite 8 + Tailwind CSS 4 - Pi Agent extension runtime Originally forked from OpenCodeUI, now an independent project. License: GPL-3.0-only
This commit is contained in:
commit
b3489e1ede
983 files changed
+158475
No files matched your search
@@ -0,0 +1,103 @@
|
||||
import { fireEvent, render, screen, waitFor } from '@testing-library/react'
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { ExtensionPanel } from './ExtensionPanel'
|
||||
|
||||
const getExtensionsMock = vi.fn()
|
||||
const installExtensionMock = vi.fn()
|
||||
const removeExtensionPackageMock = vi.fn()
|
||||
|
||||
vi.mock('../api/extension', () => ({
|
||||
getExtensions: (...args: unknown[]) => getExtensionsMock(...args),
|
||||
installExtension: (...args: unknown[]) => installExtensionMock(...args),
|
||||
removeExtensionPackage: (...args: unknown[]) => removeExtensionPackageMock(...args),
|
||||
}))
|
||||
|
||||
vi.mock('../hooks', () => ({
|
||||
useDirectory: () => ({ currentDirectory: '/workspace/demo' }),
|
||||
}))
|
||||
|
||||
vi.mock('../utils', () => ({
|
||||
apiErrorHandler: vi.fn(),
|
||||
}))
|
||||
|
||||
describe('ExtensionPanel', () => {
|
||||
beforeEach(() => {
|
||||
getExtensionsMock.mockReset()
|
||||
installExtensionMock.mockReset()
|
||||
removeExtensionPackageMock.mockReset()
|
||||
vi.spyOn(window, 'confirm').mockReturnValue(true)
|
||||
getExtensionsMock.mockResolvedValue({
|
||||
summary: { total: 3, active: 1, inactive: 1, missing: 1, error: 0 },
|
||||
packages: [
|
||||
{
|
||||
source: 'npm:pi-hud',
|
||||
scope: 'user',
|
||||
filtered: false,
|
||||
packageName: 'pi-hud',
|
||||
version: '0.4.3',
|
||||
description: 'Persistent HUD extension',
|
||||
status: 'active',
|
||||
installedPath: '/home/user/.pi/agent/npm/node_modules/pi-hud',
|
||||
resources: {
|
||||
extensions: [{ name: 'index.ts', path: '/pkg/index.ts', enabled: true }],
|
||||
skills: [{ name: 'release', path: '/pkg/skills/release/SKILL.md', enabled: true }],
|
||||
prompts: [],
|
||||
themes: [],
|
||||
},
|
||||
},
|
||||
{
|
||||
source: 'npm:pi-muted',
|
||||
scope: 'user',
|
||||
filtered: true,
|
||||
packageName: 'pi-muted',
|
||||
version: '1.0.0',
|
||||
description: 'Disabled package',
|
||||
status: 'inactive',
|
||||
installedPath: '/home/user/.pi/agent/npm/node_modules/pi-muted',
|
||||
resources: {
|
||||
extensions: [{ name: 'muted.ts', path: '/pkg/muted.ts', enabled: false }],
|
||||
skills: [],
|
||||
prompts: [],
|
||||
themes: [],
|
||||
},
|
||||
},
|
||||
{
|
||||
source: 'npm:missing-extension',
|
||||
scope: 'project',
|
||||
filtered: false,
|
||||
status: 'missing',
|
||||
resources: { extensions: [], skills: [], prompts: [], themes: [] },
|
||||
},
|
||||
],
|
||||
})
|
||||
installExtensionMock.mockResolvedValue({ source: 'npm:pi-new', scope: 'user', reloadRequired: true })
|
||||
removeExtensionPackageMock.mockResolvedValue({ source: 'npm:pi-hud', scope: 'user', reloadRequired: true })
|
||||
})
|
||||
|
||||
it('renders installed extension packages, active state, install command, and uninstall action', async () => {
|
||||
render(<ExtensionPanel />)
|
||||
|
||||
await waitFor(() => expect(screen.getByText('pi-hud')).toBeInTheDocument())
|
||||
|
||||
expect(screen.getByText('(3)')).toBeInTheDocument()
|
||||
expect(screen.getAllByText('Active').length).toBeGreaterThan(0)
|
||||
expect(screen.getAllByText('Inactive').length).toBeGreaterThan(0)
|
||||
expect(screen.getAllByText('Missing').length).toBeGreaterThan(0)
|
||||
expect(screen.getByText('Persistent HUD extension')).toBeInTheDocument()
|
||||
expect(screen.getAllByText('Extensions 1').length).toBeGreaterThan(0)
|
||||
expect(screen.getByText('Skills 1')).toBeInTheDocument()
|
||||
expect(screen.getByText('index.ts')).toBeInTheDocument()
|
||||
|
||||
const installInput = screen.getByRole('textbox', { name: 'Install command' })
|
||||
fireEvent.change(installInput, { target: { value: 'pi install npm:pi-new' } })
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Install extension' }))
|
||||
|
||||
await waitFor(() => expect(installExtensionMock).toHaveBeenCalledWith('pi install npm:pi-new', '/workspace/demo'))
|
||||
expect(await screen.findByText('Reload Pi Agent to apply extension changes.')).toBeInTheDocument()
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Uninstall pi-hud' }))
|
||||
await waitFor(() =>
|
||||
expect(removeExtensionPackageMock).toHaveBeenCalledWith('npm:pi-hud', 'user', '/workspace/demo'),
|
||||
)
|
||||
})
|
||||
})
|
||||
Reference in new issue
Block a user