|
|
@@ -12,6 +12,7 @@ import type { CallId, ContentBlock, ToolSchema } from '@deepseek-ai/dsh-llm'
|
|
|
import { HarnessError } from '@deepseek-ai/dsh-llm'
|
|
|
import type { Agent } from '@deepseek-ai/dsh-agent'
|
|
|
import type {} from '@deepseek-ai/dsh-system-prompt'
|
|
|
+import type { ToolCallView, ToolResultView } from './presentation.ts'
|
|
|
|
|
|
export {
|
|
|
defineTool,
|
|
|
@@ -26,6 +27,23 @@ export {
|
|
|
type JsonSchemaObject,
|
|
|
} from './schema.ts'
|
|
|
|
|
|
+// The render-intent vocabulary a tool declares via `presentCall`/`presentResult`
|
|
|
+// lives in its own UI-facing module; re-export it so `@deepseek-ai/dsh-tools`
|
|
|
+// stays the single public surface for consumers (producers + the ACP bridge).
|
|
|
+export type {
|
|
|
+ ToolCallKind,
|
|
|
+ FileLocation,
|
|
|
+ FileDiff,
|
|
|
+ ToolCallView,
|
|
|
+ GenericCallView,
|
|
|
+ TerminalCallView,
|
|
|
+ DiffCallView,
|
|
|
+ ToolResultView,
|
|
|
+ GenericResultView,
|
|
|
+ TerminalResultView,
|
|
|
+ DiffResultView,
|
|
|
+} from './presentation.ts'
|
|
|
+
|
|
|
declare module 'cordis' {
|
|
|
interface Context {
|
|
|
tools: ToolRegistry
|
|
|
@@ -54,191 +72,6 @@ declare module 'cordis' {
|
|
|
// parallel execution — Claude Code partitions read-only tools; phase 1
|
|
|
// executes sequentially).
|
|
|
|
|
|
-/**
|
|
|
- * Category of a tool call, used by a UI to pick an icon / treatment. A neutral
|
|
|
- * vocabulary owned here (NOT an ACP type) so tools describe themselves without
|
|
|
- * depending on any client protocol; a UI bridge maps it to its own enum. The
|
|
|
- * member set mirrors the common ACP `ToolKind` values; `other` is the default.
|
|
|
- */
|
|
|
-export type ToolCallKind = 'read' | 'edit' | 'delete' | 'move' | 'search' | 'execute' | 'fetch' | 'other'
|
|
|
-
|
|
|
-/**
|
|
|
- * A file location a tool reads or modifies, so a capable UI can "follow along" —
|
|
|
- * highlight or jump to the file (and line) as the tool runs. Provider-neutral;
|
|
|
- * a UI bridge maps it to its own affordance (the ACP bridge forwards it as
|
|
|
- * `tool_call.locations`). `path` is what the tool operated on (the model-facing
|
|
|
- * path); `line` is an optional 1-based line to focus (e.g. a read's offset).
|
|
|
- */
|
|
|
-export interface FileLocation {
|
|
|
- path: string
|
|
|
- line?: number
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * A single-file change a tool is about to make, for a UI that renders inline
|
|
|
- * diffs (an editor's diff card). Provider-neutral; the ACP bridge forwards it as
|
|
|
- * a `{ type: 'diff' }` tool-call content block. `oldText` is `null` for a
|
|
|
- * new-file create (nothing to diff against); an overwrite also uses `null`,
|
|
|
- * because a call-time presenter has no access to the file's prior content.
|
|
|
- */
|
|
|
-export interface FileDiff {
|
|
|
- path: string
|
|
|
- /** Prior content, or `null` for a new file / an overwrite (no prior content available at call time). */
|
|
|
- oldText: string | null
|
|
|
- /** Content after the change. */
|
|
|
- newText: string
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * How a tool wants ONE of its calls shown in a UI (an editor's tool-call card, a
|
|
|
- * CLI log line) BEFORE the result is known — the *pending* state. A `card`-tagged
|
|
|
- * discriminated union: a tool declares its render INTENT once and a UI bridge
|
|
|
- * switches on `card` to map it to the bridge's own wire shape. Provider-neutral —
|
|
|
- * the tool owns its presentation, so a UI never special-cases tool names.
|
|
|
- *
|
|
|
- * Returned by {@link ToolDefinition.presentCall}. See the render-intent-union
|
|
|
- * RFC (docs/rfc/implemented/architecture/2026-07-02-tool-render-intent-union.md).
|
|
|
- */
|
|
|
-export type ToolCallView = GenericCallView | TerminalCallView | DiffCallView
|
|
|
-
|
|
|
-/**
|
|
|
- * The default card: a titled tool-call row with an optional category icon, a
|
|
|
- * salient raw input, extra content blocks, and follow-along file locations. Any
|
|
|
- * tool whose call is not a terminal or a diff uses this.
|
|
|
- */
|
|
|
-export interface GenericCallView {
|
|
|
- card: 'generic'
|
|
|
- /**
|
|
|
- * Human-readable, always-visible label describing what THIS call does. Keep it
|
|
|
- * short — a UI shows it as a card header / log line.
|
|
|
- */
|
|
|
- title: string
|
|
|
- /** Category for icon/treatment; defaults to `other` when omitted. */
|
|
|
- kind?: ToolCallKind
|
|
|
- /**
|
|
|
- * The salient input to surface in a detail/expanded view (e.g. a background
|
|
|
- * task id). Omit to show nothing; a string renders as-is, an object as pretty
|
|
|
- * JSON. NOT the full raw args object unless that is genuinely what a reader wants.
|
|
|
- */
|
|
|
- rawInput?: unknown
|
|
|
- /**
|
|
|
- * UI-facing content blocks to show on the pending call alongside the title.
|
|
|
- * Omit to show none. A UI maps these to its own content blocks.
|
|
|
- */
|
|
|
- content?: ContentBlock[]
|
|
|
- /** Files this call reads/modifies, for editor follow-along. Omit for a call that touches no file. */
|
|
|
- locations?: FileLocation[]
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * A call that IS a shell command running in a working directory: a capable UI
|
|
|
- * renders it as a terminal card (cwd-headed, with the command as the title and
|
|
|
- * live/afterward output from the {@link TerminalResultView}); an incapable UI
|
|
|
- * falls back to a generic card whose body is the fenced command output. Set by a
|
|
|
- * tool whose call is a foreground command (e.g. `bash`).
|
|
|
- */
|
|
|
-export interface TerminalCallView {
|
|
|
- card: 'terminal'
|
|
|
- /** The command, shown as the terminal card's title / header line. */
|
|
|
- title: string
|
|
|
- /**
|
|
|
- * A human-readable one-line summary of what the command does, rendered ABOVE
|
|
|
- * the terminal card (the card itself has no description slot). Omit for none.
|
|
|
- */
|
|
|
- description?: string
|
|
|
- /**
|
|
|
- * Working directory the command runs in, shown as the terminal header. An
|
|
|
- * ABSOLUTE path is used as-is; a RELATIVE path is resolved by the UI bridge
|
|
|
- * against the session workspace (the pure presenter can't see the session cwd).
|
|
|
- * Omit entirely to let the bridge use the session workspace.
|
|
|
- */
|
|
|
- cwd?: string
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * A call that creates or modifies files, rendered as an inline diff card by a
|
|
|
- * capable UI. Set by a tool whose call writes/edits a file (e.g. `write`,
|
|
|
- * `edit`). The diffs are derived from the call ARGUMENTS (a create's `oldText` is
|
|
|
- * `null`); the tool emits a separate {@link DiffResultView} after `execute` — the
|
|
|
- * applied change (an edit/overwrite hunk with context, or a whole-file diff for a
|
|
|
- * create).
|
|
|
- */
|
|
|
-export interface DiffCallView {
|
|
|
- card: 'diff'
|
|
|
- /** Card header (e.g. `Write foo.txt`). */
|
|
|
- title: string
|
|
|
- /** One entry per file the call changes. */
|
|
|
- diffs: FileDiff[]
|
|
|
- /** Files this call modifies, for editor follow-along (usually the diffs' paths). */
|
|
|
- locations?: FileLocation[]
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * How a tool wants the COMPLETED call shown — the *result* state, after `execute`
|
|
|
- * returns. A `card`-tagged union mirroring {@link ToolCallView}: a UI switches on
|
|
|
- * `card`. Lets the tool reformat its result for a UI distinctly from the
|
|
|
- * model-facing text it returned from `execute`. Returned by
|
|
|
- * {@link ToolDefinition.presentResult}; omitting the method keeps the pending
|
|
|
- * title and renders the raw result content.
|
|
|
- */
|
|
|
-export type ToolResultView = GenericResultView | TerminalResultView | DiffResultView
|
|
|
-
|
|
|
-/**
|
|
|
- * The default completed card: an optional replacement title and reformatted
|
|
|
- * content. Omit a field to keep the pending title / render the raw result content.
|
|
|
- */
|
|
|
-export interface GenericResultView {
|
|
|
- card: 'generic'
|
|
|
- /** Replacement title for the completed call. Omit to keep the pending-state title. */
|
|
|
- title?: string
|
|
|
- /**
|
|
|
- * UI-facing result content (harness {@link ContentBlock}s), reformatted from
|
|
|
- * the model-facing result. Omit to let the UI render the raw result content.
|
|
|
- */
|
|
|
- content?: ContentBlock[]
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * The completed state of a {@link TerminalCallView}: the captured output and exit
|
|
|
- * status. A capable UI renders `output` in the terminal card and shows an
|
|
|
- * exit-status pill; an incapable UI gets a fenced ```console fallback the BRIDGE
|
|
|
- * derives from `output` (the tool does not double-encode it).
|
|
|
- */
|
|
|
-export interface TerminalResultView {
|
|
|
- card: 'terminal'
|
|
|
- /** Replacement title for the completed call. Omit to keep the pending-state title. */
|
|
|
- title?: string
|
|
|
- /** Captured command output (stdout+stderr as the tool chooses to combine them). */
|
|
|
- output?: string
|
|
|
- /**
|
|
|
- * Process exit code, when the run ended by exiting (not a signal). Lets a
|
|
|
- * capable UI show an exit-status pill. Omit when killed by a signal or unknown.
|
|
|
- */
|
|
|
- exitCode?: number
|
|
|
- /** Signal name that killed the process (e.g. `SIGTERM`). Mutually exclusive with `exitCode`. */
|
|
|
- signal?: string
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * A completed file mutation rendered as an inline diff card, the *result-time*
|
|
|
- * analogue of {@link DiffCallView}. Set by a tool whose `execute` applied a file
|
|
|
- * change (e.g. `write`, `edit`): `diffs` are the change to show — typically the
|
|
|
- * APPLIED hunks computed from the before/after content (one entry per hunk, each
|
|
|
- * with surrounding context lines), so the editor shows the real change in place;
|
|
|
- * a tool with no before-image (e.g. a file create) may instead give a whole-file
|
|
|
- * diff (`oldText: null`). A `tool_call_update`'s content REPLACES the call's
|
|
|
- * content in an editor, so a mutation tool returns this even when it duplicates
|
|
|
- * the call-time snippet — otherwise the model-facing result text would replace
|
|
|
- * (clobber) the pending diff card.
|
|
|
- */
|
|
|
-export interface DiffResultView {
|
|
|
- card: 'diff'
|
|
|
- /** Replacement title for the completed call. Omit to keep the pending-state title. */
|
|
|
- title?: string
|
|
|
- /** The change to show, in file order — applied contextual hunks, or a whole-file diff when there is no before-image. */
|
|
|
- diffs: FileDiff[]
|
|
|
-}
|
|
|
-
|
|
|
/**
|
|
|
* What a tool's `execute` returns. The bare {@link ContentBlock}`[]` form is the
|
|
|
* common case (model-facing content only); the object form additionally attaches
|