optio-opencode 0.2.2__tar.gz → 0.2.3__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.
- {optio_opencode-0.2.2 → optio_opencode-0.2.3}/PKG-INFO +15 -3
- {optio_opencode-0.2.2 → optio_opencode-0.2.3}/README.md +12 -0
- {optio_opencode-0.2.2 → optio_opencode-0.2.3}/pyproject.toml +3 -3
- {optio_opencode-0.2.2 → optio_opencode-0.2.3}/src/optio_opencode/prompt.py +2 -2
- {optio_opencode-0.2.2 → optio_opencode-0.2.3}/src/optio_opencode/session.py +6 -1
- {optio_opencode-0.2.2 → optio_opencode-0.2.3}/src/optio_opencode/types.py +14 -1
- {optio_opencode-0.2.2 → optio_opencode-0.2.3}/src/optio_opencode.egg-info/PKG-INFO +15 -3
- {optio_opencode-0.2.2 → optio_opencode-0.2.3}/src/optio_opencode.egg-info/requires.txt +2 -2
- {optio_opencode-0.2.2 → optio_opencode-0.2.3}/tests/test_session_local.py +37 -0
- {optio_opencode-0.2.2 → optio_opencode-0.2.3}/setup.cfg +0 -0
- {optio_opencode-0.2.2 → optio_opencode-0.2.3}/src/optio_opencode/__init__.py +0 -0
- {optio_opencode-0.2.2 → optio_opencode-0.2.3}/src/optio_opencode/conversation.py +0 -0
- {optio_opencode-0.2.2 → optio_opencode-0.2.3}/src/optio_opencode/cred_watcher.py +0 -0
- {optio_opencode-0.2.2 → optio_opencode-0.2.3}/src/optio_opencode/host_actions.py +0 -0
- {optio_opencode-0.2.2 → optio_opencode-0.2.3}/src/optio_opencode/seed_manifest.py +0 -0
- {optio_opencode-0.2.2 → optio_opencode-0.2.3}/src/optio_opencode/snapshots.py +0 -0
- {optio_opencode-0.2.2 → optio_opencode-0.2.3}/src/optio_opencode/verify.py +0 -0
- {optio_opencode-0.2.2 → optio_opencode-0.2.3}/src/optio_opencode.egg-info/SOURCES.txt +0 -0
- {optio_opencode-0.2.2 → optio_opencode-0.2.3}/src/optio_opencode.egg-info/dependency_links.txt +0 -0
- {optio_opencode-0.2.2 → optio_opencode-0.2.3}/src/optio_opencode.egg-info/top_level.txt +0 -0
- {optio_opencode-0.2.2 → optio_opencode-0.2.3}/tests/test_agent_sender_opencode.py +0 -0
- {optio_opencode-0.2.2 → optio_opencode-0.2.3}/tests/test_conversation_config.py +0 -0
- {optio_opencode-0.2.2 → optio_opencode-0.2.3}/tests/test_conversation_driver.py +0 -0
- {optio_opencode-0.2.2 → optio_opencode-0.2.3}/tests/test_conversation_session.py +0 -0
- {optio_opencode-0.2.2 → optio_opencode-0.2.3}/tests/test_conversation_ui_model.py +0 -0
- {optio_opencode-0.2.2 → optio_opencode-0.2.3}/tests/test_conversation_ui_session.py +0 -0
- {optio_opencode-0.2.2 → optio_opencode-0.2.3}/tests/test_cred_watcher.py +0 -0
- {optio_opencode-0.2.2 → optio_opencode-0.2.3}/tests/test_file_download.py +0 -0
- {optio_opencode-0.2.2 → optio_opencode-0.2.3}/tests/test_file_upload.py +0 -0
- {optio_opencode-0.2.2 → optio_opencode-0.2.3}/tests/test_host_actions.py +0 -0
- {optio_opencode-0.2.2 → optio_opencode-0.2.3}/tests/test_host_local.py +0 -0
- {optio_opencode-0.2.2 → optio_opencode-0.2.3}/tests/test_host_primitives_local.py +0 -0
- {optio_opencode-0.2.2 → optio_opencode-0.2.3}/tests/test_host_primitives_remote.py +0 -0
- {optio_opencode-0.2.2 → optio_opencode-0.2.3}/tests/test_host_remote_resume.py +0 -0
- {optio_opencode-0.2.2 → optio_opencode-0.2.3}/tests/test_host_resume.py +0 -0
- {optio_opencode-0.2.2 → optio_opencode-0.2.3}/tests/test_prompt.py +0 -0
- {optio_opencode-0.2.2 → optio_opencode-0.2.3}/tests/test_purge_seed.py +0 -0
- {optio_opencode-0.2.2 → optio_opencode-0.2.3}/tests/test_resume_sentence_opencode.py +0 -0
- {optio_opencode-0.2.2 → optio_opencode-0.2.3}/tests/test_sanity.py +0 -0
- {optio_opencode-0.2.2 → optio_opencode-0.2.3}/tests/test_seed_config.py +0 -0
- {optio_opencode-0.2.2 → optio_opencode-0.2.3}/tests/test_session_blob_hooks.py +0 -0
- {optio_opencode-0.2.2 → optio_opencode-0.2.3}/tests/test_session_hooks.py +0 -0
- {optio_opencode-0.2.2 → optio_opencode-0.2.3}/tests/test_session_remote.py +0 -0
- {optio_opencode-0.2.2 → optio_opencode-0.2.3}/tests/test_session_resume.py +0 -0
- {optio_opencode-0.2.2 → optio_opencode-0.2.3}/tests/test_session_seed.py +0 -0
- {optio_opencode-0.2.2 → optio_opencode-0.2.3}/tests/test_session_seed_saveback.py +0 -0
- {optio_opencode-0.2.2 → optio_opencode-0.2.3}/tests/test_smart_install.py +0 -0
- {optio_opencode-0.2.2 → optio_opencode-0.2.3}/tests/test_snapshots.py +0 -0
- {optio_opencode-0.2.2 → optio_opencode-0.2.3}/tests/test_types.py +0 -0
- {optio_opencode-0.2.2 → optio_opencode-0.2.3}/tests/test_verify_seed.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: optio-opencode
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.3
|
|
4
4
|
Summary: Run opencode web as an optio task; local subprocess or remote via SSH.
|
|
5
5
|
Author-email: Kristof Csillag <kristof.csillag@deai-labs.com>
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -20,9 +20,9 @@ Classifier: Topic :: Software Development :: Code Generators
|
|
|
20
20
|
Classifier: Framework :: AsyncIO
|
|
21
21
|
Requires-Python: >=3.11
|
|
22
22
|
Description-Content-Type: text/markdown
|
|
23
|
-
Requires-Dist: optio-core<0.
|
|
23
|
+
Requires-Dist: optio-core<0.4,>=0.3
|
|
24
24
|
Requires-Dist: optio-host<0.3,>=0.2
|
|
25
|
-
Requires-Dist: optio-agents<0.
|
|
25
|
+
Requires-Dist: optio-agents<0.4,>=0.3
|
|
26
26
|
Requires-Dist: asyncssh>=2.14
|
|
27
27
|
Requires-Dist: aiohttp>=3.9
|
|
28
28
|
Provides-Extra: dev
|
|
@@ -81,6 +81,18 @@ task = create_opencode_task(config)
|
|
|
81
81
|
|
|
82
82
|
Set `ssh=None` for local subprocess mode.
|
|
83
83
|
|
|
84
|
+
## Messages
|
|
85
|
+
|
|
86
|
+
- `use_client_messages` (bool, default `False`) — enable the `CLIENT_MESSAGE:`
|
|
87
|
+
log keyword: the agent can push `{keyword, data}` messages to the browser
|
|
88
|
+
session that launched the task (surfaced via optio-ui's `onClientMessage`).
|
|
89
|
+
- `on_caller_message` (async callback, default `None`) — enable the
|
|
90
|
+
`CALLER_MESSAGE:` log keyword: the agent can push `{keyword, data}` messages
|
|
91
|
+
to your application. Signature `(hook_ctx, keyword, data) -> str | None`;
|
|
92
|
+
a non-None return is sent back to the agent as feedback. Keywords that are
|
|
93
|
+
not enabled are absent from both the parser and the agent-facing protocol
|
|
94
|
+
documentation.
|
|
95
|
+
|
|
84
96
|
## License
|
|
85
97
|
|
|
86
98
|
Apache-2.0.
|
|
@@ -50,6 +50,18 @@ task = create_opencode_task(config)
|
|
|
50
50
|
|
|
51
51
|
Set `ssh=None` for local subprocess mode.
|
|
52
52
|
|
|
53
|
+
## Messages
|
|
54
|
+
|
|
55
|
+
- `use_client_messages` (bool, default `False`) — enable the `CLIENT_MESSAGE:`
|
|
56
|
+
log keyword: the agent can push `{keyword, data}` messages to the browser
|
|
57
|
+
session that launched the task (surfaced via optio-ui's `onClientMessage`).
|
|
58
|
+
- `on_caller_message` (async callback, default `None`) — enable the
|
|
59
|
+
`CALLER_MESSAGE:` log keyword: the agent can push `{keyword, data}` messages
|
|
60
|
+
to your application. Signature `(hook_ctx, keyword, data) -> str | None`;
|
|
61
|
+
a non-None return is sent back to the agent as feedback. Keywords that are
|
|
62
|
+
not enabled are absent from both the parser and the agent-facing protocol
|
|
63
|
+
documentation.
|
|
64
|
+
|
|
53
65
|
## License
|
|
54
66
|
|
|
55
67
|
Apache-2.0.
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "optio-opencode"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.3"
|
|
8
8
|
description = "Run opencode web as an optio task; local subprocess or remote via SSH."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "Apache-2.0"
|
|
@@ -26,11 +26,11 @@ classifiers = [
|
|
|
26
26
|
"Framework :: AsyncIO",
|
|
27
27
|
]
|
|
28
28
|
dependencies = [
|
|
29
|
-
"optio-core>=0.
|
|
29
|
+
"optio-core>=0.3,<0.4",
|
|
30
30
|
# 0.1.1 introduces the bind_addr kwarg on Host.establish_tunnel —
|
|
31
31
|
# required for OPTIO_WIDGET_TUNNEL_BIND to work.
|
|
32
32
|
"optio-host>=0.2,<0.3",
|
|
33
|
-
"optio-agents>=0.
|
|
33
|
+
"optio-agents>=0.3,<0.4",
|
|
34
34
|
"asyncssh>=2.14",
|
|
35
35
|
"aiohttp>=3.9",
|
|
36
36
|
]
|
|
@@ -8,7 +8,7 @@ addressed. The consumer's own task description is then appended verbatim.
|
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
from optio_agents.prompt import downloadables_block
|
|
11
|
-
from optio_agents.protocol import build_log_channel_prompt
|
|
11
|
+
from optio_agents.protocol import ProtocolFeatures, build_log_channel_prompt
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
_OPENCODE_INTRO = """# Coordination protocol with the host (optio-opencode)
|
|
@@ -163,7 +163,7 @@ def compose_agents_md(
|
|
|
163
163
|
)
|
|
164
164
|
if host_protocol:
|
|
165
165
|
if documentation is None:
|
|
166
|
-
documentation = build_log_channel_prompt("suppress")
|
|
166
|
+
documentation = build_log_channel_prompt(ProtocolFeatures(browser="suppress"))
|
|
167
167
|
base_prompt_pre = _OPENCODE_INTRO + documentation
|
|
168
168
|
else:
|
|
169
169
|
# Conversation mode without the optio.log channel: no keyword docs,
|
|
@@ -97,7 +97,11 @@ async def run_opencode_session(ctx: ProcessContext, config: OpencodeTaskConfig)
|
|
|
97
97
|
"""Execute function body for one optio-opencode task instance."""
|
|
98
98
|
# --- per-task filesystem layout ---------------------------------------
|
|
99
99
|
host: Host = _build_host(config, ctx.process_id)
|
|
100
|
-
protocol = get_protocol(
|
|
100
|
+
protocol = get_protocol(
|
|
101
|
+
browser="suppress",
|
|
102
|
+
client_messages=config.use_client_messages,
|
|
103
|
+
caller_messages=config.on_caller_message is not None,
|
|
104
|
+
)
|
|
101
105
|
|
|
102
106
|
instructions = config.consumer_instructions
|
|
103
107
|
omit_task_framing = False
|
|
@@ -502,6 +506,7 @@ async def run_opencode_session(ctx: ProcessContext, config: OpencodeTaskConfig)
|
|
|
502
506
|
body=_opencode_body,
|
|
503
507
|
prepare=_prepare,
|
|
504
508
|
on_deliverable=config.on_deliverable,
|
|
509
|
+
on_caller_message=config.on_caller_message,
|
|
505
510
|
after_execute=config.after_execute,
|
|
506
511
|
protocol=protocol,
|
|
507
512
|
agent_sender=_agent_sender,
|
|
@@ -9,7 +9,11 @@ is owned by ``optio-host``. This module re-exports them so existing
|
|
|
9
9
|
from dataclasses import dataclass, field
|
|
10
10
|
from typing import Any, Awaitable, Callable, Literal
|
|
11
11
|
|
|
12
|
-
from optio_agents.protocol.session import
|
|
12
|
+
from optio_agents.protocol.session import (
|
|
13
|
+
CallerMessageCallback,
|
|
14
|
+
DeliverableCallback,
|
|
15
|
+
HookCallback,
|
|
16
|
+
)
|
|
13
17
|
from optio_host.types import SSHConfig
|
|
14
18
|
|
|
15
19
|
|
|
@@ -28,6 +32,7 @@ _VALID_TOOL_VERBOSITY = {"silent", "description-only", "verbose"}
|
|
|
28
32
|
|
|
29
33
|
|
|
30
34
|
__all__ = [
|
|
35
|
+
"CallerMessageCallback",
|
|
31
36
|
"DeliverableCallback",
|
|
32
37
|
"HookCallback",
|
|
33
38
|
"SSHConfig",
|
|
@@ -52,6 +57,14 @@ class OpencodeTaskConfig:
|
|
|
52
57
|
opencode_config: dict[str, Any] = field(default_factory=dict)
|
|
53
58
|
ssh: SSHConfig | None = None
|
|
54
59
|
on_deliverable: DeliverableCallback | None = None
|
|
60
|
+
# Enable the CLIENT_MESSAGE keyword: agent-pushed messages routed to the
|
|
61
|
+
# originating browser session's frontend (stored as sessionEvents,
|
|
62
|
+
# surfaced via optio-ui's onClientMessage). Off by default.
|
|
63
|
+
use_client_messages: bool = False
|
|
64
|
+
# Enable the CALLER_MESSAGE keyword: agent-pushed messages routed to this
|
|
65
|
+
# callback in the embedding application. A non-None return value is sent
|
|
66
|
+
# back to the agent as feedback. Off (None) by default.
|
|
67
|
+
on_caller_message: CallerMessageCallback | None = None
|
|
55
68
|
install_if_missing: bool = True
|
|
56
69
|
# Override for the optio-owned opencode binary **cache** directory (where
|
|
57
70
|
# the opencode binary is installed/cached on the worker). ``None``
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: optio-opencode
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.3
|
|
4
4
|
Summary: Run opencode web as an optio task; local subprocess or remote via SSH.
|
|
5
5
|
Author-email: Kristof Csillag <kristof.csillag@deai-labs.com>
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -20,9 +20,9 @@ Classifier: Topic :: Software Development :: Code Generators
|
|
|
20
20
|
Classifier: Framework :: AsyncIO
|
|
21
21
|
Requires-Python: >=3.11
|
|
22
22
|
Description-Content-Type: text/markdown
|
|
23
|
-
Requires-Dist: optio-core<0.
|
|
23
|
+
Requires-Dist: optio-core<0.4,>=0.3
|
|
24
24
|
Requires-Dist: optio-host<0.3,>=0.2
|
|
25
|
-
Requires-Dist: optio-agents<0.
|
|
25
|
+
Requires-Dist: optio-agents<0.4,>=0.3
|
|
26
26
|
Requires-Dist: asyncssh>=2.14
|
|
27
27
|
Requires-Dist: aiohttp>=3.9
|
|
28
28
|
Provides-Extra: dev
|
|
@@ -81,6 +81,18 @@ task = create_opencode_task(config)
|
|
|
81
81
|
|
|
82
82
|
Set `ssh=None` for local subprocess mode.
|
|
83
83
|
|
|
84
|
+
## Messages
|
|
85
|
+
|
|
86
|
+
- `use_client_messages` (bool, default `False`) — enable the `CLIENT_MESSAGE:`
|
|
87
|
+
log keyword: the agent can push `{keyword, data}` messages to the browser
|
|
88
|
+
session that launched the task (surfaced via optio-ui's `onClientMessage`).
|
|
89
|
+
- `on_caller_message` (async callback, default `None`) — enable the
|
|
90
|
+
`CALLER_MESSAGE:` log keyword: the agent can push `{keyword, data}` messages
|
|
91
|
+
to your application. Signature `(hook_ctx, keyword, data) -> str | None`;
|
|
92
|
+
a non-None return is sent back to the agent as feedback. Keywords that are
|
|
93
|
+
not enabled are absent from both the parser and the agent-facing protocol
|
|
94
|
+
documentation.
|
|
95
|
+
|
|
84
96
|
## License
|
|
85
97
|
|
|
86
98
|
Apache-2.0.
|
|
@@ -315,6 +315,43 @@ async def test_widget_upstream_and_data_are_set(ctx_and_captures, _supply_scenar
|
|
|
315
315
|
assert decoded.startswith("/") and "optio-opencode" in decoded
|
|
316
316
|
|
|
317
317
|
|
|
318
|
+
async def test_caller_message_reaches_callback(ctx_and_captures, _supply_scenario):
|
|
319
|
+
ctx, _cap, _ = ctx_and_captures
|
|
320
|
+
_supply_scenario["name"] = "caller_message"
|
|
321
|
+
|
|
322
|
+
received: list[tuple[str, object]] = []
|
|
323
|
+
async def on_caller(hook_ctx, keyword, data):
|
|
324
|
+
received.append((keyword, data))
|
|
325
|
+
return "pong"
|
|
326
|
+
|
|
327
|
+
cfg = OpencodeTaskConfig(
|
|
328
|
+
consumer_instructions="(scenario: caller_message)",
|
|
329
|
+
on_caller_message=on_caller,
|
|
330
|
+
)
|
|
331
|
+
await run_opencode_session(ctx, cfg)
|
|
332
|
+
|
|
333
|
+
assert received == [("ping", {"n": 1})]
|
|
334
|
+
|
|
335
|
+
|
|
336
|
+
async def test_client_message_stored_as_session_event(
|
|
337
|
+
ctx_and_captures, _supply_scenario, mongo_db,
|
|
338
|
+
):
|
|
339
|
+
ctx, _cap, _ = ctx_and_captures
|
|
340
|
+
_supply_scenario["name"] = "client_message"
|
|
341
|
+
|
|
342
|
+
cfg = OpencodeTaskConfig(
|
|
343
|
+
consumer_instructions="(scenario: client_message)",
|
|
344
|
+
use_client_messages=True,
|
|
345
|
+
)
|
|
346
|
+
await run_opencode_session(ctx, cfg)
|
|
347
|
+
|
|
348
|
+
doc = await mongo_db["test_processes"].find_one({"processId": "p"})
|
|
349
|
+
events = [e for e in doc.get("sessionEvents", []) if e["type"] == "client"]
|
|
350
|
+
assert len(events) == 1
|
|
351
|
+
assert events[0]["keyword"] == "notify"
|
|
352
|
+
assert events[0]["data"] == {"msg": "hi"}
|
|
353
|
+
|
|
354
|
+
|
|
318
355
|
# ---- resume log -----------------------------------------------------------
|
|
319
356
|
|
|
320
357
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{optio_opencode-0.2.2 → optio_opencode-0.2.3}/src/optio_opencode.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|