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
8 changes: 4 additions & 4 deletions ai-dev-vscode/dist/extension.js

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions ai-dev-vscode/dist/extension.js.map

Large diffs are not rendered by default.

574 changes: 468 additions & 106 deletions ai-dev-vscode/dist/webviews/kanban/main.js

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions ai-dev-vscode/dist/webviews/kanban/main.js.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion ai-dev-vscode/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "ai-dev-studio",
"displayName": "AI Dev Studio",
"description": "AI agent orchestration sidebar for AI Dev Studio",
"version": "0.1.5",
"version": "0.1.7",
"publisher": "AllanNielsen",
"icon": "logo.png",
"repository": {
Expand Down
21 changes: 21 additions & 0 deletions ai-dev-vscode/src/StudioApiClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,18 @@ export class StudioApiClient {
await this.del(`/api/board/tasks/${enc(taskId)}?projectSlug=${enc(projectSlug)}`);
}

async addBoardColumn(projectSlug: string, id: string, title: string): Promise<void> {
await this.postJson(`/api/board/columns?projectSlug=${enc(projectSlug)}`, { id, title });
}

async renameBoardColumn(projectSlug: string, columnId: string, title: string): Promise<void> {
await this.patchJson(`/api/board/columns/${enc(columnId)}?projectSlug=${enc(projectSlug)}`, { title });
}

async removeBoardColumn(projectSlug: string, columnId: string): Promise<void> {
await this.del(`/api/board/columns/${enc(columnId)}?projectSlug=${enc(projectSlug)}`);
}

// ── Helpers ──────────────────────────────────────────────────────────────────

private async get<T>(path: string): Promise<T> {
Expand Down Expand Up @@ -129,6 +141,15 @@ export class StudioApiClient {
return res.json() as Promise<T>;
}

private async patchJson(path: string, body: unknown): Promise<void> {
const res = await this.fetcher(this.baseUrl + path, {
method: 'PATCH',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body),
});
if (!res.ok) throw new ApiError(res.status, path);
}

private async del(path: string): Promise<void> {
const res = await this.fetcher(this.baseUrl + path, {
method: 'DELETE',
Expand Down
42 changes: 33 additions & 9 deletions ai-dev-vscode/src/panels/KanbanPanelProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { BasePanelProvider } from './BasePanelProvider';
import { StudioApiClient } from '../StudioApiClient';
import { StudioSignalRClient } from '../StudioSignalRClient';
import { GitHubBoardClient } from '../GitHubBoardClient';
import type { BoardData, GitHubRepoInfo } from '../types';
import type { AgentSummary, BoardData, GitHubRepoInfo } from '../types';
import type { FromKanbanWebview } from '../webviews/shared/protocol';

const SCOPES_ISSUES_ONLY = ['repo'];
Expand Down Expand Up @@ -168,8 +168,8 @@ export class KanbanPanelProvider extends BasePanelProvider {

this.send({ type: 'loading' });
try {
const board = await this.loadLocalBoard();
this.send({ type: 'board', data: board });
const [board, agents] = await Promise.all([this.loadLocalBoard(), this.loadAgents()]);
this.send({ type: 'board', data: board, agents });
view.badge = board.columns.length > 0
? { value: Object.keys(board.tasks).length, tooltip: 'Board task count' }
: undefined;
Expand All @@ -193,9 +193,9 @@ export class KanbanPanelProvider extends BasePanelProvider {
return;
}

const board = await client.getBoard();
const [board, agents] = await Promise.all([client.getBoard(), this.loadAgents()]);
this.currentBoard = board;
this.send({ type: 'board', data: board, githubRepo: `${this.gitHubRepo.owner}/${this.gitHubRepo.repo}` });
this.send({ type: 'board', data: board, agents, githubRepo: `${this.gitHubRepo.owner}/${this.gitHubRepo.repo}` });
view.badge = { value: Object.keys(board.tasks).length, tooltip: 'GitHub Issues' };
} catch (e) {
this.send({ type: 'error', message: `Failed to load GitHub Issues: ${e}` });
Expand All @@ -210,8 +210,8 @@ export class KanbanPanelProvider extends BasePanelProvider {

this.send({ type: 'loading' });
try {
const board = await this.loadLocalBoard();
this.send({ type: 'board', data: board });
const [board, agents] = await Promise.all([this.loadLocalBoard(), this.loadAgents()]);
this.send({ type: 'board', data: board, agents });
panel.title = `AI Dev Board (${Object.keys(board.tasks).length})`;
} catch (e) {
this.send({ type: 'error', message: `Failed to load board: ${e}` });
Expand All @@ -233,9 +233,9 @@ export class KanbanPanelProvider extends BasePanelProvider {
return;
}

const board = await client.getBoard();
const [board, agents] = await Promise.all([client.getBoard(), this.loadAgents()]);
this.currentBoard = board;
this.send({ type: 'board', data: board, githubRepo: `${this.gitHubRepo.owner}/${this.gitHubRepo.repo}` });
this.send({ type: 'board', data: board, agents, githubRepo: `${this.gitHubRepo.owner}/${this.gitHubRepo.repo}` });
panel.title = `AI Dev Board — ${this.gitHubRepo.owner}/${this.gitHubRepo.repo} (${Object.keys(board.tasks).length})`;
} catch (e) {
this.send({ type: 'error', message: `Failed to load GitHub Issues: ${e}` });
Expand Down Expand Up @@ -326,6 +326,15 @@ export class KanbanPanelProvider extends BasePanelProvider {
return board;
}

private async loadAgents(): Promise<AgentSummary[]> {
if (!this.api || !this.projectSlug) return [];
try {
return await this.api.listAgents(this.projectSlug);
} catch {
return [];
}
}

private async handleAction(msg: Exclude<FromKanbanWebview, { type: 'ready' } | { type: 'githubSignIn' }>): Promise<void> {
if (this.gitHubRepo) {
await this.handleGitHubAction(msg);
Expand Down Expand Up @@ -431,6 +440,21 @@ export class KanbanPanelProvider extends BasePanelProvider {

if (msg.type === 'deleteTask') {
await this.api.deleteBoardTask(this.projectSlug, msg.taskId);
return;
}

if (msg.type === 'addColumn') {
await this.api.addBoardColumn(this.projectSlug, msg.id, msg.title);
return;
}

if (msg.type === 'renameColumn') {
await this.api.renameBoardColumn(this.projectSlug, msg.columnId, msg.title);
return;
}

if (msg.type === 'deleteColumn') {
await this.api.removeBoardColumn(this.projectSlug, msg.columnId);
}
}

Expand Down
Loading
Loading