Files
AgenticCode/openspec/exports/migrate-to-semantic-kernel-openspec.md
local d3300c7db9 feat: add extract-feature and export-spec portability skills
Two new OpenSpec skills for porting features to sandboxed codebases:
- /opsx:extract-feature generates minimal, printable code recipes
- /opsx:export-spec generates compact specs for AI-assisted reimplementation
Both support cumulative dependency analysis across archived changes.

Includes first export of migrate-to-semantic-kernel in all three formats:
code recipe (~120 lines), portable spec (~40 lines), OpenSpec variant (~25 lines).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 00:59:06 +01:00

3.1 KiB

OpenSpec Portable Variant

For hand-typing into target's OpenSpec on the sandbox

Type these two files into the target's openspec/changes/add-sk-chat/ directory. Then run /opsx:apply and let the AI implement from the tasks.

Lines to type: ~25 | vs code recipe: ~120 lines | Compression: 4.8x


File 1: proposal.md

# Add SK Chat Endpoint with Tool Calling

## Why
Need an AI chat endpoint that streams responses and supports
autonomous tool calling for structured data extraction/validation.

## What Changes
- Add Semantic Kernel 1.74.0 with OpenAI connector
- POST /api/chat endpoint streaming SSE via SK
- ExtractionPlugin with [KernelFunction] for field validation
- Shared models: ChatRequest, ChatMessage, ExtractedFields, ValidationResult

## Impact
- API project: new controller, plugin, DI wiring
- Shared project: new models
- Config: ResponsesApi section in appsettings.json

File 2: tasks.md

## 1. Shared Models
- [ ] 1.1 Create ChatMessage (Role string, Content string, Timestamp DateTime)
- [ ] 1.2 Create ChatRequest (Messages List<ChatMessage>)
- [ ] 1.3 Create ExtractedFields with required fields: Client, Project, Hours(decimal?), Rate(decimal?), Currency, Date; optional: Description, PoNumber
- [ ] 1.4 Create ValidationResult (IsValid bool, Errors List<string>)

## 2. Extraction Plugin
- [ ] 2.1 Create ExtractionPlugin class with [KernelFunction("validate_extracted_fields")]
- [ ] 2.2 Accepts fieldsJson string, deserializes to ExtractedFields with PropertyNameCaseInsensitive
- [ ] 2.3 Validates required fields non-null/non-empty, decimals > 0
- [ ] 2.4 Returns JSON serialized ValidationResult

## 3. Chat Controller
- [ ] 3.1 Create ChatController [ApiController] Route("api/[controller]") injecting Kernel
- [ ] 3.2 POST endpoint: set response to text/event-stream, no-cache
- [ ] 3.3 Convert request messages to SK ChatHistory (user/assistant roles)
- [ ] 3.4 Import ExtractionPlugin per-request via _kernel.ImportPluginFromObject
- [ ] 3.5 Use OpenAIPromptExecutionSettings with FunctionChoiceBehavior.Auto()
- [ ] 3.6 Stream via GetStreamingChatMessageContentsAsync, emit SSE: data: {"text":"..."}\n\n
- [ ] 3.7 Emit data: [DONE]\n\n on completion
- [ ] 3.8 Handle HttpRequestException (emit error SSE), TaskCanceledException (silent)

## 4. DI Wiring (Program.cs)
- [ ] 4.1 Add using Microsoft.SemanticKernel at top of Program.cs
- [ ] 4.2 Read BaseUrl and Model from config "ResponsesApi" section
- [ ] 4.3 AddOpenAIChatCompletion(modelId, endpoint with /v1 suffix, apiKey)
- [ ] 4.4 AddKernel()
- [ ] 4.5 AddSingleton<ExtractionPlugin>()

## 5. Configuration
- [ ] 5.1 Add ResponsesApi section to appsettings.json: BaseUrl "http://localhost:8317/v1", Model "claude-sonnet-4-6"
- [ ] 5.2 Add NuGet: Microsoft.SemanticKernel 1.74.0, Microsoft.SemanticKernel.Connectors.OpenAI 1.74.0

Usage on sandbox

  1. Create the change: openspec new change "add-sk-chat"
  2. Type proposal.md into openspec/changes/add-sk-chat/proposal.md
  3. Type tasks.md into openspec/changes/add-sk-chat/tasks.md
  4. Run /opsx:apply add-sk-chat — the AI implements all tasks