monoco-toolkit 0.3.2__py3-none-any.whl → 0.3.5__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 (36) hide show
  1. monoco/core/config.py +35 -0
  2. monoco/core/integrations.py +0 -6
  3. monoco/core/sync.py +6 -19
  4. monoco/features/issue/commands.py +24 -16
  5. monoco/features/issue/core.py +90 -39
  6. monoco/features/issue/domain/models.py +1 -0
  7. monoco/features/issue/domain_commands.py +47 -0
  8. monoco/features/issue/domain_service.py +69 -0
  9. monoco/features/issue/linter.py +153 -50
  10. monoco/features/issue/resolver.py +177 -0
  11. monoco/features/issue/resources/en/AGENTS.md +6 -4
  12. monoco/features/issue/resources/zh/AGENTS.md +6 -4
  13. monoco/features/issue/test_priority_integration.py +102 -0
  14. monoco/features/issue/test_resolver.py +83 -0
  15. monoco/features/issue/validator.py +97 -21
  16. monoco/features/scheduler/__init__.py +19 -0
  17. monoco/features/scheduler/cli.py +285 -0
  18. monoco/features/scheduler/config.py +68 -0
  19. monoco/features/scheduler/defaults.py +54 -0
  20. monoco/features/scheduler/engines.py +149 -0
  21. monoco/features/scheduler/manager.py +49 -0
  22. monoco/features/scheduler/models.py +24 -0
  23. monoco/features/scheduler/reliability.py +106 -0
  24. monoco/features/scheduler/session.py +87 -0
  25. monoco/features/scheduler/worker.py +133 -0
  26. monoco/main.py +5 -0
  27. {monoco_toolkit-0.3.2.dist-info → monoco_toolkit-0.3.5.dist-info}/METADATA +37 -46
  28. {monoco_toolkit-0.3.2.dist-info → monoco_toolkit-0.3.5.dist-info}/RECORD +31 -21
  29. monoco/core/agent/__init__.py +0 -3
  30. monoco/core/agent/action.py +0 -168
  31. monoco/core/agent/adapters.py +0 -133
  32. monoco/core/agent/protocol.py +0 -32
  33. monoco/core/agent/state.py +0 -106
  34. {monoco_toolkit-0.3.2.dist-info → monoco_toolkit-0.3.5.dist-info}/WHEEL +0 -0
  35. {monoco_toolkit-0.3.2.dist-info → monoco_toolkit-0.3.5.dist-info}/entry_points.txt +0 -0
  36. {monoco_toolkit-0.3.2.dist-info → monoco_toolkit-0.3.5.dist-info}/licenses/LICENSE +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: monoco-toolkit
3
- Version: 0.3.2
3
+ Version: 0.3.5
4
4
  Summary: Agent Native Toolkit for Monoco - Task Management & Kanban for AI Agents
5
5
  Project-URL: Homepage, https://monoco.io
6
6
  Project-URL: Repository, https://github.com/IndenScale/Monoco
@@ -40,45 +40,37 @@ Description-Content-Type: text/markdown
40
40
 
41
41
  > **The Operating System for Agentic Engineering.**
42
42
  >
43
- > Ground your AI Agents into deterministic workflows. Turn vague "chats" into structured, validatable, and shippable engineering units.
43
+ > Stop chatting. Start building.
44
+ > Monoco grounds your AI Agents into deterministic, validatable, and shippable engineering workflows.
44
45
 
45
46
  ---
46
47
 
47
- ## ⚡️ Why Monoco?
48
+ ## ⚡️ The Gap: "Chat" is not Engineering.
48
49
 
49
- In the era of LLMs, the bottleneck isn't **intelligence**—it's **control**.
50
+ Generating code is easy. **Engineering**—managing dependencies, maintaining state, validation, and version control—is hard.
50
51
 
51
- Generating code is easy. Managing the lifecycle of thousands of agent-generated tasks, validating their outputs, and maintaining a coherent project state is hard. **Monoco** is the missing control plane that bridges the gap between raw AI velocity and strict engineering rigor.
52
+ Most Agent workflows today are fragile "chats". Monoco turns them into **Software Engineering Processes**. It acts as the "BizOps" layer for your Agents, ensuring that every line of code generated is tracked, reviewed, and aligned with the project roadmap.
52
53
 
53
- Monoco handles the **"BizOps Logic"** of your development process, allowing you to orchestrate human and AI labor within a unified, version-controlled environment.
54
+ ## 🌟 Core Philosophy
54
55
 
55
- ## 🌟 Core Features
56
+ ### 1. Co-pilot by Design
56
57
 
57
- ### 1. Issue as Code (IaaC)
58
+ **Just-enough Automation.**
59
+ Monoco abstracts away the tedious details (Git ops, state tracking) while keeping you securely in the driver's seat. Agents can suggest and build, but **you** always have the final say on what gets merged.
58
60
 
59
- Treat your project management like your code.
61
+ ### 2. Battle-Tested Best Practices
60
62
 
61
- - **Markdown Native**: All tasks (Epics, Features, Chores) are stored as structured Markdown files in your repository.
62
- - **Git Backed**: Version control your roadmap. Review changes to requirements via Pull Requests.
63
- - **Universal Context**: Provides a standardized, hallucination-free state representation for AI Agents.
63
+ **Senior Engineer Intuition.**
64
+ Monoco enforces **Issue Driven Development (IDD)** and standard **Git Workflows**. We bake the rigorous habits of effective software teams into the Agent's core loop, ensuring every line of code is traceable and reviewed.
64
65
 
65
- ### 2. The Agent Cockpit (VS Code Extension)
66
+ ### 3. Radical Transparency (Dogfooding)
66
67
 
67
- Stop context switching. Manage your entire agentic workflow directly inside your editor.
68
-
69
- - **Native Kanban Board**: Visualize and drag-and-drop tasks without leaving VS Code.
70
- - **Hierarchical Tree View**: Drill down from high-level Epics to atomic Implementation Tasks.
71
- - **Agent Integration**: Bind specific Agent Providers (Gemini, Claude, etc.) to specific tasks.
72
-
73
- ### 3. Traceable Execution
74
-
75
- - **Deterministic State Machine**: Every task follows a strict lifecycle (Proposed -> Approved -> Doing -> Review -> Done).
76
- - **Audit Trails**: Agents log their actions and decisions directly into the task file.
77
- - **Sanity Checks**: Built-in linters ensure your task definitions are complete and valid before execution.
68
+ **Process as Product.**
69
+ Monoco is built by Monoco. We believe in open-sourcing not just the code, but the engineering process itself. Every design decision, interaction log, and failure is public—providing a live blueprint for Agentic Engineering.
78
70
 
79
71
  ## 🚀 Quick Start
80
72
 
81
- ### Installation
73
+ ### 1. Installation
82
74
 
83
75
  Monoco is available as a Python CLI tool.
84
76
 
@@ -86,33 +78,32 @@ Monoco is available as a Python CLI tool.
86
78
  pip install monoco-toolkit
87
79
  ```
88
80
 
89
- ### Initialization
81
+ ### 2. Workspace Initialization
90
82
 
91
- Turn any directory into a Monoco workspace.
83
+ Turn any directory into a Monoco Workspace. This creates the `.monoco` config and the `Issues/` directory.
92
84
 
93
85
  ```bash
94
86
  monoco init
95
87
  ```
96
88
 
97
- ### Workflow
98
-
99
- 1. **Plan**: Create a new feature request.
100
- ```bash
101
- monoco issue create feature -t "Implement Dark Mode"
102
- ```
103
- 2. **Start**: Create a feature branch automatically.
104
- ```bash
105
- monoco issue start FEAT-001 --branch
106
- ```
107
- 3. **Code & Sync**: Track modified files automatically.
108
- ```bash
109
- monoco issue sync-files
110
- ```
111
- 4. **Visualize**: Open the board in VS Code or via CLI.
112
- ```bash
113
- # Starts the local server
114
- monoco serve
115
- ```
89
+ ### 3. Agent Synchronization
90
+
91
+ **Crucial Step**: This injects the "Monoco System Neural Network" (System Prompts & Skills) into your agent configuration files (e.g., `GEMINI.md`, `CLAUDE.md`).
92
+
93
+ ```bash
94
+ monoco sync
95
+ ```
96
+
97
+ ### 4. The Engineering Loop (Agent-First)
98
+
99
+ In Monoco, you don't need to memorize CLI commands. **The Agent is your DevOps Engineer.**
100
+
101
+ 1. **Chat**: Tell your Agent in the chatbox (e.g., _"Implement Dark Mode"_).
102
+ 2. **Plan**: The Agent investigates and proposes an **Issue Ticket** for your review.
103
+ 3. **Build**: Once approved, the Agent creates a branch, writes code, and submits changes.
104
+ 4. **Ship**: You accept the results. The Agent handles the merge and closure.
105
+
106
+ ---
116
107
 
117
108
  ## 📦 Extension for VS Code
118
109
 
@@ -1,29 +1,24 @@
1
- monoco/main.py,sha256=_ZhokFhmYF1NNHubuVr9gZ_HLg6AaZPWMppnUESbpwA,5346
1
+ monoco/main.py,sha256=MscjwDCOT2DfZKpZMEZEn-M1INmqu4-4R200GEiBwrc,5562
2
2
  monoco/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
3
  monoco/cli/project.py,sha256=FqLaDD3hiWxa0_TKzxEF7PYH9RPsvmLyjO3NYVckgGs,2737
4
4
  monoco/cli/workspace.py,sha256=1TVVS835XyirLDvBGQXSblIaYVhe2Pk9EpORDvcktyk,1538
5
5
  monoco/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
- monoco/core/config.py,sha256=DsxkUaHbKK17JuMzcYLVBWnLhhs78HC_gday2fyx6sw,12250
6
+ monoco/core/config.py,sha256=M9F5De2FUgaIxFwqZBoJUXsMsph31rNh-4U-k_9rUHA,13543
7
7
  monoco/core/execution.py,sha256=7522s7uVWiNdMKtWlIb8JHzbAcJgLVuxUFp_6VmhWNQ,1801
8
8
  monoco/core/feature.py,sha256=bcK0C1CaQgNLcdMF0RuniaaQRCYSA-0JdOpQz9W_1xM,1968
9
9
  monoco/core/git.py,sha256=d3A8L30nlEj0F1pwSHk_cOoRYi1dMCiZc7KD70ViMyw,8335
10
10
  monoco/core/hooks.py,sha256=QY4c74LIYDtcjtWYax1PrK5CtVNKYTfVVVBOj-SCulo,1826
11
11
  monoco/core/injection.py,sha256=zs9RpXaBfwP-fbwOU_X2nm-AH94tQN9tVWXNtV4tCYM,6887
12
- monoco/core/integrations.py,sha256=GOWwDceEuhU6Q1nX8vvyGQ7s_kzuW0lKK23nEFkzCT0,7912
12
+ monoco/core/integrations.py,sha256=ifSz7I87DXHF-eHLyXRN3pY1-Kh8IjvMyIrG9iogGpw,7744
13
13
  monoco/core/lsp.py,sha256=GOrHzubkMWS3iBpP4H2fTFW-0JXa6D2YlU0ZEhp5zmY,2018
14
14
  monoco/core/output.py,sha256=ZlUydZ65FIP5a32_eESIIvMrhcSwghIqZ3N23OSx6Ss,3878
15
15
  monoco/core/registry.py,sha256=1m9wvkcqWqrTcARt-jUGHH1BEYMvp0NJGRkq-uduJeg,1167
16
16
  monoco/core/setup.py,sha256=YUIhzqZwjEeH7zGZm9SPA-OhgTISJtA6ByNFCGBznUU,11487
17
17
  monoco/core/skills.py,sha256=KeVN09KIcRiksjJ91AggJbN_EvjRQfMGqd_hUQfUjes,16168
18
18
  monoco/core/state.py,sha256=dfoTH1Sj_TSjtTEXuv4w0ZOp_Fd30XNymVSZo30Xshg,1820
19
- monoco/core/sync.py,sha256=DJXnWM_LxN36VniTUS5axFiAhVXYHbxLbI1uaUvV1JU,8750
19
+ monoco/core/sync.py,sha256=1p37pTfGBanogzcLhdTfMTxDqq79B5iiwiPS4fiuQaA,8378
20
20
  monoco/core/telemetry.py,sha256=GQDbtgrZwAL1ZpjgbJZuawbTyH6J0NjMXMi4ogq-Ang,2915
21
21
  monoco/core/workspace.py,sha256=H_PHD5A0HZFq841u1JtLoFjkXdQg9D6x6I7QcFtJge4,3000
22
- monoco/core/agent/__init__.py,sha256=iU3wac9iYecA1M2jaYnnPjU9wANdAS7B-jRAuT5gCo4,38
23
- monoco/core/agent/action.py,sha256=qkQGJERhL4N5MSuwDivn8NAw4sMhEa346huGtqNyFTM,5295
24
- monoco/core/agent/adapters.py,sha256=q6obVcXve46mVNBaSCBRFRYs8gImv6Y2gAJVv173Z6w,4376
25
- monoco/core/agent/protocol.py,sha256=eB0OiMjDQu1DOoeVqb_PpHsMyPy2LdNenNyt4vJ9qbQ,798
26
- monoco/core/agent/state.py,sha256=Z8qqY7loms5nt3524_TrEMmlpnurxf0aHfiCT1FgvDI,3385
27
22
  monoco/core/resources/en/AGENTS.md,sha256=vf9z43UU-LPwYKPWCrtw8TpWrmkeZ6zfMyHP4Q9JqdQ,1178
28
23
  monoco/core/resources/en/SKILL.md,sha256=wBXNpPqATOxO8TGiOM8S091gMNZ8du_WhQubO6TfNyg,3504
29
24
  monoco/core/resources/zh/AGENTS.md,sha256=KBNZSCPBIals6jDdvG5wJgjZuswi_1nKljggJSMtfy8,1156
@@ -46,16 +41,21 @@ monoco/features/i18n/resources/en/SKILL.md,sha256=Z8fAAqeMvpLDw1D_9AzZIykS5-HLVM
46
41
  monoco/features/i18n/resources/zh/AGENTS.md,sha256=lKkwLLCADRH7UDq9no4eQY2sRfJrb64JoZ_HNved8vA,175
47
42
  monoco/features/i18n/resources/zh/SKILL.md,sha256=Wynk7zVBW7CO0_6AEQNUvlD_3eMW_7EPnzEn9QUaiDs,1884
48
43
  monoco/features/issue/adapter.py,sha256=4dzKg4-0XH63uORoh8qcolvKxJR6McBDIYxYEcZJJkA,1204
49
- monoco/features/issue/commands.py,sha256=ndBE_3tP4CZK45lqAbsGpeopzvebMZKeIezZchTGIsc,37353
50
- monoco/features/issue/core.py,sha256=WoWZRpw7o9f6ERqqIgD35c-SYD7Jv1aTsJVj6ljPz9E,50369
51
- monoco/features/issue/linter.py,sha256=DQ3UruGUUMZu63EFn71eczoFDoqj31JxHHaRR3Ej6O8,21067
44
+ monoco/features/issue/commands.py,sha256=vaScb2J4qjUvO8DSlKhTrGDSfIyJ4zIUr14jhBlG6tE,37581
45
+ monoco/features/issue/core.py,sha256=kRyUbYqEBno0Zoogq7dMIcQv5M0QIRSlptvzp0pfImE,51302
46
+ monoco/features/issue/domain_commands.py,sha256=eatSF_uZp4nGpVr2PIgb00MWfEBm0OnyAd4JvUJEAAA,1535
47
+ monoco/features/issue/domain_service.py,sha256=bEs_WXOWmotgIR-lGwyWekF4nonvjsgrK1YG3pyVfwk,2564
48
+ monoco/features/issue/linter.py,sha256=LLtJEVIzoGTNm1liZARJHM3-V-EODkGRuw3ExCZtEjY,26115
52
49
  monoco/features/issue/migration.py,sha256=i0xlxZjrpmuHGHOAIN4iu31EwwVIvZn7yjveS-kU22c,4896
53
50
  monoco/features/issue/models.py,sha256=7oIMxvUEfe00n7wni9bZgKU2e9404flvArixbLQ95Dg,5902
54
51
  monoco/features/issue/monitor.py,sha256=vZN0TbR3V5fHKHRGkIhimO6UwWcwYjDHQs2qzjEG174,3549
55
- monoco/features/issue/validator.py,sha256=Rbn5M_RLEHVPi5n0Y19-VCWZvVlRWcCRFYRbsw-Oc-I,24732
52
+ monoco/features/issue/resolver.py,sha256=mAU9s7TNNHY9A2278JTwJvxU-jalGKTDJfJdjONev3E,5655
53
+ monoco/features/issue/test_priority_integration.py,sha256=Kq3XMQYkQK62R-a_lmAeEpGlZr4nRBbG6WAyW430el8,2763
54
+ monoco/features/issue/test_resolver.py,sha256=luFhK37DUvh4a3TTcFYVO-oOIJljQVCSYicwSWyDleQ,2530
55
+ monoco/features/issue/validator.py,sha256=GYqbx2-ZxXfk1HicgBXkpL__v83KK-jcOyo7eW-VRUs,27793
56
56
  monoco/features/issue/domain/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
57
57
  monoco/features/issue/domain/lifecycle.py,sha256=oIuLYTVy1RRHGngAzbNU4kTWOHMBhjuw_TuYCwNqMJw,4991
58
- monoco/features/issue/domain/models.py,sha256=eo5Ks7VzWDQsqzuu9gcBuxIafvfqnzUDNDG9wbaghsc,5797
58
+ monoco/features/issue/domain/models.py,sha256=2vuSAGaFrbAEkQapwkGG_T8cHlsmARN71fTA44PIVSM,5850
59
59
  monoco/features/issue/domain/parser.py,sha256=axfB9BjY-m4DQqYwTQBm_38plOidZaDqFtsIejW_kYI,9095
60
60
  monoco/features/issue/domain/workspace.py,sha256=nyTEFNmpLPuX7nssMCBiFI1XBhY9zbqG877Ppp_s0Fg,3658
61
61
  monoco/features/issue/engine/__init__.py,sha256=-SBvzjlZJz0O-IB1c95d9pbhr3lydJNLq2vhnfkZ8PQ,747
@@ -64,10 +64,20 @@ monoco/features/issue/engine/machine.py,sha256=Bun_5jHlFRA7Duy7zG8f1GZIbZlPKt6C7
64
64
  monoco/features/issue/engine/models.py,sha256=595Sx3ncrpg_PhnbBLthohAvuhnjA-_9oXcrsT6Lv0k,574
65
65
  monoco/features/issue/lsp/__init__.py,sha256=8bl8-WzSj3C4SkPKgVGnCeyemmvHVWBsuMZsJuJggG8,77
66
66
  monoco/features/issue/lsp/definition.py,sha256=cF6Quw1OztuKMJ1zLvgA_ek7lTAdzHF0m4LVznpbAPw,3203
67
- monoco/features/issue/resources/en/AGENTS.md,sha256=7lMJdLhokispHVTrViIyMaz5TOJ88GkPKfWZp4FlgRQ,1015
67
+ monoco/features/issue/resources/en/AGENTS.md,sha256=eHHXjLRDAV7IKrYPQSilxu0X5D0SBCAFBXmlSoc9r48,1278
68
68
  monoco/features/issue/resources/en/SKILL.md,sha256=M5khTJdraQenX0tf7RHOVcqyKHC285qwDzWdsCJ7XPI,4032
69
- monoco/features/issue/resources/zh/AGENTS.md,sha256=veb22lU0qindYcsNsuGLqzpBEjExCPDOkX5Q39OjZz0,1113
69
+ monoco/features/issue/resources/zh/AGENTS.md,sha256=oRHHqeDYx6aEc5FfdL7a-zqT7uh4SYIYt8QBRKEKrYM,1351
70
70
  monoco/features/issue/resources/zh/SKILL.md,sha256=XFE33cCCos0U1IVNkMhU7fGuqVqfxo_FNKdp1aScaoM,5055
71
+ monoco/features/scheduler/__init__.py,sha256=hvE9A14qFTeTYbWlK9iMRdXIFLMBuG8724GEZzFTHB8,483
72
+ monoco/features/scheduler/cli.py,sha256=NgsGwCf615YA4VGd-mqMpGp5VCjdMUqoZqiHZFnDdLU,8325
73
+ monoco/features/scheduler/config.py,sha256=69PTvKGHJ33fA2yhFJAq0WVq70Zbmdd5X8Wl0vIYAak,2336
74
+ monoco/features/scheduler/defaults.py,sha256=4Ne3RpF7gZ46BmHtF0hC8wYkuCIkDSuKB7hGnHhGXms,2208
75
+ monoco/features/scheduler/engines.py,sha256=ICKw4Kfme6UNl_JLJvT7hADKHo76Yr8wpFFEvtEV6z4,3799
76
+ monoco/features/scheduler/manager.py,sha256=PmNKqfktgrdpUwE-jPE_WX3IvzZat0JKdEcmzse08-0,1680
77
+ monoco/features/scheduler/models.py,sha256=rb8rx8t_TD5ilUC6xU3jvK0sud7YUZE_iEdes9Np8R0,877
78
+ monoco/features/scheduler/reliability.py,sha256=zVwtnksug5wr0_tigC2Qjl_C8VNyrheN_34ItUceGoo,3846
79
+ monoco/features/scheduler/session.py,sha256=V1xFXA65BaERhBwRYIecaye2TjDtFvAzuIy2gZ68ag8,2954
80
+ monoco/features/scheduler/worker.py,sha256=4OU2Y7nG5EKadNIKDF5GWl5V7vgVl3OPlYHShfiEeBI,4538
71
81
  monoco/features/skills/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
72
82
  monoco/features/skills/core.py,sha256=BXVvMot8E457-pj9U19lPHypBVhdLQRsx0zEAXJxpGY,3436
73
83
  monoco/features/spike/adapter.py,sha256=ZIpw-xNVoA2IIP18dbR-dmQGbQmK5ua_P-uGXuDjCeI,1021
@@ -77,8 +87,8 @@ monoco/features/spike/resources/en/AGENTS.md,sha256=NG3CMnlDk_0J8hnRUcueAM9lgIQr
77
87
  monoco/features/spike/resources/en/SKILL.md,sha256=qKDcVh0D3pDRvfNLh1Bzo4oQU3obpl4tqdlzxeiWYMk,1911
78
88
  monoco/features/spike/resources/zh/AGENTS.md,sha256=5RHNl7fc3RdYYTFH483ojJl_arGPKkyYziOuGgFbqqg,290
79
89
  monoco/features/spike/resources/zh/SKILL.md,sha256=Q82e9lCQOAYIwBs5rGnvlVUDq7bp0pz8yvO10KTWFYQ,1710
80
- monoco_toolkit-0.3.2.dist-info/METADATA,sha256=9Xyk-ImLkR4WvBAz6eQb8_N-QZiJ7TPu27P3u48Y35c,4866
81
- monoco_toolkit-0.3.2.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
82
- monoco_toolkit-0.3.2.dist-info/entry_points.txt,sha256=iYj7FWYBdtClU15-Du1skqD0s6SFSIhJvxJ29VWp8ng,43
83
- monoco_toolkit-0.3.2.dist-info/licenses/LICENSE,sha256=ACAGGjV6aod4eIlVUTx1q9PZbnZGN5bBwkSs9RHj83s,1071
84
- monoco_toolkit-0.3.2.dist-info/RECORD,,
90
+ monoco_toolkit-0.3.5.dist-info/METADATA,sha256=UD0y77LYaDLy3ZoMUphV87XScSEg8G3kGxld1DhD8Wk,4732
91
+ monoco_toolkit-0.3.5.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
92
+ monoco_toolkit-0.3.5.dist-info/entry_points.txt,sha256=iYj7FWYBdtClU15-Du1skqD0s6SFSIhJvxJ29VWp8ng,43
93
+ monoco_toolkit-0.3.5.dist-info/licenses/LICENSE,sha256=ACAGGjV6aod4eIlVUTx1q9PZbnZGN5bBwkSs9RHj83s,1071
94
+ monoco_toolkit-0.3.5.dist-info/RECORD,,
@@ -1,3 +0,0 @@
1
- """
2
- Monoco Agent Execution Layer.
3
- """
@@ -1,168 +0,0 @@
1
- import re
2
- import yaml
3
- from pathlib import Path
4
- from typing import Dict, List, Optional, Any
5
- from pydantic import BaseModel
6
-
7
-
8
- class ActionContext(BaseModel):
9
- """Context information for matching actions."""
10
-
11
- id: Optional[str] = None
12
- type: Optional[str] = None
13
- stage: Optional[str] = None
14
- status: Optional[str] = None
15
- file_path: Optional[str] = None
16
- project_id: Optional[str] = None
17
-
18
-
19
- class ActionWhen(BaseModel):
20
- """Conditions under which an action should be displayed/active."""
21
-
22
- idMatch: Optional[str] = None
23
- typeMatch: Optional[str] = None
24
- stageMatch: Optional[str] = None
25
- statusMatch: Optional[str] = None
26
- fileMatch: Optional[str] = None
27
-
28
- def matches(self, context: ActionContext) -> bool:
29
- """Evaluate if the context matches these criteria."""
30
- if self.idMatch and context.id and not re.match(self.idMatch, context.id):
31
- return False
32
- if (
33
- self.typeMatch
34
- and context.type
35
- and not re.match(self.typeMatch, context.type)
36
- ):
37
- return False
38
- if (
39
- self.stageMatch
40
- and context.stage
41
- and not re.match(self.stageMatch, context.stage)
42
- ):
43
- return False
44
- if (
45
- self.statusMatch
46
- and context.status
47
- and not re.match(self.statusMatch, context.status)
48
- ):
49
- return False
50
- if (
51
- self.fileMatch
52
- and context.file_path
53
- and not re.match(self.fileMatch, context.file_path)
54
- ):
55
- return False
56
- return True
57
-
58
-
59
- class PromptyAction(BaseModel):
60
- name: str
61
- description: str
62
- version: Optional[str] = "1.0.0"
63
- authors: List[str] = []
64
- model: Dict[str, Any] = {}
65
- inputs: Dict[str, Any] = {}
66
- outputs: Dict[str, Any] = {}
67
- template: str
68
- when: Optional[ActionWhen] = None
69
-
70
- # Monoco specific metadata
71
- path: Optional[str] = None
72
- provider: Optional[str] = None # Derived from model.api or explicitly set
73
-
74
-
75
- class ActionRegistry:
76
- def __init__(self, project_root: Optional[Path] = None):
77
- self.project_root = project_root
78
- self._actions: List[PromptyAction] = []
79
-
80
- def scan(self) -> List[PromptyAction]:
81
- """Scan user global and project local directories for .prompty files."""
82
- self._actions = []
83
-
84
- # 1. User Global: ~/.monoco/actions/
85
- user_dir = Path.home() / ".monoco" / "actions"
86
- self._scan_dir(user_dir)
87
-
88
- # 2. Project Local: {project_root}/.monoco/actions/
89
- if self.project_root:
90
- project_dir = self.project_root / ".monoco" / "actions"
91
- self._scan_dir(project_dir)
92
-
93
- return self._actions
94
-
95
- def _scan_dir(self, directory: Path):
96
- if not directory.exists():
97
- return
98
-
99
- for prompty_file in directory.glob("*.prompty"):
100
- try:
101
- action = self._load_action(prompty_file)
102
- if action:
103
- self._actions.append(action)
104
- except Exception as e:
105
- print(f"Failed to load action {prompty_file}: {e}")
106
-
107
- def _load_action(self, file_path: Path) -> Optional[PromptyAction]:
108
- content = file_path.read_text(encoding="utf-8")
109
-
110
- # Prompty Parser (Standard YAML Frontmatter + Body)
111
- # We look for the first --- and the second ---
112
- parts = re.split(r"^---\s*$", content, maxsplit=2, flags=re.MULTILINE)
113
-
114
- if len(parts) < 3:
115
- return None
116
-
117
- frontmatter_raw = parts[1]
118
- body = parts[2].strip()
119
-
120
- try:
121
- meta = yaml.safe_load(frontmatter_raw)
122
- if not meta or "name" not in meta:
123
- # Use filename as fallback name if missing? Prompty usually requires name.
124
- if not meta:
125
- meta = {}
126
- meta["name"] = meta.get("name", file_path.stem)
127
-
128
- # Map Prompty 'when' if present
129
- when_data = meta.get("when")
130
- when = ActionWhen(**when_data) if when_data else None
131
-
132
- action = PromptyAction(
133
- name=meta["name"],
134
- description=meta.get("description", ""),
135
- version=meta.get("version"),
136
- authors=meta.get("authors", []),
137
- model=meta.get("model", {}),
138
- inputs=meta.get("inputs", {}),
139
- outputs=meta.get("outputs", {}),
140
- template=body,
141
- when=when,
142
- path=str(file_path.absolute()),
143
- provider=meta.get("provider") or meta.get("model", {}).get("api"),
144
- )
145
- return action
146
-
147
- except Exception as e:
148
- print(f"Invalid Prompty in {file_path}: {e}")
149
- return None
150
-
151
- def list_available(
152
- self, context: Optional[ActionContext] = None
153
- ) -> List[PromptyAction]:
154
- if not self._actions:
155
- self.scan()
156
-
157
- if not context:
158
- return self._actions
159
-
160
- return [a for a in self._actions if not a.when or a.when.matches(context)]
161
-
162
- def get(self, name: str) -> Optional[PromptyAction]:
163
- if not self._actions:
164
- self.scan()
165
- for a in self._actions:
166
- if a.name == name:
167
- return a
168
- return None
@@ -1,133 +0,0 @@
1
- """
2
- CLI Adapters for Agent Frameworks.
3
- """
4
-
5
- import shutil
6
- from typing import List
7
- from pathlib import Path
8
- from .protocol import AgentClient
9
-
10
-
11
- class BaseCLIClient:
12
- def __init__(self, executable: str):
13
- self._executable = executable
14
-
15
- @property
16
- def name(self) -> str:
17
- return self._executable
18
-
19
- async def available(self) -> bool:
20
- return shutil.which(self._executable) is not None
21
-
22
- def _build_prompt(self, prompt: str, context_files: List[Path]) -> str:
23
- """Concatenate prompt and context files."""
24
- # Inject Language Rule
25
- try:
26
- from monoco.core.config import get_config
27
-
28
- settings = get_config()
29
- lang = settings.i18n.source_lang
30
- if lang:
31
- prompt = f"{prompt}\n\n[SYSTEM: LANGUAGE CONSTRAINT]\nThe project source language is '{lang}'. You MUST use '{lang}' for all thinking and reporting unless explicitly instructed otherwise."
32
- except Exception:
33
- pass
34
-
35
- full_prompt = [prompt]
36
- if context_files:
37
- full_prompt.append("\n\n--- CONTEXT FILES ---")
38
- for file_path in context_files:
39
- try:
40
- full_prompt.append(f"\nFile: {file_path}")
41
- full_prompt.append("```")
42
- # Read file content safely
43
- full_prompt.append(
44
- file_path.read_text(encoding="utf-8", errors="replace")
45
- )
46
- full_prompt.append("```")
47
- except Exception as e:
48
- full_prompt.append(f"Error reading {file_path}: {e}")
49
- full_prompt.append("--- END CONTEXT ---\n")
50
- return "\n".join(full_prompt)
51
-
52
- async def _run_command(self, args: List[str]) -> str:
53
- """Run the CLI command and return stdout."""
54
- # Using synchronous subprocess in async function for now
55
- # Ideally this should use asyncio.create_subprocess_exec
56
- import asyncio
57
-
58
- proc = await asyncio.create_subprocess_exec(
59
- *args, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE
60
- )
61
-
62
- stdout, stderr = await proc.communicate()
63
-
64
- if proc.returncode != 0:
65
- error_msg = stderr.decode().strip()
66
- raise RuntimeError(
67
- f"Agent CLI failed (code {proc.returncode}): {error_msg}"
68
- )
69
-
70
- return stdout.decode().strip()
71
-
72
-
73
- class GeminiClient(BaseCLIClient, AgentClient):
74
- """Adapter for Google Gemini CLI."""
75
-
76
- def __init__(self):
77
- super().__init__("gemini")
78
-
79
- async def execute(self, prompt: str, context_files: List[Path] = []) -> str:
80
- full_prompt = self._build_prompt(prompt, context_files)
81
- # Usage: gemini "prompt"
82
- return await self._run_command([self._executable, full_prompt])
83
-
84
-
85
- class ClaudeClient(BaseCLIClient, AgentClient):
86
- """Adapter for Anthropic Claude CLI."""
87
-
88
- def __init__(self):
89
- super().__init__("claude")
90
-
91
- async def execute(self, prompt: str, context_files: List[Path] = []) -> str:
92
- full_prompt = self._build_prompt(prompt, context_files)
93
- # Usage: claude -p "prompt"
94
- return await self._run_command([self._executable, "-p", full_prompt])
95
-
96
-
97
- class QwenClient(BaseCLIClient, AgentClient):
98
- """Adapter for Alibaba Qwen CLI."""
99
-
100
- def __init__(self):
101
- super().__init__("qwen")
102
-
103
- async def execute(self, prompt: str, context_files: List[Path] = []) -> str:
104
- full_prompt = self._build_prompt(prompt, context_files)
105
- # Usage: qwen "prompt"
106
- return await self._run_command([self._executable, full_prompt])
107
-
108
-
109
- class KimiClient(BaseCLIClient, AgentClient):
110
- """Adapter for Moonshot Kimi CLI."""
111
-
112
- def __init__(self):
113
- super().__init__("kimi")
114
-
115
- async def execute(self, prompt: str, context_files: List[Path] = []) -> str:
116
- full_prompt = self._build_prompt(prompt, context_files)
117
- # Usage: kimi "prompt"
118
- return await self._run_command([self._executable, full_prompt])
119
-
120
-
121
- _ADAPTERS = {
122
- "gemini": GeminiClient,
123
- "claude": ClaudeClient,
124
- "qwen": QwenClient,
125
- "kimi": KimiClient,
126
- }
127
-
128
-
129
- def get_agent_client(name: str) -> AgentClient:
130
- """Factory to get agent client by name."""
131
- if name not in _ADAPTERS:
132
- raise ValueError(f"Unknown agent provider: {name}")
133
- return _ADAPTERS[name]()
@@ -1,32 +0,0 @@
1
- """
2
- Protocol definition for Agent Clients.
3
- """
4
-
5
- from typing import Protocol, List
6
- from pathlib import Path
7
-
8
-
9
- class AgentClient(Protocol):
10
- """Protocol for interacting with CLI-based agents."""
11
-
12
- @property
13
- def name(self) -> str:
14
- """Name of the agent provider (e.g. 'gemini', 'claude')."""
15
- ...
16
-
17
- async def available(self) -> bool:
18
- """Check if the agent is available in the current environment."""
19
- ...
20
-
21
- async def execute(self, prompt: str, context_files: List[Path] = []) -> str:
22
- """
23
- Execute a prompt against the agent.
24
-
25
- Args:
26
- prompt: The main instructions.
27
- context_files: List of files to provide as context.
28
-
29
- Returns:
30
- The raw string response from the agent.
31
- """
32
- ...
@@ -1,106 +0,0 @@
1
- """
2
- Agent State Management.
3
-
4
- Handles persistence and retrieval of agent availability state.
5
- """
6
-
7
- import yaml
8
- import logging
9
- from pathlib import Path
10
- from datetime import datetime, timezone
11
- from typing import Dict, Optional
12
- from pydantic import BaseModel
13
-
14
- logger = logging.getLogger("monoco.core.agent.state")
15
-
16
-
17
- class AgentProviderState(BaseModel):
18
- available: bool
19
- path: Optional[str] = None
20
- error: Optional[str] = None
21
- latency_ms: Optional[int] = None
22
-
23
-
24
- class AgentState(BaseModel):
25
- last_checked: datetime
26
- providers: Dict[str, AgentProviderState]
27
-
28
- @property
29
- def is_stale(self) -> bool:
30
- """Check if the state is older than 7 days."""
31
- delta = datetime.now(timezone.utc) - self.last_checked
32
- return delta.days > 7
33
-
34
-
35
- class AgentStateManager:
36
- def __init__(self, state_path: Path = Path.home() / ".monoco" / "agent_state.yaml"):
37
- self.state_path = state_path
38
- self._state: Optional[AgentState] = None
39
-
40
- def load(self) -> Optional[AgentState]:
41
- """Load state from file, returning None if missing or invalid."""
42
- if not self.state_path.exists():
43
- return None
44
-
45
- try:
46
- with open(self.state_path, "r") as f:
47
- data = yaml.safe_load(f)
48
- if not data:
49
- return None
50
- # Handle ISO string to datetime conversion if needed provided by Pydantic mostly
51
- return AgentState(**data)
52
- except Exception as e:
53
- logger.warning(f"Failed to load agent state: {e}")
54
- return None
55
-
56
- def get_or_refresh(self, force: bool = False) -> AgentState:
57
- """Get current state, refreshing if missing, stale, or forced."""
58
- if not force:
59
- self._state = self.load()
60
- if self._state and not self._state.is_stale:
61
- return self._state
62
-
63
- return self.refresh()
64
-
65
- def refresh(self) -> AgentState:
66
- """Run diagnostics on all integrations and update state."""
67
- logger.info("Refreshing agent state...")
68
-
69
- from monoco.core.integrations import get_all_integrations
70
- from monoco.core.config import get_config
71
-
72
- # Load config to get possible overrides
73
- # Determine root (hacky for now, should be passed)
74
- root = Path.cwd()
75
- config = get_config(str(root))
76
-
77
- integrations = get_all_integrations(
78
- config_overrides=config.agent.integrations, enabled_only=True
79
- )
80
-
81
- providers = {}
82
- for key, integration in integrations.items():
83
- if not integration.bin_name:
84
- continue # Skip integrations that don't have a binary component
85
-
86
- health = integration.check_health()
87
- providers[key] = AgentProviderState(
88
- available=health.available,
89
- path=health.path,
90
- error=health.error,
91
- latency_ms=health.latency_ms,
92
- )
93
-
94
- state = AgentState(last_checked=datetime.now(timezone.utc), providers=providers)
95
-
96
- # Save state
97
- self.state_path.parent.mkdir(parents=True, exist_ok=True)
98
- with open(self.state_path, "w") as f:
99
- yaml.dump(state.model_dump(mode="json"), f)
100
-
101
- self._state = state
102
- return state
103
-
104
- def _find_script(self) -> Optional[Path]:
105
- """[Deprecated] No longer used."""
106
- return None