Skip to content

Extension

Extensions: named bundles of tools, prompt sections, hooks, wrappers and task definitions. An application installs them in its Registry; each conversation selects them by name in its agent (Agent.configure). Installing an extension again under the same name replaces it in place, which is how code reloads.

import { Extension, type Tool } from "@effective-harness/core"
declare const Read: Tool.Any
declare const Write: Tool.Any
const Files = Extension.make("files", {
tools: [Read, Write],
sections: [Extension.section("cwd", (input) => input.env?.cwd)]
})

Since v0.0.0


An extension of any tool type.

Signature

type Any = Extension<any>

Source

Since v0.0.0

Signature

export interface Extension<T extends Tool.Any = Tool.Any> {
readonly name: string
readonly tools?: ReadonlyArray<T>
readonly sections?: ReadonlyArray<Section<T>>
readonly hooks?: ReadonlyArray<HookRegistration>
/** Applied where this extension is selected, in order. */
readonly wraps?: ReadonlyArray<Wrap<T>>
/** Task definitions, resolved by name for every task whichever conversations select this extension. */
readonly tasks?: ReadonlyArray<Task.Any>
}

Source

Since v0.0.0

Handlers for the hooks of tasks with one name.

Signature

export interface HookRegistration {
readonly task: string
readonly handlers: object
}

Source

Since v0.0.0

What a section renders from.

Signature

export interface PromptInput<T extends Tool.Any = Tool.Any> {
readonly conversationId: ConversationId
/** The request's agent; `agent.tools` are the tools offered in this request. */
readonly agent: Agent<T>
/** The conversation's environment, built for this request. */
readonly env: ExecEnv | undefined
/** Sections already in effect, from replaying the transcript's system messages. */
readonly shown: Readonly<Record<string, string>>
}

Source

Since v0.0.0

What a renderer returns: text, nothing, or an effect that reads committed state.

Signature

type Rendered = string | undefined | Effect.Effect<string | undefined, unknown, Session>

Source

Since v0.0.0

A named part of the system prompt.

Signature

export interface Section<T extends Tool.Any = Tool.Any> {
readonly key: string
readonly render: (input: PromptInput<T>) => Rendered
/** Default `true`: wrap the text as `<key>\n…\n</key>`. */
readonly tag?: boolean
}

Source

Since v0.0.0

A wrapper of a tool or a section, applied where its extension is selected.

Signature

type Wrap<T extends Tool.Any = Tool.Any> =
| { readonly tool: string; readonly wrap: (tool: T) => T }
| { readonly section: string; readonly wrap: (section: Section<T>) => Section<T> }

Source

Since v0.0.0

Hook handlers for tasks named like task.

Signature

declare const hook: (task: Task.Any | string, handlers: object) => HookRegistration

Source

Since v0.0.0

Define an extension.

Signature

declare const make: <T extends Tool.Any = Tool.Any>(name: string, parts?: Omit<Extension<T>, "name">) => Extension<T>

Source

Since v0.0.0

Render a section as an effect, so a wrapper can build on what it renders.

Signature

declare const render: <T extends Tool.Any>(
section: Section<T>,
input: PromptInput<T>
) => Effect.Effect<string | undefined, unknown, Session>

Source

Since v0.0.0

A prompt section; tagged unless tag is false.

Signature

declare const section: <T extends Tool.Any = Tool.Any>(
key: string,
render: Section<T>["render"],
options?: { readonly tag?: boolean }
) => Section<T>

Source

Since v0.0.0

Wrap the section key wherever the wrapping extension is selected.

Signature

declare const wrapSection: <T extends Tool.Any = Tool.Any>(
key: string,
wrap: (section: Section<T>) => Section<T>
) => Wrap<T>

Source

Since v0.0.0

Wrap the tool named like tool wherever the wrapping extension is selected.

Signature

declare const wrapTool: <T extends Tool.Any>(tool: T | string, wrap: (tool: T) => T) => Wrap<T>

Source

Since v0.0.0