fix(opencode): pass input args to augment hook and allow tool search in subagents

- Fix client adapter passing output?.args instead of input?.args in tool.execute.after hook (closes #1737)
- Add tool_search and tool_search_regex permissions to OpenCode subagent profiles so deferred MCP tools can be discovered and unblocked
- Add regression tests for OpenCode adapter hook args and subagent profile permissions

Signed-off-by: Choti Wongbussakorn <126886556+Chewji9875@users.noreply.github.com>
This commit is contained in:
Choti Wongbussakorn committed 2026-09-04 21:45:24 +07:00
1 parent ffb5ebe9e8
commit 8d46d25862
4 files changed
+34 -1

No files matched your search

+11
View File
@@ -547,6 +547,17 @@ static bool render_profile_text(profile_buffer_t *buffer, cbm_graph_profile_dial
}
return true;
case CBM_GRAPH_DIALECT_OPENCODE:
if (!profile_buffer_append(buffer, "---\ndescription: ") ||
!profile_buffer_append(buffer, description) ||
!profile_buffer_append(
buffer, "\nmode: subagent\npermission:\n \"*\": deny\n read: allow\n grep: "
"allow\n glob: allow\n tool_search: allow\n tool_search_regex: "
"allow\n") ||
(direct && !append_permission_mcp_tools(buffer, dialect, tier)) ||
!profile_buffer_append(buffer, "---\n") || !profile_buffer_append(buffer, prompt)) {
return false;
}
return true;
case CBM_GRAPH_DIALECT_KILO:
if (!profile_buffer_append(buffer, "---\ndescription: ") ||
!profile_buffer_append(buffer, description) ||
+1 -1
View File
@@ -315,7 +315,7 @@ char *cbm_client_adapter_opencode(const char *binary_path) {
" seen.add(sid);\n"
" pieces.push(await lifecycle());\n"
" }\n"
" const args = output?.args ?? {};\n"
" const args = input?.args ?? {};\n"
" const search =\n"
" input?.tool === 'grep' ? 'Grep' : input?.tool === 'glob' ? 'Glob' : null;\n"
" if (search) {\n"
+3
View File
@@ -1283,6 +1283,9 @@ TEST(client_adapter_opencode_sends_the_required_hook_event) {
ASSERT_NOT_NULL(js);
ASSERT_NOT_NULL(strstr(js, "hook_event_name: 'PreToolUse'"));
ASSERT_NOT_NULL(strstr(js, "tool.execute.after"));
ASSERT_NOT_NULL(strstr(js, "const args = input?.args ?? {};"));
ASSERT_NOT_NULL(strstr(js, "tool_input: args"));
ASSERT_NULL(strstr(js, "output?.args"));
/* OpenCode reaches the tools over MCP already; this adapter must not
* register any, or we reintroduce the second tool surface. */
ASSERT_NULL(strstr(js, "registerTool"));
+19
View File
@@ -360,6 +360,24 @@ TEST(agent_profiles_omp_direct_has_prefixed_tools_and_handoff_excludes_mcp) {
PASS();
}
TEST(agent_profiles_opencode_allows_tool_search_and_subagent_permissions) {
char *direct = cbm_render_graph_profile(CBM_GRAPH_DIALECT_OPENCODE, CBM_GRAPH_TIER_VERIFY,
CBM_GRAPH_ACCESS_DIRECT, NULL);
ASSERT_NOT_NULL(direct);
ASSERT_NOT_NULL(strstr(direct, "mode: subagent\n"));
ASSERT_NOT_NULL(strstr(direct, " \"*\": deny\n"));
ASSERT_NOT_NULL(strstr(direct, " read: allow\n"));
ASSERT_NOT_NULL(strstr(direct, " grep: allow\n"));
ASSERT_NOT_NULL(strstr(direct, " glob: allow\n"));
ASSERT_NOT_NULL(strstr(direct, " tool_search: allow\n"));
ASSERT_NOT_NULL(strstr(direct, " tool_search_regex: allow\n"));
ASSERT_NOT_NULL(strstr(direct, " \"codebase-memory-mcp_search_graph\": allow\n"));
ASSERT_NOT_NULL(strstr(direct, " \"codebase-memory-mcp_check_index_coverage\": allow\n"));
ASSERT_NULL(strstr(direct, "delete_project"));
free(direct);
PASS();
}
SUITE(agent_profiles) {
RUN_TEST(agent_profiles_stable_tier_identity);
RUN_TEST(agent_profiles_direct_dialects_are_coverage_aware_and_read_only);
@@ -371,6 +389,7 @@ SUITE(agent_profiles) {
RUN_TEST(agent_profiles_codex_declares_transport_and_escapes_binary_path);
RUN_TEST(agent_profiles_vibe_uses_matching_prompt_identifier_and_contract);
RUN_TEST(agent_profiles_omp_direct_has_prefixed_tools_and_handoff_excludes_mcp);
RUN_TEST(agent_profiles_opencode_allows_tool_search_and_subagent_permissions);
RUN_TEST(agent_profiles_grok_uses_dispatcher_ids_and_named_inheritance);
RUN_TEST(agent_profiles_render_deterministically_and_reject_invalid_inputs);
}