Compare commits

...

1 Commits

Author SHA1 Message Date
Aiden Cline 180109d8b6 test(core): add CodeMode search fixture catalog 2026-07-10 23:21:00 +00:00
4 changed files with 409 additions and 0 deletions
+2
View File
@@ -38,6 +38,7 @@ import { QuestionTool } from "../tool/question"
import { ReadToolFileSystem } from "../tool/read-filesystem"
import { ReadTool } from "../tool/read"
import { ShellTool } from "../tool/shell"
import { SearchFixtureTool } from "../tool/search-fixture"
import { SkillTool } from "../tool/skill"
import { SubagentTool } from "../tool/subagent"
import { Tools } from "../tool/tools"
@@ -129,6 +130,7 @@ const pre = [
GrepTool.Plugin,
QuestionTool.Plugin,
ReadTool.Plugin,
SearchFixtureTool.Plugin,
ShellTool.Plugin,
SkillTool.Plugin,
SubagentTool.Plugin,
+355
View File
@@ -0,0 +1,355 @@
export * as SearchFixtureTool from "./search-fixture"
import type { Context as PluginContext } from "@opencode-ai/plugin/v2/effect/plugin"
import { Effect, Schema } from "effect"
import { Tool } from "./tool"
export const catalog = [
{
namespace: "slack",
label: "Slack",
operations: [
"send_message",
"schedule_message",
"create_channel",
"archive_channel",
"invite_user",
"add_reaction",
"pin_message",
"set_topic",
"start_huddle",
"export_thread",
],
},
{
namespace: "github",
label: "GitHub",
operations: [
"create_issue",
"close_issue",
"assign_issue",
"label_issue",
"create_pull_request",
"request_review",
"merge_pull_request",
"create_release",
"dispatch_workflow",
"protect_branch",
],
},
{
namespace: "linear",
label: "Linear",
operations: [
"create_issue",
"update_issue",
"assign_issue",
"move_issue",
"add_comment",
"create_project",
"update_project",
"create_cycle",
"add_label",
"archive_issue",
],
},
{
namespace: "notion",
label: "Notion",
operations: [
"create_page",
"update_page",
"archive_page",
"search_workspace",
"append_blocks",
"create_database",
"add_database_row",
"update_database_row",
"duplicate_page",
"share_page",
],
},
{
namespace: "jira",
label: "Jira",
operations: [
"create_ticket",
"transition_ticket",
"assign_ticket",
"add_comment",
"link_ticket",
"create_epic",
"add_to_sprint",
"log_work",
"set_priority",
"close_ticket",
],
},
{
namespace: "google_drive",
label: "Google Drive",
operations: [
"create_folder",
"upload_file",
"move_file",
"copy_file",
"share_file",
"revoke_access",
"rename_file",
"trash_file",
"restore_file",
"search_files",
],
},
{
namespace: "gmail",
label: "Gmail",
operations: [
"send_email",
"create_draft",
"reply_thread",
"forward_email",
"add_label",
"remove_label",
"archive_thread",
"mark_read",
"mark_unread",
"schedule_email",
],
},
{
namespace: "calendar",
label: "Google Calendar",
operations: [
"create_event",
"update_event",
"cancel_event",
"invite_attendee",
"remove_attendee",
"find_availability",
"reserve_room",
"add_conference",
"set_reminder",
"list_events",
],
},
{
namespace: "stripe",
label: "Stripe",
operations: [
"create_customer",
"update_customer",
"create_invoice",
"finalize_invoice",
"refund_payment",
"cancel_subscription",
"pause_subscription",
"resume_subscription",
"create_coupon",
"send_receipt",
],
},
{
namespace: "salesforce",
label: "Salesforce",
operations: [
"create_lead",
"convert_lead",
"update_contact",
"create_account",
"update_opportunity",
"advance_opportunity",
"add_activity",
"create_case",
"close_case",
"assign_owner",
],
},
{
namespace: "hubspot",
label: "HubSpot",
operations: [
"create_contact",
"update_contact",
"create_company",
"create_deal",
"move_deal_stage",
"enroll_workflow",
"add_note",
"create_task",
"merge_contacts",
"assign_owner",
],
},
{
namespace: "zendesk",
label: "Zendesk",
operations: [
"create_ticket",
"update_ticket",
"assign_ticket",
"add_internal_note",
"reply_ticket",
"set_priority",
"add_tag",
"remove_tag",
"merge_ticket",
"solve_ticket",
],
},
{
namespace: "datadog",
label: "Datadog",
operations: [
"create_monitor",
"mute_monitor",
"unmute_monitor",
"create_dashboard",
"add_dashboard_widget",
"annotate_event",
"create_incident",
"update_incident",
"resolve_incident",
"schedule_downtime",
],
},
{
namespace: "pagerduty",
label: "PagerDuty",
operations: [
"trigger_incident",
"acknowledge_incident",
"resolve_incident",
"reassign_incident",
"add_responder",
"add_note",
"create_escalation_policy",
"override_schedule",
"create_maintenance_window",
"snooze_incident",
],
},
{
namespace: "aws",
label: "AWS",
operations: [
"launch_instance",
"stop_instance",
"restart_instance",
"scale_service",
"deploy_lambda",
"invalidate_cache",
"rotate_secret",
"create_queue",
"publish_topic",
"snapshot_database",
],
},
{
namespace: "vercel",
label: "Vercel",
operations: [
"create_project",
"deploy_project",
"promote_deployment",
"rollback_deployment",
"add_domain",
"remove_domain",
"set_env_variable",
"remove_env_variable",
"purge_cache",
"inspect_deployment",
],
},
{
namespace: "figma",
label: "Figma",
operations: [
"create_file",
"duplicate_file",
"create_page",
"rename_layer",
"add_comment",
"resolve_comment",
"publish_library",
"create_branch",
"merge_branch",
"export_frame",
],
},
{
namespace: "airtable",
label: "Airtable",
operations: [
"create_base",
"create_table",
"add_field",
"create_record",
"update_record",
"delete_record",
"find_records",
"link_records",
"create_view",
"sort_view",
],
},
{
namespace: "dropbox",
label: "Dropbox",
operations: [
"upload_file",
"download_file",
"move_file",
"copy_file",
"delete_file",
"restore_file",
"share_link",
"revoke_link",
"create_folder",
"search_files",
],
},
{
namespace: "snowflake",
label: "Snowflake",
operations: [
"create_warehouse",
"resize_warehouse",
"suspend_warehouse",
"resume_warehouse",
"create_database",
"create_schema",
"create_table",
"load_stage",
"run_query",
"grant_role",
],
},
] as const
const Input = Schema.Struct({})
export const Plugin = {
id: "opencode.tool.search-fixture",
effect: Effect.fn("SearchFixtureTool.Plugin")(function* (ctx: PluginContext) {
yield* ctx.tool
.transform((draft) => {
catalog.forEach((group) =>
group.operations.forEach((operation) => {
const action = operation.replaceAll("_", " ")
draft.add(
operation,
Tool.make({
description: `${action[0]?.toUpperCase()}${action.slice(1)} in ${group.label}.`,
input: Input,
output: Schema.String,
execute: () => Effect.succeed(`Completed ${action}.`),
}),
{ group: group.namespace, deferred: true },
)
}),
)
})
.pipe(Effect.orDie)
}),
}
@@ -550,6 +550,7 @@ describe("LocationServiceMap", () => {
expect(blockedState.providers.some((provider) => provider.id === allowedID)).toBe(false)
expect(blockedState.tools.map((tool) => tool.name).sort()).toEqual([
"edit",
"execute",
"glob",
"grep",
"patch",
@@ -567,6 +568,7 @@ describe("LocationServiceMap", () => {
expect(allowedState.providers.some((provider) => provider.id === blockedID)).toBe(false)
expect(allowedState.tools.map((tool) => tool.name).sort()).toEqual([
"edit",
"execute",
"glob",
"grep",
"patch",
@@ -0,0 +1,50 @@
import { expect } from "bun:test"
import { AgentV2 } from "@opencode-ai/core/agent"
import { AppNodeBuilder } from "@opencode-ai/core/effect/app-node-builder"
import { SessionV2 } from "@opencode-ai/core/session"
import { SessionMessage } from "@opencode-ai/core/session/message"
import { ToolOutputStore } from "@opencode-ai/core/tool-output-store"
import { ToolRegistry } from "@opencode-ai/core/tool/registry"
import { SearchFixtureTool } from "@opencode-ai/core/tool/search-fixture"
import { Effect, Layer } from "effect"
import { testEffect } from "./lib/effect"
import { registerToolPlugin } from "./lib/tool"
const outputStore = Layer.mock(ToolOutputStore.Service, {
bound: (input) => Effect.succeed({ output: input.output, outputPaths: [] }),
})
const it = testEffect(AppNodeBuilder.build(ToolRegistry.node, [[ToolOutputStore.node, outputStore]]))
it.effect("registers 200 searchable no-op tools across namespaces", () =>
Effect.gen(function* () {
expect(SearchFixtureTool.catalog).toHaveLength(20)
expect(SearchFixtureTool.catalog.flatMap((group) => group.operations)).toHaveLength(200)
yield* registerToolPlugin(SearchFixtureTool.Plugin)
const registry = yield* ToolRegistry.Service
const tools = yield* registry.materialize()
expect(tools.definitions.map((tool) => tool.name)).toEqual(["execute"])
const invoke = (code: string, id: string) =>
tools.settle({
sessionID: SessionV2.ID.make("ses_search_fixture"),
agent: AgentV2.ID.make("build"),
assistantMessageID: SessionMessage.ID.make("msg_search_fixture"),
call: { type: "tool-call", id, name: "execute", input: { code } },
})
const searched = yield* invoke(
'return await tools.$codemode.search({ query: "refund payment", namespace: "stripe" })',
"call_search_fixture",
)
expect(searched.result.type).toBe("text")
if (searched.result.type !== "text") return
expect(JSON.parse(String(searched.result.value)).items[0]).toMatchObject({
path: "tools.stripe.refund_payment",
description: "Refund payment in Stripe.",
})
const completed = yield* invoke("return await tools.stripe.refund_payment({})", "call_run_fixture")
expect(completed.result).toEqual({ type: "text", value: "Completed refund payment." })
}),
)