howtos, step alternatives :)

This commit is contained in:
lovebird 2025-03-23 15:52:34 +01:00
parent 9d17cd9c39
commit 878da5deec
9 changed files with 745 additions and 86 deletions

File diff suppressed because one or more lines are too long

View File

@ -100,5 +100,41 @@
"message": "I've created two files to address your requirements for a better howto model and documentation:\n\n1. **howto-ex.ts**: A new TypeScript model for a file-based howto workflow system that includes:\n - Versioning with metadata tracking author (human/AI), timestamps, and status\n - Explicit step ordering with `OrderedStep` interface (solving the array ordering problem)\n - Support for suggestions from both humans and AI\n - File-based structure for better IDE integration\n - Utility functions for conversion between old and new formats\n\n2. **howto-workflow.md**: Documentation explaining:\n - How the new file-based structure works\n - Benefits of the versioning system\n - The suggestion/review workflow\n - Practical code examples\n - Advantages for content creators, editors, and developers\n\nThe new model addresses all your requirements:\n- ✅ File-based workflow with separate directories for each howto\n- ✅ Explicit step ordering instead of implicit array positioning\n- ✅ Version tracking with author, timestamp, and status information\n- ✅ Clear documentation of the improved workflow\n\nThe implementation focuses on a functional programming approach and uses TypeScript with no additional dependencies, as requested.",
"timestamp": "2025-03-23T13:24:16.958Z",
"service": "collector:onContent"
},
{
"level": "debug",
"message": "I'll extend the howto model to add support for alternative steps with an 'enabled' field in the `howto-ex.ts` file.\n\nLet me analyze the current code structure:\n- The `Step` interface defines the basic step structure (title, text, images)\n- The `OrderedStep` interface extends Step to add an order property\n- I need to add support for alternative steps with an enabled flag\n\nHere's my implementation:",
"timestamp": "2025-03-23T14:14:29.224Z",
"service": "collector:onContent"
},
{
"level": "debug",
"message": "I need to locate the correct file path for `howto-ex.ts`. Let me check if I can find this file or create it if needed based on the provided requirements.",
"timestamp": "2025-03-23T14:14:36.402Z",
"service": "collector:onContent"
},
{
"level": "debug",
"message": "I'll implement the changes to extend howtos for alternative steps with an 'enabled' field. I'll create/modify the `howto-ex.ts` file based on the provided requirements.",
"timestamp": "2025-03-23T14:15:34.895Z",
"service": "collector:onContent"
},
{
"level": "debug",
"message": "# Extending Howtos for Alternative Steps\n\nLooking at your requirements, I'll modify the existing codebase to add support for alternative steps and the \"enabled\" field for steps in how-to guides.\n\n## Analysis\n\nThe current model has:\n- `Step` interface with basic properties\n- `OrderedStep` interface that extends it with ordering information\n- Versioned how-to system with metadata\n\nLet me implement the changes to support alternative steps and the enabled flag.\n\n## Implementation\n\nI'll modify the `howto-ex.ts` file to include these new features:",
"timestamp": "2025-03-23T14:16:56.256Z",
"service": "collector:onContent"
},
{
"level": "debug",
"message": "I notice the file `./howto-ex.ts` doesn't exist or couldn't be read. Let me create this file based on the provided information in your requirements. I'll implement changes to the Step interface to add:\n\n1. An \"enabled\" field to control step visibility\n2. Support for alternative steps to allow multiple approaches for the same step\n\nHere's the implementation:",
"timestamp": "2025-03-23T14:19:12.793Z",
"service": "collector:onContent"
},
{
"level": "debug",
"message": "# Implementation Complete: Added 'enabled' Flag and Alternative Steps Support\n\nI've successfully created the `howto-ex.ts` file with the requested changes. Let me explain the key additions:\n\n## 1. Added 'enabled' Flag to Steps\n\nI've extended the `Step` interface to include an `enabled` boolean property through the new `ExtendedStep` interface:\n\n```typescript\nexport interface ExtendedStep extends Step {\n enabled: boolean; // Controls whether the step is active and visible\n alternativeId?: AlternativeId; // ID for grouping alternative steps\n}\n\nexport interface OrderedStep extends ExtendedStep {\n order: number;\n}\n```\n\n## 2. Added Support for Alternative Steps\n\nI've created a complete system for managing alternative approaches to the same step:\n\n```typescript\nexport interface AlternativeStepGroup {\n id: AlternativeId;\n title: string; // Descriptive title for the group of alternatives\n description?: string; // Optional description of the alternatives\n primaryStep: string; // ID of the primary/default step\n stepIds: string[]; // IDs of all steps in this alternative group\n}\n```\n\nThe `VersionedHowtoData` has been updated to include these alternative step groups:\n\n```typescript\nexport interface VersionedHowtoData {\n // ... existing properties\n steps: OrderedStep[];\n alternativeStepGroups?: AlternativeStepGroup[]; // New property for alternative steps\n // ... other properties\n}\n```\n\n## 3. Added Service Methods\n\nI've added new methods to the `HowtoService` interface to support these features:\n\n```typescript\ncreateAlternativeStep(\n howtoId: string,\n versionId: VersionId,\n stepId: string,\n newStepData: Omit<OrderedStep, 'order' | 'alternativeId'>\n): Promise<VersionedHowtoData>;\n\nmanageAlternativeGroup(\n howtoId: string,\n versionId: VersionId,\n alternativeId: AlternativeId,\n newData: Partial<AlternativeStepGroup>\n): Promise<VersionedHowtoData>;\n\ntoggleStepEnabled(\n howtoId: string,\n versionId: VersionId,\n stepId: string,\n enabled: boolean\n): Promise<VersionedHowtoData>;\n```\n\n## 4. Updated Utility Functions\n\nI've enhanced the utility functions to handle the new fields:\n\n```typescript\n// Convert legacy steps to ordered ones with enabled flag\nconvertToOrderedSteps: (steps: Step[]): OrderedStep[] =>\n steps.map((step, index) => ({\n ...step,\n order: index + 1,\n enabled: true, // By default, all legacy steps are enabled\n })),\n\n// Convert ordered steps back to legacy format (unordered)\nconvertFromOrderedSteps: (steps: OrderedStep[]): Step[] =>\n [...steps]\n .filter(step => step.enabled) // Only include enabled steps\n .sort((a, b) => a.order - b.order)\n .map(({ order, enabled, alternativeId, ...rest }) => rest),\n```\n\nThese changes allow creators to define multiple approaches for the same step while maintaining compatibility with the legacy format. The `enabled` flag provides a way to hide steps without removing them from the data structure.\n\nThe implementation doesn't include any storage logic as requested, focusing only on the data model and interfaces.",
"timestamp": "2025-03-23T14:19:38.856Z",
"service": "collector:onContent"
}
]

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,8 +1,37 @@
import { IHowto, IOACategory, IOATag, Step, Image, ITEM_TYPE } from './howto-model.js';
import { IHowto, IOACategory, IOATag, Step, Image } from './howto-model.js';
const ITEM_TYPE = 'howto';
type VersionStatus = 'enabled' | 'under_review' | 'new' | 'discarded';
type AuthorType = 'human' | 'ai';
type VersionId = string;
type AlternativeId = string;
/**
* Extended Step interface that includes an enabled flag
*/
export interface ExtendedStep extends Step {
enabled: boolean; // Controls whether the step is active and visible
alternativeId?: AlternativeId; // ID for grouping alternative steps
}
/**
* Ordered step extending the base Step with explicit order.
*/
export interface OrderedStep extends ExtendedStep {
order: number;
}
/**
* Alternative step group for organizing steps with different approaches
*/
export interface AlternativeStepGroup {
id: AlternativeId;
title: string; // Descriptive title for the group of alternatives
description?: string; // Optional description of the alternatives
primaryStep: string; // ID of the primary/default step
stepIds: string[]; // IDs of all steps in this alternative group
}
/**
* Metadata for a specific how-to version.
@ -17,13 +46,6 @@ export interface VersionMetadata {
comment?: string; // Optional version note
}
/**
* Ordered step extending the base Step with explicit order.
*/
export interface OrderedStep extends Step {
order: number;
}
/**
* A complete how-to version with metadata and ordered steps.
*/
@ -37,6 +59,7 @@ export interface VersionedHowtoData {
time?: string;
cover_image?: Image;
steps: OrderedStep[];
alternativeStepGroups?: AlternativeStepGroup[]; // New property for alternative steps
files?: Array<{
name: string;
path: string;
@ -95,60 +118,72 @@ export interface HowtoFileStructure {
* Defines all operations for managing the how-to lifecycle.
*/
export interface HowtoService {
createHowto(
data: Pick<VersionedHowtoData, 'title' | 'description' | 'steps'>,
author: string,
authorType: AuthorType
): Promise<FileBasedHowto>;
createHowto(data: Pick<VersionedHowtoData, 'title' | 'description' | 'steps'>,
author: string, authorType: AuthorType): Promise<FileBasedHowto>;
createVersion(
howtoId: string,
data: VersionedHowtoData,
author: string,
authorType: AuthorType
): Promise<VersionedHowtoData>;
createVersion(howtoId: string, data: VersionedHowtoData, author: string,
authorType: AuthorType): Promise<VersionedHowtoData>;
createSuggestion(
howtoId: string,
data: VersionedHowtoData,
author: string,
authorType: AuthorType
): Promise<HowtoSuggestion>;
createSuggestion(howtoId: string, data: VersionedHowtoData, author: string,
authorType: AuthorType): Promise<HowtoSuggestion>;
applySuggestion(
howtoId: string,
suggestionId: string
): Promise<VersionedHowtoData>;
applySuggestion(howtoId: string, suggestionId: string): Promise<VersionedHowtoData>;
getHowto(idOrHandle: string): Promise<FileBasedHowto>;
getVersion(
howtoId: string,
versionId: VersionId
): Promise<VersionedHowtoData>;
getVersion(howtoId: string, versionId: VersionId): Promise<VersionedHowtoData>;
setActiveVersion(
howtoId: string,
versionId: VersionId
): Promise<FileBasedHowto>;
setActiveVersion(howtoId: string, versionId: VersionId): Promise<FileBasedHowto>;
discardVersion(
howtoId: string,
versionId: VersionId
): Promise<VersionedHowtoData>;
discardVersion(howtoId: string, versionId: VersionId): Promise<VersionedHowtoData>;
compareVersions(
howtoId: string,
version1Id: VersionId,
version2Id: VersionId
): Promise<{
compareVersions(howtoId: string, version1Id: VersionId, version2Id: VersionId): Promise<{
diff: unknown;
}>;
convertLegacyHowto(
howto: IHowto,
author: string
): Promise<FileBasedHowto>;
/**
* Create an alternative step for an existing step
* @param howtoId ID of the howto
* @param versionId ID of the version
* @param stepId ID of the step to create an alternative for
* @param newStepData Data for the new alternative step
*/
createAlternativeStep(
howtoId: string,
versionId: VersionId,
stepId: string,
newStepData: Omit<OrderedStep, 'order' | 'alternativeId'>
): Promise<VersionedHowtoData>;
/**
* Manage alternative step groups
* @param howtoId ID of the howto
* @param versionId ID of the version
* @param alternativeId ID of the alternative group
* @param newData New data for the alternative group
*/
manageAlternativeGroup(
howtoId: string,
versionId: VersionId,
alternativeId: AlternativeId,
newData: Partial<AlternativeStepGroup>
): Promise<VersionedHowtoData>;
/**
* Toggle the enabled state of a step
* @param howtoId ID of the howto
* @param versionId ID of the version
* @param stepId ID of the step to toggle
* @param enabled The new enabled state
*/
toggleStepEnabled(
howtoId: string,
versionId: VersionId,
stepId: string,
enabled: boolean
): Promise<VersionedHowtoData>;
convertLegacyHowto(howto: IHowto, author: string): Promise<FileBasedHowto>;
convertToLegacyFormat(howto: FileBasedHowto): Promise<IHowto>;
}
@ -172,6 +207,7 @@ export const utils = {
title: '',
description: '',
steps: [],
alternativeStepGroups: [], // Initialize empty alternative step groups
}),
// Create a base FileBasedHowto from versioned data
@ -195,18 +231,35 @@ export const utils = {
},
}),
// Convert legacy steps to ordered ones
// Create an alternative step group
createAlternativeStepGroup: (primaryStep: string, title: string): AlternativeStepGroup => ({
id: crypto.randomUUID(),
title,
primaryStep,
stepIds: [primaryStep],
}),
// Convert legacy steps to ordered ones with enabled flag
convertToOrderedSteps: (steps: Step[]): OrderedStep[] =>
steps.map((step, index) => ({
...step,
order: index + 1,
enabled: true, // By default, all legacy steps are enabled
})),
// Convert ordered steps back to legacy format (unordered)
convertFromOrderedSteps: (steps: OrderedStep[]): Step[] =>
[...steps]
.filter(step => step.enabled) // Only include enabled steps
.sort((a, b) => a.order - b.order)
.map(({ order, ...rest }) => rest),
.map(({ order, enabled, alternativeId, ...rest }) => rest),
// Find all alternative steps for a given step
getAlternativeSteps: (stepId: string, steps: OrderedStep[], alternativeGroups: AlternativeStepGroup[]): OrderedStep[] => {
const group = alternativeGroups.find(g => g.stepIds.includes(stepId));
if (!group) return [];
return steps.filter(step => group.stepIds.includes(step._animationKey));
},
// Convert a legacy IHowto into a VersionedHowtoData
convertLegacyToVersioned: (
@ -228,5 +281,6 @@ export const utils = {
time: howto.time,
cover_image: howto.cover_image,
steps: utils.convertToOrderedSteps(howto.steps || []),
alternativeStepGroups: [], // Initialize with no alternative steps
}),
};

View File

@ -1,10 +1,9 @@
kbotd --preferences ./todos-workflow.md \
--include=./howto-model.ts \
--include=./howto-ex.ts \
--include=./howto_sample.json \
--disable=terminal,git,npm,user,interact,email \
--disableTools=read_files,list_files,file_exists \
--model=anthropic/claude-3.7-sonnet:thinking \
--mode_=completion \
--filters=code \
--dst=./howto-ex.ts
--filters=code

View File

@ -1,33 +1,6 @@
## Goal
Design a better interface/model for a **file-based how-to workflow** system. The aim is to improve how-tos via IDE or API. Use **TypeScript**, **ESM**, **functional programming**, and **zero dependencies**.
- [ ] Extend howtos for alternative steps, also, add a field : 'enabled'
> 🔧 **Code only**: return minimal, ready-to-use TypeScript code. No comments, no explanations, no external packages.
---
## Requirements
- ✅ Each how-to is stored in its own **folder**.
- ✅ Output your interface/model in `./howto-ex.ts` (extending `./howto-model.ts`).
- 🚫 Do **not** implement or design any storage logic.
---
## Key Design Improvements
- Replace the current `steps: Step[]` (unordered) with a model that makes **step order explicit**.
- Include **metadata for versioning/staging**:
- version history saved to disk (for comparison)
- authored by human or AI
- status: `enabled` | `under_review` | `new` | `discarded`
- timestamped entries
- Support multiple **suggestions** per step/version.
- Allow the author to **choose**, **pin**, and **track** them.
---
## Deliverables
- [ ] `./howto-ex.ts`: new interfaces/models extending `./howto-model.ts`
- [ ] `./howto-workflow.md`: explain the rationale behind your design choices
- integrate changes in `./howto-ex.ts`
- Do **not** implement or design any storage logic.