cteno-sdk 2.10.13__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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) Cteno contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,119 @@
1
+ Metadata-Version: 2.4
2
+ Name: cteno-sdk
3
+ Version: 2.10.13
4
+ Summary: Run Cteno agents from Python. Platform wheels bundle a local Cteno daemon; no desktop app or account needed.
5
+ Author: Cteno contributors
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/zalan159/cteno-sdk
8
+ Project-URL: Source, https://github.com/zalan159/cteno-sdk/tree/main/python
9
+ Project-URL: Issues, https://github.com/zalan159/cteno-sdk/issues
10
+ Project-URL: Changelog, https://github.com/zalan159/cteno-sdk/blob/main/CHANGELOG.md
11
+ Keywords: cteno,agent,sdk,llm,ai-agent
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3 :: Only
16
+ Classifier: Framework :: AsyncIO
17
+ Classifier: Operating System :: MacOS
18
+ Classifier: Operating System :: POSIX :: Linux
19
+ Classifier: Operating System :: Microsoft :: Windows
20
+ Requires-Python: >=3.9
21
+ Description-Content-Type: text/markdown
22
+ License-File: LICENSE
23
+ Dynamic: license-file
24
+
25
+ # cteno-sdk (Python)
26
+
27
+ Run Cteno agents from Python — same protocol and shape as the Node package
28
+ `@cteno/sdk`. Standard library only, Python ≥ 3.9, asyncio.
29
+
30
+ > **The PyPI package is coming soon** (with Cteno 2.10.12). Until then, install from
31
+ > source with `pip install ./python` and point the SDK at a daemon: see the repository
32
+ > README, "Use from source".
33
+
34
+ The platform wheels (planned: macOS arm64/x64, Linux x64 with glibc ≥ 2.34, Windows x64;
35
+ Linux arm64 is not supported yet)
36
+ include the Cteno daemon. `CtenoSession.open()` starts it in local mode on first use:
37
+ no desktop app, no account, your own model key.
38
+
39
+ ## Install
40
+
41
+ ```bash
42
+ # coming soon — not published yet
43
+ pip install cteno-sdk
44
+ ```
45
+
46
+ On a platform without a wheel pip falls back to the sdist, which has no daemon: set
47
+ `CTENO_SDK_DAEMON_PATH` to a `cteno-host-cli` binary, or pass `socket_path` to a daemon
48
+ you run yourself.
49
+
50
+ ## Quickstart
51
+
52
+ ```python
53
+ import asyncio, os
54
+ from cteno_sdk import CtenoSession
55
+
56
+ async def main():
57
+ async with await CtenoSession.open() as cteno: # starts the bundled daemon if needed
58
+ await cteno.configure_model(base_url="https://api.openai.com/v1", model="gpt-4.1-mini",
59
+ api_key=os.environ["OPENAI_API_KEY"]) # once; stays the default
60
+ sid = await cteno.create(cwd=".")
61
+ result = await cteno.run(sid, "Reply with exactly: hello from Cteno")
62
+ print(result.text if result.ok else result.error) # hello from Cteno
63
+ await cteno.close_session(sid)
64
+
65
+ asyncio.run(main())
66
+ ```
67
+
68
+ Tools that are not read-only are denied at once unless you approve them:
69
+
70
+ ```python
71
+ result = await cteno.run(sid, "Run the tests", can_use_tool=lambda req: req["tool_name"] == "Bash")
72
+ ```
73
+
74
+ `can_use_tool` may be async and may return `{"allow": False, "reason": "..."}`. The
75
+ daemon keeps running after your process exits; `await stop_daemon()` stops it.
76
+
77
+ ## Your own agent
78
+
79
+ ```python
80
+ import asyncio
81
+ from cteno_sdk import CtenoSession, AgentSpec, ClientTool
82
+
83
+ async def search_places(args, ctx): # runs in YOUR process
84
+ return {"name": "Quiet Corner Cafe", "keyword": args["keyword"]}
85
+
86
+ async def main():
87
+ async with await CtenoSession.open() as cteno: # bundled daemon, or open("/path/to/host.sock")
88
+ sid = await cteno.create(model="my-profile", spec=AgentSpec(
89
+ system_prompt="You are a city guide.",
90
+ tools={"allow": []},
91
+ client_tools=[ClientTool("search_places", "Search places",
92
+ {"type": "object", "properties": {"keyword": {"type": "string"}},
93
+ "required": ["keyword"]},
94
+ handler=search_places)],
95
+ limits={"maxIterations": 10, "turnTimeoutMs": 60_000},
96
+ ))
97
+ result = await cteno.run(sid, "Somewhere quiet for coffee?", timeout=90)
98
+ print(result.ok, result.text, result.tool_calls)
99
+ await cteno.close_session(sid)
100
+
101
+ asyncio.run(main())
102
+ ```
103
+
104
+ `AgentSpec` (custom prompt, client tools, terminal tools, output schema, limits,
105
+ history, tenant) is supported by the bundled daemon; with an explicit `socket_path` to
106
+ another daemon it needs ≥ 2.10.10 (`"sdk-session-spec-v1" in await cteno.capabilities()`).
107
+ See the [repository README](../README.md) for authentication and compatibility, and
108
+ the Node [README](../js/README.md) for the full spec field reference (same fields, snake_case here).
109
+
110
+ ## Tests
111
+
112
+ ```bash
113
+ python -m unittest discover -s tests
114
+ ```
115
+
116
+ ## License
117
+
118
+ MIT. The daemon binaries under `cteno_sdk/_bin` are not MIT; see
119
+ `cteno_sdk/_bin/LICENSE.daemon` in the wheel.
@@ -0,0 +1,95 @@
1
+ # cteno-sdk (Python)
2
+
3
+ Run Cteno agents from Python — same protocol and shape as the Node package
4
+ `@cteno/sdk`. Standard library only, Python ≥ 3.9, asyncio.
5
+
6
+ > **The PyPI package is coming soon** (with Cteno 2.10.12). Until then, install from
7
+ > source with `pip install ./python` and point the SDK at a daemon: see the repository
8
+ > README, "Use from source".
9
+
10
+ The platform wheels (planned: macOS arm64/x64, Linux x64 with glibc ≥ 2.34, Windows x64;
11
+ Linux arm64 is not supported yet)
12
+ include the Cteno daemon. `CtenoSession.open()` starts it in local mode on first use:
13
+ no desktop app, no account, your own model key.
14
+
15
+ ## Install
16
+
17
+ ```bash
18
+ # coming soon — not published yet
19
+ pip install cteno-sdk
20
+ ```
21
+
22
+ On a platform without a wheel pip falls back to the sdist, which has no daemon: set
23
+ `CTENO_SDK_DAEMON_PATH` to a `cteno-host-cli` binary, or pass `socket_path` to a daemon
24
+ you run yourself.
25
+
26
+ ## Quickstart
27
+
28
+ ```python
29
+ import asyncio, os
30
+ from cteno_sdk import CtenoSession
31
+
32
+ async def main():
33
+ async with await CtenoSession.open() as cteno: # starts the bundled daemon if needed
34
+ await cteno.configure_model(base_url="https://api.openai.com/v1", model="gpt-4.1-mini",
35
+ api_key=os.environ["OPENAI_API_KEY"]) # once; stays the default
36
+ sid = await cteno.create(cwd=".")
37
+ result = await cteno.run(sid, "Reply with exactly: hello from Cteno")
38
+ print(result.text if result.ok else result.error) # hello from Cteno
39
+ await cteno.close_session(sid)
40
+
41
+ asyncio.run(main())
42
+ ```
43
+
44
+ Tools that are not read-only are denied at once unless you approve them:
45
+
46
+ ```python
47
+ result = await cteno.run(sid, "Run the tests", can_use_tool=lambda req: req["tool_name"] == "Bash")
48
+ ```
49
+
50
+ `can_use_tool` may be async and may return `{"allow": False, "reason": "..."}`. The
51
+ daemon keeps running after your process exits; `await stop_daemon()` stops it.
52
+
53
+ ## Your own agent
54
+
55
+ ```python
56
+ import asyncio
57
+ from cteno_sdk import CtenoSession, AgentSpec, ClientTool
58
+
59
+ async def search_places(args, ctx): # runs in YOUR process
60
+ return {"name": "Quiet Corner Cafe", "keyword": args["keyword"]}
61
+
62
+ async def main():
63
+ async with await CtenoSession.open() as cteno: # bundled daemon, or open("/path/to/host.sock")
64
+ sid = await cteno.create(model="my-profile", spec=AgentSpec(
65
+ system_prompt="You are a city guide.",
66
+ tools={"allow": []},
67
+ client_tools=[ClientTool("search_places", "Search places",
68
+ {"type": "object", "properties": {"keyword": {"type": "string"}},
69
+ "required": ["keyword"]},
70
+ handler=search_places)],
71
+ limits={"maxIterations": 10, "turnTimeoutMs": 60_000},
72
+ ))
73
+ result = await cteno.run(sid, "Somewhere quiet for coffee?", timeout=90)
74
+ print(result.ok, result.text, result.tool_calls)
75
+ await cteno.close_session(sid)
76
+
77
+ asyncio.run(main())
78
+ ```
79
+
80
+ `AgentSpec` (custom prompt, client tools, terminal tools, output schema, limits,
81
+ history, tenant) is supported by the bundled daemon; with an explicit `socket_path` to
82
+ another daemon it needs ≥ 2.10.10 (`"sdk-session-spec-v1" in await cteno.capabilities()`).
83
+ See the [repository README](../README.md) for authentication and compatibility, and
84
+ the Node [README](../js/README.md) for the full spec field reference (same fields, snake_case here).
85
+
86
+ ## Tests
87
+
88
+ ```bash
89
+ python -m unittest discover -s tests
90
+ ```
91
+
92
+ ## License
93
+
94
+ MIT. The daemon binaries under `cteno_sdk/_bin` are not MIT; see
95
+ `cteno_sdk/_bin/LICENSE.daemon` in the wheel.
@@ -0,0 +1,65 @@
1
+ """Cteno Agent SDK for Python — same owner-socket protocol as ``@cteno/sdk/core``.
2
+
3
+ import asyncio
4
+ from cteno_sdk import CtenoSession, AgentSpec, ClientTool
5
+
6
+ async def main():
7
+ # Starts (or reuses) the SDK's own local daemon; no Cteno app or login needed.
8
+ async with await CtenoSession.open() as cteno:
9
+ await cteno.configure_model(base_url="https://api.deepseek.com/anthropic",
10
+ model="deepseek-chat", api_key=os.environ["DEEPSEEK_API_KEY"],
11
+ api_format="anthropic")
12
+ sid = await cteno.create(spec=AgentSpec(
13
+ system_prompt="You are a food guide.",
14
+ client_tools=[ClientTool("lookup_place", "Find a place", {"type": "object"},
15
+ handler=lambda args, ctx: {"name": args.get("name")})],
16
+ ))
17
+ result = await cteno.run(sid, "Where should I eat?")
18
+ print(result.text)
19
+
20
+ asyncio.run(main())
21
+
22
+ See the repository README for the full guide.
23
+ """
24
+ from .client import (
25
+ AGENT_SPEC_CAPABILITY,
26
+ AgentSpec,
27
+ ClientTool,
28
+ ClientToolContext,
29
+ CtenoSession,
30
+ RunResult,
31
+ SdkError,
32
+ TenantRef,
33
+ discover_owner_sockets,
34
+ spec_to_wire,
35
+ )
36
+ from .daemon import (
37
+ DaemonError,
38
+ default_instance_root,
39
+ ensure_daemon,
40
+ instance_layout,
41
+ isolated_pipe_name,
42
+ resolve_daemon_binary,
43
+ stop_daemon,
44
+ )
45
+
46
+ __all__ = [
47
+ "AGENT_SPEC_CAPABILITY",
48
+ "AgentSpec",
49
+ "ClientTool",
50
+ "ClientToolContext",
51
+ "CtenoSession",
52
+ "RunResult",
53
+ "SdkError",
54
+ "TenantRef",
55
+ "discover_owner_sockets",
56
+ "spec_to_wire",
57
+ "DaemonError",
58
+ "default_instance_root",
59
+ "ensure_daemon",
60
+ "instance_layout",
61
+ "isolated_pipe_name",
62
+ "resolve_daemon_binary",
63
+ "stop_daemon",
64
+ ]
65
+ __version__ = "0.2.0"