gitcode-api 1.2.9__py3-none-any.whl → 1.2.11__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.
@@ -3,6 +3,8 @@
3
3
  from importlib import import_module
4
4
  from typing import TYPE_CHECKING, Any, Dict
5
5
 
6
+ from ._tool import GitCodeLLMTool
7
+
6
8
  if TYPE_CHECKING:
7
9
  from .jiuwen import create_openjiuwen_gitcode_api_tool
8
10
  from .mcp import (
@@ -25,7 +27,7 @@ _IMPORT_MAP = {
25
27
  "create_openjiuwen_gitcode_api_tool": ".jiuwen",
26
28
  }
27
29
 
28
- _IMPORT_CACHE: Dict[str, Any] = {}
30
+ _IMPORT_CACHE: Dict[str, Any] = {"GitCodeLLMTool": GitCodeLLMTool}
29
31
 
30
32
 
31
33
  def __getattr__(name: str) -> object:
@@ -50,6 +52,7 @@ def __dir__() -> list[str]:
50
52
 
51
53
 
52
54
  __all__ = [
55
+ "GitCodeLLMTool",
53
56
  "GitCodeOpenAITool",
54
57
  "GitCodeMCP",
55
58
  "create_mcp_gitcode_api_tool",
gitcode_api/llm/_tool.py CHANGED
@@ -227,11 +227,11 @@ class GitCodeLLMTool:
227
227
  :param client: Optional synchronous GitCode client.
228
228
  :param async_client: Optional asynchronous GitCode client.
229
229
  :param api_key: Personal access token used when clients are not supplied.
230
- :param owner: Default repository owner for generated clients.
231
- :param repo: Default repository name for generated clients.
232
230
  :param base_url: Base URL for generated clients.
233
231
  :param timeout: Request timeout for generated clients.
234
232
  :param decrypt: Optional decryption function for encrypted access tokens.
233
+ :param owner: Default repository owner for generated clients.
234
+ :param repo: Default repository name for generated clients.
235
235
  """
236
236
 
237
237
  def __init__(
@@ -240,11 +240,11 @@ class GitCodeLLMTool:
240
240
  client: Optional[GitCode] = None,
241
241
  async_client: Optional[AsyncGitCode] = None,
242
242
  api_key: Optional[str] = None,
243
- owner: Optional[str] = None,
244
- repo: Optional[str] = None,
245
243
  base_url: str = DEFAULT_BASE_URL,
246
244
  timeout: Optional[float] = None,
247
245
  decrypt: Optional[Callable] = None,
246
+ owner: Optional[str] = None,
247
+ repo: Optional[str] = None,
248
248
  ) -> None:
249
249
  """Create a reusable tool with lazy sync and async clients."""
250
250
  self._client = client
gitcode_api/llm/jiuwen.py CHANGED
@@ -11,6 +11,7 @@ from ._tool import TOOL_DESCRIPTION, TOOL_NAME, TOOL_PARAMETERS, GitCodeLLMTool
11
11
  if TYPE_CHECKING:
12
12
  from openjiuwen.core.foundation.tool import LocalFunction
13
13
 
14
+
14
15
  def _missing_openjiuwen_error() -> ImportError:
15
16
  return ImportError(
16
17
  "The openJiuwen tool support requires the optional dependency: pip install openjiuwen. "
@@ -29,8 +30,30 @@ def _openjiuwen_tool_decorator() -> Callable[..., Any]:
29
30
  class _GitCodeJiuwenTool(GitCodeLLMTool):
30
31
  """Build an openJiuwen ``LocalFunction`` bound to :class:`GitCodeLLMTool` (async invoke only)."""
31
32
 
32
- def __init__(self, *, name: Optional[str] = None, description: Optional[str] = None, **kwargs) -> None:
33
- super().__init__(**kwargs)
33
+ def __init__(
34
+ self,
35
+ *,
36
+ name: Optional[str] = None,
37
+ description: Optional[str] = None,
38
+ client: Optional[GitCode] = None,
39
+ async_client: Optional[AsyncGitCode] = None,
40
+ api_key: Optional[str] = None,
41
+ base_url: str = DEFAULT_BASE_URL,
42
+ timeout: Optional[float] = None,
43
+ decrypt: Optional[Callable[..., Any]] = None,
44
+ owner: Optional[str] = None,
45
+ repo: Optional[str] = None,
46
+ ) -> None:
47
+ super().__init__(
48
+ client=client,
49
+ async_client=async_client,
50
+ api_key=api_key,
51
+ owner=owner,
52
+ repo=repo,
53
+ base_url=base_url,
54
+ timeout=timeout,
55
+ decrypt=decrypt,
56
+ )
34
57
  tool_name = name if name is not None else TOOL_NAME
35
58
  tool_description = description if description is not None else TOOL_DESCRIPTION
36
59
  oj_tool = _openjiuwen_tool_decorator()
@@ -59,11 +82,11 @@ def create_openjiuwen_gitcode_api_tool(
59
82
  client: Optional[GitCode] = None,
60
83
  async_client: Optional[AsyncGitCode] = None,
61
84
  api_key: Optional[str] = None,
62
- owner: Optional[str] = None,
63
- repo: Optional[str] = None,
64
85
  base_url: str = DEFAULT_BASE_URL,
65
86
  timeout: Optional[float] = None,
66
87
  decrypt: Optional[Callable[..., Any]] = None,
88
+ owner: Optional[str] = None,
89
+ repo: Optional[str] = None,
67
90
  ) -> "LocalFunction":
68
91
  """Create an openJiuwen ``LocalFunction`` for the GitCode API tool.
69
92
 
@@ -72,11 +95,11 @@ def create_openjiuwen_gitcode_api_tool(
72
95
  :param client: Optional synchronous GitCode client.
73
96
  :param async_client: Optional asynchronous GitCode client.
74
97
  :param api_key: Personal access token when clients are not supplied.
75
- :param owner: Default repository owner for generated clients.
76
- :param repo: Default repository name for generated clients.
77
98
  :param base_url: Base URL for generated clients.
78
99
  :param timeout: Request timeout for generated clients.
79
100
  :param decrypt: Optional decryption function for encrypted access tokens.
101
+ :param owner: Default repository owner for generated clients.
102
+ :param repo: Default repository name for generated clients.
80
103
  :returns: openJiuwen ``LocalFunction`` with the standard parameter schema.
81
104
  """
82
105
  adapter = _GitCodeJiuwenTool(
gitcode_api/llm/openai.py CHANGED
@@ -1,7 +1,11 @@
1
1
  """OpenAI tool adapter for the GitCode SDK."""
2
2
 
3
+ import json
3
4
  from functools import cached_property
4
- from typing import Any, Dict, Optional
5
+ from typing import Any, Callable, Coroutine, Dict, Optional, Union
6
+
7
+ from gitcode_api import AsyncGitCode, GitCode
8
+ from gitcode_api._base_client import DEFAULT_BASE_URL
5
9
 
6
10
  from ._tool import TOOL_DESCRIPTION, TOOL_NAME, TOOL_PARAMETERS, GitCodeLLMTool
7
11
 
@@ -10,25 +14,49 @@ class GitCodeOpenAITool(GitCodeLLMTool):
10
14
  """OpenAI-compatible callable tool for invoking GitCode SDK resources.
11
15
 
12
16
  :param async_mode: When true, calling the instance returns the async tool coroutine.
13
- :param kwargs: Forwarded to :class:`gitcode_api.llm.GitCodeLLMTool`. ``{"async": True}``
14
- is also accepted for frameworks that construct tools from dictionaries.
17
+ :param indent: ``indent`` argument passed to :func:`json.dumps` when serializing
18
+ invocation results (default ``2``).
19
+ :param client: Optional synchronous GitCode client.
20
+ :param async_client: Optional asynchronous GitCode client.
21
+ :param api_key: Personal access token used when clients are not supplied.
22
+ :param base_url: Base URL for generated clients.
23
+ :param timeout: Request timeout for generated clients.
24
+ :param decrypt: Optional decryption function for encrypted access tokens.
25
+ :param owner: Default repository owner for generated clients.
26
+ :param repo: Default repository name for generated clients.
15
27
  """
16
28
 
17
29
  name = TOOL_NAME
18
30
  description = TOOL_DESCRIPTION
19
31
  parameters = TOOL_PARAMETERS
20
32
 
21
- def __init__(self, async_mode: Optional[bool] = None, **kwargs) -> None:
33
+ def __init__(
34
+ self,
35
+ async_mode: bool = False,
36
+ indent: int = 2,
37
+ *,
38
+ client: Optional[GitCode] = None,
39
+ async_client: Optional[AsyncGitCode] = None,
40
+ api_key: Optional[str] = None,
41
+ base_url: str = DEFAULT_BASE_URL,
42
+ timeout: Optional[float] = None,
43
+ decrypt: Optional[Callable] = None,
44
+ owner: Optional[str] = None,
45
+ repo: Optional[str] = None,
46
+ ) -> None:
22
47
  """Create an OpenAI tool wrapper."""
23
- async_kw = kwargs.pop("async", None)
24
- if async_mode is None:
25
- async_mode = bool(async_kw)
26
- elif async_kw is not None:
27
- raise TypeError("Pass only one of async_mode or async")
48
+ self.indent = indent
28
49
  self.async_mode = bool(async_mode)
29
- super().__init__(**kwargs)
30
- if self.async_mode:
31
- self.__call__ = self.__async_call__ # type: ignore[method-assign]
50
+ super().__init__(
51
+ client=client,
52
+ async_client=async_client,
53
+ api_key=api_key,
54
+ owner=owner,
55
+ repo=repo,
56
+ base_url=base_url,
57
+ timeout=timeout,
58
+ decrypt=decrypt,
59
+ )
32
60
 
33
61
  @cached_property
34
62
  def tool(self) -> Dict[str, Any]:
@@ -46,11 +74,15 @@ class GitCodeOpenAITool(GitCodeLLMTool):
46
74
  """Return this tool in OpenAI Chat Completions tool format."""
47
75
  return self.tool
48
76
 
49
- def __call__(self, *args: Any, **kwargs) -> Any:
77
+ async def __async_call__(self, *args, **kwargs) -> str:
78
+ result = await super().__async_call__(*args, **kwargs)
79
+ return json.dumps(result, ensure_ascii=False, indent=self.indent)
80
+
81
+ def __call__(self, *args, **kwargs) -> Union[str, Coroutine[Any, Any, str]]:
50
82
  """Invoke the configured sync or async tool callable."""
51
83
  if self.async_mode:
52
84
  return self.__async_call__(*args, **kwargs)
53
- return super().__call__(*args, **kwargs)
85
+ return json.dumps(super().__call__(*args, **kwargs), ensure_ascii=False, indent=self.indent)
54
86
 
55
87
 
56
88
  __all__ = ["GitCodeOpenAITool"]
gitcode_api/version.txt CHANGED
@@ -1 +1 @@
1
- 1.2.9
1
+ 1.2.11
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gitcode-api
3
- Version: 1.2.9
3
+ Version: 1.2.11
4
4
  Summary: Easy to use Python SDK for the GitCode REST API. Providing builtin CLI tool, and optional LLM integration (MCP, OpenAI tool, and openJiuwen tool) for agents. Community-maintained.
5
5
  Author-email: Hugo Huang <hugo@hugohuang.com>
6
6
  License-Expression: MIT
@@ -231,7 +231,7 @@ Every resource group inherits a cached `methods` property from the shared resour
231
231
 
232
232
  ## LLM tools, MCP, and openJiuwen
233
233
 
234
- The `gitcode_api.llm` module exposes a single logical tool, **`gitcode_api_tool`**, that routes calls to sync or async SDK resources. Model-facing parameters match the JSON schema used by OpenAI-style function tools:
234
+ The `gitcode_api.llm` module exposes a single unified tool, **`gitcode_api_tool`**, that routes calls to respective sync or async SDK resource groups. Model-facing parameters match the JSON schema used by OpenAI-style function tools:
235
235
 
236
236
  | Parameter | Role |
237
237
  | --- | --- |
@@ -240,11 +240,11 @@ The `gitcode_api.llm` module exposes a single logical tool, **`gitcode_api_tool`
240
240
  | `params` | Keyword arguments for the method as a JSON object; omitted or `null` is treated as `{}`. |
241
241
  | `help` | When `true`, returns formatted help (available methods or a target signature) instead of performing a normal API call where applicable. |
242
242
 
243
- Successful results are JSON-friendly (`APIObject.to_dict()`, base64-wrapped `bytes`, and similar). Failures are returned as objects with `"error": true` and a `"message"` string (HTTP and configuration errors include extra fields when available).
243
+ Tool payloads are JSON-serialized strings: successes look like plain objects (`APIObject.to_dict()`, base64-wrapped `bytes`, and similar); failures use `"error": true`, a `"message"` string, and optional extra fields on HTTP/configuration errors.
244
244
 
245
245
  ### OpenAI tool (`GitCodeOpenAITool`)
246
246
 
247
- No extra dependencies beyond the core package. Build a Chat Completions–style tool definition with `.tool` or `.to_dict()`, then invoke the same instance with the arguments above (sync) or configure async mode for `await`.
247
+ No extra dependencies beyond the core package. Build a Chat Completions–style tool definition with `.tool` or `.to_dict()`, then invoke the same instance with the arguments above (sync) or configure async mode for `await`. Each invocation applies `json.dumps` to payload so the return type is **always `str`**. The default keyword argument `indent=2` pretty-prints JSON; pass `indent=None` for a compact single-line string.
248
248
 
249
249
  ```python
250
250
  from gitcode_api.llm import GitCodeOpenAITool
@@ -265,33 +265,43 @@ and handle tool calls directly:
265
265
 
266
266
  ```python
267
267
  import json
268
- from openai import OpenAI
269
- from gitcode_api.llm import GitCodeOpenAITool
268
+ import os
269
+ from typing import Dict, List
270
270
 
271
- tools = {
272
- "gitcode_api_tool": GitCodeOpenAITool(owner="SushiNinja", repo="GitCode-API"),
273
- }
274
- client = OpenAI(
275
- api_key="your-openai-compatible-api-key",
276
- base_url="https://your-openai-compatible-base-url/v1",
277
- )
271
+ from openai import OpenAI
278
272
 
279
- response = client.chat.completions.create(
280
- model="gpt-4.1-mini",
281
- messages=[{"role": "user", "content": "List the last 5 commits."}],
282
- tools=[tools["gitcode_api_tool"].tool],
283
- )
273
+ from gitcode_api.llm import GitCodeOpenAITool
284
274
 
285
- for tool_call in response.choices[0].message.tool_calls:
286
- selected_tool = tools[tool_call.function.name]
287
- print(f"Calling tool {tool_call.function.name}({tool_call.function.arguments}):")
288
- print("---result---")
289
- print(selected_tool(**json.loads(tool_call.function.arguments)))
290
- print("---result---")
275
+ MESSAGE_SEP = "\n" + "=" * 60 + "\n"
276
+ USER_QUERY = "List the repos owned by SushiNinja."
277
+ CONVERSATION: List[Dict[str, str]] = [dict(role="user", content=USER_QUERY)]
278
+
279
+ tools = {"gitcode_api_tool": GitCodeOpenAITool()}
280
+ client = OpenAI()
281
+
282
+ print("U:\n" + USER_QUERY + MESSAGE_SEP)
283
+ while True:
284
+ response = (
285
+ client.chat.completions.create(
286
+ model="gpt-5.4-nano",
287
+ messages=CONVERSATION,
288
+ tools=[tools["gitcode_api_tool"].tool],
289
+ )
290
+ .choices[0]
291
+ .message
292
+ )
293
+ CONVERSATION.append(response.to_dict())
294
+ print("A:\n" + (response.content or ""))
295
+ for tool_call in response.tool_calls or []:
296
+ selected_tool = tools[tool_call.function.name]
297
+ result = selected_tool(**json.loads(tool_call.function.arguments))
298
+ CONVERSATION.append(dict(role="tool", tool_call_id=tool_call.id, content=result))
299
+ print(f"<Calling tool {tool_call.function.name}({tool_call.function.arguments})>")
300
+ print(MESSAGE_SEP)
301
+ if not response.tool_calls:
302
+ break
291
303
  ```
292
304
 
293
- Constructor options mirror `GitCode` / `AsyncGitCode`: `client=`, `async_client=`, `api_key=`, `owner=`, `repo=`, `base_url=`, `timeout=`, and `decrypt=`. For dict-driven setups that reserve the name `async`, you may pass `**{"async": True}` instead of `async_mode=True` (but not both).
294
-
295
305
  ### MCP server and MCP tool (FastMCP)
296
306
 
297
307
  [MCP](https://modelcontextprotocol.io) integration uses [FastMCP](https://github.com/jlowin/fastmcp). Install the optional extra (requires **Python 3.10+** because of the `fastmcp` dependency):
@@ -9,21 +9,21 @@ gitcode_api/_models.py,sha256=v-GZzCGAb3_frY6wFiQww9m271U5MigivpEHDHnoDcI,109030
9
9
  gitcode_api/cli.py,sha256=7LLDRCKJg7avaLgIwckZZC5LewSpMPWNQFFDRhAQkEs,16616
10
10
  gitcode_api/py.typed,sha256=mDShSrm8qg9qjacQc2F-rI8ATllqP6EdgHuEYxuCXZ0,7
11
11
  gitcode_api/run_mcp.py,sha256=a7zNrcAooGovzokJwTHQGj6iT4g7iltaUoD_E1KLvMg,130
12
- gitcode_api/version.txt,sha256=yNg8JnLF45fOFqLuJ1rEWRcAK5s2dl932Z8xvfge6Cg,6
13
- gitcode_api/llm/__init__.py,sha256=7xD9jHpk0eE12J8SQ3G0SB-8A0wEUoAsdx6SOBW6OUI,1604
14
- gitcode_api/llm/_tool.py,sha256=mBQPYzQ-SuSWgumapcjv3pjGQfcPYt-IxUXBT5un2Lk,16239
15
- gitcode_api/llm/jiuwen.py,sha256=7AqvBH4x0sCa4LxlRdImdph22mL6eSkCE0FL5BoMwzU,3637
12
+ gitcode_api/version.txt,sha256=NzEMfzSBZRIsy59KhUwpSFOVuzrwZZulp3vgZsFRFnk,7
13
+ gitcode_api/llm/__init__.py,sha256=rU75ZlJvTWNVxBLc3QzdfWmSjqVc9z6hfQ8z6jVVKOk,1693
14
+ gitcode_api/llm/_tool.py,sha256=b65iUiHo1H29uA6mFM3WlD0zZlISsENx1tpEqlkiUoA,16239
15
+ gitcode_api/llm/jiuwen.py,sha256=axwAcoG86XkPkN37PTh47Cdzwh3yACUpe4bTjlaAFDc,4244
16
16
  gitcode_api/llm/mcp.py,sha256=eeAuEETZ4THw31wbcnQaTlZQJ-9ZolvsejQY630OqHs,5702
17
- gitcode_api/llm/openai.py,sha256=CcS3tFntzAuN2HMbbQDctb54AnasU3n3a1Jr9LWAHwM,1998
17
+ gitcode_api/llm/openai.py,sha256=r8LZi3oK9D80dfiPpv1TpP-PwKUXpAGqgNGE3hOIAaA,3200
18
18
  gitcode_api/resources/__init__.py,sha256=nsCKW0bFDZ5ombJZxLThmO82sOuF7o4OKUMRkAmwbwk,1725
19
19
  gitcode_api/resources/_shared.py,sha256=7bCym8bIfs818SiYYrBGI7-ZtiYlxECSDG3RduInu10,5387
20
20
  gitcode_api/resources/account.py,sha256=mnc2p7wI-nBnHFNdWPNiHfmZpT6d3RDQC777gewtm4M,38801
21
21
  gitcode_api/resources/collaboration.py,sha256=8lyk78GTjVXddiE9fieutsMGovRjteGfTJcAhwLoR0M,101607
22
22
  gitcode_api/resources/misc.py,sha256=guDwh4cxbTVsSa7EivaYM3bKMJ8_Op4KucGbKEoayKE,22412
23
23
  gitcode_api/resources/repositories.py,sha256=EAK2znZhEsgVUu-NDEQslSEEYJzvb-kHuh4mW57y6sc,78178
24
- gitcode_api-1.2.9.dist-info/licenses/LICENSE,sha256=gOACXuWhMu6PJKVLr9RQbxX3HULnZIGNXCaMFJIXhoA,1067
25
- gitcode_api-1.2.9.dist-info/METADATA,sha256=01794VzZAr36F-7Eg0MeHGJuAmTSHciiUosdj18igBs,21768
26
- gitcode_api-1.2.9.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
27
- gitcode_api-1.2.9.dist-info/entry_points.txt,sha256=dIPylJcgohIE2RRIlt3In2WzcwDK8TOdkL_ReKuij4o,53
28
- gitcode_api-1.2.9.dist-info/top_level.txt,sha256=gIlg0ptyOUHJT64ajOjWIhRPYgIQnMIvnhhnesw9fxU,12
29
- gitcode_api-1.2.9.dist-info/RECORD,,
24
+ gitcode_api-1.2.11.dist-info/licenses/LICENSE,sha256=gOACXuWhMu6PJKVLr9RQbxX3HULnZIGNXCaMFJIXhoA,1067
25
+ gitcode_api-1.2.11.dist-info/METADATA,sha256=3VOsMVB8v0K7pMtOetkpLGH4UJjeF9R_QsEmF9GbZrs,22054
26
+ gitcode_api-1.2.11.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
27
+ gitcode_api-1.2.11.dist-info/entry_points.txt,sha256=dIPylJcgohIE2RRIlt3In2WzcwDK8TOdkL_ReKuij4o,53
28
+ gitcode_api-1.2.11.dist-info/top_level.txt,sha256=gIlg0ptyOUHJT64ajOjWIhRPYgIQnMIvnhhnesw9fxU,12
29
+ gitcode_api-1.2.11.dist-info/RECORD,,