hypha-debugger 0.1.5__tar.gz → 0.1.6__tar.gz

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 (22) hide show
  1. {hypha_debugger-0.1.5 → hypha_debugger-0.1.6}/PKG-INFO +1 -1
  2. {hypha_debugger-0.1.5 → hypha_debugger-0.1.6}/hypha_debugger/__init__.py +1 -1
  3. {hypha_debugger-0.1.5 → hypha_debugger-0.1.6}/hypha_debugger/debugger.py +10 -0
  4. hypha_debugger-0.1.6/hypha_debugger/services/source.py +187 -0
  5. {hypha_debugger-0.1.5 → hypha_debugger-0.1.6}/hypha_debugger.egg-info/PKG-INFO +1 -1
  6. {hypha_debugger-0.1.5 → hypha_debugger-0.1.6}/hypha_debugger.egg-info/SOURCES.txt +1 -0
  7. {hypha_debugger-0.1.5 → hypha_debugger-0.1.6}/pyproject.toml +1 -1
  8. {hypha_debugger-0.1.5 → hypha_debugger-0.1.6}/tests/test_services.py +44 -0
  9. {hypha_debugger-0.1.5 → hypha_debugger-0.1.6}/README.md +0 -0
  10. {hypha_debugger-0.1.5 → hypha_debugger-0.1.6}/hypha_debugger/__main__.py +0 -0
  11. {hypha_debugger-0.1.5 → hypha_debugger-0.1.6}/hypha_debugger/services/__init__.py +0 -0
  12. {hypha_debugger-0.1.5 → hypha_debugger-0.1.6}/hypha_debugger/services/execute.py +0 -0
  13. {hypha_debugger-0.1.5 → hypha_debugger-0.1.6}/hypha_debugger/services/filesystem.py +0 -0
  14. {hypha_debugger-0.1.5 → hypha_debugger-0.1.6}/hypha_debugger/services/info.py +0 -0
  15. {hypha_debugger-0.1.5 → hypha_debugger-0.1.6}/hypha_debugger/services/inspect_vars.py +0 -0
  16. {hypha_debugger-0.1.5 → hypha_debugger-0.1.6}/hypha_debugger/utils/__init__.py +0 -0
  17. {hypha_debugger-0.1.5 → hypha_debugger-0.1.6}/hypha_debugger/utils/env.py +0 -0
  18. {hypha_debugger-0.1.5 → hypha_debugger-0.1.6}/hypha_debugger.egg-info/dependency_links.txt +0 -0
  19. {hypha_debugger-0.1.5 → hypha_debugger-0.1.6}/hypha_debugger.egg-info/entry_points.txt +0 -0
  20. {hypha_debugger-0.1.5 → hypha_debugger-0.1.6}/hypha_debugger.egg-info/requires.txt +0 -0
  21. {hypha_debugger-0.1.5 → hypha_debugger-0.1.6}/hypha_debugger.egg-info/top_level.txt +0 -0
  22. {hypha_debugger-0.1.5 → hypha_debugger-0.1.6}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hypha-debugger
3
- Version: 0.1.5
3
+ Version: 0.1.6
4
4
  Summary: Injectable debugger for Python processes and AI agents, powered by Hypha RPC
5
5
  Author: Amun AI AB
6
6
  License: MIT
@@ -12,5 +12,5 @@ Usage (sync):
12
12
 
13
13
  from hypha_debugger.debugger import start_debugger, start_debugger_sync, DebugSession
14
14
 
15
- __version__ = "0.1.5"
15
+ __version__ = "0.1.6"
16
16
  __all__ = ["start_debugger", "start_debugger_sync", "DebugSession", "__version__"]
@@ -15,6 +15,7 @@ from hypha_debugger.services.inspect_vars import (
15
15
  get_stack_trace,
16
16
  )
17
17
  from hypha_debugger.services.filesystem import list_files, read_file, write_file
18
+ from hypha_debugger.services.source import get_source, get_skill_md
18
19
 
19
20
  logger = logging.getLogger("hypha_debugger")
20
21
 
@@ -67,6 +68,8 @@ def _build_instruction_block(service_url: str, token: str = "") -> str:
67
68
  "# read_file - Read file content (with offset/limit)",
68
69
  "# write_file - Write/append to a file",
69
70
  "# get_installed_packages - List pip packages",
71
+ "# get_source - Get debugger source code (for self-inspection)",
72
+ "# get_skill_md - Get full API docs as Markdown",
70
73
  "#",
71
74
  "# POST endpoints accept JSON body with parameter names as keys.",
72
75
  "",
@@ -96,6 +99,9 @@ def _build_instruction_block(service_url: str, token: str = "") -> str:
96
99
  f'curl -X POST "$SERVICE_URL/read_file"{auth}'
97
100
  ' -H "Content-Type: application/json"'
98
101
  " -d '{\"path\": \"hello.txt\"}'",
102
+ "",
103
+ "# Get full API documentation:",
104
+ f'curl "$SERVICE_URL/get_skill_md"{auth}',
99
105
  ]
100
106
  return "\n".join(lines)
101
107
 
@@ -272,6 +278,8 @@ async def start_debugger(
272
278
  "list_files": list_files,
273
279
  "read_file": read_file,
274
280
  "write_file": write_file,
281
+ "get_source": get_source,
282
+ "get_skill_md": get_skill_md,
275
283
  }
276
284
 
277
285
  svc_info = await server.register_service(service)
@@ -353,6 +361,8 @@ def start_debugger_sync(
353
361
  "list_files": list_files,
354
362
  "read_file": read_file,
355
363
  "write_file": write_file,
364
+ "get_source": get_source,
365
+ "get_skill_md": get_skill_md,
356
366
  }
357
367
 
358
368
  svc_info = server.register_service(service)
@@ -0,0 +1,187 @@
1
+ """Source code and skill documentation service."""
2
+
3
+ import inspect
4
+ import os
5
+
6
+ try:
7
+ from pydantic import Field
8
+ from hypha_rpc.utils.schema import schema_function
9
+
10
+ @schema_function
11
+ def get_source(
12
+ module: str = Field(
13
+ default="",
14
+ description=(
15
+ 'Module path relative to hypha_debugger, e.g. "services.execute". '
16
+ 'Empty string returns a list of available modules.'
17
+ ),
18
+ ),
19
+ ) -> dict:
20
+ """Get the source code of hypha-debugger modules.
21
+
22
+ Use this to understand exactly what functions are available, their
23
+ parameters, and how they work. Pass an empty string to list modules.
24
+ """
25
+ return _get_source_impl(module)
26
+
27
+ @schema_function
28
+ def get_skill_md() -> str:
29
+ """Get full API documentation for all debugger service functions.
30
+
31
+ Returns a Markdown document describing every available function,
32
+ its parameters, return values, and curl usage examples. Suitable
33
+ for pasting into an AI agent context.
34
+ """
35
+ return _get_skill_md_impl()
36
+
37
+ except ImportError:
38
+
39
+ def get_source(module: str = "") -> dict:
40
+ """Get the source code of hypha-debugger modules."""
41
+ return _get_source_impl(module)
42
+
43
+ def get_skill_md() -> str:
44
+ """Get full API documentation for all debugger service functions."""
45
+ return _get_skill_md_impl()
46
+
47
+
48
+ _MODULES = {
49
+ "debugger": "hypha_debugger.debugger",
50
+ "services.execute": "hypha_debugger.services.execute",
51
+ "services.filesystem": "hypha_debugger.services.filesystem",
52
+ "services.info": "hypha_debugger.services.info",
53
+ "services.inspect_vars": "hypha_debugger.services.inspect_vars",
54
+ "services.source": "hypha_debugger.services.source",
55
+ "utils.env": "hypha_debugger.utils.env",
56
+ }
57
+
58
+
59
+ def _get_source_impl(module: str) -> dict:
60
+ if not module:
61
+ return {
62
+ "modules": list(_MODULES.keys()),
63
+ "hint": 'Pass a module name, e.g. get_source(module="services.execute")',
64
+ }
65
+
66
+ full_name = _MODULES.get(module)
67
+ if not full_name:
68
+ return {
69
+ "error": f"Unknown module: {module}",
70
+ "available": list(_MODULES.keys()),
71
+ }
72
+
73
+ try:
74
+ mod = __import__(full_name, fromlist=["_"])
75
+ source = inspect.getsource(mod)
76
+ return {
77
+ "module": module,
78
+ "full_name": full_name,
79
+ "source": source,
80
+ "lines": source.count("\n") + 1,
81
+ }
82
+ except Exception as e:
83
+ return {"error": f"Failed to get source: {e}"}
84
+
85
+
86
+ def _get_skill_md_impl() -> str:
87
+ return """# Hypha Remote Debugger — Python Process API
88
+
89
+ ## Overview
90
+ A debugger is attached to a running Python process. You can remotely execute code,
91
+ read/write files, inspect variables, and query process info via the HTTP API.
92
+
93
+ ## Functions
94
+
95
+ ### get_process_info()
96
+ Get information about the current Python process.
97
+ - **Returns**: `{pid, cwd, python_version, hostname, platform, memory_mb, cpu_count, ...}`
98
+ - **Example**: `curl "$SERVICE_URL/get_process_info"`
99
+
100
+ ### execute_code(code, namespace?, timeout?)
101
+ Execute arbitrary Python code in the process.
102
+ - **code** (string, required): Python code to execute.
103
+ - **namespace** (string, default `"__main__"`): Module namespace to execute in.
104
+ - **timeout** (int, default `30`): Timeout in seconds. 0 for no timeout.
105
+ - **Returns**: `{stdout, stderr, result, result_type, error?, timed_out?}`
106
+ - Tries `eval()` first (returns value), falls back to `exec()` (returns None).
107
+ - **Example**:
108
+ ```bash
109
+ curl -X POST "$SERVICE_URL/execute_code" \\
110
+ -H "Content-Type: application/json" \\
111
+ -d '{"code": "import sys; sys.version"}'
112
+ ```
113
+
114
+ ### get_variable(name, namespace?)
115
+ Inspect a variable by name.
116
+ - **name** (string, required): Variable name.
117
+ - **namespace** (string, default `"__main__"`): Module namespace.
118
+ - **Returns**: `{name, type, repr, length?, shape?, dtype?, keys?}`
119
+
120
+ ### list_variables(namespace?, filter?, include_private?)
121
+ List variables in a namespace.
122
+ - **namespace** (string, default `"__main__"`): Module namespace.
123
+ - **filter** (string): Substring filter for names.
124
+ - **include_private** (bool, default `false`): Include `_`-prefixed names.
125
+ - **Returns**: List of `{name, type, repr}`.
126
+
127
+ ### get_stack_trace()
128
+ Get stack traces of all threads.
129
+ - **Returns**: List of `{thread_id, thread_name, stack}`.
130
+ - **Example**: `curl "$SERVICE_URL/get_stack_trace"`
131
+
132
+ ### list_files(path?, pattern?)
133
+ List files and directories (sandboxed to CWD).
134
+ - **path** (string, default `"."`): Directory path relative to CWD.
135
+ - **pattern** (string): Glob filter, e.g. `"*.py"`.
136
+ - **Returns**: `{path, entries: [{name, type, size?}], total}`
137
+ - **Example**: `curl "$SERVICE_URL/list_files"`
138
+
139
+ ### read_file(path, max_lines?, offset?, encoding?)
140
+ Read a file (sandboxed to CWD).
141
+ - **path** (string, required): File path relative to CWD.
142
+ - **max_lines** (int, default `500`): Max lines to read.
143
+ - **offset** (int, default `0`): Lines to skip from beginning.
144
+ - **Returns**: `{path, content, lines_read, offset, truncated}`
145
+ - **Example**:
146
+ ```bash
147
+ curl -X POST "$SERVICE_URL/read_file" \\
148
+ -H "Content-Type: application/json" \\
149
+ -d '{"path": "main.py"}'
150
+ ```
151
+
152
+ ### write_file(path, content, mode?, create_dirs?, encoding?)
153
+ Write content to a file (sandboxed to CWD).
154
+ - **path** (string, required): File path relative to CWD.
155
+ - **content** (string, required): Content to write.
156
+ - **mode** (string, default `"w"`): `"w"` to overwrite, `"a"` to append.
157
+ - **create_dirs** (bool, default `true`): Create parent directories.
158
+ - **Returns**: `{path, bytes_written, mode}`
159
+ - **Example**:
160
+ ```bash
161
+ curl -X POST "$SERVICE_URL/write_file" \\
162
+ -H "Content-Type: application/json" \\
163
+ -d '{"path": "hello.txt", "content": "Hello!"}'
164
+ ```
165
+
166
+ ### get_installed_packages(filter?)
167
+ List installed pip packages.
168
+ - **filter** (string): Substring filter for package names.
169
+ - **Returns**: List of `{name, version}`.
170
+ - **Example**: `curl "$SERVICE_URL/get_installed_packages"`
171
+
172
+ ### get_source(module?)
173
+ Get the source code of debugger modules.
174
+ - **module** (string): Module path, e.g. `"services.execute"`. Empty to list modules.
175
+ - **Returns**: `{module, source, lines}` or `{modules, hint}`.
176
+
177
+ ### get_skill_md()
178
+ Get this API documentation as Markdown.
179
+ - **Returns**: This document as a string.
180
+ - **Example**: `curl "$SERVICE_URL/get_skill_md"`
181
+
182
+ ## Notes
183
+ - All file operations are sandboxed to the process CWD.
184
+ - POST endpoints accept JSON body with parameter names as keys.
185
+ - GET endpoints take no parameters (or use query params).
186
+ - Code execution has a default 30s timeout to prevent hangs.
187
+ """
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hypha-debugger
3
- Version: 0.1.5
3
+ Version: 0.1.6
4
4
  Summary: Injectable debugger for Python processes and AI agents, powered by Hypha RPC
5
5
  Author: Amun AI AB
6
6
  License: MIT
@@ -14,6 +14,7 @@ hypha_debugger/services/execute.py
14
14
  hypha_debugger/services/filesystem.py
15
15
  hypha_debugger/services/info.py
16
16
  hypha_debugger/services/inspect_vars.py
17
+ hypha_debugger/services/source.py
17
18
  hypha_debugger/utils/__init__.py
18
19
  hypha_debugger/utils/env.py
19
20
  tests/test_services.py
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "hypha-debugger"
7
- version = "0.1.5"
7
+ version = "0.1.6"
8
8
  description = "Injectable debugger for Python processes and AI agents, powered by Hypha RPC"
9
9
  readme = "README.md"
10
10
  license = {text = "MIT"}
@@ -225,6 +225,50 @@ def test_instruction_block_with_token():
225
225
  assert "Authorization" in block
226
226
 
227
227
 
228
+ # --- source ---
229
+
230
+ def test_get_source_list_modules():
231
+ from hypha_debugger.services.source import get_source
232
+ result = get_source("")
233
+ assert "modules" in result
234
+ assert "services.execute" in result["modules"]
235
+ assert "services.filesystem" in result["modules"]
236
+ assert "debugger" in result["modules"]
237
+
238
+
239
+ def test_get_source_module():
240
+ from hypha_debugger.services.source import get_source
241
+ result = get_source("services.execute")
242
+ assert "source" in result
243
+ assert "execute_code" in result["source"]
244
+ assert result["lines"] > 10
245
+
246
+
247
+ def test_get_source_unknown():
248
+ from hypha_debugger.services.source import get_source
249
+ result = get_source("nonexistent")
250
+ assert "error" in result
251
+ assert "available" in result
252
+
253
+
254
+ def test_get_skill_md():
255
+ from hypha_debugger.services.source import get_skill_md
256
+ md = get_skill_md()
257
+ assert isinstance(md, str)
258
+ assert "execute_code" in md
259
+ assert "write_file" in md
260
+ assert "get_source" in md
261
+ assert "get_skill_md" in md
262
+ assert "SERVICE_URL" in md
263
+
264
+
265
+ def test_instruction_block_includes_new_functions():
266
+ from hypha_debugger.debugger import _build_instruction_block
267
+ block = _build_instruction_block("https://example.com/ws/services/py-debugger-abc")
268
+ assert "get_source" in block
269
+ assert "get_skill_md" in block
270
+
271
+
228
272
  def test_debug_session_print_instructions(capsys):
229
273
  from hypha_debugger.debugger import DebugSession
230
274
  session = DebugSession(
File without changes
File without changes