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.
- monoco/core/config.py +35 -0
- monoco/core/integrations.py +0 -6
- monoco/core/sync.py +6 -19
- monoco/features/issue/commands.py +24 -16
- monoco/features/issue/core.py +90 -39
- monoco/features/issue/domain/models.py +1 -0
- monoco/features/issue/domain_commands.py +47 -0
- monoco/features/issue/domain_service.py +69 -0
- monoco/features/issue/linter.py +153 -50
- monoco/features/issue/resolver.py +177 -0
- monoco/features/issue/resources/en/AGENTS.md +6 -4
- monoco/features/issue/resources/zh/AGENTS.md +6 -4
- monoco/features/issue/test_priority_integration.py +102 -0
- monoco/features/issue/test_resolver.py +83 -0
- monoco/features/issue/validator.py +97 -21
- monoco/features/scheduler/__init__.py +19 -0
- monoco/features/scheduler/cli.py +285 -0
- monoco/features/scheduler/config.py +68 -0
- monoco/features/scheduler/defaults.py +54 -0
- monoco/features/scheduler/engines.py +149 -0
- monoco/features/scheduler/manager.py +49 -0
- monoco/features/scheduler/models.py +24 -0
- monoco/features/scheduler/reliability.py +106 -0
- monoco/features/scheduler/session.py +87 -0
- monoco/features/scheduler/worker.py +133 -0
- monoco/main.py +5 -0
- {monoco_toolkit-0.3.2.dist-info → monoco_toolkit-0.3.5.dist-info}/METADATA +37 -46
- {monoco_toolkit-0.3.2.dist-info → monoco_toolkit-0.3.5.dist-info}/RECORD +31 -21
- monoco/core/agent/__init__.py +0 -3
- monoco/core/agent/action.py +0 -168
- monoco/core/agent/adapters.py +0 -133
- monoco/core/agent/protocol.py +0 -32
- monoco/core/agent/state.py +0 -106
- {monoco_toolkit-0.3.2.dist-info → monoco_toolkit-0.3.5.dist-info}/WHEEL +0 -0
- {monoco_toolkit-0.3.2.dist-info → monoco_toolkit-0.3.5.dist-info}/entry_points.txt +0 -0
- {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.
|
|
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
|
-
>
|
|
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
|
-
## ⚡️
|
|
48
|
+
## ⚡️ The Gap: "Chat" is not Engineering.
|
|
48
49
|
|
|
49
|
-
|
|
50
|
+
Generating code is easy. **Engineering**—managing dependencies, maintaining state, validation, and version control—is hard.
|
|
50
51
|
|
|
51
|
-
|
|
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
|
-
|
|
54
|
+
## 🌟 Core Philosophy
|
|
54
55
|
|
|
55
|
-
|
|
56
|
+
### 1. Co-pilot by Design
|
|
56
57
|
|
|
57
|
-
|
|
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
|
-
|
|
61
|
+
### 2. Battle-Tested Best Practices
|
|
60
62
|
|
|
61
|
-
|
|
62
|
-
|
|
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
|
-
###
|
|
66
|
+
### 3. Radical Transparency (Dogfooding)
|
|
66
67
|
|
|
67
|
-
|
|
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
|
|
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
|
-
###
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
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=
|
|
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=
|
|
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=
|
|
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=
|
|
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=
|
|
50
|
-
monoco/features/issue/core.py,sha256=
|
|
51
|
-
monoco/features/issue/
|
|
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/
|
|
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=
|
|
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=
|
|
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=
|
|
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.
|
|
81
|
-
monoco_toolkit-0.3.
|
|
82
|
-
monoco_toolkit-0.3.
|
|
83
|
-
monoco_toolkit-0.3.
|
|
84
|
-
monoco_toolkit-0.3.
|
|
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,,
|
monoco/core/agent/__init__.py
DELETED
monoco/core/agent/action.py
DELETED
|
@@ -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
|
monoco/core/agent/adapters.py
DELETED
|
@@ -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]()
|
monoco/core/agent/protocol.py
DELETED
|
@@ -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
|
-
...
|
monoco/core/agent/state.py
DELETED
|
@@ -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
|