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
1 change: 1 addition & 0 deletions docs/product-name-audit.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ git grep -n -i -E 'kapi|ilchul' -- ':!package-lock.json' ':!node_modules'
- Registry entry types now use the semantic `WorkflowRegistryEntry` name across the domain, adapter, CLI, presentation, and tests.
- Store abstractions now use semantic `WorkflowStore` / `FileWorkflowStore` names across application ports, adapters, and runtime probe scripts; compatibility imports have been migrated and the temporary store alias has been removed.
- Service source surfaces now use semantic `WorkflowService` in the implementation, local factory, presentation layer, runtime probe scripts, and active tests; the temporary `KapiService` export has been removed after migrating the large remaining test clusters.
- Presentation registration/UI action helpers now use semantic workflow names (`registerWorkflowExtension`, `registerWorkflowCommandsAndTools`, `registerWorkflowTools`, `WorkflowUiActionContext`, `installWorkflowAutocomplete`, `toggleWorkflowWidgetExpanded`) while leaving public `kapi_*` tool names and `/kapi-*` contracts intact.

## Residual scan after service filename rename

Expand Down
6 changes: 3 additions & 3 deletions index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { registerKapiExtension, type ExtensionAPI } from "./src/presentation/pi-extension.js";
import { registerWorkflowExtension, type ExtensionAPI } from "./src/presentation/pi-extension.js";

export default function kapi(pi: ExtensionAPI): void {
registerKapiExtension(pi);
export default function extension(pi: ExtensionAPI): void {
registerWorkflowExtension(pi);
}
4 changes: 2 additions & 2 deletions src/presentation/command-ui-actions.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { isTerminalStatus } from "../domain/state-machine.js";
import type { KapiUiActionContext } from "./tool-core-types.js";
import type { WorkflowUiActionContext } from "./tool-core-types.js";
import { formatWorkflowError, labelLatestSessionEntry, resumeUiState, updateUi } from "./ui.js";

interface CommandErrorInput extends KapiUiActionContext {
interface CommandErrorInput extends WorkflowUiActionContext {
command: string;
error: unknown;
details?: Record<string, unknown>;
Expand Down
6 changes: 3 additions & 3 deletions src/presentation/extension-registration.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import type { ExtensionAPI, WorkflowService } from "./tool-core-types.js";
import { WORKFLOW_DEFINITIONS } from "../domain/workflows.js";
import { registerPrimaryWorkflowCommands, registerSupportCommands } from "./commands.js";
import { registerKapiTools } from "./tools.js";
import { registerWorkflowTools } from "./tools.js";

export function registerKapiCommandsAndTools(pi: ExtensionAPI, service: WorkflowService): void {
export function registerWorkflowCommandsAndTools(pi: ExtensionAPI, service: WorkflowService): void {
registerPrimaryWorkflowCommands(pi, service, WORKFLOW_DEFINITIONS);
registerSupportCommands(pi, service);
registerKapiTools(pi, service);
registerWorkflowTools(pi, service);
}
18 changes: 9 additions & 9 deletions src/presentation/pi-extension.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import type { ExtensionAPI, ExtensionContext } from "@mariozechner/pi-coding-agent";
import { createLocalWorkflowService } from "../adapters/workflow-service-factory.js";
import { registerKapiCommandsAndTools } from "./extension-registration.js";
import { existingResourcePath, extensionRootFromImportMeta, installKapiAutocomplete, loadedSkillSummary, toggleKapiWidgetExpanded, updateUi } from "./ui.js";
import { registerWorkflowCommandsAndTools } from "./extension-registration.js";
import { existingResourcePath, extensionRootFromImportMeta, installWorkflowAutocomplete, loadedSkillSummary, toggleWorkflowWidgetExpanded, updateUi } from "./ui.js";

export type { ExtensionAPI };

const KAPI_EXTENSION_ROOT = extensionRootFromImportMeta(import.meta.url);
const EXTENSION_ROOT = extensionRootFromImportMeta(import.meta.url);

export function registerKapiExtension(pi: ExtensionAPI): void {
export function registerWorkflowExtension(pi: ExtensionAPI): void {
const service = createLocalWorkflowService();

registerKapiCommandsAndTools(pi, service);
registerWorkflowCommandsAndTools(pi, service);

const withActiveState = async (ctx: ExtensionContext, handler: (state: NonNullable<Awaited<ReturnType<typeof service.getActiveStatus>>>) => void): Promise<void> => {
const state = await service.getActiveStatus(ctx.cwd);
Expand All @@ -27,19 +27,19 @@ export function registerKapiExtension(pi: ExtensionAPI): void {
ctx.ui.notify("Kapi: no active workflow to expand.", "info");
return;
}
const expanded = toggleKapiWidgetExpanded();
const expanded = toggleWorkflowWidgetExpanded();
updateUi(ctx, state);
ctx.ui.notify(`Kapi status ${expanded ? "expanded" : "collapsed"}.`, "info");
},
});

pi.on("resources_discover", async () => ({
skillPaths: existingResourcePath(KAPI_EXTENSION_ROOT, "skills"),
promptPaths: existingResourcePath(KAPI_EXTENSION_ROOT, "prompts"),
skillPaths: existingResourcePath(EXTENSION_ROOT, "skills"),
promptPaths: existingResourcePath(EXTENSION_ROOT, "prompts"),
}));

pi.on("session_start", async (_event, ctx) => {
installKapiAutocomplete(ctx);
installWorkflowAutocomplete(ctx);
const state = await service.getActiveStatus(ctx.cwd);
updateUi(ctx, state);
});
Expand Down
2 changes: 1 addition & 1 deletion src/presentation/tool-core-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import type { AgentToolResult, ExtensionAPI, ExtensionContext, Theme } from "@ma

export type { AgentToolResult, ExtensionAPI, ExtensionContext, WorkflowService, LifecycleStatus, StartWorkflowInput, Theme, WorkflowDefinition, WorkflowId, WorkflowState, WriteArtifactInput };

export interface KapiUiActionContext {
export interface WorkflowUiActionContext {
pi: ExtensionAPI;
service: WorkflowService;
ctx: ExtensionContext;
Expand Down
34 changes: 17 additions & 17 deletions src/presentation/tools.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { AgentToolResult, ExtensionAPI, ExtensionContext, WorkflowService, KapiUiActionContext, LifecycleStatus, StartWorkflowInput, WorkflowId, WriteArtifactInput } from "./tool-core-types.js";
import type { AgentToolResult, ExtensionAPI, ExtensionContext, WorkflowService, WorkflowUiActionContext, LifecycleStatus, StartWorkflowInput, WorkflowId, WriteArtifactInput } from "./tool-core-types.js";
import { projectRunContract } from "../domain/run-contract.js";
import type { WorkflowState } from "../domain/types.js";
import { getWorkflowDefinition } from "../domain/workflows.js";
Expand Down Expand Up @@ -62,13 +62,13 @@ function workflowEvidenceInput(ctx: ExtensionContext, params: WorkflowEvidenceTo
};
}

interface ToolErrorRequest extends KapiUiActionContext {
interface ToolErrorRequest extends WorkflowUiActionContext {
tool: string;
error: unknown;
details?: Record<string, unknown>;
}

async function kapiToolError(request: ToolErrorRequest): Promise<AgentToolResult<unknown>> {
async function workflowToolError(request: ToolErrorRequest): Promise<AgentToolResult<unknown>> {
const message = formatWorkflowError(request.error);
request.pi.appendEntry("kapi-workflow", { event: "tool-error", tool: request.tool, message, ...(request.details ?? {}) });
updateToolUi(request.ctx, await request.service.getActiveStatus(request.ctx.cwd));
Expand All @@ -78,7 +78,7 @@ async function kapiToolError(request: ToolErrorRequest): Promise<AgentToolResult
};
}

export function registerKapiTools(pi: ExtensionAPI, service: WorkflowService): void {
export function registerWorkflowTools(pi: ExtensionAPI, service: WorkflowService): void {
const startWorkflowTool: WorkflowToolDefinition = {
name: "kapi_start_workflow",
label: "Kapi Start Workflow",
Expand Down Expand Up @@ -112,7 +112,7 @@ export function registerKapiTools(pi: ExtensionAPI, service: WorkflowService): v
details: { state: result.state },
};
} catch (error) {
return kapiToolError({ pi, service, ctx, tool: "kapi_start_workflow", error });
return workflowToolError({ pi, service, ctx, tool: "kapi_start_workflow", error });
}
},
};
Expand Down Expand Up @@ -254,7 +254,7 @@ export function registerKapiTools(pi: ExtensionAPI, service: WorkflowService): v
updateUiForWorkflowPatch(ctx, state);
return stateTextResult(formatStatus(state), state);
} catch (error) {
return kapiToolError({ pi, service, ctx, tool: "kapi_update_workflow", error });
return workflowToolError({ pi, service, ctx, tool: "kapi_update_workflow", error });
}
},
});
Expand All @@ -279,7 +279,7 @@ export function registerKapiTools(pi: ExtensionAPI, service: WorkflowService): v
updateToolUi(ctx, state);
return stateTextResult(formatStatus(state), state);
} catch (error) {
return kapiToolError({ pi, service, ctx, tool: "kapi_record_evidence", error });
return workflowToolError({ pi, service, ctx, tool: "kapi_record_evidence", error });
}
},
});
Expand All @@ -306,7 +306,7 @@ export function registerKapiTools(pi: ExtensionAPI, service: WorkflowService): v
details: { state },
};
} catch (error) {
return kapiToolError({ pi, service, ctx, tool: "kapi_complete_workflow", error });
return workflowToolError({ pi, service, ctx, tool: "kapi_complete_workflow", error });
}
},
});
Expand Down Expand Up @@ -337,7 +337,7 @@ export function registerKapiTools(pi: ExtensionAPI, service: WorkflowService): v
details: { state },
};
} catch (error) {
return kapiToolError({ pi, service, ctx, tool: "kapi_fail_workflow", error });
return workflowToolError({ pi, service, ctx, tool: "kapi_fail_workflow", error });
}
},
});
Expand All @@ -358,7 +358,7 @@ export function registerKapiTools(pi: ExtensionAPI, service: WorkflowService): v
};
} catch (error) {
const errorRequest = { pi, service, ctx, tool: "kapi_write_artifact", error, details: { artifactName: params.artifactName } };
return kapiToolError(errorRequest);
return workflowToolError(errorRequest);
}
},
});
Expand All @@ -385,7 +385,7 @@ export function registerKapiTools(pi: ExtensionAPI, service: WorkflowService): v
details: { state },
};
} catch (error) {
return kapiToolError({ pi, service, ctx, tool: "kapi_write_artifacts", error });
return workflowToolError({ pi, service, ctx, tool: "kapi_write_artifacts", error });
}
},
});
Expand All @@ -407,7 +407,7 @@ export function registerKapiTools(pi: ExtensionAPI, service: WorkflowService): v
};
} catch (error) {
const errorRequest = { pi, service, ctx, tool: "kapi_read_artifact", error, details: { artifactName: params.artifactName } };
return kapiToolError(errorRequest);
return workflowToolError(errorRequest);
}
},
});
Expand Down Expand Up @@ -478,7 +478,7 @@ export function registerKapiTools(pi: ExtensionAPI, service: WorkflowService): v
details: result,
};
} catch (error) {
return kapiToolError({ pi, service, ctx, tool: "kapi_prepare_worker", error });
return workflowToolError({ pi, service, ctx, tool: "kapi_prepare_worker", error });
}
},
});
Expand All @@ -501,7 +501,7 @@ export function registerKapiTools(pi: ExtensionAPI, service: WorkflowService): v
details: result,
};
} catch (error) {
return kapiToolError({ pi, service, ctx, tool: "kapi_prepare_tmux_worker", error });
return workflowToolError({ pi, service, ctx, tool: "kapi_prepare_tmux_worker", error });
}
},
});
Expand All @@ -524,7 +524,7 @@ export function registerKapiTools(pi: ExtensionAPI, service: WorkflowService): v
details: result,
};
} catch (error) {
return kapiToolError({ pi, service, ctx, tool: "kapi_prepare_worktree_worker", error });
return workflowToolError({ pi, service, ctx, tool: "kapi_prepare_worktree_worker", error });
}
},
});
Expand All @@ -548,7 +548,7 @@ export function registerKapiTools(pi: ExtensionAPI, service: WorkflowService): v
};
} catch (error) {
const errorRequest = { pi, service, ctx, tool: "kapi_dispatch_worker_task", error, details: { workerId: params.workerId } };
return kapiToolError(errorRequest);
return workflowToolError(errorRequest);
}
},
});
Expand All @@ -572,7 +572,7 @@ export function registerKapiTools(pi: ExtensionAPI, service: WorkflowService): v
};
} catch (error) {
const errorRequest = { pi, service, ctx, tool: "kapi_refresh_worker_status", error, details: { workerId: params.workerId } };
return kapiToolError(errorRequest);
return workflowToolError(errorRequest);
}
},
});
Expand Down
2 changes: 1 addition & 1 deletion src/presentation/ui-resources.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export function loadedSkillSummary(event: { systemPromptOptions?: { skills?: unk
return typeof skillCount === "number" ? `\n\nPi native context: ${skillCount} skills are loaded in this turn; Kapi should preserve explicit user skill/prompt intent.` : "";
}

export function installKapiAutocomplete(ctx: ExtensionContext): void {
export function installWorkflowAutocomplete(ctx: ExtensionContext): void {
const ui = ctx.ui as ExtensionContext["ui"] & { addAutocompleteProvider?: ExtensionContext["ui"]["addAutocompleteProvider"] };
if (typeof ui.addAutocompleteProvider !== "function") return;
ui.addAutocompleteProvider((current) => ({
Expand Down
14 changes: 7 additions & 7 deletions src/presentation/ui.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { isTerminalStatus, statusWidgetLines, type ExtensionAPI, type ExtensionContext, type WorkflowService, type Theme, type WorkflowState } from "./ui-support.js";

let kapiWidgetExpanded = false;
let workflowWidgetExpanded = false;

export function toggleKapiWidgetExpanded(): boolean {
kapiWidgetExpanded = !kapiWidgetExpanded;
return kapiWidgetExpanded;
export function toggleWorkflowWidgetExpanded(): boolean {
workflowWidgetExpanded = !workflowWidgetExpanded;
return workflowWidgetExpanded;
}

export function updateUi(ctx: ExtensionContext, state: WorkflowState | undefined): void {
Expand All @@ -16,8 +16,8 @@ export function updateUi(ctx: ExtensionContext, state: WorkflowState | undefined
}
ctx.ui.setWidget("kapi", (_tui: unknown, theme: Theme) => ({
render(width: number): string[] {
const lines = statusWidgetLines(state, { expanded: kapiWidgetExpanded });
const hint = kapiWidgetExpanded ? "ctrl+shift+t collapse" : "ctrl+shift+t expand";
const lines = statusWidgetLines(state, { expanded: workflowWidgetExpanded });
const hint = workflowWidgetExpanded ? "ctrl+shift+t collapse" : "ctrl+shift+t expand";
const dimHint = theme.fg ? theme.fg("dim", `│ ${hint}`) : `│ ${hint}`;
const rendered = [...lines.slice(0, -1), `${lines.at(-1) ?? ""} ${dimHint}`];
return rendered.map((line) => (width > 0 && line.length > width ? `${line.slice(0, Math.max(0, width - 1))}…` : line));
Expand All @@ -41,4 +41,4 @@ export async function resumeUiState(service: WorkflowService, ctx: ExtensionCont
return isTerminalStatus(resumed.status) ? service.getActiveStatus(ctx.cwd) : resumed;
}

export { existingResourcePath, extensionRootFromImportMeta, installKapiAutocomplete, loadedSkillSummary } from "./ui-resources.js";
export { existingResourcePath, extensionRootFromImportMeta, installWorkflowAutocomplete, loadedSkillSummary } from "./ui-resources.js";
6 changes: 3 additions & 3 deletions test/presentation-ui.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import os from "node:os";
import path from "node:path";
import { test } from "node:test";
import { formatStatus, statusWidgetLines } from "../src/presentation/messages.js";
import { existingResourcePath, installKapiAutocomplete, labelLatestSessionEntry, loadedSkillSummary, updateUi } from "../src/presentation/ui.js";
import { existingResourcePath, installWorkflowAutocomplete, labelLatestSessionEntry, loadedSkillSummary, updateUi } from "../src/presentation/ui.js";
import type { WorkflowState } from "../src/domain/types.js";

function activeWorkflow(): WorkflowState {
Expand Down Expand Up @@ -126,7 +126,7 @@ test("presentation UI helpers preserve Pi skill context and session labels witho
});

test("Kapi autocomplete no-ops when the Pi UI autocomplete API is unavailable", () => {
assert.doesNotThrow(() => installKapiAutocomplete({ ui: {} } as never));
assert.doesNotThrow(() => installWorkflowAutocomplete({ ui: {} } as never));
});

test("Kapi autocomplete suggests workflow references only for @kapi prefix", async () => {
Expand All @@ -150,7 +150,7 @@ test("Kapi autocomplete suggests workflow references only for @kapi prefix", asy
},
};

installKapiAutocomplete(ctx as never);
installWorkflowAutocomplete(ctx as never);

const suggestions = await provider.getSuggestions(["please use @kapi:pla"], 0, "please use @kapi:pla".length, {});
assert.equal(suggestions.prefix, "@kapi:pla");
Expand Down
Loading