allternit-computer-driver 0.1.0__tar.gz → 0.2.0__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.
- allternit_computer_driver-0.2.0/PKG-INFO +116 -0
- allternit_computer_driver-0.2.0/README.md +105 -0
- allternit_computer_driver-0.2.0/allternit_computer_driver/__init__.py +42 -0
- allternit_computer_driver-0.2.0/allternit_computer_driver/_v2_types.py +262 -0
- {allternit_computer_driver-0.1.0 → allternit_computer_driver-0.2.0}/allternit_computer_driver/anthropic.py +41 -0
- {allternit_computer_driver-0.1.0 → allternit_computer_driver-0.2.0}/allternit_computer_driver/client.py +50 -3
- {allternit_computer_driver-0.1.0 → allternit_computer_driver-0.2.0}/allternit_computer_driver/gemini.py +39 -1
- {allternit_computer_driver-0.1.0 → allternit_computer_driver-0.2.0}/allternit_computer_driver/openai.py +38 -2
- allternit_computer_driver-0.2.0/allternit_computer_driver/v2.py +240 -0
- allternit_computer_driver-0.2.0/allternit_computer_driver.egg-info/PKG-INFO +116 -0
- {allternit_computer_driver-0.1.0 → allternit_computer_driver-0.2.0}/allternit_computer_driver.egg-info/SOURCES.txt +2 -0
- {allternit_computer_driver-0.1.0 → allternit_computer_driver-0.2.0}/pyproject.toml +2 -2
- allternit_computer_driver-0.1.0/PKG-INFO +0 -47
- allternit_computer_driver-0.1.0/README.md +0 -36
- allternit_computer_driver-0.1.0/allternit_computer_driver/__init__.py +0 -15
- allternit_computer_driver-0.1.0/allternit_computer_driver.egg-info/PKG-INFO +0 -47
- {allternit_computer_driver-0.1.0 → allternit_computer_driver-0.2.0}/allternit_computer_driver/py.typed +0 -0
- {allternit_computer_driver-0.1.0 → allternit_computer_driver-0.2.0}/allternit_computer_driver.egg-info/dependency_links.txt +0 -0
- {allternit_computer_driver-0.1.0 → allternit_computer_driver-0.2.0}/allternit_computer_driver.egg-info/requires.txt +0 -0
- {allternit_computer_driver-0.1.0 → allternit_computer_driver-0.2.0}/allternit_computer_driver.egg-info/top_level.txt +0 -0
- {allternit_computer_driver-0.1.0 → allternit_computer_driver-0.2.0}/setup.cfg +0 -0
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: allternit-computer-driver
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Drop-in drivers for Allternit hosted computers: a plain client, contract-v2 structured UI driving (read_ui, act, run_batch, verify, run_subtask, …) and Anthropic (computer/browser toolset), OpenAI computer-use and Gemini computer_use adapters.
|
|
5
|
+
License: Apache-2.0
|
|
6
|
+
Project-URL: Documentation, https://docs.allternit.com/api/platform/sdks/python
|
|
7
|
+
Requires-Python: >=3.9
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
Provides-Extra: anthropic
|
|
10
|
+
Requires-Dist: anthropic; extra == "anthropic"
|
|
11
|
+
|
|
12
|
+
# allternit-computer-driver
|
|
13
|
+
|
|
14
|
+
Drive an Allternit hosted computer (`/v1/computers`) from Claude, OpenAI computer use, or Gemini computer use. Standard library only; `pip install allternit-computer-driver[anthropic]` adds the Anthropic SDK. Needs a project key with the `computers` scope and the hosted driver turned on for the project.
|
|
15
|
+
|
|
16
|
+
```python
|
|
17
|
+
from allternit_computer_driver import AllternitComputers
|
|
18
|
+
client = AllternitComputers() # reads ALLTERNIT_API_KEY
|
|
19
|
+
computer = client.create(name="agent-1")
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Structured UI driving (allternit.computer.v2)
|
|
23
|
+
|
|
24
|
+
Contract v2 adds ten driver-backed structured members — `read_ui`, `act`, `run_batch`, `verify`, `request_human`, `use_credential`, `run_subtask`, `run_parallel`, `run_skill`, `skills` — typed end to end. `ComputerV2Driver` calls them directly; every adapter also exposes them to the model as the `computer_v2` function tool. The structured members need the Allternit Driver on the computer (this-device today).
|
|
25
|
+
|
|
26
|
+
```python
|
|
27
|
+
from allternit_computer_driver import ComputerV2Driver
|
|
28
|
+
|
|
29
|
+
v2 = ComputerV2Driver(client, computer["id"], on_approval=lambda a: ask_a_person(a))
|
|
30
|
+
|
|
31
|
+
# Read the UI as an element tree — no screenshots.
|
|
32
|
+
ui = v2.read_ui({"app": "Safari"})
|
|
33
|
+
field = next((e for e in ui.get("elements", []) if e.get("role") == "textfield"), None)
|
|
34
|
+
if field:
|
|
35
|
+
v2.act({"id": field["id"], "op": "set_value", "value": "hello@example.com", "version": ui["version"]})
|
|
36
|
+
|
|
37
|
+
# Hand a bounded step sequence to the fast decision loop instead of clicking through it yourself.
|
|
38
|
+
sub = v2.run_subtask({
|
|
39
|
+
"goal": "Fill the signup form and submit it",
|
|
40
|
+
"inputs": [{"name": "email", "value": "hello@example.com"}],
|
|
41
|
+
"success": [{"role": "button", "name": "Submit"}],
|
|
42
|
+
})
|
|
43
|
+
if sub["status"] != "done":
|
|
44
|
+
print(sub["status"], sub.get("next"))
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Subtask safety statuses
|
|
48
|
+
|
|
49
|
+
`run_subtask` / `run_skill` / `run_parallel` results end with a `status`:
|
|
50
|
+
|
|
51
|
+
- `done` — the goal is met.
|
|
52
|
+
- `escalated` — handed back with a `reason` and the current `screen`; continue from there yourself.
|
|
53
|
+
- `needs_confirmation` — the next step (`held_step`) needs the person's confirmation; run it yourself with `act`/`run_batch` and the server asks them.
|
|
54
|
+
- `paused` — the safety monitor paused the subtask; stop and call `request_human`.
|
|
55
|
+
- `denied` — the step isn't allowed on this computer (app/domain lists or a credential binding); find another way.
|
|
56
|
+
- `use_api` — make the named API/MCP call yourself (`api["tool"]`); the screen is untouched.
|
|
57
|
+
- `failed` — ran out of steps, budget or a hard error.
|
|
58
|
+
|
|
59
|
+
### The computer_v2 function tool in a model loop
|
|
60
|
+
|
|
61
|
+
Each adapter exposes the structured members with the same steering guidance gizzi sends:
|
|
62
|
+
|
|
63
|
+
```python
|
|
64
|
+
from allternit_computer_driver.anthropic import ComputerV2Tool # to_dict()/tool_result(tool_use)
|
|
65
|
+
from allternit_computer_driver import (
|
|
66
|
+
openai_computer_v2_tool, run_openai_v2_call,
|
|
67
|
+
gemini_computer_v2_declaration, run_gemini_v2_call,
|
|
68
|
+
computer_v2_tool,
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
# Anthropic: put ComputerV2Tool(client, computer_id).to_dict() next to the toolset in tools.
|
|
72
|
+
# OpenAI: put openai_computer_v2_tool() in tools; answer function_call items with
|
|
73
|
+
# run_openai_v2_call(client, computer_id, call.call_id, json.loads(call.arguments)).
|
|
74
|
+
# Gemini: put gemini_computer_v2_declaration() in function_declarations; answer
|
|
75
|
+
# functionCall parts with run_gemini_v2_call(client, computer_id, part.function_call.name, dict(part.function_call.args)).
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
`computer_v2_tool()` returns the provider-neutral `{"name", "description", "schema"}` dict if you wire tools yourself.
|
|
79
|
+
|
|
80
|
+
## Claude
|
|
81
|
+
|
|
82
|
+
```python
|
|
83
|
+
from allternit_computer_driver.anthropic import AllternitComputerToolset, ComputerV2Tool
|
|
84
|
+
toolset = AllternitComputerToolset(client, computer["id"], on_approval=lambda approval: ask_a_person(approval))
|
|
85
|
+
v2_tool = ComputerV2Tool(client, computer["id"], on_approval=lambda approval: ask_a_person(approval))
|
|
86
|
+
# tools=[toolset.to_dict(), v2_tool.to_dict()] (the toolset subclasses the SDK's abstract toolsets when present)
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Each member runs on the server through `POST /v1/computers/{id}/toolset`. A 409 `approval_required` calls `on_approval`: `True` approves it and resends with the grant, `False` returns the held result to the model as an error. When the installed `anthropic` package has `anthropic.tools.computer` / `anthropic.tools.browser`, these classes subclass its abstract toolsets. Older releases get a small stand-in with `to_dict()` and `tool_result(tool_use)` for a hand-written loop.
|
|
90
|
+
|
|
91
|
+
## OpenAI computer use
|
|
92
|
+
|
|
93
|
+
```python
|
|
94
|
+
from allternit_computer_driver import run_openai_action
|
|
95
|
+
step = run_openai_action(client, computer_id, call.call_id, call.action.model_dump(), display={"width": 1280, "height": 800})
|
|
96
|
+
next_input.append(step["output"])
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Gemini computer use
|
|
100
|
+
|
|
101
|
+
```python
|
|
102
|
+
from allternit_computer_driver import run_gemini_call
|
|
103
|
+
step = run_gemini_call(client, computer_id, fc.name, dict(fc.args))
|
|
104
|
+
# step["function_response"] and step["inline_data"] (0-999 coords sent as normalized_1000)
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
The OpenAI and Gemini pixel adapters raise `ApprovalRequiredError`; call `client.approve()` and resend.
|
|
108
|
+
|
|
109
|
+
## Errors
|
|
110
|
+
|
|
111
|
+
- `ApprovalRequiredError` — 409 `approval_required`; carries `approval` (id, member, `approve_url`) and the held `result`. `client.toolset_with_approval(computer_id, call, on_approval)` approves and resends with the `approval_grant` for you.
|
|
112
|
+
- `ComputerV2Error` — a structured member answered `is_error: True`; carries the member name and raw `result`.
|
|
113
|
+
- `ComputerBusyError` — 423 `computer_busy` / `computer_controlled_elsewhere`.
|
|
114
|
+
- `SandboxRequiredError` — 409 `sandbox_required` (the call needs a sandbox computer).
|
|
115
|
+
- `ComputerConflictError` — 409 `computer_conflict` (another subtask or lease conflicts).
|
|
116
|
+
- `AllternitApiError` — everything else, with `status`, `code` and `type`.
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# allternit-computer-driver
|
|
2
|
+
|
|
3
|
+
Drive an Allternit hosted computer (`/v1/computers`) from Claude, OpenAI computer use, or Gemini computer use. Standard library only; `pip install allternit-computer-driver[anthropic]` adds the Anthropic SDK. Needs a project key with the `computers` scope and the hosted driver turned on for the project.
|
|
4
|
+
|
|
5
|
+
```python
|
|
6
|
+
from allternit_computer_driver import AllternitComputers
|
|
7
|
+
client = AllternitComputers() # reads ALLTERNIT_API_KEY
|
|
8
|
+
computer = client.create(name="agent-1")
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Structured UI driving (allternit.computer.v2)
|
|
12
|
+
|
|
13
|
+
Contract v2 adds ten driver-backed structured members — `read_ui`, `act`, `run_batch`, `verify`, `request_human`, `use_credential`, `run_subtask`, `run_parallel`, `run_skill`, `skills` — typed end to end. `ComputerV2Driver` calls them directly; every adapter also exposes them to the model as the `computer_v2` function tool. The structured members need the Allternit Driver on the computer (this-device today).
|
|
14
|
+
|
|
15
|
+
```python
|
|
16
|
+
from allternit_computer_driver import ComputerV2Driver
|
|
17
|
+
|
|
18
|
+
v2 = ComputerV2Driver(client, computer["id"], on_approval=lambda a: ask_a_person(a))
|
|
19
|
+
|
|
20
|
+
# Read the UI as an element tree — no screenshots.
|
|
21
|
+
ui = v2.read_ui({"app": "Safari"})
|
|
22
|
+
field = next((e for e in ui.get("elements", []) if e.get("role") == "textfield"), None)
|
|
23
|
+
if field:
|
|
24
|
+
v2.act({"id": field["id"], "op": "set_value", "value": "hello@example.com", "version": ui["version"]})
|
|
25
|
+
|
|
26
|
+
# Hand a bounded step sequence to the fast decision loop instead of clicking through it yourself.
|
|
27
|
+
sub = v2.run_subtask({
|
|
28
|
+
"goal": "Fill the signup form and submit it",
|
|
29
|
+
"inputs": [{"name": "email", "value": "hello@example.com"}],
|
|
30
|
+
"success": [{"role": "button", "name": "Submit"}],
|
|
31
|
+
})
|
|
32
|
+
if sub["status"] != "done":
|
|
33
|
+
print(sub["status"], sub.get("next"))
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### Subtask safety statuses
|
|
37
|
+
|
|
38
|
+
`run_subtask` / `run_skill` / `run_parallel` results end with a `status`:
|
|
39
|
+
|
|
40
|
+
- `done` — the goal is met.
|
|
41
|
+
- `escalated` — handed back with a `reason` and the current `screen`; continue from there yourself.
|
|
42
|
+
- `needs_confirmation` — the next step (`held_step`) needs the person's confirmation; run it yourself with `act`/`run_batch` and the server asks them.
|
|
43
|
+
- `paused` — the safety monitor paused the subtask; stop and call `request_human`.
|
|
44
|
+
- `denied` — the step isn't allowed on this computer (app/domain lists or a credential binding); find another way.
|
|
45
|
+
- `use_api` — make the named API/MCP call yourself (`api["tool"]`); the screen is untouched.
|
|
46
|
+
- `failed` — ran out of steps, budget or a hard error.
|
|
47
|
+
|
|
48
|
+
### The computer_v2 function tool in a model loop
|
|
49
|
+
|
|
50
|
+
Each adapter exposes the structured members with the same steering guidance gizzi sends:
|
|
51
|
+
|
|
52
|
+
```python
|
|
53
|
+
from allternit_computer_driver.anthropic import ComputerV2Tool # to_dict()/tool_result(tool_use)
|
|
54
|
+
from allternit_computer_driver import (
|
|
55
|
+
openai_computer_v2_tool, run_openai_v2_call,
|
|
56
|
+
gemini_computer_v2_declaration, run_gemini_v2_call,
|
|
57
|
+
computer_v2_tool,
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
# Anthropic: put ComputerV2Tool(client, computer_id).to_dict() next to the toolset in tools.
|
|
61
|
+
# OpenAI: put openai_computer_v2_tool() in tools; answer function_call items with
|
|
62
|
+
# run_openai_v2_call(client, computer_id, call.call_id, json.loads(call.arguments)).
|
|
63
|
+
# Gemini: put gemini_computer_v2_declaration() in function_declarations; answer
|
|
64
|
+
# functionCall parts with run_gemini_v2_call(client, computer_id, part.function_call.name, dict(part.function_call.args)).
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
`computer_v2_tool()` returns the provider-neutral `{"name", "description", "schema"}` dict if you wire tools yourself.
|
|
68
|
+
|
|
69
|
+
## Claude
|
|
70
|
+
|
|
71
|
+
```python
|
|
72
|
+
from allternit_computer_driver.anthropic import AllternitComputerToolset, ComputerV2Tool
|
|
73
|
+
toolset = AllternitComputerToolset(client, computer["id"], on_approval=lambda approval: ask_a_person(approval))
|
|
74
|
+
v2_tool = ComputerV2Tool(client, computer["id"], on_approval=lambda approval: ask_a_person(approval))
|
|
75
|
+
# tools=[toolset.to_dict(), v2_tool.to_dict()] (the toolset subclasses the SDK's abstract toolsets when present)
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Each member runs on the server through `POST /v1/computers/{id}/toolset`. A 409 `approval_required` calls `on_approval`: `True` approves it and resends with the grant, `False` returns the held result to the model as an error. When the installed `anthropic` package has `anthropic.tools.computer` / `anthropic.tools.browser`, these classes subclass its abstract toolsets. Older releases get a small stand-in with `to_dict()` and `tool_result(tool_use)` for a hand-written loop.
|
|
79
|
+
|
|
80
|
+
## OpenAI computer use
|
|
81
|
+
|
|
82
|
+
```python
|
|
83
|
+
from allternit_computer_driver import run_openai_action
|
|
84
|
+
step = run_openai_action(client, computer_id, call.call_id, call.action.model_dump(), display={"width": 1280, "height": 800})
|
|
85
|
+
next_input.append(step["output"])
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Gemini computer use
|
|
89
|
+
|
|
90
|
+
```python
|
|
91
|
+
from allternit_computer_driver import run_gemini_call
|
|
92
|
+
step = run_gemini_call(client, computer_id, fc.name, dict(fc.args))
|
|
93
|
+
# step["function_response"] and step["inline_data"] (0-999 coords sent as normalized_1000)
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
The OpenAI and Gemini pixel adapters raise `ApprovalRequiredError`; call `client.approve()` and resend.
|
|
97
|
+
|
|
98
|
+
## Errors
|
|
99
|
+
|
|
100
|
+
- `ApprovalRequiredError` — 409 `approval_required`; carries `approval` (id, member, `approve_url`) and the held `result`. `client.toolset_with_approval(computer_id, call, on_approval)` approves and resends with the `approval_grant` for you.
|
|
101
|
+
- `ComputerV2Error` — a structured member answered `is_error: True`; carries the member name and raw `result`.
|
|
102
|
+
- `ComputerBusyError` — 423 `computer_busy` / `computer_controlled_elsewhere`.
|
|
103
|
+
- `SandboxRequiredError` — 409 `sandbox_required` (the call needs a sandbox computer).
|
|
104
|
+
- `ComputerConflictError` — 409 `computer_conflict` (another subtask or lease conflicts).
|
|
105
|
+
- `AllternitApiError` — everything else, with `status`, `code` and `type`.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"""Drive Allternit hosted computers from Claude, OpenAI computer use or Gemini computer use.
|
|
2
|
+
|
|
3
|
+
The Anthropic toolsets live in ``allternit_computer_driver.anthropic`` so importing this package
|
|
4
|
+
never needs the optional ``anthropic`` dependency."""
|
|
5
|
+
|
|
6
|
+
from .client import (
|
|
7
|
+
DEFAULT_BASE_URL,
|
|
8
|
+
AllternitApiError,
|
|
9
|
+
AllternitComputers,
|
|
10
|
+
ApprovalRequiredError,
|
|
11
|
+
ComputerBusyError,
|
|
12
|
+
ComputerConflictError,
|
|
13
|
+
SandboxRequiredError,
|
|
14
|
+
result_image,
|
|
15
|
+
result_text,
|
|
16
|
+
)
|
|
17
|
+
from .gemini import gemini_computer_v2_declaration, gemini_keys, gemini_to_calls, run_gemini_call, run_gemini_v2_call
|
|
18
|
+
from .openai import openai_computer_v2_tool, openai_keys, openai_to_calls, run_openai_action, run_openai_v2_call
|
|
19
|
+
from .v2 import (
|
|
20
|
+
COMPUTER_V2_MEMBER_NAMES,
|
|
21
|
+
COMPUTER_V2_STRUCTURED_MEMBER_NAMES,
|
|
22
|
+
COMPUTER_V2_TOOL_NAME,
|
|
23
|
+
V2_TOOL_MARKER,
|
|
24
|
+
ComputerV2Driver,
|
|
25
|
+
ComputerV2Error,
|
|
26
|
+
computer_v2_parameters,
|
|
27
|
+
computer_v2_tool,
|
|
28
|
+
computer_v2_tool_description,
|
|
29
|
+
run_computer_v2_member,
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
__version__ = "0.2.0"
|
|
33
|
+
|
|
34
|
+
__all__ = [
|
|
35
|
+
"AllternitComputers", "AllternitApiError", "ApprovalRequiredError", "ComputerBusyError",
|
|
36
|
+
"ComputerConflictError", "SandboxRequiredError", "DEFAULT_BASE_URL", "result_image", "result_text",
|
|
37
|
+
"gemini_keys", "gemini_to_calls", "run_gemini_call", "gemini_computer_v2_declaration", "run_gemini_v2_call",
|
|
38
|
+
"openai_keys", "openai_to_calls", "run_openai_action", "openai_computer_v2_tool", "run_openai_v2_call",
|
|
39
|
+
"COMPUTER_V2_MEMBER_NAMES", "COMPUTER_V2_STRUCTURED_MEMBER_NAMES", "COMPUTER_V2_TOOL_NAME", "V2_TOOL_MARKER",
|
|
40
|
+
"ComputerV2Driver", "ComputerV2Error", "computer_v2_parameters", "computer_v2_tool",
|
|
41
|
+
"computer_v2_tool_description", "run_computer_v2_member",
|
|
42
|
+
]
|