shotgun-sh 0.1.0.dev25__tar.gz → 0.1.0.dev26__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of shotgun-sh might be problematic. Click here for more details.
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/PKG-INFO +1 -1
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/pyproject.toml +1 -1
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/agents/agent_manager.py +24 -8
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/agents/common.py +112 -27
- shotgun_sh-0.1.0.dev26/src/shotgun/agents/conversation_history.py +106 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/agents/models.py +17 -0
- shotgun_sh-0.1.0.dev26/src/shotgun/prompts/agents/export.j2 +214 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/prompts/agents/partials/common_agent_system_prompt.j2 +1 -1
- shotgun_sh-0.1.0.dev26/src/shotgun/prompts/agents/plan.j2 +144 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/prompts/agents/state/system_state.j2 +5 -3
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/tui/screens/chat.py +10 -14
- shotgun_sh-0.1.0.dev26/src/shotgun/tui/screens/chat_screen/hint_message.py +40 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/tui/screens/chat_screen/history.py +6 -2
- shotgun_sh-0.1.0.dev25/src/shotgun/agents/conversation_history.py +0 -56
- shotgun_sh-0.1.0.dev25/src/shotgun/prompts/agents/export.j2 +0 -106
- shotgun_sh-0.1.0.dev25/src/shotgun/prompts/agents/plan.j2 +0 -73
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/.gitignore +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/LICENSE +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/README.md +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/hatch_build.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/__init__.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/agents/__init__.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/agents/config/__init__.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/agents/config/constants.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/agents/config/manager.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/agents/config/models.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/agents/config/provider.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/agents/conversation_manager.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/agents/export.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/agents/history/__init__.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/agents/history/compaction.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/agents/history/constants.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/agents/history/context_extraction.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/agents/history/history_building.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/agents/history/history_processors.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/agents/history/message_utils.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/agents/history/token_counting.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/agents/history/token_estimation.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/agents/plan.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/agents/research.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/agents/specify.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/agents/tasks.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/agents/tools/__init__.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/agents/tools/codebase/__init__.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/agents/tools/codebase/codebase_shell.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/agents/tools/codebase/directory_lister.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/agents/tools/codebase/file_read.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/agents/tools/codebase/models.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/agents/tools/codebase/query_graph.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/agents/tools/codebase/retrieve_code.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/agents/tools/file_management.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/agents/tools/user_interaction.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/agents/tools/web_search/__init__.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/agents/tools/web_search/anthropic.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/agents/tools/web_search/gemini.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/agents/tools/web_search/openai.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/agents/tools/web_search/utils.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/build_constants.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/cli/__init__.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/cli/codebase/__init__.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/cli/codebase/commands.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/cli/codebase/models.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/cli/config.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/cli/export.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/cli/models.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/cli/plan.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/cli/research.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/cli/specify.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/cli/tasks.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/cli/update.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/cli/utils.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/codebase/__init__.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/codebase/core/__init__.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/codebase/core/change_detector.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/codebase/core/code_retrieval.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/codebase/core/ingestor.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/codebase/core/language_config.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/codebase/core/manager.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/codebase/core/nl_query.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/codebase/core/parser_loader.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/codebase/models.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/codebase/service.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/logging_config.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/main.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/posthog_telemetry.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/prompts/__init__.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/prompts/agents/__init__.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/prompts/agents/partials/codebase_understanding.j2 +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/prompts/agents/partials/content_formatting.j2 +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/prompts/agents/partials/interactive_mode.j2 +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/prompts/agents/research.j2 +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/prompts/agents/specify.j2 +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/prompts/agents/state/codebase/codebase_graphs_available.j2 +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/prompts/agents/tasks.j2 +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/prompts/codebase/__init__.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/prompts/codebase/cypher_query_patterns.j2 +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/prompts/codebase/cypher_system.j2 +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/prompts/codebase/enhanced_query_context.j2 +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/prompts/codebase/partials/cypher_rules.j2 +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/prompts/codebase/partials/graph_schema.j2 +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/prompts/codebase/partials/temporal_context.j2 +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/prompts/history/__init__.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/prompts/history/incremental_summarization.j2 +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/prompts/history/summarization.j2 +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/prompts/loader.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/py.typed +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/sdk/__init__.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/sdk/codebase.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/sdk/exceptions.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/sdk/models.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/sdk/services.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/sentry_telemetry.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/telemetry.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/tui/__init__.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/tui/app.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/tui/commands/__init__.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/tui/components/prompt_input.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/tui/components/spinner.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/tui/components/splash.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/tui/components/vertical_tail.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/tui/screens/chat.tcss +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/tui/screens/chat_screen/__init__.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/tui/screens/chat_screen/command_providers.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/tui/screens/directory_setup.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/tui/screens/provider_config.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/tui/screens/splash.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/tui/styles.tcss +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/tui/utils/__init__.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/tui/utils/mode_progress.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/utils/__init__.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/utils/env_utils.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/utils/file_system_utils.py +0 -0
- {shotgun_sh-0.1.0.dev25 → shotgun_sh-0.1.0.dev26}/src/shotgun/utils/update_checker.py +0 -0
|
@@ -37,6 +37,7 @@ from textual.widget import Widget
|
|
|
37
37
|
|
|
38
38
|
from shotgun.agents.common import add_system_prompt_message, add_system_status_message
|
|
39
39
|
from shotgun.agents.models import AgentType, FileOperation
|
|
40
|
+
from shotgun.tui.screens.chat_screen.hint_message import HintMessage
|
|
40
41
|
|
|
41
42
|
from .export import create_export_agent
|
|
42
43
|
from .history.compaction import apply_persistent_compaction
|
|
@@ -54,7 +55,7 @@ class MessageHistoryUpdated(Message):
|
|
|
54
55
|
|
|
55
56
|
def __init__(
|
|
56
57
|
self,
|
|
57
|
-
messages: list[ModelMessage],
|
|
58
|
+
messages: list[ModelMessage | HintMessage],
|
|
58
59
|
agent_type: AgentType,
|
|
59
60
|
file_operations: list[FileOperation] | None = None,
|
|
60
61
|
) -> None:
|
|
@@ -143,7 +144,7 @@ class AgentManager(Widget):
|
|
|
143
144
|
self._current_agent_type: AgentType = initial_type
|
|
144
145
|
|
|
145
146
|
# Maintain shared message history
|
|
146
|
-
self.ui_message_history: list[ModelMessage] = []
|
|
147
|
+
self.ui_message_history: list[ModelMessage | HintMessage] = []
|
|
147
148
|
self.message_history: list[ModelMessage] = []
|
|
148
149
|
self.recently_change_files: list[FileOperation] = []
|
|
149
150
|
self._stream_state: _PartialStreamState | None = None
|
|
@@ -461,8 +462,8 @@ class AgentManager(Widget):
|
|
|
461
462
|
)
|
|
462
463
|
|
|
463
464
|
def _filter_system_prompts(
|
|
464
|
-
self, messages: list[ModelMessage]
|
|
465
|
-
) -> list[ModelMessage]:
|
|
465
|
+
self, messages: list[ModelMessage | HintMessage]
|
|
466
|
+
) -> list[ModelMessage | HintMessage]:
|
|
466
467
|
"""Filter out system prompts from messages for UI display.
|
|
467
468
|
|
|
468
469
|
Args:
|
|
@@ -473,8 +474,12 @@ class AgentManager(Widget):
|
|
|
473
474
|
"""
|
|
474
475
|
from pydantic_ai.messages import SystemPromptPart
|
|
475
476
|
|
|
476
|
-
filtered_messages: list[ModelMessage] = []
|
|
477
|
+
filtered_messages: list[ModelMessage | HintMessage] = []
|
|
477
478
|
for msg in messages:
|
|
479
|
+
if isinstance(msg, HintMessage):
|
|
480
|
+
filtered_messages.append(msg)
|
|
481
|
+
continue
|
|
482
|
+
|
|
478
483
|
parts: Sequence[ModelRequestPart] | Sequence[ModelResponsePart] | None = (
|
|
479
484
|
msg.parts if hasattr(msg, "parts") else None
|
|
480
485
|
)
|
|
@@ -514,6 +519,7 @@ class AgentManager(Widget):
|
|
|
514
519
|
|
|
515
520
|
return ConversationState(
|
|
516
521
|
agent_messages=self.message_history.copy(),
|
|
522
|
+
ui_messages=self.ui_message_history.copy(),
|
|
517
523
|
agent_type=self._current_agent_type.value,
|
|
518
524
|
)
|
|
519
525
|
|
|
@@ -524,10 +530,16 @@ class AgentManager(Widget):
|
|
|
524
530
|
state: ConversationState object to restore
|
|
525
531
|
"""
|
|
526
532
|
# Restore message history for agents (includes system prompts)
|
|
527
|
-
|
|
533
|
+
non_hint_messages = [
|
|
534
|
+
msg for msg in state.agent_messages if not isinstance(msg, HintMessage)
|
|
535
|
+
]
|
|
536
|
+
self.message_history = non_hint_messages
|
|
528
537
|
|
|
529
|
-
# Filter out system prompts for UI display
|
|
530
|
-
|
|
538
|
+
# Filter out system prompts for UI display while keeping hints
|
|
539
|
+
ui_source = state.ui_messages or cast(
|
|
540
|
+
list[ModelMessage | HintMessage], state.agent_messages
|
|
541
|
+
)
|
|
542
|
+
self.ui_message_history = self._filter_system_prompts(ui_source)
|
|
531
543
|
|
|
532
544
|
# Restore agent type
|
|
533
545
|
self._current_agent_type = AgentType(state.agent_type)
|
|
@@ -535,6 +547,10 @@ class AgentManager(Widget):
|
|
|
535
547
|
# Notify listeners about the restored messages
|
|
536
548
|
self._post_messages_updated()
|
|
537
549
|
|
|
550
|
+
def add_hint_message(self, message: HintMessage) -> None:
|
|
551
|
+
self.ui_message_history.append(message)
|
|
552
|
+
self._post_messages_updated()
|
|
553
|
+
|
|
538
554
|
|
|
539
555
|
# Re-export AgentType for backward compatibility
|
|
540
556
|
__all__ = [
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import asyncio
|
|
4
4
|
from collections.abc import Callable
|
|
5
|
+
from pathlib import Path
|
|
5
6
|
from typing import Any
|
|
6
7
|
|
|
7
8
|
from pydantic_ai import (
|
|
@@ -28,7 +29,7 @@ from shotgun.utils.file_system_utils import get_shotgun_base_path
|
|
|
28
29
|
|
|
29
30
|
from .history import token_limit_compactor
|
|
30
31
|
from .history.compaction import apply_persistent_compaction
|
|
31
|
-
from .models import AgentDeps, AgentRuntimeOptions
|
|
32
|
+
from .models import AgentDeps, AgentRuntimeOptions, PipelineConfigEntry
|
|
32
33
|
from .tools import (
|
|
33
34
|
append_file,
|
|
34
35
|
ask_user,
|
|
@@ -197,33 +198,24 @@ def create_base_agent(
|
|
|
197
198
|
return agent, deps
|
|
198
199
|
|
|
199
200
|
|
|
200
|
-
def
|
|
201
|
-
|
|
201
|
+
def _extract_file_toc_content(
|
|
202
|
+
file_path: Path, max_depth: int | None = None, max_chars: int = 500
|
|
203
|
+
) -> str | None:
|
|
204
|
+
"""Extract TOC from a single file with depth and character limits.
|
|
202
205
|
|
|
203
206
|
Args:
|
|
204
|
-
|
|
207
|
+
file_path: Path to the markdown file
|
|
208
|
+
max_depth: Maximum heading depth (1=#, 2=##, None=all)
|
|
209
|
+
max_chars: Maximum characters for the TOC
|
|
205
210
|
|
|
206
211
|
Returns:
|
|
207
|
-
Formatted TOC string
|
|
212
|
+
Formatted TOC string or None if file doesn't exist
|
|
208
213
|
"""
|
|
209
|
-
|
|
210
|
-
if (
|
|
211
|
-
not agent_mode
|
|
212
|
-
or agent_mode == AgentType.EXPORT
|
|
213
|
-
or agent_mode not in AGENT_DIRECTORIES
|
|
214
|
-
):
|
|
215
|
-
return None
|
|
216
|
-
|
|
217
|
-
base_path = get_shotgun_base_path()
|
|
218
|
-
md_file = AGENT_DIRECTORIES[agent_mode]
|
|
219
|
-
md_path = base_path / md_file
|
|
220
|
-
|
|
221
|
-
# Check if the markdown file exists
|
|
222
|
-
if not md_path.exists():
|
|
214
|
+
if not file_path.exists():
|
|
223
215
|
return None
|
|
224
216
|
|
|
225
217
|
try:
|
|
226
|
-
content =
|
|
218
|
+
content = file_path.read_text(encoding="utf-8")
|
|
227
219
|
lines = content.split("\n")
|
|
228
220
|
|
|
229
221
|
# Extract headings
|
|
@@ -239,6 +231,10 @@ def extract_markdown_toc(agent_mode: AgentType | None) -> str | None:
|
|
|
239
231
|
else:
|
|
240
232
|
break
|
|
241
233
|
|
|
234
|
+
# Skip if exceeds max_depth
|
|
235
|
+
if max_depth and level > max_depth:
|
|
236
|
+
continue
|
|
237
|
+
|
|
242
238
|
# Get the heading text (remove the # symbols and clean up)
|
|
243
239
|
heading_text = stripped[level:].strip()
|
|
244
240
|
if heading_text:
|
|
@@ -246,21 +242,110 @@ def extract_markdown_toc(agent_mode: AgentType | None) -> str | None:
|
|
|
246
242
|
indent = " " * (level - 1)
|
|
247
243
|
toc_lines.append(f"{indent}{'#' * level} {heading_text}")
|
|
248
244
|
|
|
245
|
+
# Check if we're approaching the character limit
|
|
246
|
+
current_length = sum(len(line) + 1 for line in toc_lines)
|
|
247
|
+
if current_length > max_chars:
|
|
248
|
+
# Remove the last line and add ellipsis
|
|
249
|
+
toc_lines.pop()
|
|
250
|
+
if toc_lines:
|
|
251
|
+
toc_lines.append(" ...")
|
|
252
|
+
break
|
|
253
|
+
|
|
249
254
|
if not toc_lines:
|
|
250
255
|
return None
|
|
251
256
|
|
|
252
|
-
|
|
253
|
-
toc = "\n".join(toc_lines)
|
|
254
|
-
if len(toc) > 2000:
|
|
255
|
-
toc = toc[:1997] + "..."
|
|
256
|
-
|
|
257
|
-
return toc
|
|
257
|
+
return "\n".join(toc_lines)
|
|
258
258
|
|
|
259
259
|
except Exception as e:
|
|
260
|
-
logger.debug(f"Failed to extract TOC from {
|
|
260
|
+
logger.debug(f"Failed to extract TOC from {file_path}: {e}")
|
|
261
261
|
return None
|
|
262
262
|
|
|
263
263
|
|
|
264
|
+
def extract_markdown_toc(agent_mode: AgentType | None) -> str | None:
|
|
265
|
+
"""Extract TOCs from current and prior agents' files in the pipeline.
|
|
266
|
+
|
|
267
|
+
Shows full TOC of agent's own file and high-level summaries of prior agents'
|
|
268
|
+
files to maintain context awareness while keeping context window tight.
|
|
269
|
+
|
|
270
|
+
Args:
|
|
271
|
+
agent_mode: The agent mode to extract TOC for
|
|
272
|
+
|
|
273
|
+
Returns:
|
|
274
|
+
Formatted multi-file TOC string or None if not applicable
|
|
275
|
+
"""
|
|
276
|
+
# Skip if no mode
|
|
277
|
+
if not agent_mode:
|
|
278
|
+
return None
|
|
279
|
+
|
|
280
|
+
# Define pipeline order and dependencies
|
|
281
|
+
pipeline_config: dict[AgentType, PipelineConfigEntry] = {
|
|
282
|
+
AgentType.RESEARCH: PipelineConfigEntry(
|
|
283
|
+
own_file="research.md",
|
|
284
|
+
prior_files=[], # First in pipeline
|
|
285
|
+
),
|
|
286
|
+
AgentType.SPECIFY: PipelineConfigEntry(
|
|
287
|
+
own_file="specification.md",
|
|
288
|
+
prior_files=["research.md"],
|
|
289
|
+
),
|
|
290
|
+
AgentType.PLAN: PipelineConfigEntry(
|
|
291
|
+
own_file="plan.md",
|
|
292
|
+
prior_files=["research.md", "specification.md"],
|
|
293
|
+
),
|
|
294
|
+
AgentType.TASKS: PipelineConfigEntry(
|
|
295
|
+
own_file="tasks.md",
|
|
296
|
+
prior_files=["research.md", "specification.md", "plan.md"],
|
|
297
|
+
),
|
|
298
|
+
AgentType.EXPORT: PipelineConfigEntry(
|
|
299
|
+
own_file=None, # Export uses directory
|
|
300
|
+
prior_files=["research.md", "specification.md", "plan.md", "tasks.md"],
|
|
301
|
+
),
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
# Get configuration for current agent
|
|
305
|
+
if agent_mode not in pipeline_config:
|
|
306
|
+
return None
|
|
307
|
+
|
|
308
|
+
config = pipeline_config[agent_mode]
|
|
309
|
+
base_path = get_shotgun_base_path()
|
|
310
|
+
toc_sections: list[str] = []
|
|
311
|
+
|
|
312
|
+
# Extract TOCs from prior files (high-level only)
|
|
313
|
+
for prior_file in config.prior_files:
|
|
314
|
+
file_path = base_path / prior_file
|
|
315
|
+
# Only show # and ## headings from prior files, max 500 chars each
|
|
316
|
+
prior_toc = _extract_file_toc_content(file_path, max_depth=2, max_chars=500)
|
|
317
|
+
if prior_toc:
|
|
318
|
+
# Add section header
|
|
319
|
+
file_label = prior_file.replace(".md", "").replace("_", " ").title()
|
|
320
|
+
toc_sections.append(
|
|
321
|
+
f"=== Prior Context: {file_label} (summary) ===\n{prior_toc}"
|
|
322
|
+
)
|
|
323
|
+
|
|
324
|
+
# Extract TOC from own file (full detail)
|
|
325
|
+
if config.own_file:
|
|
326
|
+
own_path = base_path / config.own_file
|
|
327
|
+
own_toc = _extract_file_toc_content(own_path, max_depth=None, max_chars=2000)
|
|
328
|
+
if own_toc:
|
|
329
|
+
file_label = config.own_file.replace(".md", "").replace("_", " ").title()
|
|
330
|
+
# Put own file TOC at the beginning
|
|
331
|
+
toc_sections.insert(
|
|
332
|
+
0, f"=== Your Current Document: {file_label} ===\n{own_toc}"
|
|
333
|
+
)
|
|
334
|
+
|
|
335
|
+
# Combine all sections
|
|
336
|
+
if not toc_sections:
|
|
337
|
+
return None
|
|
338
|
+
|
|
339
|
+
combined_toc = "\n\n".join(toc_sections)
|
|
340
|
+
|
|
341
|
+
# Final truncation if needed (should rarely happen with our limits)
|
|
342
|
+
max_total = 3500 # Conservative total limit
|
|
343
|
+
if len(combined_toc) > max_total:
|
|
344
|
+
combined_toc = combined_toc[: max_total - 3] + "..."
|
|
345
|
+
|
|
346
|
+
return combined_toc
|
|
347
|
+
|
|
348
|
+
|
|
264
349
|
def get_agent_existing_files(agent_mode: AgentType | None = None) -> list[str]:
|
|
265
350
|
"""Get list of existing files for the given agent mode.
|
|
266
351
|
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"""Models and utilities for persisting TUI conversation history."""
|
|
2
|
+
|
|
3
|
+
from datetime import datetime
|
|
4
|
+
from typing import Any, cast
|
|
5
|
+
|
|
6
|
+
from pydantic import BaseModel, ConfigDict, Field
|
|
7
|
+
from pydantic_ai.messages import (
|
|
8
|
+
ModelMessage,
|
|
9
|
+
ModelMessagesTypeAdapter,
|
|
10
|
+
)
|
|
11
|
+
from pydantic_core import to_jsonable_python
|
|
12
|
+
|
|
13
|
+
from shotgun.tui.screens.chat_screen.hint_message import HintMessage
|
|
14
|
+
|
|
15
|
+
SerializedMessage = dict[str, Any]
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class ConversationState(BaseModel):
|
|
19
|
+
"""Represents the complete state of a conversation in memory."""
|
|
20
|
+
|
|
21
|
+
agent_messages: list[ModelMessage]
|
|
22
|
+
ui_messages: list[ModelMessage | HintMessage] = Field(default_factory=list)
|
|
23
|
+
agent_type: str # Will store AgentType.value
|
|
24
|
+
|
|
25
|
+
model_config = ConfigDict(arbitrary_types_allowed=True)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class ConversationHistory(BaseModel):
|
|
29
|
+
"""Persistent conversation history for TUI sessions."""
|
|
30
|
+
|
|
31
|
+
version: int = 1
|
|
32
|
+
agent_history: list[SerializedMessage] = Field(
|
|
33
|
+
default_factory=list
|
|
34
|
+
) # Stores serialized ModelMessage objects
|
|
35
|
+
ui_history: list[SerializedMessage] = Field(
|
|
36
|
+
default_factory=list
|
|
37
|
+
) # Stores serialized ModelMessage and HintMessage objects
|
|
38
|
+
last_agent_model: str = "research"
|
|
39
|
+
updated_at: datetime = Field(default_factory=datetime.now)
|
|
40
|
+
|
|
41
|
+
model_config = ConfigDict(arbitrary_types_allowed=True)
|
|
42
|
+
|
|
43
|
+
def set_agent_messages(self, messages: list[ModelMessage]) -> None:
|
|
44
|
+
"""Set agent_history from a list of ModelMessage objects.
|
|
45
|
+
|
|
46
|
+
Args:
|
|
47
|
+
messages: List of ModelMessage objects to serialize and store
|
|
48
|
+
"""
|
|
49
|
+
# Serialize ModelMessage list to JSON-serializable format
|
|
50
|
+
self.agent_history = to_jsonable_python(
|
|
51
|
+
messages, fallback=lambda x: str(x), exclude_none=True
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
def set_ui_messages(self, messages: list[ModelMessage | HintMessage]) -> None:
|
|
55
|
+
"""Set ui_history from a list of UI messages."""
|
|
56
|
+
|
|
57
|
+
def _serialize_message(
|
|
58
|
+
message: ModelMessage | HintMessage,
|
|
59
|
+
) -> Any:
|
|
60
|
+
if isinstance(message, HintMessage):
|
|
61
|
+
data = message.model_dump()
|
|
62
|
+
data["message_type"] = "hint"
|
|
63
|
+
return data
|
|
64
|
+
payload = to_jsonable_python(
|
|
65
|
+
message, fallback=lambda x: str(x), exclude_none=True
|
|
66
|
+
)
|
|
67
|
+
if isinstance(payload, dict):
|
|
68
|
+
payload.setdefault("message_type", "model")
|
|
69
|
+
return payload
|
|
70
|
+
|
|
71
|
+
self.ui_history = [_serialize_message(msg) for msg in messages]
|
|
72
|
+
|
|
73
|
+
def get_agent_messages(self) -> list[ModelMessage]:
|
|
74
|
+
"""Get agent_history as a list of ModelMessage objects.
|
|
75
|
+
|
|
76
|
+
Returns:
|
|
77
|
+
List of deserialized ModelMessage objects
|
|
78
|
+
"""
|
|
79
|
+
if not self.agent_history:
|
|
80
|
+
return []
|
|
81
|
+
|
|
82
|
+
# Deserialize from JSON format back to ModelMessage objects
|
|
83
|
+
return ModelMessagesTypeAdapter.validate_python(self.agent_history)
|
|
84
|
+
|
|
85
|
+
def get_ui_messages(self) -> list[ModelMessage | HintMessage]:
|
|
86
|
+
"""Get ui_history as a list of Model or hint messages."""
|
|
87
|
+
|
|
88
|
+
if not self.ui_history:
|
|
89
|
+
# Fallback for older conversation files without UI history
|
|
90
|
+
return cast(list[ModelMessage | HintMessage], self.get_agent_messages())
|
|
91
|
+
|
|
92
|
+
messages: list[ModelMessage | HintMessage] = []
|
|
93
|
+
for item in self.ui_history:
|
|
94
|
+
message_type = item.get("message_type") if isinstance(item, dict) else None
|
|
95
|
+
if message_type == "hint":
|
|
96
|
+
messages.append(HintMessage.model_validate(item))
|
|
97
|
+
continue
|
|
98
|
+
|
|
99
|
+
# Backwards compatibility: data may not include the type marker
|
|
100
|
+
payload = item
|
|
101
|
+
if isinstance(payload, dict):
|
|
102
|
+
payload = {k: v for k, v in payload.items() if k != "message_type"}
|
|
103
|
+
deserialized = ModelMessagesTypeAdapter.validate_python([payload])
|
|
104
|
+
messages.append(deserialized[0])
|
|
105
|
+
|
|
106
|
+
return messages
|
|
@@ -27,6 +27,23 @@ class AgentType(StrEnum):
|
|
|
27
27
|
EXPORT = "export"
|
|
28
28
|
|
|
29
29
|
|
|
30
|
+
class PipelineConfigEntry(BaseModel):
|
|
31
|
+
"""Configuration for each agent in the pipeline.
|
|
32
|
+
|
|
33
|
+
This model defines what files an agent can write to and what
|
|
34
|
+
files from prior agents it should read for context.
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
own_file: str | None = Field(
|
|
38
|
+
default=None,
|
|
39
|
+
description="The file this agent writes to (None for export agent)",
|
|
40
|
+
)
|
|
41
|
+
prior_files: list[str] = Field(
|
|
42
|
+
default_factory=list,
|
|
43
|
+
description="Files from prior agents in pipeline to read for context",
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
|
|
30
47
|
class UserAnswer(BaseModel):
|
|
31
48
|
"""A answer from the user."""
|
|
32
49
|
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
You are an experienced Export Specialist and Data Transformation Expert.
|
|
2
|
+
|
|
3
|
+
Your job is to help export project documentation and findings to various formats and destinations in the exports/ folder.
|
|
4
|
+
|
|
5
|
+
{% include 'agents/partials/common_agent_system_prompt.j2' %}
|
|
6
|
+
|
|
7
|
+
## MEMORY MANAGEMENT PROTOCOL
|
|
8
|
+
|
|
9
|
+
- You can ONLY write to the `exports/` directory
|
|
10
|
+
- SHOULD READ all files: `research.md`, `specification.md`, `plan.md`, `tasks.md`
|
|
11
|
+
- Create new export files, don't modify source files
|
|
12
|
+
- Name exports descriptively with timestamps: `exports/AGENTS_[timestamp].md`
|
|
13
|
+
- Each export is a standalone deliverable for AI agents
|
|
14
|
+
|
|
15
|
+
## AI AGENT PIPELINE AWARENESS
|
|
16
|
+
|
|
17
|
+
**CRITICAL**: Your exports will be consumed by AI coding agents (Claude Code, Cursor, Windsurf, etc.)
|
|
18
|
+
- The AGENTS.md file is THE primary deliverable for AI agents
|
|
19
|
+
- Consolidate all relevant information into a single, actionable document
|
|
20
|
+
- Include all necessary context without requiring access to source files
|
|
21
|
+
- Structure exports for immediate AI agent consumption
|
|
22
|
+
- Prioritize tasks and implementation steps from tasks.md
|
|
23
|
+
- Include specifications and API details from specification.md
|
|
24
|
+
- Add relevant research findings that affect implementation
|
|
25
|
+
- Format as executable instructions, not educational content
|
|
26
|
+
|
|
27
|
+
## EXPORT WORKFLOW
|
|
28
|
+
|
|
29
|
+
For AGENTS.md exports:
|
|
30
|
+
1. **MANDATORY: Read ALL pipeline files**:
|
|
31
|
+
- `tasks.md` - Extract actionable tasks with inputs/outputs
|
|
32
|
+
- `specification.md` - Get primary objective and constraints
|
|
33
|
+
- `plan.md` - Convert stages to success criteria
|
|
34
|
+
- `research.md` - Extract codebase context and open questions
|
|
35
|
+
2. **Map content to template sections**:
|
|
36
|
+
- Primary Objective: From specification.md's main goal
|
|
37
|
+
- Tasks: From tasks.md, formatted as action items
|
|
38
|
+
- Research Needed: Unresolved questions from research.md
|
|
39
|
+
- Codebase Context: Technical findings from research.md
|
|
40
|
+
- Success Criteria: Plan.md stages as measurable outcomes
|
|
41
|
+
- Important Notes: Critical constraints from all files
|
|
42
|
+
- References: Documentation links from research.md
|
|
43
|
+
3. **Transform content**: Convert to action-oriented language for AI agents
|
|
44
|
+
4. **Create export**: Save as `exports/AGENTS.md` or `exports/AGENTS_[timestamp].md`
|
|
45
|
+
5. **Validate**: Ensure every section has actionable content
|
|
46
|
+
|
|
47
|
+
For other export tasks:
|
|
48
|
+
1. **Check existing files**: Read relevant source files
|
|
49
|
+
2. **Understand requirements**: Determine format and scope
|
|
50
|
+
3. **Read source content**: Load all necessary information
|
|
51
|
+
4. **Transform and format**: Convert to requested format
|
|
52
|
+
5. **Create export files**: Save in exports/ folder
|
|
53
|
+
6. **Validate output**: Verify proper formatting
|
|
54
|
+
|
|
55
|
+
## SUPPORTED EXPORT FORMATS
|
|
56
|
+
|
|
57
|
+
- **AGENTS.md**: See below
|
|
58
|
+
- **Markdown (.md)**: Nicely formatted Markdown file with everything the user wants to export
|
|
59
|
+
- **Multiple files**: Can create multiple export files in the exports/ folder as needed
|
|
60
|
+
|
|
61
|
+
### AGENTS.md - Primary Export Format for AI Agents
|
|
62
|
+
|
|
63
|
+
**CRITICAL**: The AGENTS.md file is THE primary deliverable for AI coding agents. It MUST follow this exact template:
|
|
64
|
+
|
|
65
|
+
```markdown
|
|
66
|
+
# [Project Name] Implementation Guide for AI Agents
|
|
67
|
+
|
|
68
|
+
## Primary Objective
|
|
69
|
+
[1-2 sentences describing WHAT needs to be built, not HOW]
|
|
70
|
+
|
|
71
|
+
## Tasks
|
|
72
|
+
|
|
73
|
+
### Task 1: [Action-oriented title]
|
|
74
|
+
**Input**: [What files/data this task needs]
|
|
75
|
+
**Output**: [What files/code this task produces]
|
|
76
|
+
**Constraints**: [Security, performance, or architectural requirements]
|
|
77
|
+
|
|
78
|
+
### Task 2: [Next action]
|
|
79
|
+
[Continue pattern...]
|
|
80
|
+
|
|
81
|
+
## Research Needed
|
|
82
|
+
- [ ] [Specific technical question to investigate]
|
|
83
|
+
- [ ] [API endpoint to understand]
|
|
84
|
+
- [ ] [Integration pattern to review]
|
|
85
|
+
|
|
86
|
+
## Codebase Context
|
|
87
|
+
- **Language**: [Primary language and version]
|
|
88
|
+
- **Key Files**: [Critical files to read first]
|
|
89
|
+
- **Patterns**: [Design patterns used in codebase]
|
|
90
|
+
- **Dependencies**: [Important libraries/frameworks]
|
|
91
|
+
|
|
92
|
+
## Success Criteria
|
|
93
|
+
- [ ] [Measurable outcome 1]
|
|
94
|
+
- [ ] [Measurable outcome 2]
|
|
95
|
+
- [ ] [Tests pass / Coverage meets X%]
|
|
96
|
+
|
|
97
|
+
## Important Notes
|
|
98
|
+
- [Critical constraint or requirement]
|
|
99
|
+
- [Security consideration]
|
|
100
|
+
- [Performance requirement]
|
|
101
|
+
|
|
102
|
+
## References
|
|
103
|
+
- [Link to API documentation]
|
|
104
|
+
- [Link to architecture diagrams]
|
|
105
|
+
- [Link to test requirements]
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
**Export Requirements**:
|
|
109
|
+
- Extract Primary Objective from specification.md
|
|
110
|
+
- Map tasks from tasks.md into action-oriented Task sections
|
|
111
|
+
- Pull research questions from research.md that are still relevant
|
|
112
|
+
- Include codebase context from research findings
|
|
113
|
+
- Convert plan stages into Success Criteria
|
|
114
|
+
- Add implementation constraints from specifications
|
|
115
|
+
- Format ALL content for immediate AI agent execution
|
|
116
|
+
- NO educational content, NO "learn X" instructions
|
|
117
|
+
- Every section must be actionable by Claude Code
|
|
118
|
+
|
|
119
|
+
**Example of GOOD AGENTS.md Content**:
|
|
120
|
+
```markdown
|
|
121
|
+
# E-commerce API Implementation Guide for AI Agents
|
|
122
|
+
|
|
123
|
+
## Primary Objective
|
|
124
|
+
Build a REST API for product catalog management with authentication, supporting CRUD operations and search functionality.
|
|
125
|
+
|
|
126
|
+
## Tasks
|
|
127
|
+
|
|
128
|
+
### Task 1: Implement Database Models
|
|
129
|
+
**Input**: requirements.md, existing database schema
|
|
130
|
+
**Output**: models/product.py, models/user.py, migrations/
|
|
131
|
+
**Constraints**: Use SQLAlchemy ORM, maintain backward compatibility
|
|
132
|
+
|
|
133
|
+
### Task 2: Create Authentication Endpoints
|
|
134
|
+
**Input**: models/user.py, auth requirements
|
|
135
|
+
**Output**: api/auth.py, middleware/auth.py
|
|
136
|
+
**Constraints**: JWT tokens, 15-minute expiry, refresh token support
|
|
137
|
+
|
|
138
|
+
## Research Needed
|
|
139
|
+
- [ ] Check if existing auth middleware supports JWT refresh tokens
|
|
140
|
+
- [ ] Verify PostgreSQL full-text search capabilities for product search
|
|
141
|
+
- [ ] Review rate limiting implementation in current middleware
|
|
142
|
+
|
|
143
|
+
## Codebase Context
|
|
144
|
+
- **Language**: Python 3.11
|
|
145
|
+
- **Key Files**: src/api/__init__.py, src/models/base.py
|
|
146
|
+
- **Patterns**: Repository pattern, dependency injection
|
|
147
|
+
- **Dependencies**: FastAPI, SQLAlchemy, Pydantic
|
|
148
|
+
|
|
149
|
+
## Success Criteria
|
|
150
|
+
- [ ] All CRUD endpoints return correct status codes
|
|
151
|
+
- [ ] Authentication enforced on protected routes
|
|
152
|
+
- [ ] Test coverage exceeds 80%
|
|
153
|
+
- [ ] API response times under 200ms
|
|
154
|
+
|
|
155
|
+
## Important Notes
|
|
156
|
+
- Database migrations must be reversible
|
|
157
|
+
- All endpoints require input validation
|
|
158
|
+
- Search must support pagination
|
|
159
|
+
|
|
160
|
+
## References
|
|
161
|
+
- FastAPI docs: https://fastapi.tiangolo.com
|
|
162
|
+
- Project API spec: docs/openapi.yaml
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
## EXPORT PRINCIPLES
|
|
167
|
+
|
|
168
|
+
- Preserve content structure and meaning during transformation
|
|
169
|
+
- Include proper headers, metadata, and formatting for target format
|
|
170
|
+
- Maintain links, references, and cross-references where applicable
|
|
171
|
+
- Create self-contained exports that can be used independently
|
|
172
|
+
- Add appropriate file extensions and format indicators
|
|
173
|
+
- Include export timestamp and source information
|
|
174
|
+
- Validate exported content is properly formatted and complete
|
|
175
|
+
- Handle missing or incomplete source data gracefully
|
|
176
|
+
- Consider target audience and use case for formatting decisions
|
|
177
|
+
- Always save exports in the exports/ folder
|
|
178
|
+
|
|
179
|
+
{% if interactive_mode %}
|
|
180
|
+
USER INTERACTION - CLARIFY EXPORT REQUIREMENTS:
|
|
181
|
+
|
|
182
|
+
- ALWAYS ask clarifying questions when export requirements are unclear
|
|
183
|
+
- Use ask_user tool to gather specific details about:
|
|
184
|
+
- Target format and file type preferences
|
|
185
|
+
- Intended use case and audience for the export
|
|
186
|
+
- Specific content sections to include/exclude from files
|
|
187
|
+
- Output structure and organization preferences
|
|
188
|
+
- Destination filename(s) in the exports/ folder
|
|
189
|
+
- Ask follow-up questions to ensure exports meet exact needs
|
|
190
|
+
- Confirm export scope and format before proceeding with large exports
|
|
191
|
+
- Better to ask 2-3 targeted questions than create generic exports
|
|
192
|
+
{% else %}
|
|
193
|
+
NON-INTERACTIVE MODE - MAKE REASONABLE EXPORT DECISIONS:
|
|
194
|
+
|
|
195
|
+
- Make reasonable assumptions about format based on content type
|
|
196
|
+
- Use standard formats and conventions for the target format
|
|
197
|
+
- Include comprehensive content unless scope is clearly limited
|
|
198
|
+
- Apply sensible default formatting and structure
|
|
199
|
+
- Export to commonly used and widely compatible formats
|
|
200
|
+
- Include standard metadata and documentation
|
|
201
|
+
{% endif %}
|
|
202
|
+
|
|
203
|
+
IMPORTANT RULES:
|
|
204
|
+
- Always verify source files exist before attempting export
|
|
205
|
+
- Preserve all critical information during format conversion
|
|
206
|
+
- Include source attribution and export metadata
|
|
207
|
+
- Create well-structured, properly formatted output
|
|
208
|
+
- Always save exports in the exports/ folder (create if needed)
|
|
209
|
+
{% if interactive_mode %}
|
|
210
|
+
- When export requirements are ambiguous, ASK before proceeding
|
|
211
|
+
{% else %}
|
|
212
|
+
- When requirements are unclear, use industry standard practices
|
|
213
|
+
{% endif %}
|
|
214
|
+
- Ensure exported content is self-contained and usable
|
|
@@ -7,7 +7,7 @@ Your extensive expertise spans, among other things:
|
|
|
7
7
|
## KEY RULES
|
|
8
8
|
|
|
9
9
|
{% if interactive_mode %}
|
|
10
|
-
0. Always ask
|
|
10
|
+
0. Always ask CLARIFYING QUESTIONS if the user's request is ambiguous or lacks sufficient detail. Do not make assumptions about what the user wants.
|
|
11
11
|
{% endif %}
|
|
12
12
|
1. Above all, prefer using tools to do the work and NEVER respond with text.
|
|
13
13
|
2. IMPORTANT: Always ask for review and go ahead to move forward after using write_file().
|