indent 0.1.14__tar.gz → 0.1.16__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 (52) hide show
  1. {indent-0.1.14 → indent-0.1.16}/PKG-INFO +2 -1
  2. {indent-0.1.14 → indent-0.1.16}/exponent/__init__.py +2 -2
  3. {indent-0.1.14 → indent-0.1.16}/exponent/core/remote_execution/cli_rpc_types.py +3 -1
  4. {indent-0.1.14 → indent-0.1.16}/exponent/core/remote_execution/client.py +21 -17
  5. indent-0.1.16/exponent/core/remote_execution/tool_type_utils.py +39 -0
  6. {indent-0.1.14 → indent-0.1.16}/exponent/core/remote_execution/types.py +4 -0
  7. {indent-0.1.14 → indent-0.1.16}/pyproject.toml +1 -0
  8. {indent-0.1.14 → indent-0.1.16}/.gitignore +0 -0
  9. {indent-0.1.14 → indent-0.1.16}/exponent/cli.py +0 -0
  10. {indent-0.1.14 → indent-0.1.16}/exponent/commands/cloud_commands.py +0 -0
  11. {indent-0.1.14 → indent-0.1.16}/exponent/commands/common.py +0 -0
  12. {indent-0.1.14 → indent-0.1.16}/exponent/commands/config_commands.py +0 -0
  13. {indent-0.1.14 → indent-0.1.16}/exponent/commands/run_commands.py +0 -0
  14. {indent-0.1.14 → indent-0.1.16}/exponent/commands/settings.py +0 -0
  15. {indent-0.1.14 → indent-0.1.16}/exponent/commands/types.py +0 -0
  16. {indent-0.1.14 → indent-0.1.16}/exponent/commands/upgrade.py +0 -0
  17. {indent-0.1.14 → indent-0.1.16}/exponent/commands/utils.py +0 -0
  18. {indent-0.1.14 → indent-0.1.16}/exponent/commands/workflow_commands.py +0 -0
  19. {indent-0.1.14 → indent-0.1.16}/exponent/core/config.py +0 -0
  20. {indent-0.1.14 → indent-0.1.16}/exponent/core/graphql/__init__.py +0 -0
  21. {indent-0.1.14 → indent-0.1.16}/exponent/core/graphql/client.py +0 -0
  22. {indent-0.1.14 → indent-0.1.16}/exponent/core/graphql/get_chats_query.py +0 -0
  23. {indent-0.1.14 → indent-0.1.16}/exponent/core/graphql/github_config_queries.py +0 -0
  24. {indent-0.1.14 → indent-0.1.16}/exponent/core/graphql/mutations.py +0 -0
  25. {indent-0.1.14 → indent-0.1.16}/exponent/core/graphql/queries.py +0 -0
  26. {indent-0.1.14 → indent-0.1.16}/exponent/core/graphql/subscriptions.py +0 -0
  27. {indent-0.1.14 → indent-0.1.16}/exponent/core/remote_execution/checkpoints.py +0 -0
  28. {indent-0.1.14 → indent-0.1.16}/exponent/core/remote_execution/code_execution.py +0 -0
  29. {indent-0.1.14 → indent-0.1.16}/exponent/core/remote_execution/error_info.py +0 -0
  30. {indent-0.1.14 → indent-0.1.16}/exponent/core/remote_execution/exceptions.py +0 -0
  31. {indent-0.1.14 → indent-0.1.16}/exponent/core/remote_execution/file_write.py +0 -0
  32. {indent-0.1.14 → indent-0.1.16}/exponent/core/remote_execution/files.py +0 -0
  33. {indent-0.1.14 → indent-0.1.16}/exponent/core/remote_execution/git.py +0 -0
  34. {indent-0.1.14 → indent-0.1.16}/exponent/core/remote_execution/http_fetch.py +0 -0
  35. {indent-0.1.14 → indent-0.1.16}/exponent/core/remote_execution/languages/python_execution.py +0 -0
  36. {indent-0.1.14 → indent-0.1.16}/exponent/core/remote_execution/languages/shell_streaming.py +0 -0
  37. {indent-0.1.14 → indent-0.1.16}/exponent/core/remote_execution/languages/types.py +0 -0
  38. {indent-0.1.14 → indent-0.1.16}/exponent/core/remote_execution/session.py +0 -0
  39. {indent-0.1.14 → indent-0.1.16}/exponent/core/remote_execution/system_context.py +0 -0
  40. {indent-0.1.14 → indent-0.1.16}/exponent/core/remote_execution/tool_execution.py +0 -0
  41. {indent-0.1.14 → indent-0.1.16}/exponent/core/remote_execution/truncation.py +0 -0
  42. {indent-0.1.14 → indent-0.1.16}/exponent/core/remote_execution/utils.py +0 -0
  43. {indent-0.1.14 → indent-0.1.16}/exponent/core/types/__init__.py +0 -0
  44. {indent-0.1.14 → indent-0.1.16}/exponent/core/types/command_data.py +0 -0
  45. {indent-0.1.14 → indent-0.1.16}/exponent/core/types/event_types.py +0 -0
  46. {indent-0.1.14 → indent-0.1.16}/exponent/core/types/generated/__init__.py +0 -0
  47. {indent-0.1.14 → indent-0.1.16}/exponent/core/types/generated/strategy_info.py +0 -0
  48. {indent-0.1.14 → indent-0.1.16}/exponent/migration-docs/login.md +0 -0
  49. {indent-0.1.14 → indent-0.1.16}/exponent/py.typed +0 -0
  50. {indent-0.1.14 → indent-0.1.16}/exponent/utils/__init__.py +0 -0
  51. {indent-0.1.14 → indent-0.1.16}/exponent/utils/colors.py +0 -0
  52. {indent-0.1.14 → indent-0.1.16}/exponent/utils/version.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: indent
3
- Version: 0.1.14
3
+ Version: 0.1.16
4
4
  Summary: Indent is an AI Pair Programmer
5
5
  Author-email: Sashank Thupukari <sashank@exponent.run>
6
6
  Requires-Python: <3.13,>=3.10
@@ -22,6 +22,7 @@ Requires-Dist: msgspec>=0.19.0
22
22
  Requires-Dist: packaging~=24.1
23
23
  Requires-Dist: pip<26,>=25.0.1
24
24
  Requires-Dist: prompt-toolkit<4,>=3.0.36
25
+ Requires-Dist: pydantic-ai==0.0.30
25
26
  Requires-Dist: pydantic-settings<3,>=2.2.1
26
27
  Requires-Dist: pydantic[email]<3,>=2.6.4
27
28
  Requires-Dist: pygit2<2,>=1.15.0
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
28
28
  commit_id: COMMIT_ID
29
29
  __commit_id__: COMMIT_ID
30
30
 
31
- __version__ = version = '0.1.14'
32
- __version_tuple__ = version_tuple = (0, 1, 14)
31
+ __version__ = version = '0.1.16'
32
+ __version_tuple__ = version_tuple = (0, 1, 16)
33
33
 
34
34
  __commit_id__ = commit_id = None
@@ -2,6 +2,7 @@ from typing import TYPE_CHECKING, Any
2
2
 
3
3
  import msgspec
4
4
  import yaml
5
+ from pydantic_ai.format_as_xml import format_as_xml
5
6
 
6
7
  if TYPE_CHECKING:
7
8
  from exponent_server.core.tools.edit_tool import (
@@ -28,6 +29,7 @@ class ToolInput(msgspec.Struct, tag_field="tool_name", omit_defaults=True):
28
29
  return msgspec.to_builtins(self) # type: ignore[no-any-return]
29
30
 
30
31
  def to_text(self) -> str:
32
+ """This text is purely used for human debugging, it's not fed to the llm"""
31
33
  d = msgspec.to_builtins(self)
32
34
  del d["tool_name"]
33
35
  return yaml.dump(d)
@@ -41,7 +43,7 @@ class ToolResult(msgspec.Struct, tag_field="tool_name", omit_defaults=True):
41
43
  This provides a default textual representation of the tool result. Override it as needed for your tool."""
42
44
  d = msgspec.to_builtins(self)
43
45
  del d["tool_name"]
44
- return yaml.dump(d)
46
+ return format_as_xml(d, include_root_tag=False, item_tag="item")
45
47
 
46
48
 
47
49
  class ErrorToolResult(ToolResult, tag="error"):
@@ -5,7 +5,7 @@ import json
5
5
  import logging
6
6
  import time
7
7
  import uuid
8
- from collections.abc import AsyncGenerator, Callable, Generator
8
+ from collections.abc import AsyncGenerator, Callable, Coroutine, Generator
9
9
  from contextlib import asynccontextmanager
10
10
  from dataclasses import dataclass
11
11
  from typing import Any, TypeVar, cast
@@ -30,6 +30,7 @@ from exponent.core.remote_execution.cli_rpc_types import (
30
30
  CliRpcRequest,
31
31
  CliRpcResponse,
32
32
  ErrorResponse,
33
+ ErrorToolResult,
33
34
  GetAllFilesRequest,
34
35
  GetAllFilesResponse,
35
36
  HttpRequest,
@@ -611,33 +612,36 @@ class RemoteExecutionClient:
611
612
  response=GetAllFilesResponse(files=files),
612
613
  )
613
614
  elif isinstance(request.request, BatchToolExecutionRequest):
614
- results: list[ToolResultType] = []
615
+ coros: list[Coroutine[Any, Any, ToolResultType]] = []
615
616
  for tool_input in request.request.tool_inputs:
616
- try:
617
- if isinstance(tool_input, BashToolInput):
618
- raw_result = await execute_bash_tool(
617
+ if isinstance(tool_input, BashToolInput):
618
+ coros.append(
619
+ execute_bash_tool(
619
620
  tool_input,
620
621
  self.working_directory,
621
622
  should_halt=self.get_halt_check(request.request_id),
622
623
  )
623
- else:
624
- raw_result = await execute_tool( # type: ignore[assignment]
625
- tool_input, self.working_directory
626
- )
627
- tool_result = truncate_result(raw_result)
628
- results.append(tool_result)
629
- except Exception as e:
630
- logger.error(f"Error executing tool {tool_input}: {e}")
631
- from exponent.core.remote_execution.cli_rpc_types import (
632
- ErrorToolResult,
633
624
  )
625
+ else:
626
+ coros.append(execute_tool(tool_input, self.working_directory))
627
+
628
+ results: list[ToolResultType | BaseException] = await asyncio.gather(
629
+ *coros, return_exceptions=True
630
+ )
634
631
 
635
- results.append(ErrorToolResult(error_message=str(e)))
632
+ processed_results: list[ToolResultType] = []
633
+ for result in results:
634
+ if not isinstance(result, BaseException):
635
+ processed_results.append(truncate_result(result))
636
+ else:
637
+ processed_results.append(
638
+ ErrorToolResult(error_message=str(result))
639
+ )
636
640
 
637
641
  return CliRpcResponse(
638
642
  request_id=request.request_id,
639
643
  response=BatchToolExecutionResponse(
640
- tool_results=results,
644
+ tool_results=processed_results,
641
645
  ),
642
646
  )
643
647
  elif isinstance(request.request, HttpRequest):
@@ -0,0 +1,39 @@
1
+ from typing import Any
2
+
3
+ import msgspec
4
+
5
+ from exponent.core.remote_execution.cli_rpc_types import ToolResult
6
+
7
+
8
+ def to_mostly_xml(tool_result: ToolResult) -> str:
9
+ """
10
+ This provides a default textual representation of the tool result. Override it as needed for your tool."""
11
+ d = msgspec.to_builtins(tool_result)
12
+ del d["tool_name"]
13
+ return to_mostly_xml_helper(d)
14
+
15
+
16
+ def to_mostly_xml_helper(
17
+ d: Any,
18
+ ) -> str:
19
+ if isinstance(d, dict):
20
+ # No outer wrapper at top level, each field gets XML tags
21
+ parts = []
22
+ for key, value in d.items():
23
+ if isinstance(value, list):
24
+ # Handle lists with item tags
25
+ list_items = "\n".join(
26
+ f"<item>\n{to_mostly_xml_helper(item)}\n</item>" for item in value
27
+ )
28
+ parts.append(f"<{key}>\n{list_items}\n</{key}>")
29
+ elif isinstance(value, dict):
30
+ # Nested dict
31
+ parts.append(f"<{key}>\n{to_mostly_xml_helper(value)}\n</{key}>")
32
+ else:
33
+ # Scalar value
34
+ parts.append(f"<{key}>\n{value!s}\n</{key}>")
35
+ return "\n".join(parts)
36
+ elif isinstance(d, list):
37
+ raise ValueError("Lists are not allowed at the top level")
38
+ else:
39
+ return str(d)
@@ -517,6 +517,10 @@ class ChatMode(str, Enum):
517
517
  DATABASE = "DATABASE" # chat with database connection
518
518
  WORKFLOW = "WORKFLOW"
519
519
 
520
+ @classmethod
521
+ def requires_cli(cls, mode: "ChatMode") -> bool:
522
+ return mode not in [cls.DATABASE]
523
+
520
524
 
521
525
  class ChatSource(str, Enum):
522
526
  CLI_SHELL = "CLI_SHELL"
@@ -21,6 +21,7 @@ dependencies = [
21
21
  "prompt-toolkit>=3.0.36,<4",
22
22
  "pydantic[email]>=2.6.4,<3",
23
23
  "pydantic-settings>=2.2.1,<3",
24
+ "pydantic-ai==0.0.30",
24
25
  "pygit2>=1.15.0,<2",
25
26
  "questionary>=2.0.1,<3",
26
27
  "rapidfuzz>=3.9.0,<4",
File without changes
File without changes
File without changes
File without changes