raggiecode 0.2.1__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.
- Agent/__init__.py +0 -0
- Agent/agent.py +891 -0
- Agent/chat_history_db.py +1500 -0
- Agent/command.py +49 -0
- Agent/config.py +46 -0
- Agent/effort_levels.py +33 -0
- Agent/git_manager.py +727 -0
- Agent/tools.py +35 -0
- Commands/__init__.py +18 -0
- Commands/effort.py +42 -0
- Commands/global_todo.py +23 -0
- Commands/help.py +22 -0
- Commands/reasoning.py +24 -0
- Commands/redo.py +11 -0
- Commands/reindex.py +27 -0
- Commands/shell.py +28 -0
- Commands/stream.py +24 -0
- Commands/undo.py +13 -0
- Commands/unlimited_effort.py +8 -0
- Commands/window_size.py +29 -0
- RAG/__init__.py +0 -0
- RAG/document.py +119 -0
- RAG/find.py +408 -0
- RAG/graph.py +231 -0
- Tools/GetFileCodeStructure.py +43 -0
- Tools/GetSymbolSourceCode.py +27 -0
- Tools/__init__.py +39 -0
- Tools/ask_user.py +102 -0
- Tools/dispatch_subagent.py +215 -0
- Tools/document.py +35 -0
- Tools/edit_symbol.py +250 -0
- Tools/fuzzy_search.py +119 -0
- Tools/list_dir.py +51 -0
- Tools/read.py +49 -0
- Tools/read_image.py +75 -0
- Tools/remove.py +75 -0
- Tools/replace.py +305 -0
- Tools/search.py +41 -0
- Tools/shell.py +149 -0
- Tools/shell_kill.py +87 -0
- Tools/temp_background_service.py +113 -0
- Tools/todo_list.py +481 -0
- Tools/utils.py +116 -0
- Tools/view_changes.py +179 -0
- Tools/walk_call_tree.py +30 -0
- Tools/web_fetch.py +175 -0
- Tools/web_search.py +69 -0
- Tools/write.py +48 -0
- cli.py +111 -0
- config/__init__.py +0 -0
- config/coder_system_prompt.md +119 -0
- config/roles.json +43 -0
- config/tools.json +709 -0
- indexing/__init__.py +0 -0
- indexing/cli.py +128 -0
- indexing/code_index_sdk.py +832 -0
- indexing/code_indexer.py +1763 -0
- indexing/db_schema.py +396 -0
- indexing/export_to_json.py +346 -0
- indexing/extractors.py +189 -0
- indexing/file_utils.py +97 -0
- indexing/frontend/__init__.py +0 -0
- indexing/frontend/css_extractor.py +195 -0
- indexing/frontend/css_parser.py +387 -0
- indexing/frontend/css_selector_utils.py +226 -0
- indexing/frontend/edit_safety.py +573 -0
- indexing/frontend/graph.py +838 -0
- indexing/frontend/html_extractor.py +496 -0
- indexing/frontend/html_parser.py +314 -0
- indexing/frontend/jsx_extractor.py +1204 -0
- indexing/frontend/location_lookup.py +247 -0
- indexing/frontend/resolver.py +485 -0
- indexing/frontend/runtime_resolver.py +862 -0
- indexing/frontend/semantic_output.py +705 -0
- indexing/frontend/source_location.py +69 -0
- indexing/frontend_config.py +72 -0
- indexing/frontend_models.py +347 -0
- indexing/language_config.py +360 -0
- indexing/models.py +284 -0
- indexing/node_utils.py +1112 -0
- indexing/parse_worker.py +1082 -0
- indexing/queries.py +1542 -0
- indexing/sdk_examples.py +426 -0
- interactive.py +248 -0
- raggie.py +673 -0
- raggiecode-0.2.1.dist-info/METADATA +944 -0
- raggiecode-0.2.1.dist-info/RECORD +93 -0
- raggiecode-0.2.1.dist-info/WHEEL +5 -0
- raggiecode-0.2.1.dist-info/entry_points.txt +2 -0
- raggiecode-0.2.1.dist-info/top_level.txt +10 -0
- skills/__init__.py +3 -0
- skills/manager.py +114 -0
- skills/tool.py +121 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
cli.py,sha256=SJehNTIu9RNqIF0STVueFSrPqhkBDBF8HxQFqWyOnQg,5410
|
|
2
|
+
interactive.py,sha256=9KflbeVtVNBzGHXW_gg9j8n9HvgPwyvUfQaIFo2JPGU,8138
|
|
3
|
+
raggie.py,sha256=Al34Mo5GF0FwxUq_8B08twhSAEQOqdkihLaS4b3pijI,22085
|
|
4
|
+
Agent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
5
|
+
Agent/agent.py,sha256=R-gq8LRnOgP9lhj-ZZjSMGOAofdlk3TaTkCm56P20CA,36383
|
|
6
|
+
Agent/chat_history_db.py,sha256=72oGUrEePJoT-0dqKRo8p38lPZVrbW7NazndQGU-nJ4,46920
|
|
7
|
+
Agent/command.py,sha256=sVYQqk54dkP_Ty_XO3ZPKZJEqNhKDULJES1NWcWftAM,1735
|
|
8
|
+
Agent/config.py,sha256=DzMPVgeVDl7uHhEGiUaV6fIYTx7pfEvfX-youjoqyzY,1416
|
|
9
|
+
Agent/effort_levels.py,sha256=Ri4YMEYd4cJlmwQC5xyPZZe9lDxtXV-9KCKejvcSU_E,800
|
|
10
|
+
Agent/git_manager.py,sha256=paE1u6DScyj9H8_9tuJNeYanKzWwJGQVRQ8ak6aC4zM,28195
|
|
11
|
+
Agent/tools.py,sha256=GnOn5JDGHo8j38vMSMvXR2vME99_hTNSWtuQuddf4RU,1183
|
|
12
|
+
Commands/__init__.py,sha256=Sc_Nt4wo_dEC7_yTVQYS-qpIztzoYWHsgysSy6PFJtA,834
|
|
13
|
+
Commands/effort.py,sha256=b3U5HgEBi5PsBJOxxKnvelLpT9UUd-OgCWX9QWhGNS8,1371
|
|
14
|
+
Commands/global_todo.py,sha256=1TghrpYQEApgXu2CH0XUh5cf9ZLBBdQYLVwoT8kPs68,912
|
|
15
|
+
Commands/help.py,sha256=-LH9Rmz0zHq8TpZ8Ap36xYZRRiRZeUf9LtgdjX4-IEg,1148
|
|
16
|
+
Commands/reasoning.py,sha256=4UHGntpbWZNE8TrKH0XUQUjEhL18XHi9w3WvXPXxOl8,747
|
|
17
|
+
Commands/redo.py,sha256=vobzA9xU4SsKvHkw7hFNyDPZPRKUdYHws5gF9LYB87k,332
|
|
18
|
+
Commands/reindex.py,sha256=UncnVpR-nJUDR2VlIaEU9sODEUCX59wotiJt5Z2sapw,804
|
|
19
|
+
Commands/shell.py,sha256=_anLkvDGAV7t7cczuL0LsKkg5vz4TZe_cSyr6LOMBdI,716
|
|
20
|
+
Commands/stream.py,sha256=e-CubXDcMBHZzmtz7IvQMkz2NJfe4CZo7Tc8bXLkEGY,738
|
|
21
|
+
Commands/undo.py,sha256=29QKE9WUZT2UgSUaOCfxz3CgSS-8qKs-1MSWqc1zQug,350
|
|
22
|
+
Commands/unlimited_effort.py,sha256=uM8pi7d_DjY7UE_oqZqpoRuho6VH0alDuBr5T7Pdaoc,302
|
|
23
|
+
Commands/window_size.py,sha256=oriT9ACRxu9IFqrxbQRRyP62nHw49hhoR2k-sPz2V58,739
|
|
24
|
+
RAG/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
25
|
+
RAG/document.py,sha256=mO0b64qOIWMtZB_OVImw5_9QLEoQNKYMgpBqUgQqlAA,4903
|
|
26
|
+
RAG/find.py,sha256=rLjWDqe0I3dyJlXfhC1U6oZ3NdACc2UC6F0m1-G6Ugo,15319
|
|
27
|
+
RAG/graph.py,sha256=kOYeaSIvpi7Wg4YAGzMul4DcbvvjLwTK6zX423fsWgQ,9522
|
|
28
|
+
Tools/GetFileCodeStructure.py,sha256=WbVVpa3Q5YkBJ12V2aRlh43iIIpIOvH7OhOQ2bK34-U,1542
|
|
29
|
+
Tools/GetSymbolSourceCode.py,sha256=mbODXc7SKg3wLnE64nhKSl5Xj7WfIQex5MiUT9x4dRM,870
|
|
30
|
+
Tools/__init__.py,sha256=uEot7KyesKc5-EFuG30tZ5kOaiMvTu_nNkVs6SOxv00,2598
|
|
31
|
+
Tools/ask_user.py,sha256=_d9spFoWJ56xlJWHQTNDCryIIgS5Wa-ppoJys-k1hZw,3591
|
|
32
|
+
Tools/dispatch_subagent.py,sha256=4wR003hrC24JJ79p_91ne09MB5a8rylMALY8OM3gr2M,8427
|
|
33
|
+
Tools/document.py,sha256=dum7_sbAttWo4mMfS0_oH8oPgAglArvJn-jovUtSz4o,1285
|
|
34
|
+
Tools/edit_symbol.py,sha256=0l5hrWhu5H3vNrLsmyGRX3CFjzqKkkgJZJq4dr8JHGw,8538
|
|
35
|
+
Tools/fuzzy_search.py,sha256=GK_XnxC0UhmhD-9txZbjD6G3KPb_qyqh5sZYAJNPWs0,3609
|
|
36
|
+
Tools/list_dir.py,sha256=xO4nKdDT-DYs_jZHWMukrRZC1K9T1dcHISjP7k_FrdA,1648
|
|
37
|
+
Tools/read.py,sha256=KhNS2C8isBerIvHrpWXWAGaHI-51jobboNqI4VWfenE,1457
|
|
38
|
+
Tools/read_image.py,sha256=aEKnX--hYv0BGkNgJDTCLdh0FBNcwYQaEcIMy7AHvHo,2538
|
|
39
|
+
Tools/remove.py,sha256=r0FAI4xxQRLjHRLR0rTi1m3sjl86y3y2-aGC5MewnB4,2886
|
|
40
|
+
Tools/replace.py,sha256=F5S0NnOf4lzLeYQ-LgmN_275Ywg7MruXUymN2OIZIg4,11114
|
|
41
|
+
Tools/search.py,sha256=c-7AL6gM-AXPJhUJP3y6XG36V1aunNGycQaw1WhGWew,1254
|
|
42
|
+
Tools/shell.py,sha256=hotlLHye6rlK4RAaxQwkzy997QmLAiJ8xV86pvAoFfQ,5056
|
|
43
|
+
Tools/shell_kill.py,sha256=fmBDscJqvccx4AwzwHo_-y8-eRc0vf8hzUEYKYQYWTI,2535
|
|
44
|
+
Tools/temp_background_service.py,sha256=C1tWMMLT9rBNae8vZTWIr6JVfYsUQT72csdTksoNSBM,3797
|
|
45
|
+
Tools/todo_list.py,sha256=zeuqu4vPwuUyLjZNJPd3PW1lo5bPkahgg3mAYeQwbW4,19101
|
|
46
|
+
Tools/utils.py,sha256=qR7VQ-DDoeb51wFwm9ZiF8uGFiYYsXVLVVzmV8heGOM,3367
|
|
47
|
+
Tools/view_changes.py,sha256=pMn1NgKGUPNnHgFiPXAUfZTl5P6t3KDNpYKABbjHtyQ,7123
|
|
48
|
+
Tools/walk_call_tree.py,sha256=7GopT44xWQdMti35F-WmHKKCkI4MyRzKurVWfGJ9km0,1031
|
|
49
|
+
Tools/web_fetch.py,sha256=eBM5wQvEbP3AUDQwC2G4nMKpJ2hCNTiIlXe1RV6RJm0,5407
|
|
50
|
+
Tools/web_search.py,sha256=tBxao6YCZpPDKSm3z1-XNJUIL6PH6kzKhM56FOl7qU4,1948
|
|
51
|
+
Tools/write.py,sha256=jyAUt-kGbBacNzLNT2WBsxrPLUPFa1z8FnGYbCwdeCI,1745
|
|
52
|
+
config/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
53
|
+
config/coder_system_prompt.md,sha256=cK0PKoZOHUXihDtqXrqsN6glWyqv7PmW0WRoQQWRGbo,7102
|
|
54
|
+
config/roles.json,sha256=OhEUl309DqQTtumRw94GM3CT59XssA3hNT6BFlzu_uE,1132
|
|
55
|
+
config/tools.json,sha256=YOLnfCkKvFYhOufAmCArQZPeP-muI9hlIfYq4JsDHAk,39638
|
|
56
|
+
indexing/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
57
|
+
indexing/cli.py,sha256=k8BR-anjCjvK-swb6N8Tsqhsd8MOUOcD9fjW0o2pL4w,4007
|
|
58
|
+
indexing/code_index_sdk.py,sha256=4g5y4WbWp-a85qTljw0Ud3HridmK85RPIl8xudAGrLo,34921
|
|
59
|
+
indexing/code_indexer.py,sha256=FtBQeYZA6M0gyuuxp7kX5Wv6nvz_sbhSoC9W9gYVRm8,80149
|
|
60
|
+
indexing/db_schema.py,sha256=pJs_6BqD08RidX67k0f9JQVc2IU8Dp0JK6YqInpAzpE,18918
|
|
61
|
+
indexing/export_to_json.py,sha256=srml0G802HiuCIg29aLqxCKF3tQ_N8XqLN927lNuQBM,12253
|
|
62
|
+
indexing/extractors.py,sha256=RFMgtS3AZWNI0fllQ5q19SHUeWyembt5BGpqfODtufY,5606
|
|
63
|
+
indexing/file_utils.py,sha256=Kan4jJGQ4i1XRuzwaC_kP_cMxg_ZRl_dksOE_qnQ_UI,3562
|
|
64
|
+
indexing/frontend_config.py,sha256=kQy4uYW6NmoDKzIgmk3GB7vXlJtfUn08KQThwuHP0ao,2606
|
|
65
|
+
indexing/frontend_models.py,sha256=eN-JjZt-3KKeE68oTnfUdEW-oMbX6isG4rlSE-wtfJc,10549
|
|
66
|
+
indexing/language_config.py,sha256=4lJl5sEw9IbIolA7E-BSQS5odoIvjHZb_roH1lL4GWk,11297
|
|
67
|
+
indexing/models.py,sha256=qsB6tSRFae2SrUBRgarE9QEPz1YMUWB-daiKgLK9Q_w,8381
|
|
68
|
+
indexing/node_utils.py,sha256=7eJhdL745w6_IvClASIB-ZrZghRPXZjaoHHZ5w6U59s,50731
|
|
69
|
+
indexing/parse_worker.py,sha256=HRipYB0Vskp5hcAFBg6fsB_7mX__tPAZ7Hu3LlNOHlY,46830
|
|
70
|
+
indexing/queries.py,sha256=_mFw-qBjmxYIO5AGvpVFq5Gy2eGrn5C2j_s9LtbtJKw,60879
|
|
71
|
+
indexing/sdk_examples.py,sha256=VP2G_z9GY1hP7YNEqeMJkvzzz1Aau8kx_zPhMwo7niE,16283
|
|
72
|
+
indexing/frontend/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
73
|
+
indexing/frontend/css_extractor.py,sha256=P8cvi-fc6fx_U76TutMcNK_Flh7g45_9nYA3GtcUpQc,7633
|
|
74
|
+
indexing/frontend/css_parser.py,sha256=i6oSQWX4yGN2BpTVBeiJEHlFEYc2Cdfu4O_UDmxgLqo,13579
|
|
75
|
+
indexing/frontend/css_selector_utils.py,sha256=0bSlzT4Gg7HZ3WlYWky7UrjPM5Hu4TLhSWJlwB8xoFo,7439
|
|
76
|
+
indexing/frontend/edit_safety.py,sha256=0ScSjrS9_h5VuAjttNjGawMp0xkoMawPi7nKEqh3FcE,21239
|
|
77
|
+
indexing/frontend/graph.py,sha256=Bts0h6WFSGRsjKTV9Iy4DcsSuM1P8sNoLV-9SLYWwCI,33156
|
|
78
|
+
indexing/frontend/html_extractor.py,sha256=8MqUHuyYBilMd6dGPLL7vCDlaynq4_TwTYccEQ-_LKE,20579
|
|
79
|
+
indexing/frontend/html_parser.py,sha256=8AAuj5doTPZ-6QFxEBiYPl53M-uZcLuXeDQOevCVDeo,11084
|
|
80
|
+
indexing/frontend/jsx_extractor.py,sha256=bhHsaAwyJTJ7nKayAVpRPkytBGlZNKsc36P-_ew_7G8,49804
|
|
81
|
+
indexing/frontend/location_lookup.py,sha256=qWwl9FPtwKsooZCj7wP_Igrr1y2ofrnLDydvNQpGDAA,7312
|
|
82
|
+
indexing/frontend/resolver.py,sha256=FuXhdmhQEzVW5iWVIyRVnn4KZ1WjnphvRu_5q26GFjE,18974
|
|
83
|
+
indexing/frontend/runtime_resolver.py,sha256=5K8jqVYtvkvI8ah7YbFgUoJEtf_khBPWa7polwXTs_o,34418
|
|
84
|
+
indexing/frontend/semantic_output.py,sha256=yDtIow5AXYJ5qT3RFHu6dTfvE9n1os-W4MyyU5T7hJU,27782
|
|
85
|
+
indexing/frontend/source_location.py,sha256=guLp3l7G2zWPexkMN9KmetrDgC7mREQ3m5cil8MghdI,2289
|
|
86
|
+
skills/__init__.py,sha256=HJpODd-3moOdeHPqwpCJpqaF-JjoEmAQH3iuD9FhzOA,62
|
|
87
|
+
skills/manager.py,sha256=K8JZojN6w-rGSLQA_2bQ4kCShI0pl6NK-qBRF8YH9X4,4023
|
|
88
|
+
skills/tool.py,sha256=UQq50ASdp6DKmfv0M6PO5YFJ3mGd647E9QLbdAvuAlw,3708
|
|
89
|
+
raggiecode-0.2.1.dist-info/METADATA,sha256=6tnme1W4fITgFMx9d614VAR77PP5VPIyjddeDf6PduA,43901
|
|
90
|
+
raggiecode-0.2.1.dist-info/WHEEL,sha256=K260EYznzXsJYBQGqmI8VTxEdiZYNvDZwW9cBh9-_MA,91
|
|
91
|
+
raggiecode-0.2.1.dist-info/entry_points.txt,sha256=aJhU834hBoHFBoD4l8QlZgtYLz8YErjn3_2OUFJ29fY,39
|
|
92
|
+
raggiecode-0.2.1.dist-info/top_level.txt,sha256=fotJtewIK0UIUyouskZsCa59JIC-J5dduxa6ijRlR10,71
|
|
93
|
+
raggiecode-0.2.1.dist-info/RECORD,,
|
skills/__init__.py
ADDED
skills/manager.py
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import sqlite3
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
from typing import Optional
|
|
4
|
+
from Agent.chat_history_db import DB_PATH
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class SkillManager:
|
|
8
|
+
"""Manages role-specific skills stored in the database."""
|
|
9
|
+
|
|
10
|
+
def __init__(self):
|
|
11
|
+
"""Initialize the skill manager."""
|
|
12
|
+
# No directory creation needed since DB_PATH is the file itself
|
|
13
|
+
|
|
14
|
+
def get_skill(self, role: str, name: str) -> Optional[str]:
|
|
15
|
+
"""Load a specific skill for a role by name from the database."""
|
|
16
|
+
conn = sqlite3.connect(DB_PATH)
|
|
17
|
+
cursor = conn.cursor()
|
|
18
|
+
|
|
19
|
+
cursor.execute("""
|
|
20
|
+
SELECT content FROM skills
|
|
21
|
+
WHERE role = ? AND name = ?
|
|
22
|
+
""", (role, name))
|
|
23
|
+
|
|
24
|
+
result = cursor.fetchone()
|
|
25
|
+
conn.close()
|
|
26
|
+
|
|
27
|
+
return result[0] if result else None
|
|
28
|
+
|
|
29
|
+
def list_skills_by_role(self, role: str) -> list:
|
|
30
|
+
"""Return all skills for a specific role with brief summaries."""
|
|
31
|
+
conn = sqlite3.connect(DB_PATH)
|
|
32
|
+
cursor = conn.cursor()
|
|
33
|
+
|
|
34
|
+
cursor.execute("""
|
|
35
|
+
SELECT name, content FROM skills
|
|
36
|
+
WHERE role = ?
|
|
37
|
+
ORDER BY name ASC
|
|
38
|
+
""", (role,))
|
|
39
|
+
|
|
40
|
+
skills = []
|
|
41
|
+
for row in cursor.fetchall():
|
|
42
|
+
name = row[0]
|
|
43
|
+
content = row[1] or ""
|
|
44
|
+
summary = content.strip().split("\n")[0][:200]
|
|
45
|
+
skills.append({"role": role, "name": name, "summary": summary})
|
|
46
|
+
|
|
47
|
+
conn.close()
|
|
48
|
+
return skills
|
|
49
|
+
|
|
50
|
+
def list_skills(self) -> list:
|
|
51
|
+
"""Return all skills with brief summaries (role + name + first ~200 chars of content)."""
|
|
52
|
+
conn = sqlite3.connect(DB_PATH)
|
|
53
|
+
cursor = conn.cursor()
|
|
54
|
+
|
|
55
|
+
cursor.execute("""
|
|
56
|
+
SELECT role, name, content FROM skills
|
|
57
|
+
ORDER BY role ASC, name ASC
|
|
58
|
+
""")
|
|
59
|
+
|
|
60
|
+
skills = []
|
|
61
|
+
for row in cursor.fetchall():
|
|
62
|
+
role = row[0]
|
|
63
|
+
name = row[1]
|
|
64
|
+
content = row[2] or ""
|
|
65
|
+
summary = content.strip().split("\n")[0][:200]
|
|
66
|
+
skills.append({"role": role, "name": name, "summary": summary})
|
|
67
|
+
|
|
68
|
+
conn.close()
|
|
69
|
+
return skills
|
|
70
|
+
|
|
71
|
+
def set_skill(self, role: str, name: str, content: str) -> None:
|
|
72
|
+
"""Save a skill for a specific role with a given name to the database."""
|
|
73
|
+
conn = sqlite3.connect(DB_PATH)
|
|
74
|
+
cursor = conn.cursor()
|
|
75
|
+
|
|
76
|
+
cursor.execute("""
|
|
77
|
+
INSERT INTO skills (role, name, content, updated_at)
|
|
78
|
+
VALUES (?, ?, ?, CURRENT_TIMESTAMP)
|
|
79
|
+
ON CONFLICT(role, name) DO UPDATE SET content = excluded.content, updated_at = CURRENT_TIMESTAMP
|
|
80
|
+
""", (role, name, content))
|
|
81
|
+
|
|
82
|
+
conn.commit()
|
|
83
|
+
conn.close()
|
|
84
|
+
|
|
85
|
+
def import_from_markdown(self, role: str, name: str, file_path: str) -> None:
|
|
86
|
+
"""Load skill from a markdown file into the database."""
|
|
87
|
+
path = Path(file_path)
|
|
88
|
+
if not path.exists():
|
|
89
|
+
raise FileNotFoundError(f"Skill file not found: {file_path}")
|
|
90
|
+
|
|
91
|
+
content = path.read_text(encoding='utf-8')
|
|
92
|
+
self.set_skill(role, name, content)
|
|
93
|
+
|
|
94
|
+
def export_to_markdown(self, role: str, name: str, file_path: str) -> None:
|
|
95
|
+
"""Export skill from the database to a markdown file."""
|
|
96
|
+
content = self.get_skill(role, name)
|
|
97
|
+
if content is None:
|
|
98
|
+
raise ValueError(f"No skill found for role '{role}' with name '{name}'")
|
|
99
|
+
|
|
100
|
+
path = Path(file_path)
|
|
101
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
102
|
+
path.write_text(content, encoding='utf-8')
|
|
103
|
+
|
|
104
|
+
def delete_skill(self, role: str, name: str) -> bool:
|
|
105
|
+
"""Delete a skill by role and name. Returns True if a row was deleted."""
|
|
106
|
+
conn = sqlite3.connect(DB_PATH)
|
|
107
|
+
cursor = conn.cursor()
|
|
108
|
+
cursor.execute("""
|
|
109
|
+
DELETE FROM skills WHERE role = ? AND name = ?
|
|
110
|
+
""", (role, name))
|
|
111
|
+
deleted = cursor.rowcount > 0
|
|
112
|
+
conn.commit()
|
|
113
|
+
conn.close()
|
|
114
|
+
return deleted
|
skills/tool.py
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
from .manager import SkillManager
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def handle_get_skill(args, tool_call_id, agent_role=None):
|
|
5
|
+
"""Handle the GetSkill tool call — fetches the full content of a specific skill by name for the caller's role."""
|
|
6
|
+
name = args.get("name")
|
|
7
|
+
|
|
8
|
+
if not agent_role:
|
|
9
|
+
return {
|
|
10
|
+
"role": "tool",
|
|
11
|
+
"tool_call_id": tool_call_id,
|
|
12
|
+
"content": "Error: could not determine agent role"
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
if not name:
|
|
16
|
+
return {
|
|
17
|
+
"role": "tool",
|
|
18
|
+
"tool_call_id": tool_call_id,
|
|
19
|
+
"content": "Error: 'name' parameter is required"
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
manager = SkillManager()
|
|
23
|
+
content = manager.get_skill(agent_role, name)
|
|
24
|
+
|
|
25
|
+
if content is None:
|
|
26
|
+
return {
|
|
27
|
+
"role": "tool",
|
|
28
|
+
"tool_call_id": tool_call_id,
|
|
29
|
+
"content": f"No skill found for role '{agent_role}' with name '{name}'. Use SetSkill to create one."
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return {
|
|
33
|
+
"role": "tool",
|
|
34
|
+
"tool_call_id": tool_call_id,
|
|
35
|
+
"content": f"Skill '{name}' for role '{agent_role}':\n\n{content}"
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def handle(args, tool_call_id, agent_role=None):
|
|
40
|
+
"""Handle the SetSkill tool call with user consent.
|
|
41
|
+
|
|
42
|
+
The agent can only create/update skills for its own role.
|
|
43
|
+
"""
|
|
44
|
+
name = args.get("name")
|
|
45
|
+
content = args.get("content")
|
|
46
|
+
|
|
47
|
+
if not agent_role:
|
|
48
|
+
return {
|
|
49
|
+
"role": "tool",
|
|
50
|
+
"tool_call_id": tool_call_id,
|
|
51
|
+
"content": "Error: could not determine agent role"
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if not name:
|
|
55
|
+
return {
|
|
56
|
+
"role": "tool",
|
|
57
|
+
"tool_call_id": tool_call_id,
|
|
58
|
+
"content": "Error: 'name' parameter is required"
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if not content:
|
|
62
|
+
return {
|
|
63
|
+
"role": "tool",
|
|
64
|
+
"tool_call_id": tool_call_id,
|
|
65
|
+
"content": "Error: 'content' parameter is required"
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
# Check if skill already exists to provide better feedback
|
|
69
|
+
manager = SkillManager()
|
|
70
|
+
existing_skill = manager.get_skill(agent_role, name)
|
|
71
|
+
action = "update" if existing_skill else "create"
|
|
72
|
+
|
|
73
|
+
# Ask for user consent
|
|
74
|
+
print(f"\n{'='*60}")
|
|
75
|
+
print(f"Agent wants to {action} skill '{name}' for role: {agent_role}")
|
|
76
|
+
print(f"{'='*60}")
|
|
77
|
+
print(f"Proposed skill content:")
|
|
78
|
+
print("-" * 60)
|
|
79
|
+
print(content)
|
|
80
|
+
print("-" * 60)
|
|
81
|
+
|
|
82
|
+
consent = ""
|
|
83
|
+
try:
|
|
84
|
+
consent = input(f"\nDo you accept this {action} of '{name}' skill for role '{agent_role}'? (y/n): ").strip().lower()
|
|
85
|
+
except KeyboardInterrupt:
|
|
86
|
+
print()
|
|
87
|
+
exit(0)
|
|
88
|
+
except EOFError:
|
|
89
|
+
print()
|
|
90
|
+
exit(0)
|
|
91
|
+
|
|
92
|
+
if consent == 'y' or consent == 'yes':
|
|
93
|
+
try:
|
|
94
|
+
manager.set_skill(agent_role, name, content)
|
|
95
|
+
return {
|
|
96
|
+
"role": "tool",
|
|
97
|
+
"tool_call_id": tool_call_id,
|
|
98
|
+
"content": f"Successfully {action}d skill '{name}' for role '{agent_role}'"
|
|
99
|
+
}
|
|
100
|
+
except Exception as e:
|
|
101
|
+
return {
|
|
102
|
+
"role": "tool",
|
|
103
|
+
"tool_call_id": tool_call_id,
|
|
104
|
+
"content": f"Error {action}ing skill: {str(e)}"
|
|
105
|
+
}
|
|
106
|
+
else:
|
|
107
|
+
try:
|
|
108
|
+
reason = input(f"Reason for refusal (optional, press Enter to skip): ").strip()
|
|
109
|
+
except (KeyboardInterrupt, EOFError):
|
|
110
|
+
reason = ""
|
|
111
|
+
if reason:
|
|
112
|
+
return {
|
|
113
|
+
"role": "tool",
|
|
114
|
+
"tool_call_id": tool_call_id,
|
|
115
|
+
"content": f"Skill {action} rejected by user. Reason: {reason}"
|
|
116
|
+
}
|
|
117
|
+
return {
|
|
118
|
+
"role": "tool",
|
|
119
|
+
"tool_call_id": tool_call_id,
|
|
120
|
+
"content": f"Skill {action} rejected by user"
|
|
121
|
+
}
|