docs(sdk): fige le contrat command-and-feedback et aligne l'exemple hello-plugin

Documente la règle publique menu -> command handler -> tâche de fond optionnelle
-> feedback (docs/commands-and-feedback.md + README), clarifie via JSDoc les
invariants de runCommand/recordOnly/ownerAgentId dans runtime.ts, et met à jour
l'exemple hello-plugin (feedback structuré launched/skipped, watch non-fatal)
pour qu'il illustre fidèlement le contrat documenté. Publie docs/ dans le
package npm.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-08-03 15:51:30 +02:00
parent e509e796b4
commit 5b55996558
7 changed files with 318 additions and 29 deletions

View File

@ -128,6 +128,7 @@ export interface WorkspaceService {
/**
* Extension point for host file watching. The MVP SDK reserves the public
* shape; hosts may reject with a clear not-implemented error until #127 lands.
* Plugins must treat watch setup as best-effort and non-fatal.
*/
watch(path: string, handler: WorkspaceWatchHandler, projectId?: string): Promise<WorkspaceWatch>;
/** Queries a bounded, generic project structure read model. */
@ -219,9 +220,19 @@ export interface ProjectStructure {
export interface BackgroundTaskStatus {
taskId: string;
/**
* Agent that owns completion delivery and Work attribution for this task.
* This is host-assigned for existing tasks and should be treated as an opaque
* agent id by plugins.
*/
ownerAgentId: string;
projectId: string;
kind: string;
/**
* Work read-model status. A skipped plugin command is not a background task
* and therefore never appears here; skipped commands should be reported by
* the command handler return value and plugin logs.
*/
status: "pending" | "running" | "completed" | "failed" | "cancelled" | "delivered";
exitCode: number | null;
summary: string | null;
@ -245,7 +256,11 @@ export interface BackgroundTaskRetryResult {
export interface RunCommandTaskOptions {
/** Project that owns the command workspace. Defaults to the focused project. */
projectId?: string;
/** Agent id used by IdeA Work for ownership, cancellation and completion delivery. */
/**
* Real agent id used by IdeA Work for ownership, cancellation and completion
* delivery. Plugins must obtain this from host/plugin state for the workflow
* they are serving; placeholder ids are only acceptable in isolated examples.
*/
ownerAgentId: string;
/** Human-facing label shown in Work. Defaults to the command line. */
label?: string;
@ -257,7 +272,12 @@ export interface RunCommandTaskOptions {
cwd?: string;
/** Extra environment variables for the command. */
env?: Record<string, string> | Array<[string, string]>;
/** When true, completion is recorded without waking the owner agent. */
/**
* When true, completion is recorded without waking the owner agent. This does
* not hide the task from Work/background-task surfaces and does not represent
* a skipped command. If preconditions fail, return readable command feedback
* instead of launching a record-only task.
*/
recordOnly?: boolean;
/** Optional absolute deadline, epoch milliseconds. */
deadlineMs?: number;
@ -265,9 +285,17 @@ export interface RunCommandTaskOptions {
export interface CommandTaskStatus {
taskId: string;
/**
* Agent that owns this command task. The host uses it for correlation,
* cancellation and completion delivery.
*/
ownerAgentId: string;
projectId: string;
kind: string;
/**
* Lifecycle state of a command task that was actually launched. There is no
* `skipped` state: skipped commands are command-handler feedback, not tasks.
*/
state: "queued" | "running" | "waiting" | "completed" | "failed" | "cancelled" | "expired";
exitCode: number | null;
summary: string | null;
@ -479,7 +507,15 @@ export interface ConfigDocumentService {
}
export interface BackgroundTaskService {
/** Launches a non-interactive command as a first-class IdeA background task. */
/**
* Launches a non-interactive command as a first-class IdeA background task.
*
* Call this only after command preconditions are satisfied. The returned
* `CommandTaskStatus` means a task exists and can be inspected through command
* status APIs and Work/background-task surfaces. A plugin command that decides
* not to launch work should return readable command feedback, for example
* `{ status: "skipped", reason, message }`, and should not call `runCommand()`.
*/
runCommand(options: RunCommandTaskOptions): Promise<CommandTaskStatus>;
/** Reads one command task directly from the host task store. */
getCommandStatus(taskId: string): Promise<CommandTaskStatus | null>;