feat(sdk,plugins): ajoute capability tooling et services runtime publics (workspace/terminal/tasks)

- capability manifeste tooling supportée backend + transport runtime catalog
- ctx.services publique côté SDK/runtime, gated par tooling
- surface honnête: workspace, terminal, et tasks en observation/contrôle uniquement
- docs/exemple/tests mis à jour
- QA PASS sur feature/sdk-plugin-tooling-build-debug-surface
This commit is contained in:
2026-08-02 00:31:15 +02:00
parent efaeb31a38
commit 033e9a86d5
21 changed files with 748 additions and 10 deletions

View File

@ -17,7 +17,19 @@ export type {
CommandDisposable,
CommandHandler,
CommandRegistry,
BackgroundTaskOutputAttachment,
BackgroundTaskRetryResult,
BackgroundTaskService,
BackgroundTaskStatus,
IdeAPluginModule,
PluginLogger,
PluginStorage
PluginServices,
PluginStorage,
TerminalOpenOptions,
TerminalReattachOptions,
TerminalReattachResult,
TerminalService,
TerminalSession,
WorkspaceProject,
WorkspaceService
} from "./runtime.js";

View File

@ -59,8 +59,8 @@ function validateCapabilities(value, errors) {
return;
}
value.forEach((capability, index) => {
if (capability !== "ui" && capability !== "mcp") {
errors.push(`capabilities[${index}] must be "ui" or "mcp"`);
if (capability !== "ui" && capability !== "mcp" && capability !== "tooling") {
errors.push(`capabilities[${index}] must be "ui", "mcp" or "tooling"`);
}
});
}

View File

@ -17,7 +17,7 @@ export interface IdeAPluginManifest {
};
}
export type IdeAPluginCapability = "ui" | "mcp";
export type IdeAPluginCapability = "ui" | "mcp" | "tooling";
export interface IdeAPluginEngineConstraints {
idea?: string;
@ -145,8 +145,8 @@ function validateCapabilities(value: unknown, errors: string[]): void {
}
value.forEach((capability, index) => {
if (capability !== "ui" && capability !== "mcp") {
errors.push(`capabilities[${index}] must be "ui" or "mcp"`);
if (capability !== "ui" && capability !== "mcp" && capability !== "tooling") {
errors.push(`capabilities[${index}] must be "ui", "mcp" or "tooling"`);
}
});
}

View File

@ -4,6 +4,12 @@ export interface ActivateContext {
subscriptions: CommandDisposable[];
commands?: CommandRegistry;
storage?: PluginStorage;
/**
* Stable public service facade for plugins that need workspace, background
* task, or terminal operations. This intentionally does not expose IdeA's
* internal runtime/gateway objects.
*/
services?: PluginServices;
}
export interface IdeAPluginModule {
@ -34,3 +40,103 @@ export interface PluginStorage {
delete(key: string): Promise<void>;
}
export interface PluginServices {
workspace: WorkspaceService;
tasks: BackgroundTaskService;
terminal: TerminalService;
}
export interface WorkspaceProject {
id: string;
name: string;
root: string;
}
export interface WorkspaceService {
/** Returns the currently focused project, or null when no project is active. */
getCurrentProject(): Promise<WorkspaceProject | null>;
/** Returns the root path for the given project or for the current project. */
getProjectRoot(projectId?: string): Promise<string>;
/** Reads IdeA's shared project context for the given or current project. */
readProjectContext(projectId?: string): Promise<string>;
/** Updates IdeA's shared project context for the given or current project. */
updateProjectContext(content: string, projectId?: string): Promise<void>;
}
export interface BackgroundTaskStatus {
taskId: string;
ownerAgentId: string;
projectId: string;
kind: string;
status: "pending" | "running" | "completed" | "failed" | "cancelled" | "delivered";
exitCode: number | null;
summary: string | null;
stdoutTail: string | null;
stderrTail: string | null;
updatedAtMs: number;
}
export interface BackgroundTaskOutputAttachment {
taskId: string;
scrollback: Uint8Array;
live: boolean;
detach(): void;
}
export interface BackgroundTaskRetryResult {
/** Present when the host reports the replacement task id. */
taskId?: string;
}
export interface BackgroundTaskService {
/** Lists background tasks visible in the project work-state read model. */
list(projectId?: string): Promise<BackgroundTaskStatus[]>;
/** Reads one task status from the project work-state read model. */
getStatus(taskId: string, projectId?: string): Promise<BackgroundTaskStatus | null>;
/** Attaches to retained/live output for a task. */
attachOutput(
taskId: string,
onData: (bytes: Uint8Array) => void,
): Promise<BackgroundTaskOutputAttachment>;
/** Cancels a pending/running task. */
cancel(taskId: string): Promise<void>;
/** Retries a failed/cancelled task; future hosts may return the new task id. */
retry(taskId: string): Promise<BackgroundTaskRetryResult>;
}
export interface TerminalOpenOptions {
cwd?: string;
rows?: number;
cols?: number;
onData?: (bytes: Uint8Array) => void;
}
export interface TerminalReattachOptions {
onData?: (bytes: Uint8Array) => void;
}
export interface TerminalSession {
readonly sessionId: string;
write(data: Uint8Array): Promise<void>;
resize(rows: number, cols: number): Promise<void>;
detach(): void;
close(): Promise<void>;
}
export interface TerminalReattachResult {
session: TerminalSession;
scrollback: Uint8Array;
}
export interface TerminalService {
/**
* Opens a shell PTY in the requested/current project directory. This MVP is a
* terminal control surface, not a command runner; use tasks for build/test
* commands that should be tracked in the Work panel.
*/
open(options?: TerminalOpenOptions): Promise<TerminalSession>;
/** Reattaches to an already-running PTY and returns retained scrollback. */
reattach(sessionId: string, options?: TerminalReattachOptions): Promise<TerminalReattachResult>;
/** Kills a PTY by id. */
close(sessionId: string): Promise<void>;
}