2026 03 22 Chat Plugin Core And Native Vscode Chat
Documentation for Plans
Chat Plugin Core & Native VSCode Chat — Implementation Plan
For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (
- [ ]) syntax for tracking.
Goal: Extract a framework-agnostic plugin core from vitto-chat and build a native Chat tab in the VSCode extension.
Architecture: New NX library @libs-ai/chat-plugin-core with zero Angular deps. All 17 plugin factories migrated with ReactiveValue<T> replacing Signal, ComponentRef replacing Type<unknown>. VSCode extension gets a third "Chat" tab with Lit-based agent chat consuming plugins from the core library.
Tech Stack: TypeScript, NX, Lit, esbuild, SSE streaming
Spec: docs/superpowers/specs/2026-03-22-chat-plugin-core-and-native-vscode-chat-design.md
Git note: Session S258 runs concurrently with another session — do NOT commit. Mark commit steps as skipped.
File Structure
Files to Create
libs/libs-ai/chat-plugin-core/
├── project.json
├── tsconfig.json
├── tsconfig.lib.json
├── src/
│ ├── index.ts
│ └── lib/
│ ├── types/
│ │ ├── reactive.types.ts
│ │ ├── plugin-categories.ts
│ │ ├── plugin-capabilities.ts
│ │ ├── model-constants.ts
│ │ └── chat-core.types.ts
│ ├── interfaces/
│ │ ├── chat-plugin.interface.ts
│ │ ├── plugin-providers.interface.ts
│ │ └── plugin-resolution.ts
│ ├── plugins/
│ │ ├── index.ts
│ │ ├── context/
│ │ │ ├── rich-context.plugin.ts
│ │ │ ├── capabilities.plugin.ts
│ │ │ └── suggestions.plugin.ts
│ │ ├── intelligence/
│ │ │ ├── model.plugin.ts
│ │ │ ├── agent.plugin.ts
│ │ │ ├── mastery.plugin.ts
│ │ │ └── learning.plugin.ts
│ │ ├── generation/
│ │ │ ├── generation.plugin.ts
│ │ │ ├── module-builder.plugin.ts
│ │ │ ├── teach.plugin.ts
│ │ │ └── prompt-library.plugin.ts
│ │ ├── bridge/
│ │ │ ├── computer-use-bridge.plugin.ts
│ │ │ ├── observatory.plugin.ts
│ │ │ └── awareness.plugin.ts
│ │ └── input/
│ │ ├── voice.plugin.ts
│ │ ├── action.plugin.ts
│ │ └── context-legacy.plugin.ts
│ ├── composition/
│ │ └── plugin-preset.factory.ts
│ └── utils/
│ └── plugin-guards.ts
apps/vitto-vscode-extension/src/
├── services/
│ ├── ide-tool.service.ts
│ ├── agent-session.service.ts
│ └── context-provider.service.ts
└── panels/webview/components/agent/
├── agent-chat-view.ts
└── agent-message.ts
Files to Modify
tsconfig.base.json # Add @libs-ai/chat-plugin-core path
libs/libs-foundational/core-models/src/lib/types/context.types.ts # Add IDE RouteContext values
libs/libs-ai/vitto-chat/src/lib/plugins/index.ts # Re-export shim
libs/libs-ai/vitto-chat/src/index.ts # Re-export shim
apps/vitto-vscode-extension/src/panels/main-panel.ts # Add Chat tab + agent handlers
apps/vitto-vscode-extension/src/panels/webview/types.ts # Add agent message types
apps/vitto-vscode-extension/esbuild.mjs # Add path alias plugin for webview
apps/vitto-vscode-extension/tsconfig.webview.json # Extend tsconfig.base.json
apps/vitto-vscode-extension/src/panels/webview/index.ts # Mount agent-chat-view in #pane-agent-chat
Task 1: Create NX Library Scaffold
Files:
Create:
libs/libs-ai/chat-plugin-core/project.jsonCreate:
libs/libs-ai/chat-plugin-core/tsconfig.jsonCreate:
libs/libs-ai/chat-plugin-core/tsconfig.lib.jsonCreate:
libs/libs-ai/chat-plugin-core/src/index.tsModify:
tsconfig.base.json— add path mappingStep 1: Create project.json
{
"name": "chat-plugin-core",
"$schema": "../../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "libs/libs-ai/chat-plugin-core/src",
"prefix": "lib",
"projectType": "library",
"tags": ["scope:ai", "type:core"],
"targets": {
"lint": { "executor": "@nx/eslint:lint" }
}
}
- Step 2: Create tsconfig.json (NO angularCompilerOptions)
{
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"moduleResolution": "bundler",
"strict": true,
"noImplicitOverride": true,
"noPropertyAccessFromIndexSignature": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"module": "preserve"
},
"files": [],
"include": [],
"references": [{ "path": "./tsconfig.lib.json" }]
}
- Step 3: Create tsconfig.lib.json
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../../dist/out-tsc",
"declaration": true,
"declarationMap": true,
"inlineSources": true,
"types": []
},
"exclude": ["src/**/*.spec.ts", "src/test-setup.ts", "jest.config.ts", "src/**/*.test.ts"],
"include": ["src/**/*.ts"]
}
- Step 4: Create placeholder barrel
src/index.ts
/**
* @libs-ai/chat-plugin-core
*
* Framework-agnostic plugin system for Vitto chat.
* Zero Angular dependencies. Works with Angular, Lit, React Native, Flutter.
*
* Session 258: Extracted from @libs-ai/vitto-chat
*/
// Types (populated in Task 2)
// Interfaces (populated in Task 3)
// Plugins (populated in Tasks 4-8)
// Composition (populated in Task 9)
- Step 5: Add path mapping to tsconfig.base.json
Find the @libs-ai/vitto-chat entry in tsconfig.base.json paths and add after it:
"@libs-ai/chat-plugin-core": ["libs/libs-ai/chat-plugin-core/src"],
"@libs-ai/chat-plugin-core/*": ["libs/libs-ai/chat-plugin-core/src/*"],
- Step 6: Verify NX detects the library
Run: npx nx show project chat-plugin-core
Expected: Shows project config with sourceRoot and tags.
- Step 7: Skip commit (concurrent session)
Task 2: Core Types
Files:
Create:
libs/libs-ai/chat-plugin-core/src/lib/types/reactive.types.tsCreate:
libs/libs-ai/chat-plugin-core/src/lib/types/plugin-categories.tsCreate:
libs/libs-ai/chat-plugin-core/src/lib/types/plugin-capabilities.tsCreate:
libs/libs-ai/chat-plugin-core/src/lib/types/model-constants.tsCreate:
libs/libs-ai/chat-plugin-core/src/lib/types/chat-core.types.tsModify:
libs/libs-ai/chat-plugin-core/src/index.ts— export typesStep 1: Create
reactive.types.ts
Copy the ReactiveValue<T> and ComponentRef definitions from spec Section 3.
- Step 2: Create
plugin-categories.ts
Copy from spec Section 4. Contains PluginCategory type, PluginCategoryMetadata, and PLUGIN_CATEGORIES record.
- Step 3: Create
plugin-capabilities.ts
Copy from spec Section 5. Contains PlatformCapability, PluginPlatform, and PLATFORM_CAPABILITIES record.
- Step 4: Create
model-constants.ts
/**
* LLM model identifiers for the model plugin.
* Extracted from @libs-foundational/api-config to avoid Angular barrel.
* Keep in sync with api-config/ai-models.config.ts.
*/
export const CHAT_MODEL_IDS = {
fast: 'claude-sonnet-4-6',
reasoning: 'claude-opus-4-6',
haiku: 'claude-haiku-4-5-20251001',
} as const;
- Step 5: Create
chat-core.types.ts
Migrate these types from libs/libs-ai/vitto-chat/src/lib/types/chat.types.ts:
ChatMessageRole,VittoMood,ChatMessage,ChatMessageMetadata,ToolCallInfoVittoPhase,TaskProgressState,TaskDelegation,TaskCheckpointSlashCommandDefinition,SlashCommandActionableOutput,ActionableOutputTypeChatPluginTab,QuickActionVittoRichContext,VittoAppTypeVittoCapability,CapabilityActionTypeVittoSuggestion,SuggestionTypePluginDropPayload(new — lightweight version of DragPayload)
Import PlatformRole from @libs-foundational/core-models and RouteContext as SpaceContext.
Critical: Do NOT import from @libs-ux/embeddable-bridge, @libs-foundational/api-config, or any Angular library barrel.
- Step 6: Update barrel
src/index.ts
export * from './lib/types/reactive.types';
export * from './lib/types/plugin-categories';
export * from './lib/types/plugin-capabilities';
export * from './lib/types/model-constants';
export * from './lib/types/chat-core.types';
- Step 7: Verify compilation
Run: npx tsc -p libs/libs-ai/chat-plugin-core/tsconfig.lib.json --noEmit
Expected: 0 errors
- Step 8: Skip commit (concurrent session)
Task 3: Core Interfaces
Files:
Create:
libs/libs-ai/chat-plugin-core/src/lib/interfaces/chat-plugin.interface.tsCreate:
libs/libs-ai/chat-plugin-core/src/lib/interfaces/plugin-providers.interface.tsCreate:
libs/libs-ai/chat-plugin-core/src/lib/interfaces/plugin-resolution.tsCreate:
libs/libs-ai/chat-plugin-core/src/lib/utils/plugin-guards.tsModify:
libs/libs-ai/chat-plugin-core/src/index.ts— export interfacesStep 1: Create
chat-plugin.interface.ts
Copy from spec Section 3 — the full ChatPlugin interface with category, requires, platforms, all UI composition fields, message processing, and lifecycle hooks.
Import from local types only (../types/). Never from Angular.
- Step 2: Create
plugin-providers.interface.ts
Copy from spec Section 3 — AwarenessStateProvider, CUBridgeState, RoutineSuggestion, ContextSuggestionProvider, CapabilityEntry.
- Step 3: Create
plugin-resolution.ts
Copy from spec Section 6 — isPluginCompatible() and resolvePluginsForPlatform().
Note: This is the ONLY location for resolution logic. Do NOT create a separate composition/plugin-resolver.ts — the preset factory imports from here.
- Step 4: Create
plugin-guards.ts
import { ChatPlugin } from '../interfaces/chat-plugin.interface';
/**
* category and requires are optional in the interface (defaults applied
* by the resolver) to avoid breaking existing code that creates
* ChatPlugin objects directly without these fields.
* All NEW plugins should always set them explicitly.
*/
export function isChatPlugin(obj: unknown): obj is ChatPlugin {
return typeof obj === 'object' && obj !== null && 'id' in obj;
}
export function getPluginCategory(plugin: ChatPlugin): PluginCategory {
return plugin.category ?? 'context';
}
export function getPluginRequires(plugin: ChatPlugin): PlatformCapability[] {
return plugin.requires ?? [];
}
export function hasCapability(plugin: ChatPlugin, cap: PlatformCapability): boolean {
return getPluginRequires(plugin).includes(cap);
}
- Step 5: Update barrel
Add to src/index.ts:
export * from './lib/interfaces/chat-plugin.interface';
export * from './lib/interfaces/plugin-providers.interface';
export * from './lib/interfaces/plugin-resolution';
export * from './lib/utils/plugin-guards';
- Step 6: Verify compilation
Run: npx tsc -p libs/libs-ai/chat-plugin-core/tsconfig.lib.json --noEmit
Expected: 0 errors
- Step 7: Skip commit (concurrent session)
Task 4: Migrate Context Plugins
Files:
Create:
libs/libs-ai/chat-plugin-core/src/lib/plugins/context/rich-context.plugin.tsCreate:
libs/libs-ai/chat-plugin-core/src/lib/plugins/context/capabilities.plugin.tsCreate:
libs/libs-ai/chat-plugin-core/src/lib/plugins/context/suggestions.plugin.tsSource:
libs/libs-ai/vitto-chat/src/lib/plugins/rich-context.plugin.tsSource:
libs/libs-ai/vitto-chat/src/lib/plugins/capabilities.plugin.tsSource:
libs/libs-ai/vitto-chat/src/lib/plugins/suggestions.plugin.tsStep 1: Migrate rich-context.plugin.ts
Copy from source. Changes:
Replace
import { Signal } from '@angular/core'→import { ReactiveValue } from '../../types/reactive.types'Replace
Signal<VittoRichContext | null>→ReactiveValue<VittoRichContext | null>Replace
import { SpaceContext } from '../services/vitto-chat-context.service'→import { RouteContext } from '@libs-foundational/core-models'and add local aliastype SpaceContext = RouteContext(or replace all usages withRouteContextdirectly). Same pattern for capabilities.plugin.ts and suggestions.plugin.ts.Add
category: 'context'andrequires: []to return objectStep 2: Migrate capabilities.plugin.ts
Copy from source. Changes:
Replace
import { Signal } from '@angular/core'→import { ReactiveValue } from '../../types/reactive.types'Replace
VittoChatContextServiceimport →import { ContextSuggestionProvider } from '../../interfaces/plugin-providers.interface'Config type:
contextService?: VittoChatContextService→contextProvider?: ContextSuggestionProviderAdd
category: 'context',requires: []Step 3: Migrate suggestions.plugin.ts
Copy from source. Changes:
Replace
import { Signal, inject } from '@angular/core'→import { ReactiveValue } from '../../types/reactive.types'Remove
import { VittoPageContextRegistry } from '@libs-ai/vitto-core'Replace
pageRegistry?: VittoPageContextRegistry→activeSuggestions?: ReactiveValue<string[]>Replace
config.pageRegistry.activeSuggestions()→config.activeSuggestions?.()Replace
VittoChatContextService→ContextSuggestionProviderAdd
category: 'context',requires: []Step 4: Verify compilation
Run: npx tsc -p libs/libs-ai/chat-plugin-core/tsconfig.lib.json --noEmit
- Step 5: Skip commit (concurrent session)
Task 5: Migrate Intelligence Plugins
Files:
Create:
libs/libs-ai/chat-plugin-core/src/lib/plugins/intelligence/model.plugin.tsCreate:
libs/libs-ai/chat-plugin-core/src/lib/plugins/intelligence/agent.plugin.tsCreate:
libs/libs-ai/chat-plugin-core/src/lib/plugins/intelligence/mastery.plugin.tsCreate:
libs/libs-ai/chat-plugin-core/src/lib/plugins/intelligence/learning.plugin.tsStep 1: Migrate model.plugin.ts
Copy from source. Changes:
Replace
import { Type } from '@angular/core'→import { ComponentRef } from '../../types/reactive.types'Replace
import { AI_MODELS_CONFIG } from '@libs-foundational/api-config'→import { CHAT_MODEL_IDS } from '../../types/model-constants'Replace
Type<unknown>→ComponentRefReplace
AI_MODELS_CONFIG.anthropic.fast→CHAT_MODEL_IDS.fastReplace
AI_MODELS_CONFIG.anthropic.reasoning→CHAT_MODEL_IDS.reasoningAdd
category: 'intelligence',requires: []Step 2: Migrate agent.plugin.ts (already pure TS)
Copy from source. Only changes:
Import types from local
../../types/chat-core.typesAdd
category: 'intelligence',requires: []Step 3: Migrate mastery.plugin.ts (already pure TS)
Copy from source. Only changes:
Import types from local
../../types/chat-core.typesAdd
category: 'intelligence',requires: []Step 4: Migrate learning.plugin.ts (already pure TS)
Copy from source. Only changes:
Import types from local
../../types/chat-core.typesAdd
category: 'intelligence',requires: []Step 5: Verify compilation
Step 6: Skip commit (concurrent session)
Task 6: Migrate Generation Plugins
Files:
Create:
libs/libs-ai/chat-plugin-core/src/lib/plugins/generation/generation.plugin.tsCreate:
libs/libs-ai/chat-plugin-core/src/lib/plugins/generation/module-builder.plugin.tsCreate:
libs/libs-ai/chat-plugin-core/src/lib/plugins/generation/teach.plugin.tsCreate:
libs/libs-ai/chat-plugin-core/src/lib/plugins/generation/prompt-library.plugin.tsStep 1: Migrate generation.plugin.ts (already nearly pure)
Copy from source. Changes:
Import
ChatPluginTab,QuickActionfrom local typesAdd
category: 'generation',requires: ['component-rendering']Step 2: Migrate module-builder.plugin.ts
Copy from source. Changes:
Replace
import { Signal } from '@angular/core'→import { ReactiveValue } from '../../types/reactive.types'Replace
import { DragPayload } from '@libs-ux/embeddable-bridge'→import { PluginDropPayload } from '../../types/chat-core.types'Replace all
Signal<...>→ReactiveValue<...>Replace
DragPayload→PluginDropPayloadin onDropAdd
category: 'generation',requires: []Step 3: Migrate teach.plugin.ts (already pure)
Copy from source. Add category: 'generation', requires: ['component-rendering']
- Step 4: Migrate prompt-library.plugin.ts
Read source, copy, add category: 'generation', requires: ['component-rendering']
Step 5: Verify compilation
Step 6: Skip commit (concurrent session)
Task 7: Migrate Bridge & Input Plugins
Files:
Create:
libs/libs-ai/chat-plugin-core/src/lib/plugins/bridge/computer-use-bridge.plugin.tsCreate:
libs/libs-ai/chat-plugin-core/src/lib/plugins/bridge/observatory.plugin.tsCreate:
libs/libs-ai/chat-plugin-core/src/lib/plugins/bridge/awareness.plugin.tsCreate:
libs/libs-ai/chat-plugin-core/src/lib/plugins/input/voice.plugin.tsCreate:
libs/libs-ai/chat-plugin-core/src/lib/plugins/input/action.plugin.tsCreate:
libs/libs-ai/chat-plugin-core/src/lib/plugins/input/context-legacy.plugin.tsStep 1: Migrate computer-use-bridge.plugin.ts
Changes:
Replace
import { Type } from '@angular/core'→import { ComponentRef } from '../../types/reactive.types'Replace
AwarenessDataService→AwarenessStateProviderfrom interfacesReplace
Type<unknown>→ComponentRefAdd
category: 'bridge',requires: []Step 2: Migrate observatory.plugin.ts
Changes:
Replace
import { Type } from '@angular/core'→import { ComponentRef } from '../../types/reactive.types'Replace
Type<unknown>→ComponentRefAdd
category: 'bridge',requires: ['component-rendering']Step 3: Migrate awareness.plugin.ts
Changes:
Replace
import { Type } from '@angular/core'→import { ComponentRef } from '../../types/reactive.types'Replace
AwarenessDataService→AwarenessStateProviderAdd
category: 'bridge',requires: []Step 4: Migrate voice.plugin.ts (already pure)
Copy, add category: 'input', requires: ['speech-api']
- Step 5: Migrate action.plugin.ts
Read source, copy, replace DragPayload → PluginDropPayload, add category: 'input', requires: ['drag-drop']
- Step 6: Migrate context.plugin.ts → context-legacy.plugin.ts
Read source, copy, add category: 'input', requires: ['route-context']
Step 7: Verify compilation
Step 8: Skip commit (concurrent session)
Task 8: Plugin Index & Composition Layer
Files:
Create:
libs/libs-ai/chat-plugin-core/src/lib/plugins/index.tsCreate:
libs/libs-ai/chat-plugin-core/src/lib/composition/plugin-resolver.tsCreate:
libs/libs-ai/chat-plugin-core/src/lib/composition/plugin-preset.factory.tsModify:
libs/libs-ai/chat-plugin-core/src/index.ts— final barrelStep 1: Create
plugins/index.ts
Export all 17 plugin factories and their config types from category subdirectories.
- Step 2: Create
plugin-preset.factory.ts
Implement createStandardPluginSet(config: StandardPluginSetConfig) from spec Section 7. This is the platform-aware canonical composition.
Key: import all plugin factories, build in category order, filter via resolvePluginsForPlatform().
- Step 4: Finalize barrel
src/index.ts
/**
* @libs-ai/chat-plugin-core
*
* Framework-agnostic plugin system for Vitto chat.
* Zero Angular dependencies. Works with Angular, Lit, React Native, Flutter.
*
* Session 258: Extracted from @libs-ai/vitto-chat
*/
// Types
export * from './lib/types/reactive.types';
export * from './lib/types/plugin-categories';
export * from './lib/types/plugin-capabilities';
export * from './lib/types/model-constants';
export * from './lib/types/chat-core.types';
// Interfaces
export * from './lib/interfaces/chat-plugin.interface';
export * from './lib/interfaces/plugin-providers.interface';
export * from './lib/interfaces/plugin-resolution';
// Plugins
export * from './lib/plugins';
// Composition
export * from './lib/composition/plugin-preset.factory';
// Utils
export * from './lib/utils/plugin-guards';
- Step 5: Full compilation check
Run: npx tsc -p libs/libs-ai/chat-plugin-core/tsconfig.lib.json --noEmit
Expected: 0 errors
- Step 6: Skip commit (concurrent session)
Task 9: Re-export Shim in vitto-chat
Files:
Modify:
libs/libs-ai/vitto-chat/src/lib/plugins/index.tsModify:
libs/libs-ai/vitto-chat/src/lib/plugins/chat-plugin.interface.tsModify:
libs/libs-ai/vitto-chat/src/lib/types/chat.types.tsModify:
libs/libs-ai/vitto-chat/src/index.tsStep 1: Update
plugins/chat-plugin.interface.ts
Replace the interface definition with a re-export:
/**
* Chat Plugin Interface — Re-export from @libs-ai/chat-plugin-core
* Original: Session 133. Migrated to chat-plugin-core: Session 258.
*/
export type { ChatPlugin } from '@libs-ai/chat-plugin-core';
export { isChatPlugin } from '@libs-ai/chat-plugin-core';
- Step 2: Update
plugins/index.ts
Replace all local exports with re-exports from @libs-ai/chat-plugin-core:
// Session 258: All plugins migrated to @libs-ai/chat-plugin-core.
// These re-exports maintain backward compatibility.
export {
type ChatPlugin,
isChatPlugin,
createGenerationPlugin,
createContextPlugin,
createAgentPlugin,
createModelPlugin,
createActionPlugin,
createRichContextPlugin,
createCapabilitiesPlugin,
createSuggestionsPlugin,
createObservatoryPlugin,
createLearningPlugin,
createVoicePlugin,
createTeachPlugin,
createPromptLibraryPlugin,
createComputerUseBridgePlugin,
createMasteryPlugin,
createModuleBuilderPlugin,
createAwarenessPlugin, // NOTE: This is a NEW export — not previously in vitto-chat barrel
createStandardPluginSet,
// Re-export types
type StandardPluginSetConfig,
type PluginCategory,
type PlatformCapability,
type PluginPlatform,
} from '@libs-ai/chat-plugin-core';
// Keep PluginPresetConfig as backward-compat alias
export type { StandardPluginSetConfig as PluginPresetConfig } from '@libs-ai/chat-plugin-core';
- Step 3: Update
types/chat.types.ts
Add re-exports for migrated types at the top, keep Angular-specific types local:
// Session 258: Core types migrated to @libs-ai/chat-plugin-core
export type {
ChatMessage, ChatMessageRole, ChatMessageMetadata, ToolCallInfo, VittoMood,
TaskProgressState, TaskDelegation, TaskCheckpoint, VittoPhase,
SlashCommandDefinition, SlashCommand,
ActionableOutput, ActionableOutputType,
ChatPluginTab, QuickAction,
VittoRichContext, VittoAppType,
VittoCapability, CapabilityActionType,
VittoSuggestion, SuggestionType,
PluginDropPayload,
} from '@libs-ai/chat-plugin-core';
Remove the local definitions of these types (they now come from core).
- Step 4: Update
plugin-presets.tsas Angular adapter
The existing plugin-presets.ts imports Signal and Type from @angular/core — it CANNOT be replaced by a re-export. Instead, convert it to an Angular adapter that maps PluginPresetConfig → StandardPluginSetConfig and delegates to createStandardPluginSet from core:
// plugin-presets.ts — Angular adapter (Session 258)
import { Signal, Type } from '@angular/core';
import { createStandardPluginSet, type StandardPluginSetConfig, type ChatPlugin } from '@libs-ai/chat-plugin-core';
import type { PlatformRole } from '@libs-foundational/core-models';
import type { VittoRichContext } from '@libs-ai/chat-plugin-core';
import type { ModuleContextState } from '@libs-ai/chat-plugin-core';
import type { AwarenessDataService } from '../services/awareness-data.service';
export interface PluginPresetConfig {
// ... keep existing interface exactly as-is (with Signal, Type, service refs)
}
export function createStandardPluginSet(config: PluginPresetConfig): ChatPlugin[] {
// Angular Signals ARE ReactiveValues — pass through directly
// Angular Type<T> IS ComponentRef — pass through directly
// Angular services implement provider interfaces — pass through
const coreConfig: StandardPluginSetConfig = {
platform: 'web',
platformRole: config.platformRole,
contextSignal: config.contextSignal,
onModelChange: config.onModelChange,
onAgentStatusRequested: config.onAgentStatusRequested,
generationComponents: config.generationComponents,
teachComponent: config.teachComponent,
promptComponent: config.promptComponent,
observatoryComponent: config.observatoryComponent,
userId: config.userId,
spaceId: config.spaceId,
roleLevel: config.roleLevel,
includeVoice: config.includeVoice,
moduleContextSignal: config.moduleContextSignal,
onEntityExtract: config.onEntityExtract,
onModuleGenerate: config.onModuleGenerate,
onModuleValidate: config.onModuleValidate,
onModuleExport: config.onModuleExport,
contextProvider: config.contextService,
awarenessProvider: config.awarenessService,
awarenessComponents: config.awarenessComponents,
};
return createStandardPluginSet(coreConfig);
}
Note: The re-exported createStandardPluginSet in plugins/index.ts should export the Angular adapter version (from plugin-presets.ts), NOT the core version. This preserves backward compatibility for Angular consumers.
- Step 5: Update
plugins/index.tsre-export to use adapter
Ensure the re-export for createStandardPluginSet comes from ./plugin-presets (the Angular adapter), not from @libs-ai/chat-plugin-core. All other plugin factories come from core.
- Step 6: Verify Angular apps build
Run: npx nx lint vitto-chat
Run: npx tsc -p libs/libs-ai/vitto-chat/tsconfig.lib.json --noEmit
Expected: 0 errors (all consumers still import from @libs-ai/vitto-chat — same paths)
- Step 7: Skip commit (concurrent session)
Task 10: VSCode Extension — esbuild Path Resolution
Files:
- Modify:
apps/vitto-vscode-extension/esbuild.mjs(line ~63) - Modify:
apps/vitto-vscode-extension/tsconfig.webview.json
CRITICAL: The webview build runs tsc THEN esbuild. BOTH steps must resolve @libs-* paths:
tscneeds path aliases → tsconfig extension (Step 1)esbuildneeds path aliases → alias plugin (Step 2) If either is missing, the build fails. Step 1 is prerequisite for Step 2.Step 1: Update
tsconfig.webview.jsonto extend base (MANDATORY — tsc fails without it)
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"module": "ESNext",
"target": "ES2022",
"moduleResolution": "bundler",
"lib": ["ES2022", "DOM", "DOM.Iterable"],
"sourceMap": true,
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"experimentalDecorators": true,
"useDefineForClassFields": false
},
"include": ["src/panels/webview/**/*"]
}
Key change: Added "extends": "../../tsconfig.base.json" — gives webview access to @libs-* path mappings. The child compilerOptions override the parent for module, target, moduleResolution.
After extending, verify that module: ESNext, target: ES2022, and moduleResolution: bundler are correctly applied (child overrides parent).
- Step 2: Add esbuild alias plugin for webview build (MANDATORY — esbuild fails without it)
In esbuild.mjs, add a path alias plugin for the webview build context (around line 63). The plugin reads tsconfig paths and maps them for esbuild:
import { readFileSync } from 'fs';
function createPathAliasPlugin() {
const tsconfig = JSON.parse(readFileSync(join(__dirname, '../../tsconfig.base.json'), 'utf8'));
const paths = tsconfig.compilerOptions?.paths || {};
const rootDir = join(__dirname, '../..');
return {
name: 'path-alias',
setup(build) {
for (const [alias, targets] of Object.entries(paths)) {
if (alias.endsWith('/*')) continue; // Skip wildcard variants
const target = targets[0]; // e.g. "libs/libs-ai/chat-plugin-core/src"
const resolved = join(rootDir, target, 'index.ts');
const filter = new RegExp(`^${alias.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}$`);
build.onResolve({ filter }, () => ({ path: resolved }));
}
},
};
}
Then add plugins: [createPathAliasPlugin()] to the webview esbuild context options.
- Step 3: Test webview build
Run: cd apps/vitto-vscode-extension && node esbuild.mjs
Expected: Build succeeds for both extension and webview.
- Step 4: Skip commit (concurrent session)
Task 11: VSCode Extension — Chat Tab Shell
Files:
Modify:
apps/vitto-vscode-extension/src/panels/main-panel.ts:1753-1787Step 1: Add Chat tab button to shell nav
In getHtmlContent(), add a third tab button after the Vitto button (around line 1761):
<button class="shell-tab" data-pane="agent-chat">
<span class="tab-icon">⚡</span>
<span>Chat</span>
</button>
- Step 2: Add Chat pane to shell content
After #pane-chat div (around line 1774), add:
<!-- Native Agent Chat (Lit component) -->
<div id="pane-agent-chat" class="shell-pane lit-pane">
<!-- agent-chat-view mounts here via webview index.ts -->
</div>
- Step 3: Verify tab switching works
The existing switchPane() JS function (line 1780) uses data-pane → pane-{id} mapping. Adding data-pane="agent-chat" automatically matches #pane-agent-chat. No JS changes needed.
- Step 4: Build and test extension
Run: cd apps/vitto-vscode-extension && node esbuild.mjs
Expected: Build succeeds. Chat tab visible but empty.
- Step 5: Skip commit (concurrent session)
Task 12: VSCode Extension — Message Protocol Extensions
Files:
Modify:
apps/vitto-vscode-extension/src/panels/webview/types.ts:59,239-278,280-304Step 1: Extend TabId (if needed for internal state)
This is optional — the Chat tab is at the shell level (not inside the Lit app). Skip unless internal state tracking is needed.
- Step 2: Add agent message types to MessageToExtension
Add to the union (around line 278):
| { type: 'agentMessage'; text: string; sessionId?: string }
| { type: 'agentCancel' }
| { type: 'agentApproveEdit'; path: string }
| { type: 'agentRejectEdit'; path: string }
| { type: 'getIdeContext' }
- Step 3: Add agent message types to MessageFromExtension
Add to the union (around line 304):
| { type: 'agentText'; content: string }
| { type: 'agentThinking'; content: string }
| { type: 'agentToolStart'; tool: string; input: Record<string, unknown> }
| { type: 'agentToolResult'; tool: string; result: { success: boolean; output: string; error?: string } }
| { type: 'agentDone'; summary: string }
| { type: 'agentError'; message: string }
| { type: 'agentCancelled' }
| { type: 'ideContext'; context: IdeContext }
- Step 4: Add IdeContext type
export interface IdeContext {
activeFile?: { path: string; language: string; content: string };
selection?: { text: string; startLine: number; endLine: number };
openFiles: string[];
diagnostics: Array<{ file: string; errors: number; warnings: number }>;
gitStatus?: { branch: string; modified: string[]; staged: string[] };
workspaceRoot: string;
projectType: string;
}
- Step 5: Verify compilation
Run: cd apps/vitto-vscode-extension && node esbuild.mjs
- Step 6: Skip commit (concurrent session)
Task 13: VSCode Extension — Context Provider Service
Files:
Create:
apps/vitto-vscode-extension/src/services/context-provider.service.tsStep 1: Implement ContextProviderService
Follow spec Section 6 (Context Providers). The service gathers IDE context using VSCode API:
gatherContext()→ returnsIdeContextgetGitStatus()→ reads from VSCode Git extension APIdetectProjectType()→ checks for nx.json, angular.json, etc.getSummaryDiagnostics()→ readsvscode.languages.getDiagnostics()Step 2: Add to extension.ts service registration
Register the service in activate() so it's available for the agent session service.
- Step 3: Verify extension build
Run: cd apps/vitto-vscode-extension && node esbuild.mjs
- Step 4: Skip commit (concurrent session)
Task 14: VSCode Extension — IDE Tool Service
Files:
Create:
apps/vitto-vscode-extension/src/services/ide-tool.service.tsStep 1: Implement IdeToolService
Follow spec S240 Section 2. Implement 7 tools:
readFile(path)→workspace.fs.readFile()writeFile(path, content, options)→ diff preview or auto-writerunCommand(command, options)→ terminal with shell integrationsearchCode(pattern, options)→workspace.findFiles()+ text searchlistFiles(pattern)→workspace.findFiles()getDiagnostics(path?)→languages.getDiagnostics()showDiff(path, content)→commands.executeCommand('vscode.diff', ...)
All methods return Promise<IdeToolResult> where:
interface IdeToolResult {
success: boolean;
output: string;
error?: string;
metadata?: Record<string, unknown>;
}
Step 2: Verify extension build
Step 3: Skip commit (concurrent session)
Task 15: VSCode Extension — Agent Session Service
Files:
Create:
apps/vitto-vscode-extension/src/services/agent-session.service.tsStep 1: Implement AgentSessionService
Follow spec S240 Section 3. Core methods:
chat(options)→ SSE stream to vitto-api/engine/agent-sessionhandleStreamEvent()→ routes text/thinking/tool_use/done/error eventsexecuteTool()→ dispatches to IdeToolService methodscancel()→ aborts SSE stream
The service:
- Opens SSE to
http://localhost:3003/engine/agent-session - On
tool_useevent: executes tool locally via IdeToolService - POSTs tool result back to
/engine/agent-session/:id/tool-result - On
textevent: forwards to webview viapostMessage
- Step 2: Add message handlers in main-panel.ts
Add cases to handleMessage() switch for agentMessage, agentCancel, agentApproveEdit, agentRejectEdit, getIdeContext.
Each handler delegates to AgentSessionService and forwards events to webview.
Step 3: Verify extension build
Step 4: Skip commit (concurrent session)
Task 16: VSCode Extension — Agent Chat View (Lit Component)
Files:
Create:
apps/vitto-vscode-extension/src/panels/webview/components/agent/agent-chat-view.tsCreate:
apps/vitto-vscode-extension/src/panels/webview/components/agent/agent-message.tsModify:
apps/vitto-vscode-extension/src/panels/webview/index.ts:318-320— mount in #pane-agent-chatStep 1: Create
agent-message.ts
Simple Lit component for rendering a single chat message:
User messages: plain text
AI text: markdown rendering (reuse existing
markdown-viewcomponent)Thinking: collapsible
<details>blockTool start: tool name + spinner
Tool result: collapsible code block with success/error indicator
Error: styled error message
Step 2: Create
agent-chat-view.ts
Main chat container. Follow spec S240 Section 5:
@state() messages: AgentMessage[]@state() isStreaming: boolean@state() inputText: string- Message list with auto-scroll
- Input bar: textarea + send/cancel button
- Quick action chips (from plugins via
createStandardPluginSet) - Context bar: active file, branch, diagnostic count
- Slash command palette (from plugins)
Consume plugins:
import { createStandardPluginSet } from '@libs-ai/chat-plugin-core';
const plugins = createStandardPluginSet({
platform: 'vscode',
platformRole: 'developer',
contextSignal: () => this.ideContext,
onModelChange: (id) => send({ type: 'setModel', modelId: id }),
});
Listen for extension messages:
window.addEventListener('message', (e) => {
const msg = e.data;
switch (msg.type) {
case 'agentText': // append to streaming message
case 'agentThinking': // add thinking block
case 'agentToolStart': // add tool-start message
case 'agentToolResult': // update tool result
case 'agentDone': // finalize
case 'agentError': // show error
case 'agentCancelled': // show cancelled
case 'ideContext': // update context bar
}
});
- Step 3: Mount in webview index.ts
After the gograb-app mount (around line 320 of index.ts), add:
import './components/agent/agent-chat-view';
import './components/agent/agent-message';
// Mount agent chat into #pane-agent-chat (if shell has it)
const agentChatTarget = document.getElementById('pane-agent-chat');
if (agentChatTarget) {
const agentChat = document.createElement('agent-chat-view');
agentChatTarget.appendChild(agentChat);
}
- Step 4: Add scoped CSS
Scope agent chat styles to #pane-agent-chat in the webview index.ts theme styles, following the convention for #pane-mcp.
- Step 5: Build and test
Run: cd apps/vitto-vscode-extension && node esbuild.mjs
Expected: Build succeeds. Chat tab shows the agent chat UI.
- Step 6: Skip commit (concurrent session)
Task 17: RouteContext IDE Extensions
Files:
Modify:
libs/libs-foundational/core-models/src/lib/types/context.types.ts:15-29,31-45,48-63Step 1: Add IDE RouteContext values
Add to RouteContext type (after 'computer-use', before 'unknown'):
// IDE contexts (S258)
| 'ide-editor'
| 'ide-terminal'
| 'ide-debug'
| 'ide-diff'
- Step 2: Add IDE CapabilityContext value
Add to CapabilityContext type:
| 'ide-assistant'
- Step 3: Add ROUTE_TO_CAPABILITY mappings
Add to the record:
'ide-editor': 'ide-assistant',
'ide-terminal': 'ide-assistant',
'ide-debug': 'ide-assistant',
'ide-diff': 'ide-assistant',
- Step 4: Verify core-models builds
Run: npx tsc -p libs/libs-foundational/core-models/tsconfig.lib.json --noEmit
- Step 5: Add IDE capabilities to capabilities.plugin.ts
In chat-plugin-core/src/lib/plugins/context/capabilities.plugin.ts, add IDE capabilities to CAPABILITIES_BY_CONTEXT:
'ide-editor': [
{ id: 'cap-explain-code', label: 'Explain Code', description: 'Explain the active file', icon: '💬', actionType: 'analyze', prompt: 'Explain this code', priority: 10, contexts: ['ide-editor'] },
{ id: 'cap-fix-errors', label: 'Fix Errors', description: 'Fix diagnostics errors', icon: '🔧', actionType: 'analyze', prompt: 'Fix the errors in this file', priority: 8, contexts: ['ide-editor'] },
{ id: 'cap-refactor', label: 'Refactor', description: 'Refactor selected code', icon: '🔄', actionType: 'optimize', prompt: 'Refactor this code for clarity', priority: 6, contexts: ['ide-editor'] },
{ id: 'cap-gen-tests', label: 'Generate Tests', description: 'Generate tests for this file', icon: '🧪', actionType: 'generate', prompt: 'Generate tests for this file', priority: 4, contexts: ['ide-editor'] },
],
- Step 6: Skip commit (concurrent session)
Verification Checklist
After all tasks complete:
-
npx tsc -p libs/libs-ai/chat-plugin-core/tsconfig.lib.json --noEmit→ 0 errors -
npx tsc -p libs/libs-ai/vitto-chat/tsconfig.lib.json --noEmit→ 0 errors -
npx tsc -p libs/libs-foundational/core-models/tsconfig.lib.json --noEmit→ 0 errors -
cd apps/vitto-vscode-extension && node esbuild.mjs→ Build succeeds - Extension Chat tab is visible and renders agent-chat-view
- Plugin quick actions appear in the Chat tab input bar
- Slash commands from plugins are accessible
- No
@angular/coreimports anywhere inlibs/libs-ai/chat-plugin-core/
Out of Scope (Future Sessions)
- Backend
/engine/agent-sessionSSE endpoint on vitto-api (Phase 6 in spec) - DiffContentProvider for write previews
- Keybindings and commands (Cmd+Shift+V, context menu)
- Terminal output capture via shell integration
- Rate limiting enforcement
- Agent session history persistence