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 README.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ cxk create-spec template.md
# ? How would you like to provide the value for 'ticket_id'?
# › Provide value directly
# Use MCP tool to fetch value
# Read from file
```

### Output to File
Expand Down
46 changes: 44 additions & 2 deletions prompt/prompt_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,24 +159,27 @@ def validate_string(value):

async def collect_var_value_interactive(self, var_name: str) -> str:
"""
Interactive variable collection - user chooses between direct value or MCP tool.
Interactive variable collection - user chooses between direct value, MCP tool, or file.

:param var_name: Name of the variable to collect
:return: String value for the variable
"""
# Ask user to choose between direct value or MCP tool
# Ask user to choose between direct value, MCP tool, or file
choice = await questionary.select(
f"How would you like to provide the value for '{var_name}'?",
choices=[
questionary.Choice("Provide value directly", "direct"),
questionary.Choice("Use MCP tool to fetch value", "mcp"),
questionary.Choice("Read from file", "file"),
],
).ask_async()

if choice == "direct":
return await self.collect_var_value(var_name)
elif choice == "mcp":
return await self._collect_var_value_from_mcp(var_name)
elif choice == "file":
return await self._collect_var_value_from_file(var_name)
else:
raise ValueError("Invalid choice")

Expand Down Expand Up @@ -245,6 +248,45 @@ async def _collect_var_value_from_mcp(self, var_name: str) -> str:
logging.info(f"Tool result for '{var_name}': {content}")
return content

async def _collect_var_value_from_file(self, var_name: str) -> str:
"""
Collect variable value by reading from a file.

:param var_name: Name of the variable to collect
:return: String content of the selected file
"""
import os
Copy link

Copilot AI Sep 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The import statement should be moved to the top of the file with other imports rather than inside the function. This follows Python import conventions and improves code organization.

Copilot uses AI. Check for mistakes.

# Use questionary.path to select a file
file_path = await questionary.path(
f"Select a file for variable '{var_name}':",
default="./",
only_directories=False,
).ask_async()

if not file_path:
raise ValueError("No file selected")

# Ensure the path exists and is a file
if not os.path.exists(file_path):
raise ValueError(f"File does not exist: {file_path}")

if not os.path.isfile(file_path):
raise ValueError(f"Path is not a file: {file_path}")

try:
# Try to read the file as UTF-8
with open(file_path, encoding='utf-8') as f:
Copy link

Copilot AI Sep 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Consider using 'r' mode explicitly for better clarity: open(file_path, 'r', encoding='utf-8')

Suggested change
with open(file_path, encoding='utf-8') as f:
with open(file_path, 'r', encoding='utf-8') as f:

Copilot uses AI. Check for mistakes.
content = f.read()

logging.info(f"Successfully read file '{file_path}' for variable '{var_name}'")
return content

except UnicodeDecodeError as e:
raise ValueError(f"File '{file_path}' is not a valid UTF-8 text file: {e}") from e
except Exception as e:
raise ValueError(f"Failed to read file '{file_path}': {e}") from e

async def _select_mcp_server(self) -> str | None:
"""
Present user with list of available MCP servers to choose from.
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "context-kit"
version = "0.1.1"
version = "0.2.1"
description = "A CLI tool and MCP client, used to create spec files for AI coding agents with context baked in, based on reusable spec templates"
readme = "README.md"
requires-python = ">=3.11"
Expand Down