vamp-cli 0.1.0__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 (57) hide show
  1. vamp_cli/__init__.py +0 -0
  2. vamp_cli/agent/__init__.py +0 -0
  3. vamp_cli/agent/context_sync.py +72 -0
  4. vamp_cli/agent/graph.py +159 -0
  5. vamp_cli/agent/instructions.py +18 -0
  6. vamp_cli/agent/nodes.py +375 -0
  7. vamp_cli/agent/roles.py +8 -0
  8. vamp_cli/agent/runtime/__init__.py +0 -0
  9. vamp_cli/agent/runtime/runtime.py +133 -0
  10. vamp_cli/agent/state.py +55 -0
  11. vamp_cli/agent/status.py +17 -0
  12. vamp_cli/config/__init__.py +0 -0
  13. vamp_cli/config/loader.py +152 -0
  14. vamp_cli/config/schema.py +82 -0
  15. vamp_cli/llm/__init__.py +0 -0
  16. vamp_cli/llm/adapter.py +52 -0
  17. vamp_cli/llm/adapter_registry.py +26 -0
  18. vamp_cli/llm/debug_callbacks.py +18 -0
  19. vamp_cli/llm/router.py +247 -0
  20. vamp_cli/llm/usage.py +170 -0
  21. vamp_cli/logging_setup/logging_setup.py +37 -0
  22. vamp_cli/main.py +1023 -0
  23. vamp_cli/persistence/__init__.py +29 -0
  24. vamp_cli/persistence/compaction.py +372 -0
  25. vamp_cli/persistence/emitter.py +371 -0
  26. vamp_cli/persistence/event_log.py +303 -0
  27. vamp_cli/persistence/fork.py +81 -0
  28. vamp_cli/persistence/loader.py +616 -0
  29. vamp_cli/persistence/transcript.py +160 -0
  30. vamp_cli/prompts/prompts.py +182 -0
  31. vamp_cli/sandbox/__init__.py +0 -0
  32. vamp_cli/sandbox/base.py +22 -0
  33. vamp_cli/sandbox/config.py +16 -0
  34. vamp_cli/sandbox/docker.py +293 -0
  35. vamp_cli/sandbox/manager.py +31 -0
  36. vamp_cli/sandbox/result.py +14 -0
  37. vamp_cli/sandbox/terminal.py +151 -0
  38. vamp_cli/tools/__init__.py +0 -0
  39. vamp_cli/tools/base.py +44 -0
  40. vamp_cli/tools/diagnostic.py +120 -0
  41. vamp_cli/tools/execute_cmd.py +16 -0
  42. vamp_cli/tools/files.py +652 -0
  43. vamp_cli/tools/registry.py +163 -0
  44. vamp_cli/tools/tools_classes.py +622 -0
  45. vamp_cli/utils/__init__.py +0 -0
  46. vamp_cli/utils/error_codes.py +7 -0
  47. vamp_cli/utils/ignore.py +36 -0
  48. vamp_cli/utils/sha_256.py +32 -0
  49. vamp_cli/utils/token_tracker.py +31 -0
  50. vamp_cli/workspace/__init__.py +0 -0
  51. vamp_cli/workspace/workspace.py +16 -0
  52. vamp_cli-0.1.0.dist-info/METADATA +317 -0
  53. vamp_cli-0.1.0.dist-info/RECORD +57 -0
  54. vamp_cli-0.1.0.dist-info/WHEEL +5 -0
  55. vamp_cli-0.1.0.dist-info/entry_points.txt +2 -0
  56. vamp_cli-0.1.0.dist-info/licenses/LICENSE +21 -0
  57. vamp_cli-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,163 @@
1
+ # registry.py
2
+ from typing import Dict, List, Optional, Any
3
+ from vamp_cli.tools.base import Tools
4
+
5
+
6
+ class ToolRegistry:
7
+ """
8
+ Registry mapping tool names -> tool instances.
9
+
10
+ Tools are expected to inherit from `Tools` (exposing `name`,
11
+ `description`, `input_schema`, `schema()` and `run()`).
12
+ """
13
+
14
+ def __init__(self) -> None:
15
+ self._tools: Dict[str, Tools] = {}
16
+
17
+ # ------------------------------------------------------------------
18
+ # Registration
19
+ # ------------------------------------------------------------------
20
+ def register(self, tool: Tools) -> None:
21
+ """Register a single tool. Raises if the name is already taken."""
22
+ if not getattr(tool, "name", None):
23
+ raise ValueError("Tool must define a non-empty `name`.")
24
+ if tool.name in self._tools:
25
+ raise ValueError(f"Tool '{tool.name}' is already registered.")
26
+ self._tools[tool.name] = tool
27
+
28
+ def register_many(self, tools: List[Tools]) -> None:
29
+ """Register several tools at once (atomic: fails on first conflict)."""
30
+ for tool in tools:
31
+ self.register(tool)
32
+
33
+ def unregister(self, name: str) -> None:
34
+ """Remove a tool by name. Raises KeyError if not found."""
35
+ if name not in self._tools:
36
+ raise KeyError(f"Tool '{name}' not found.")
37
+ del self._tools[name]
38
+
39
+ def clear(self) -> None:
40
+ """Remove all registered tools."""
41
+ self._tools.clear()
42
+
43
+ # ------------------------------------------------------------------
44
+ # Lookup
45
+ # ------------------------------------------------------------------
46
+ def get_tool(self, name: str) -> Dict[str, Tools]:
47
+ """
48
+ Return a single tool as `{name: tool_object}`.
49
+ Raises KeyError if the tool is not registered.
50
+ """
51
+ if name not in self._tools:
52
+ raise KeyError(f"Tool '{name}' not found.")
53
+ return {name: self._tools[name]}
54
+
55
+ def get_optional_tool(self, name: str) -> Optional[Dict[str, Tools]]:
56
+ """
57
+ Return `{name: tool_object}` if registered, otherwise None.
58
+ """
59
+ tool = self._tools.get(name)
60
+ return {name: tool} if tool is not None else None
61
+
62
+ def get_tools(self, names: List[str]) -> Dict[str, Tools]:
63
+ """
64
+ Resolve a list of tool names to `{name: tool_object}`.
65
+
66
+ - Missing tools are skipped silently.
67
+ - Duplicate names collapse into a single entry.
68
+ """
69
+ resolved: Dict[str, Tools] = {}
70
+ for name in names:
71
+ tool = self._tools.get(name)
72
+ if tool is not None:
73
+ resolved[name] = tool
74
+ return resolved
75
+
76
+ def get_tools_strict(self, names: List[str]) -> Dict[str, Tools]:
77
+ """
78
+ Same as `get_tools` but raises KeyError listing every missing name.
79
+ """
80
+ missing = [n for n in names if n not in self._tools]
81
+ if missing:
82
+ raise KeyError(f"Tool(s) not found: {', '.join(missing)}")
83
+ return {n: self._tools[n] for n in names}
84
+
85
+ def get_all_tools(self) -> Dict[str, Tools]:
86
+ """Return every registered tool as `{name: tool_object}`."""
87
+ return dict(self._tools)
88
+
89
+
90
+ def get_tool_list(self, names: Optional[List[str]] = None) -> List[Tools]:
91
+ """
92
+ Return Tools **objects as a list** — the shape ModelRouter.get expects.
93
+ Unknown names are skipped. Order preserved. Duplicates collapse.
94
+ """
95
+ if names is None:
96
+ return list(self._tools.values())
97
+ seen: set[str] = set()
98
+ out: List[Tools] = []
99
+ for n in names:
100
+ if n in seen:
101
+ continue
102
+ tool = self._tools.get(n)
103
+ if tool is not None:
104
+ out.append(tool)
105
+ seen.add(n)
106
+ return out
107
+
108
+ def get_openai_tools(self, names: Optional[List[str]] = None) -> List[Dict[str, Any]]:
109
+ """Ready-to-bind OpenAI-format tool list."""
110
+ return [t.to_openai_tool() for t in self.get_tool_list(names)]
111
+
112
+ # ------------------------------------------------------------------
113
+ # Introspection
114
+ # ------------------------------------------------------------------
115
+ def has_tool(self, name: str) -> bool:
116
+ """True if a tool with the given name is registered."""
117
+ return name in self._tools
118
+
119
+ def list_tool_names(self) -> List[str]:
120
+ """All registered tool names."""
121
+ return list(self._tools.keys())
122
+
123
+ def get_schemas(self, names: Optional[List[str]] = None) -> List[dict]:
124
+ """
125
+ Return schemas for the given names (or all tools when names is None).
126
+ Suitable for passing to the LLM as the tool/function list.
127
+ """
128
+ if names is None:
129
+ tools = self._tools.values()
130
+ else:
131
+ tools = (self._tools[n] for n in names if n in self._tools)
132
+ return [tool.schema() for tool in tools]
133
+
134
+ def __len__(self) -> int:
135
+ return len(self._tools)
136
+
137
+ def __contains__(self, name: str) -> bool:
138
+ return name in self._tools
139
+
140
+ def __iter__(self):
141
+ return iter(self._tools)
142
+
143
+ def __repr__(self) -> str:
144
+ return f"ToolRegistry(tools={self.list_tool_names()})"
145
+
146
+
147
+
148
+ async def call(self, name: str, args: dict[str, Any]) -> str:
149
+ if name not in self._tools:
150
+ raise KeyError(f"Tool '{name}' not found.")
151
+ return await self._tools[name].arun(**args)
152
+
153
+ def is_parallel_safe(self, name: str) -> bool:
154
+ if name not in self._tools:
155
+ raise KeyError(f"Tool '{name}' not found.")
156
+ return self._tools[name].parallel_safe
157
+
158
+
159
+
160
+ # used in agent langraph loop if llm demands a tool
161
+
162
+ # tool_obj = registry.get_tool(name)[name] # dict as you specified
163
+ # result = tool_obj.run(**json.loads(tool_call["function"]["arguments"]))