nc1709 1.15.4__py3-none-any.whl

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.
Files changed (86) hide show
  1. nc1709/__init__.py +13 -0
  2. nc1709/agent/__init__.py +36 -0
  3. nc1709/agent/core.py +505 -0
  4. nc1709/agent/mcp_bridge.py +245 -0
  5. nc1709/agent/permissions.py +298 -0
  6. nc1709/agent/tools/__init__.py +21 -0
  7. nc1709/agent/tools/base.py +440 -0
  8. nc1709/agent/tools/bash_tool.py +367 -0
  9. nc1709/agent/tools/file_tools.py +454 -0
  10. nc1709/agent/tools/notebook_tools.py +516 -0
  11. nc1709/agent/tools/search_tools.py +322 -0
  12. nc1709/agent/tools/task_tool.py +284 -0
  13. nc1709/agent/tools/web_tools.py +555 -0
  14. nc1709/agents/__init__.py +17 -0
  15. nc1709/agents/auto_fix.py +506 -0
  16. nc1709/agents/test_generator.py +507 -0
  17. nc1709/checkpoints.py +372 -0
  18. nc1709/cli.py +3380 -0
  19. nc1709/cli_ui.py +1080 -0
  20. nc1709/cognitive/__init__.py +149 -0
  21. nc1709/cognitive/anticipation.py +594 -0
  22. nc1709/cognitive/context_engine.py +1046 -0
  23. nc1709/cognitive/council.py +824 -0
  24. nc1709/cognitive/learning.py +761 -0
  25. nc1709/cognitive/router.py +583 -0
  26. nc1709/cognitive/system.py +519 -0
  27. nc1709/config.py +155 -0
  28. nc1709/custom_commands.py +300 -0
  29. nc1709/executor.py +333 -0
  30. nc1709/file_controller.py +354 -0
  31. nc1709/git_integration.py +308 -0
  32. nc1709/github_integration.py +477 -0
  33. nc1709/image_input.py +446 -0
  34. nc1709/linting.py +519 -0
  35. nc1709/llm_adapter.py +667 -0
  36. nc1709/logger.py +192 -0
  37. nc1709/mcp/__init__.py +18 -0
  38. nc1709/mcp/client.py +370 -0
  39. nc1709/mcp/manager.py +407 -0
  40. nc1709/mcp/protocol.py +210 -0
  41. nc1709/mcp/server.py +473 -0
  42. nc1709/memory/__init__.py +20 -0
  43. nc1709/memory/embeddings.py +325 -0
  44. nc1709/memory/indexer.py +474 -0
  45. nc1709/memory/sessions.py +432 -0
  46. nc1709/memory/vector_store.py +451 -0
  47. nc1709/models/__init__.py +86 -0
  48. nc1709/models/detector.py +377 -0
  49. nc1709/models/formats.py +315 -0
  50. nc1709/models/manager.py +438 -0
  51. nc1709/models/registry.py +497 -0
  52. nc1709/performance/__init__.py +343 -0
  53. nc1709/performance/cache.py +705 -0
  54. nc1709/performance/pipeline.py +611 -0
  55. nc1709/performance/tiering.py +543 -0
  56. nc1709/plan_mode.py +362 -0
  57. nc1709/plugins/__init__.py +17 -0
  58. nc1709/plugins/agents/__init__.py +18 -0
  59. nc1709/plugins/agents/django_agent.py +912 -0
  60. nc1709/plugins/agents/docker_agent.py +623 -0
  61. nc1709/plugins/agents/fastapi_agent.py +887 -0
  62. nc1709/plugins/agents/git_agent.py +731 -0
  63. nc1709/plugins/agents/nextjs_agent.py +867 -0
  64. nc1709/plugins/base.py +359 -0
  65. nc1709/plugins/manager.py +411 -0
  66. nc1709/plugins/registry.py +337 -0
  67. nc1709/progress.py +443 -0
  68. nc1709/prompts/__init__.py +22 -0
  69. nc1709/prompts/agent_system.py +180 -0
  70. nc1709/prompts/task_prompts.py +340 -0
  71. nc1709/prompts/unified_prompt.py +133 -0
  72. nc1709/reasoning_engine.py +541 -0
  73. nc1709/remote_client.py +266 -0
  74. nc1709/shell_completions.py +349 -0
  75. nc1709/slash_commands.py +649 -0
  76. nc1709/task_classifier.py +408 -0
  77. nc1709/version_check.py +177 -0
  78. nc1709/web/__init__.py +8 -0
  79. nc1709/web/server.py +950 -0
  80. nc1709/web/templates/index.html +1127 -0
  81. nc1709-1.15.4.dist-info/METADATA +858 -0
  82. nc1709-1.15.4.dist-info/RECORD +86 -0
  83. nc1709-1.15.4.dist-info/WHEEL +5 -0
  84. nc1709-1.15.4.dist-info/entry_points.txt +2 -0
  85. nc1709-1.15.4.dist-info/licenses/LICENSE +9 -0
  86. nc1709-1.15.4.dist-info/top_level.txt +1 -0
nc1709/plan_mode.py ADDED
@@ -0,0 +1,362 @@
1
+ """
2
+ Plan Mode for NC1709
3
+
4
+ Provides planning capabilities similar to Claude Code's plan mode:
5
+ - Think through tasks before executing
6
+ - Generate step-by-step plans
7
+ - Review and approve plans before execution
8
+ - Iterate on plans with user feedback
9
+ """
10
+
11
+ from dataclasses import dataclass, field
12
+ from typing import Optional, List, Dict, Any
13
+ from datetime import datetime
14
+ from enum import Enum
15
+
16
+
17
+ class PlanStatus(Enum):
18
+ """Status of a plan"""
19
+ DRAFT = "draft"
20
+ PENDING_APPROVAL = "pending_approval"
21
+ APPROVED = "approved"
22
+ REJECTED = "rejected"
23
+ IN_PROGRESS = "in_progress"
24
+ COMPLETED = "completed"
25
+ FAILED = "failed"
26
+
27
+
28
+ @dataclass
29
+ class PlanStep:
30
+ """A single step in a plan"""
31
+ id: int
32
+ description: str
33
+ details: Optional[str] = None
34
+ status: str = "pending" # pending, in_progress, completed, skipped, failed
35
+ result: Optional[str] = None
36
+ files_affected: List[str] = field(default_factory=list)
37
+
38
+
39
+ @dataclass
40
+ class Plan:
41
+ """A complete execution plan"""
42
+ id: str
43
+ title: str
44
+ description: str
45
+ steps: List[PlanStep]
46
+ status: PlanStatus = PlanStatus.DRAFT
47
+ created_at: datetime = field(default_factory=datetime.now)
48
+ approved_at: Optional[datetime] = None
49
+ completed_at: Optional[datetime] = None
50
+ user_feedback: Optional[str] = None
51
+ estimated_files: List[str] = field(default_factory=list)
52
+ risks: List[str] = field(default_factory=list)
53
+ alternatives: List[str] = field(default_factory=list)
54
+
55
+
56
+ class PlanManager:
57
+ """
58
+ Manages plan mode operations.
59
+
60
+ Features:
61
+ - Create and store plans
62
+ - Track plan status and progress
63
+ - Support plan approval workflow
64
+ - Persist plans for review
65
+ """
66
+
67
+ def __init__(self):
68
+ self._current_plan: Optional[Plan] = None
69
+ self._plan_history: List[Plan] = []
70
+ self._plan_mode_active: bool = False
71
+ self._plan_counter: int = 0
72
+
73
+ @property
74
+ def is_plan_mode(self) -> bool:
75
+ """Check if plan mode is active"""
76
+ return self._plan_mode_active
77
+
78
+ @property
79
+ def current_plan(self) -> Optional[Plan]:
80
+ """Get the current plan"""
81
+ return self._current_plan
82
+
83
+ def enter_plan_mode(self) -> None:
84
+ """Enter plan mode"""
85
+ self._plan_mode_active = True
86
+
87
+ def exit_plan_mode(self) -> None:
88
+ """Exit plan mode"""
89
+ self._plan_mode_active = False
90
+
91
+ def create_plan(
92
+ self,
93
+ title: str,
94
+ description: str,
95
+ steps: List[Dict[str, Any]],
96
+ estimated_files: Optional[List[str]] = None,
97
+ risks: Optional[List[str]] = None,
98
+ alternatives: Optional[List[str]] = None
99
+ ) -> Plan:
100
+ """
101
+ Create a new plan.
102
+
103
+ Args:
104
+ title: Plan title
105
+ description: Plan description
106
+ steps: List of step dictionaries with description and optional details
107
+ estimated_files: List of files that may be affected
108
+ risks: List of potential risks
109
+ alternatives: List of alternative approaches
110
+
111
+ Returns:
112
+ The created Plan
113
+ """
114
+ self._plan_counter += 1
115
+ plan_id = f"plan_{self._plan_counter}_{datetime.now().strftime('%Y%m%d_%H%M%S')}"
116
+
117
+ plan_steps = []
118
+ for i, step_data in enumerate(steps, 1):
119
+ step = PlanStep(
120
+ id=i,
121
+ description=step_data.get("description", ""),
122
+ details=step_data.get("details"),
123
+ files_affected=step_data.get("files", [])
124
+ )
125
+ plan_steps.append(step)
126
+
127
+ plan = Plan(
128
+ id=plan_id,
129
+ title=title,
130
+ description=description,
131
+ steps=plan_steps,
132
+ status=PlanStatus.PENDING_APPROVAL,
133
+ estimated_files=estimated_files or [],
134
+ risks=risks or [],
135
+ alternatives=alternatives or []
136
+ )
137
+
138
+ self._current_plan = plan
139
+ return plan
140
+
141
+ def approve_plan(self) -> bool:
142
+ """Approve the current plan for execution"""
143
+ if not self._current_plan:
144
+ return False
145
+
146
+ self._current_plan.status = PlanStatus.APPROVED
147
+ self._current_plan.approved_at = datetime.now()
148
+ return True
149
+
150
+ def reject_plan(self, feedback: Optional[str] = None) -> bool:
151
+ """Reject the current plan"""
152
+ if not self._current_plan:
153
+ return False
154
+
155
+ self._current_plan.status = PlanStatus.REJECTED
156
+ self._current_plan.user_feedback = feedback
157
+ self._plan_history.append(self._current_plan)
158
+ self._current_plan = None
159
+ return True
160
+
161
+ def start_execution(self) -> bool:
162
+ """Start executing the approved plan"""
163
+ if not self._current_plan or self._current_plan.status != PlanStatus.APPROVED:
164
+ return False
165
+
166
+ self._current_plan.status = PlanStatus.IN_PROGRESS
167
+ return True
168
+
169
+ def update_step(self, step_id: int, status: str, result: Optional[str] = None) -> bool:
170
+ """Update a step's status"""
171
+ if not self._current_plan:
172
+ return False
173
+
174
+ for step in self._current_plan.steps:
175
+ if step.id == step_id:
176
+ step.status = status
177
+ step.result = result
178
+ return True
179
+
180
+ return False
181
+
182
+ def complete_plan(self, success: bool = True) -> None:
183
+ """Mark the plan as complete"""
184
+ if not self._current_plan:
185
+ return
186
+
187
+ self._current_plan.status = PlanStatus.COMPLETED if success else PlanStatus.FAILED
188
+ self._current_plan.completed_at = datetime.now()
189
+ self._plan_history.append(self._current_plan)
190
+ self._current_plan = None
191
+ self._plan_mode_active = False
192
+
193
+ def get_plan_summary(self) -> Optional[str]:
194
+ """Get a formatted summary of the current plan"""
195
+ if not self._current_plan:
196
+ return None
197
+
198
+ plan = self._current_plan
199
+ lines = []
200
+
201
+ # Header
202
+ lines.append(f"\n\033[1m{plan.title}\033[0m")
203
+ lines.append(f"\033[90mStatus: {plan.status.value}\033[0m")
204
+ lines.append("")
205
+ lines.append(plan.description)
206
+ lines.append("")
207
+
208
+ # Steps
209
+ lines.append("\033[1mSteps:\033[0m")
210
+ for step in plan.steps:
211
+ status_icon = {
212
+ "pending": "○",
213
+ "in_progress": "◐",
214
+ "completed": "●",
215
+ "skipped": "○",
216
+ "failed": "✗"
217
+ }.get(step.status, "○")
218
+
219
+ lines.append(f" {status_icon} {step.id}. {step.description}")
220
+ if step.details:
221
+ lines.append(f" \033[90m{step.details}\033[0m")
222
+ if step.files_affected:
223
+ lines.append(f" \033[36mFiles: {', '.join(step.files_affected)}\033[0m")
224
+
225
+ lines.append("")
226
+
227
+ # Files
228
+ if plan.estimated_files:
229
+ lines.append("\033[1mFiles that may be affected:\033[0m")
230
+ for f in plan.estimated_files:
231
+ lines.append(f" • {f}")
232
+ lines.append("")
233
+
234
+ # Risks
235
+ if plan.risks:
236
+ lines.append("\033[1;33mPotential Risks:\033[0m")
237
+ for risk in plan.risks:
238
+ lines.append(f" ⚠ {risk}")
239
+ lines.append("")
240
+
241
+ # Alternatives
242
+ if plan.alternatives:
243
+ lines.append("\033[1mAlternative Approaches:\033[0m")
244
+ for alt in plan.alternatives:
245
+ lines.append(f" → {alt}")
246
+ lines.append("")
247
+
248
+ return "\n".join(lines)
249
+
250
+ def get_execution_prompt(self) -> Optional[str]:
251
+ """Get the prompt text for executing the plan"""
252
+ if not self._current_plan:
253
+ return None
254
+
255
+ steps_text = "\n".join([
256
+ f"{step.id}. {step.description}"
257
+ + (f"\n Details: {step.details}" if step.details else "")
258
+ for step in self._current_plan.steps
259
+ ])
260
+
261
+ return f"""Execute the following plan:
262
+
263
+ **{self._current_plan.title}**
264
+
265
+ {self._current_plan.description}
266
+
267
+ Steps to follow:
268
+ {steps_text}
269
+
270
+ Files that may be affected: {', '.join(self._current_plan.estimated_files) if self._current_plan.estimated_files else 'TBD based on steps'}
271
+
272
+ Please execute each step in order, updating progress as you go.
273
+ """
274
+
275
+ def get_plan_history(self, limit: int = 10) -> List[Dict[str, Any]]:
276
+ """Get recent plan history"""
277
+ return [
278
+ {
279
+ "id": plan.id,
280
+ "title": plan.title,
281
+ "status": plan.status.value,
282
+ "created": plan.created_at.isoformat(),
283
+ "steps_count": len(plan.steps)
284
+ }
285
+ for plan in self._plan_history[-limit:]
286
+ ]
287
+
288
+
289
+ # Global plan manager
290
+ _plan_manager: Optional[PlanManager] = None
291
+
292
+
293
+ def get_plan_manager() -> PlanManager:
294
+ """Get or create the global plan manager"""
295
+ global _plan_manager
296
+ if _plan_manager is None:
297
+ _plan_manager = PlanManager()
298
+ return _plan_manager
299
+
300
+
301
+ def generate_plan_from_task(task: str) -> Dict[str, Any]:
302
+ """
303
+ Generate a plan structure from a task description.
304
+
305
+ This is a template that would be filled in by the LLM.
306
+
307
+ Args:
308
+ task: The task description
309
+
310
+ Returns:
311
+ A plan structure dict
312
+ """
313
+ return {
314
+ "title": f"Plan: {task[:50]}{'...' if len(task) > 50 else ''}",
315
+ "description": f"Implementation plan for: {task}",
316
+ "steps": [],
317
+ "estimated_files": [],
318
+ "risks": [],
319
+ "alternatives": []
320
+ }
321
+
322
+
323
+ # Plan mode prompt template
324
+ PLAN_MODE_SYSTEM_PROMPT = """You are in PLAN MODE. Before making any changes, you must:
325
+
326
+ 1. **Analyze** the task thoroughly
327
+ 2. **Create a plan** with clear, numbered steps
328
+ 3. **Identify** files that will be affected
329
+ 4. **Consider** potential risks or issues
330
+ 5. **Present alternatives** if applicable
331
+
332
+ Format your plan as:
333
+
334
+ ## Plan: [Title]
335
+
336
+ ### Description
337
+ [Brief description of what this plan accomplishes]
338
+
339
+ ### Steps
340
+ 1. [First step]
341
+ 2. [Second step]
342
+ ...
343
+
344
+ ### Files Affected
345
+ - file1.py
346
+ - file2.ts
347
+
348
+ ### Potential Risks
349
+ - [Risk 1]
350
+ - [Risk 2]
351
+
352
+ ### Alternative Approaches
353
+ - [Alternative 1]
354
+ - [Alternative 2]
355
+
356
+ After presenting the plan, ask the user if they want to:
357
+ - **Approve** the plan and proceed with execution
358
+ - **Modify** the plan with their feedback
359
+ - **Reject** the plan and start over
360
+
361
+ Do NOT make any file changes until the plan is approved.
362
+ """
@@ -0,0 +1,17 @@
1
+ """
2
+ NC1709 Plugin System
3
+ Extensible plugin architecture for agents and tools
4
+ """
5
+
6
+ from .base import Plugin, PluginMetadata, PluginCapability, PluginStatus
7
+ from .registry import PluginRegistry
8
+ from .manager import PluginManager
9
+
10
+ __all__ = [
11
+ "Plugin",
12
+ "PluginMetadata",
13
+ "PluginCapability",
14
+ "PluginStatus",
15
+ "PluginRegistry",
16
+ "PluginManager"
17
+ ]
@@ -0,0 +1,18 @@
1
+ """
2
+ NC1709 Built-in Agents
3
+ Specialized plugins for common development tasks
4
+ """
5
+
6
+ from .git_agent import GitAgent
7
+ from .docker_agent import DockerAgent
8
+ from .fastapi_agent import FastAPIAgent
9
+ from .nextjs_agent import NextJSAgent
10
+ from .django_agent import DjangoAgent
11
+
12
+ __all__ = [
13
+ "GitAgent",
14
+ "DockerAgent",
15
+ "FastAPIAgent",
16
+ "NextJSAgent",
17
+ "DjangoAgent"
18
+ ]