Skip to main content
← Back to list
01Issue
FeatureOpenSwamp CLI
AssigneesNone

Relationships

#587 Extension model method execute lacks typed args/context — every author has to use ': any' to unblock tests

Opened by stack72 · 6/7/2026

Problem

The extension model API requires writing methods: { foo: { arguments: ZodSchema, execute: async (args, context) => {...} } }, but no typed interface is published for args or context. Every existing extension in bixu/swamp-extensions either:

  1. Annotates with : any (e.g. extensions/models/honeycomb.ts:107: execute: async (args: any, context: any) =>)
  2. Leaves them untyped and fails Deno's type-check whenever a sibling test file transitively imports the module

Reproduction (Deno 2.x, swamp 20260606.235053.0):

// foo.ts
methods: {
  doThing: {
    arguments: z.object({ name: z.string() }),
    execute: async (args, context) => { /* ... */ },
  },
}
// foo_test.ts
import { somePureHelper } from "./foo.ts";
// ... tests
$ deno task test
TS7006 [ERROR]: Parameter 'args' implicitly has an 'any' type.
TS7006 [ERROR]: Parameter 'context' implicitly has an 'any' type.

The error doesn't surface until you write tests for the module — the file alone doesn't get type-checked.

Why this matters

  • Extension authors lose type safety on the most-used parameters in their methods. args.something should be inferred from the Zod schema; instead it's any, so misspellings, missing fields, and wrong types compile silently.
  • context.logger, context.writeResource, context.globalArgs, etc. should be typed against the swamp runtime API. Today there's nothing to import.
  • Adding a test for any pure helper in the same file as a methods: block immediately breaks deno task test until the author either annotates : any or refactors to extract helpers into separate files.
  • For agents (Claude Code, etc.) writing extensions, the failure mode is opaque: tests "work" until you add coverage, then they don't.

Proposed solutions

Two shapes from prior art, either would solve it:

Option A: publish typed interfaces

import type { MethodContext, MethodResult } from "@swamp/extension";

execute: async (
  args: z.infer<typeof DoThingArgs>,
  context: MethodContext,
): Promise<MethodResult> => { /* ... */ }

Requires shipping a typed @swamp/extension package (or jsr:@swamp/extension) that authors can import. The Zod inference handles args; MethodContext covers logger, writeResource, globalArgs, etc.

Option B: generic method factory

import { defineMethod } from "@swamp/extension";

methods: {
  doThing: defineMethod(DoThingArgs, async (args, context) => {
    // args inferred as z.infer<typeof DoThingArgs>
    // context typed against MethodContext
  }),
}

Cleaner ergonomics — no manual annotation needed. The factory consumes the schema and a callback whose argument types are inferred.

Option B is the friendlier API. Option A is the minimum viable fix and doesn't require touching every existing extension.

Workaround today

execute: async (args: any, context: any) => { /* ... */ } plus a // deno-lint-ignore no-explicit-any if no-explicit-any is on. This is what every extension in bixu/swamp-extensions currently does.

Co-authored-by: Claude noreply@anthropic.com


Automoved by swampadmin from https://github.com/swamp-club/swamp/issues/1524

02Bog Flow
OPENTRIAGEDIN PROGRESSSHIPPED

Open

6/7/2026, 4:52:20 PM

No activity in this phase yet.

03Sludge Pulse

Sign in to post a ripple.