tools

package
v0.9.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 29, 2026 License: Apache-2.0, MIT Imports: 67 Imported by: 0

Documentation

Overview

Package tools — capability requirements for built-in agent tools.

This file is the Go mirror of `frontend/src/utils/tool-capabilities.ts`. They MUST be kept in sync: whenever you add a tool to the registry with specific KB requirements, update both maps.

Why duplicate it? The frontend uses it to gray out tools and filter KBs in the agent editor and `@` mention menu; the backend uses it as the authoritative last line of defense in the retrieval pipeline — a client that skips the frontend filter (old tab, curl, rogue plugin) shouldn't be able to hand incompatible KBs/files to a tool that would just silently skip them.

Package tools — edit_sandbox_file.

Surgical text replacement for a file already in the session sandbox. write_sandbox_file is the right first step for a new script; this tool exists so a one-line path fix (or similar) does not force the model to regenerate the whole file — that burns tokens and often truncates.

Design notes:

  • Same writable scope as write_sandbox_file: session sandbox except /workspace/input.
  • One input shape: every change is an entry in edits[]. Each entry resolves against the original content, so a batch is order-independent and overlaps are rejected rather than silently corrupting the file.
  • Default is a unique match (Cursor-style). Per-entry replace_all replaces every occurrence. 0 matches or an ambiguous match without replace_all fail without writing.
  • Result is path + replacement count + size; contents are not echoed.

Package tools — list_sandbox_files.

Read-only tool that lets the LLM enumerate files under a session's inspectable sandbox directories. Without this tool, the LLM cannot see files produced by prior skill invocations or staged chat attachments and has to guess paths when chaining work together.

Design notes:

  • Session-scoped: the sandbox path is resolved from the tool exec context (`ToolExecContext.SessionID`). The LLM cannot pass an arbitrary session ID.
  • Paths are inside the current session's sandbox. Relative paths resolve from the workspace root. Omitting `path` lists the layout default (remote: `$WEKNORA_SKILL_OUTPUT_DIR` / `/workspace/output`; host: the workspace root).
  • Read-only: this tool never creates, modifies or deletes anything inside the sandbox. Model-authored files go through write_sandbox_file.
  • Graceful "no sandbox": if the session has never spawned a sandbox yet (chat-only turn, or sandbox was reaped), the tool returns an empty listing with a helpful message rather than an error, so the LLM can decide to invoke a skill first.

Package tools — write_sandbox_file.

Lets the LLM write a text file into the current session's sandbox without stuffing the bytes through a shell_exec heredoc. shell_exec keeps an 8 KiB command cap; generated scripts (PPT builders, reports) routinely exceed it.

Design notes:

  • Session-scoped: the sandbox is resolved from ToolExecContext.SessionID.
  • Path guardrail: writes stay under the session layout's WriteRoots and never under InputDir (staged attachments are the user's, not ours). Remote sessions collect OutputDir for download; host sessions with an empty OutputDir edit in place. Only the InputDir half is enforced here; "finished deliverable" is guidance the tool cannot judge.
  • Content stays out of ToolResult.Data/Output: the model already has the bytes it just sent. The result is path + size so the next call can shell_exec the file.

Package tools — shell_exec.

General shell command execution primitive for the agent. The LLM can freely explore and operate inside its session-scoped Cube MicroVM: inspect files, transform data, run programs, install dependencies, and prepare or verify skill outputs.

Design notes:

  • Session-sandbox capability: registration is feature-gated on the sandbox backend exposing SandboxCommandExecutor (Cube, E2B, Docker). Remote sessions never run on the WeKnora host. Host layouts clamp work_dir to the layout's writable roots; the OS sandbox is the process perimeter.
  • Session-scoped: the sandbox is resolved from ToolExecContext.SessionID so the LLM cannot execute against a foreign session, and installed dependencies persist across subsequent tool calls in the same session.
  • Non-zero exit is a normal signal, not a tool failure: pip install failures, missing binaries, etc. are all valid results the LLM must inspect. Wire-level errors (sandbox unreachable) and commands that were killed or timed out surface as ToolResult.Success = false.
  • Output truncation: shell installers produce thousands of lines that would blow up the LLM context. We keep the head (leading messages) and the tail (final errors) with an ellipsis marker so the tail — usually the most informative segment — is preserved.
  • Command shape blacklist: the sandbox is throwaway, but we still refuse obviously destructive patterns (rm -rf /, fork bombs, mkfs...) to protect the LLM from its own hallucinations.
  • No backgrounding: trailing '&' and 'nohup' are rejected up-front to avoid orphaned processes inside the sandbox. Optional stdin is allowed as data; when the command is an interpreter that would run stdin as a program, the same blacklist and command-size cap apply to that payload.

Package tools — write_skill_file / edit_skill_file.

The installer agent's only writer used to be `shell_exec` with a heredoc. That caps every file at the shell's command-length limit and puts the content through two levels of quoting, so a requirements.json or a small patch script routinely arrived truncated or mangled. These two tools write the same bytes over the file API instead.

They are separate from write_sandbox_file / edit_sandbox_file rather than a loosening of them. Those write /workspace, which is wiped before the snapshot; the skill tree lives under /opt/weknora/tenant/skills and is what the snapshot keeps. Sharing one tool would mean one path guard covering both a per-session scratch area and the shared image.

Scope: one install writes one skill. The tool is constructed with that skill's directory and refuses everything outside it, so an installer cannot reach a neighbouring skill in the shared image even though its shell runs as root. The prompt asks for the same thing; this enforces it.

Package tools — read_file.

Read-only tool that lets the LLM read a file inside the session's sandbox. Known paths can be read directly; directory discovery is optional.

Design notes:

  • Session-scoped: path must belong to the current session's sandbox, enforced by delegating to SandboxFileSource.ReadSessionFile which itself takes the session ID from context.
  • Absolute paths are sandbox-local; relative paths resolve from /workspace. Reading a file does not make it a downloadable artifact.
  • Paginated reads: a page is bounded by a line count, a byte budget, and the registry's rune budget, and a partial page ends with the offset to continue from. Files over 8 MiB are never downloaded; the model gets metadata and uses shell_exec with sed/head/tail/grep/awk instead.
  • Binary handling: an image file is returned as a prepared vision image in ToolResult.Images, which is never persisted; other binary bytes are never returned or base64-encoded. ArtifactCollector remains the download path.

Index

Constants

View Source
const (
	// Capability-scoped MCP discovery and invocation; not tenant-selectable builtins.
	ToolDiscoverMCPTools = "discover_mcp_tools"
	ToolCallMCPTool      = "call_mcp_tool"
	ToolThinking         = "thinking"
	ToolTodoWrite        = "todo_write"
	// ToolAskUser asks the user a question through a card and waits for the
	// answer; the run may suspend until it arrives.
	ToolAskUser = "ask_user"
	// Knowledge retrieval surface. search_knowledge covers semantic, keyword
	// and hybrid retrieval over chunk-indexed knowledge bases; read_document
	// reads a document's metadata and chunks (by page, by chunk handle, or by
	// an in-document text search); list_documents browses one knowledge base.
	ToolSearchKnowledge     = "search_knowledge"
	ToolReadDocument        = "read_document"
	ToolListDocuments       = "list_documents"
	ToolQueryKnowledgeGraph = "query_knowledge_graph"
	ToolSearchConversations = "search_conversations"
	ToolSearchMemory        = "search_memory"
	ToolDatabaseQuery       = "database_query"
	ToolDataAnalysis        = "data_analysis"
	ToolDataSchema          = "data_schema"
	ToolWebSearch           = "web_search"
	ToolWebFetch            = "web_fetch"
	// Unified reading: workspace access follows sandbox file capability;
	// skill resources follow SkillsEnabled and do not require a sandbox.
	// attachment:// is added whenever the session has stored attachments,
	// because a file the user just sent is not something an allowlist should
	// be able to hide from the agent.
	ToolReadFile = "read_file"
	// Sandbox filesystem tools (only available when the sandbox backend
	// supports per-session files — Cube, E2B, Docker). list/read inspect
	// the session workspace; write creates text files so generated
	// scripts do not have to travel through a shell_exec heredoc; edit
	// patches an existing file without regenerating it.
	//
	// Deliberately absent from AvailableToolDefinitions and
	// DefaultAllowedTools, like search_memory and web_search: the sandbox
	// switch already decides whether a run has a workspace at all, and
	// registerSandboxFileTools registers these from that capability rather
	// than from the allowlist. A checkbox would have been a lie — clearing
	// it changed nothing.
	ToolListSandboxFiles = "list_sandbox_files"
	ToolWriteSandboxFile = "write_sandbox_file"
	ToolEditSandboxFile  = "edit_sandbox_file"
	// ToolWriteSkillFile / ToolEditSkillFile write the skill tree under
	// /opt/weknora/tenant/skills rather than /workspace, and exist only for
	// the built-in skill installer. They are scoped to the one skill being
	// installed; see internal/agent/tools/skill_file.go.
	//
	// Deliberately absent from AvailableToolDefinitions: these write the
	// shared snapshot image, so they are granted by install mode alone and
	// must not become selectable on a tenant-editable agent config.
	ToolWriteSkillFile = "write_skill_file"
	ToolEditSkillFile  = "edit_skill_file"
	// ToolShellExec lets the LLM execute ad-hoc shell commands inside the
	// current session's sandbox (dependency installs, environment probing).
	// Registered only when the resolved backend advertises the session shell
	// capability (Cube, E2B, Docker). The command never runs on the WeKnora host.
	//
	// Also absent from AvailableToolDefinitions: registerSandboxShellIfAllowed
	// keys it on SkillsEnabled (or install mode), so the shell follows the
	// skills switch and not a per-agent tool checkbox.
	ToolShellExec = "shell_exec"
	// ToolShellExecAsync submits a shell command as background work (plan 4).
	// Like shell_exec it is registered per run, not in AvailableToolDefinitions.
	ToolShellExecAsync = "shell_exec_async"
	// ToolWorkWait / ToolWorkCancel wait on and stop background work. They are
	// registered per run, only when the run can submit background work, so
	// they are absent from AvailableToolDefinitions like shell_exec.
	ToolWorkWait   = "work_wait"
	ToolWorkCancel = "work_cancel"
	// Wiki-related tools (only available when wiki KBs are in scope)
	ToolWikiReadPage    = "wiki_read_page"
	ToolWikiWritePage   = "wiki_write_page"
	ToolWikiReplaceText = "wiki_replace_text"
	ToolWikiRenamePage  = "wiki_rename_page"
	ToolWikiDeletePage  = "wiki_delete_page"
	ToolWikiSearch      = "wiki_search"
	ToolWikiFlagIssue   = "wiki_flag_issue"
	ToolWikiReadIssue   = "wiki_read_issue"
	ToolWikiUpdateIssue = "wiki_update_issue"
)

Tool names constants

View Source
const (
	ToolGroupBase      = "base"
	ToolGroupRAG       = "rag"
	ToolGroupWikiRead  = "wiki_read"
	ToolGroupWikiEdit  = "wiki_edit"
	ToolGroupWikiIssue = "wiki_issue"
	ToolGroupData      = "data"
)

Tool groups the agent editor sections its checkboxes by.

View Source
const (
	LegacyToolExecuteSkillScript = "execute_skill_script"
	LegacyToolReadSkill          = "read_skill"
	LegacyToolReadSandboxFile    = "read_sandbox_file"
	// The pre-consolidation knowledge retrieval surface. knowledge_search and
	// grep_chunks were folded into search_knowledge (mode=semantic|keyword|
	// hybrid); list_knowledge_chunks, get_document_info and
	// wiki_read_source_doc were folded into read_document.
	LegacyToolKnowledgeSearch     = "knowledge_search"
	LegacyToolGrepChunks          = "grep_chunks"
	LegacyToolListKnowledgeChunks = "list_knowledge_chunks"
	LegacyToolGetDocumentInfo     = "get_document_info"
	LegacyToolWikiReadSourceDoc   = "wiki_read_source_doc"
)

Retired tool identifiers are retained only for decoding existing histories and ignoring obsolete allowlist entries. They have no implementation or registration path and are never offered in model tool schemas.

View Source
const (
	ToolFindOperations = "find_operations"
	ToolRunOperation   = "run_operation"
)

Operation catalog tool names.

View Source
const (
	ToolReadPage  = "read_page"
	ToolFillPage  = "fill_page"
	ToolSelectTab = "select_tab"
)

Tools that read and fill the WeKnora page the user has open beside the assistant. They run in the user's browser through a page_action prompt.

View Source
const (
	ToolSearchWeKnoraDocs = "search_weknora_docs"
	ToolReadWeKnoraDoc    = "read_weknora_doc"
)

WeKnora documentation tool names.

View Source
const (
	SearchModeHybrid   = "hybrid"
	SearchModeSemantic = "semantic"
	SearchModeKeyword  = "keyword"
)

Retrieval modes accepted by search_knowledge.

View Source
const DataAnalysisTableName = "dataset"

DataAnalysisTableName is the only table name the model needs to know when querying a CSV/Excel document through data_analysis. Each document is loaded into a physical DuckDB table named after its knowledge ID; that name is never shown to the model. Every query runs on a private connection where "dataset" is a temporary view over the selected document, so the model references the same fixed identifier for every document and the knowledge ID never has to appear inside SQL text.

View Source
const (
	// DefaultMaxToolOutput is the default maximum character (rune) count for tool output.
	// Outputs exceeding this limit are truncated with head + tail preservation.
	// This counts Unicode characters (runes), not bytes, so CJK text is treated fairly.
	DefaultMaxToolOutput = 24000
)
View Source
const ToolOpenPage = "open_page"

ToolOpenPage offers the user a link to a WeKnora page, optionally with a form filled in for them to finish and save.

View Source
const ToolViewPage = "view_page"

ToolViewPage opens a WeKnora page in the user's browser and returns what it shows, so the model can answer about it.

Variables

View Source
var AgentEditorSections = []string{
	"basic", "prompts", "model", "multimodal", "conversation", "suggestions",
	"tools", "mcp", "skills", "knowledge", "websearch", "retrieval", "share",
}

AgentEditorSections are the agent editor tabs a link may open.

View Source
var CollaborationToolNames = []string{
	"spawn_agent",
	"list_agents",
	"send_message",
	"followup_task",
	"interrupt_agent",
	"wait_agent",
}

CollaborationToolNames lists the six runtime collaboration tools.

View Source
var ErrProtocolArtifact = errors.New("model returned internal protocol data instead of an answer")

ErrProtocolArtifact indicates an internal protocol fragment in place of an answer.

View Source
var SettingsSections = map[string]openPageSection{
	"general":               {"常规设置", "General Settings"},
	"userprofile":           {"用户信息", "User Profile"},
	"assistant":             {"助手", "Assistant"},
	"mymemory":              {"我的记忆", "My memory"},
	"envvars":               {"沙箱密钥", "Sandbox secrets"},
	"tenant":                {"空间信息", "Workspace Info"},
	"members":               {"成员管理", "Members"},
	"chathistory":           {"消息管理", "Message Management"},
	"memory":                {"长期记忆", "Long-term memory"},
	"models":                {"模型管理", "Model Management"},
	"ollama":                {"Ollama", "Ollama"},
	"weknoracloud":          {"WeKnora Cloud", "WeKnora Cloud"},
	"websearch":             {"网络搜索", "Web Search"},
	"vectorstore":           {"向量数据库引擎", "Vector DB Engine"},
	"parser":                {"解析引擎", "Parser Engine"},
	"storage":               {"存储引擎", "Storage Engine"},
	"sandbox":               {"沙箱配置", "Sandbox Config"},
	"system":                {"版本信息", "Version Info"},
	"system-global":         {"系统设置", "System Settings"},
	"model-catalog":         {"模型目录", "Model catalog"},
	"runtime-queues":        {"任务队列", "Task Queues"},
	"platform-api-keys":     {"平台 API Key", "Platform API Keys"},
	"system-audit-log":      {"审计日志", "Audit log"},
	"integration-im":        {"IM 集成", "IM Integration"},
	"integration-embed":     {"网页嵌入", "Web Embed"},
	"integration-api":       {"API 集成", "API Integration"},
	"integration-mcpserver": {"MCP Server", "MCP Server"},
	"integration-cli":       {"CLI", "CLI"},
	"integration-chrome":    {"Chrome 插件", "Chrome Extension"},
	"integration-claw":      {"Claw Skill", "Claw Skill"},
}

SettingsSections are the settings dialog's sections, keyed as the client's navigation keys them, with the names it shows.

View Source
var SystemSettingsPanels = map[string]openPageSection{
	"access":   {"注册与访问", "Registration and access"},
	"users":    {"用户管理", "User management"},
	"tenant":   {"空间默认值", "Workspace defaults"},
	"runtime":  {"运行与并发", "Runtime and concurrency"},
	"security": {"网络安全", "Network security"},
}

SystemSettingsPanels are the tabs inside settings section system-global. "other" is conditional on the page and is reached with select_tab instead.

View Source
var ToolCapabilityRequirements = map[string]ToolRequirement{

	"thinking":   {},
	"todo_write": {},
	"ask_user":   {},

	"search_knowledge":      {AnyOf: []KBCapability{CapVector, CapKeyword}, ConsumesFiles: true},
	"read_document":         documentReaderRequirement,
	"list_documents":        documentReaderRequirement,
	"query_knowledge_graph": {AllOf: []KBCapability{CapGraph}, ConsumesFiles: true},
	"database_query":        {AnyOf: []KBCapability{CapVector, CapKeyword}, ConsumesFiles: true},

	"knowledge_search":      {AnyOf: []KBCapability{CapVector, CapKeyword}, ConsumesFiles: true},
	"grep_chunks":           {AnyOf: []KBCapability{CapVector, CapKeyword}, ConsumesFiles: true},
	"list_knowledge_chunks": {AnyOf: []KBCapability{CapVector, CapKeyword}, ConsumesFiles: true},
	"get_document_info":     {AnyOf: []KBCapability{CapVector, CapKeyword}, ConsumesFiles: true},

	"wiki_search":          {AllOf: []KBCapability{CapWiki}},
	"wiki_read_page":       {AllOf: []KBCapability{CapWiki}},
	"wiki_read_source_doc": documentReaderRequirement,
	"wiki_flag_issue":      {AllOf: []KBCapability{CapWiki}},
	"wiki_write_page":      {AllOf: []KBCapability{CapWiki}},
	"wiki_replace_text":    {AllOf: []KBCapability{CapWiki}},
	"wiki_rename_page":     {AllOf: []KBCapability{CapWiki}},
	"wiki_delete_page":     {AllOf: []KBCapability{CapWiki}},
	"wiki_read_issue":      {AllOf: []KBCapability{CapWiki}},
	"wiki_update_issue":    {AllOf: []KBCapability{CapWiki}},

	"data_analysis": {AnyOf: []KBCapability{CapVector, CapKeyword}, ConsumesFiles: true},
	"data_schema":   {AnyOf: []KBCapability{CapVector, CapKeyword}, ConsumesFiles: true},
}

ToolCapabilityRequirements maps tool names to their capability needs. Keep this aligned with `frontend/src/utils/tool-capabilities.ts`.

Tools absent from this map default to "no requirement" and are treated as always available / file-consuming (permissive fallback: unknown MCP tools shouldn't silently break).

View Source
var ToolboxSections = map[string]openPageSection{
	"skills":            {"技能管理", "Skill Management"},
	"mcp":               {"MCP 服务", "MCP services"},
	"browserconnection": {"浏览器连接", "Browser connection"},
}

ToolboxSections are the toolbox's tools.

Functions

func BrowserSkillScope

func BrowserSkillScope(ctx context.Context) browserskill.Scope

BrowserSkillScope names the caller's browser. A shared agent runs in its owner's workspace, but the browser stays paired to the member who asked.

func CanRunConcurrently

func CanRunConcurrently(name string) bool

CanRunConcurrently is an explicit allowlist of built-in reads. Mutations, arbitrary code, and unknown/MCP tools form execution barriers. In particular, a file write must finish before the next shell or skill call starts.

func CastParams

func CastParams(args json.RawMessage, schema json.RawMessage) json.RawMessage

CastParams performs schema-driven type casting on tool arguments. LLMs sometimes return incorrect types (e.g., "true" instead of true, "123" instead of 123). This function attempts safe conversions based on the JSON Schema definition of the tool's parameters.

If the schema is nil or cannot be parsed, the original args are returned unchanged.

func ChangedOutputFileLinks(outputDir string, before, after []sandbox.RemoteDirEntry) []string

ChangedOutputFileLinks reports deliverable links for files that appeared or changed between two output-directory listings. An empty non-nil slice means the listings were compared and nothing changed.

func CompactToolOutputForHistory

func CompactToolOutputForHistory(toolName string, result *types.ToolResult) string

CompactToolOutputForHistory rebuilds a short tool message when replaying history.

func CountContentLines

func CountContentLines(s string) int

CountContentLines is the +N / -M unit for sandbox file mutations: empty is 0, a trailing newline does not add an extra line.

func DefaultAllowedTools

func DefaultAllowedTools() []string

DefaultAllowedTools returns the default allowed tools list.

func EffectiveAllowedTools

func EffectiveAllowedTools(allowed []string) []string

EffectiveAllowedTools returns the built-in tools an agent's allowed_tools value asks for. A nil list means the value was never set, as on agents saved before allowed_tools existed, and selects the default tools. Any other list, including an empty one, is taken as given: an empty list means no built-in tools. Retired names are rewritten to their successors.

Tool registration, the session config and the rerank requirement all go through this function, so they cannot disagree about what an empty list means.

func FormatMatchType

func FormatMatchType(mt types.MatchType) string

FormatMatchType converts MatchType to a human-readable string

func FormatValidationErrors

func FormatValidationErrors(errs []ValidationError) string

FormatValidationErrors formats a list of validation errors into a human-readable string.

func GetMCPToolsInfo

func GetMCPToolsInfo(
	ctx context.Context,
	services []*types.MCPService,
	mcpManager *mcp.MCPManager,
) (map[string][]string, error)

GetMCPToolsInfo returns information about available MCP tools

func GetRelevanceLevel

func GetRelevanceLevel(score float64) string

GetRelevanceLevel converts a score to a human-readable relevance level

func GoRecovered

func GoRecovered(ctx context.Context, fn func())

GoRecovered runs fn on a new goroutine and contains a panic raised there.

recover only covers the goroutine that calls it, so the barrier in executeRecovered (registry.go) protects the call to tool.Execute alone: a goroutine a tool starts for itself — an MCP client, a sandbox, a third-party SDK, a retrieval adapter — must install its own barrier, or one panic escapes every recover site and takes the whole server (and every conversation, upload and sync in flight) down with it.

Deferred calls inside fn still run while a panic unwinds, so wait groups and cleanup are released. A caller that must also degrade the failed work into an error result uses RecoverGoroutine directly and records it in onPanic.

func IsLegacyRetrievalTool

func IsLegacyRetrievalTool(name string) bool

IsLegacyRetrievalTool reports whether name is a retired knowledge retrieval tool that NormalizeAllowedTools rewrites to its successor.

func IsPageButtonTool added in v0.9.0

func IsPageButtonTool(name string) bool

IsPageButtonTool reports whether a tool only offers the user a page button. Its result tells the model nothing new, so text written before it in the same reply is the answer rather than a preamble to further work.

func IsPageHandleShaped added in v0.9.0

func IsPageHandleShaped(value string) bool

IsPageHandleShaped reports a page reference the registry could not resolve, in the url://N syntax or the legacy wN one.

func IsProtocolArtifact added in v0.9.0

func IsProtocolArtifact(s string) bool

IsProtocolArtifact recognizes whole responses containing only internal protocol data.

func KBSatisfiesAgentRequirements

func KBSatisfiesAgentRequirements(caps types.KBCapabilities, agentMode string, allowedTools []string) bool

KBSatisfiesAgentRequirements is the agent-aware variant of KBSatisfiesToolRequirements: it also enforces the implicit capability constraints of `agentMode` (currently: quick-answer requires vector or keyword indexing on the KB).

func KBSatisfiesToolRequirements

func KBSatisfiesToolRequirements(caps types.KBCapabilities, allowedTools []string) bool

KBSatisfiesToolRequirements reports whether a single KB is compatible with the agent's tool set. "Compatible" means: the KB exposes at least one capability that some tool in `allowedTools` requires. When the tool set imposes no KB requirement at all, every KB is considered compatible.

func MCPToolNamesByServiceID

func MCPToolNamesByServiceID(registry *ToolRegistry) map[string][]string

MCPToolNamesByServiceID returns registered MCP tool names grouped by service ID.

func NewCollaborationTools added in v0.9.0

func NewCollaborationTools(b *collaboration.Binding, resolve ResolveDelegatedAgent) []types.Tool

NewCollaborationTools builds the tool set available to a parent or child execution.

func NewWikiDeletePageTool

func NewWikiDeletePageTool(
	wikiPageService interfaces.WikiPageService,
	kbIDs []string,
	routes ...*WikiRouteResolver,
) types.Tool

NewWikiDeletePageTool creates a new wiki_delete_page tool

func NewWikiFlagIssueTool

func NewWikiFlagIssueTool(
	wikiService interfaces.WikiPageService,
	kbIDs []string,
	routes ...*WikiRouteResolver,
) *wikiFlagIssueTool

func NewWikiReadIssueTool

func NewWikiReadIssueTool(wikiService interfaces.WikiPageService, kbIDs []string) types.Tool

func NewWikiReadPageTool

func NewWikiReadPageTool(
	wikiService interfaces.WikiPageService,
	knowledgeService interfaces.KnowledgeService,
	scopes []WikiScope,
	routes *WikiRouteResolver,
) types.Tool

func NewWikiRenamePageTool

func NewWikiRenamePageTool(
	wikiPageService interfaces.WikiPageService,
	kbIDs []string,
	routes ...*WikiRouteResolver,
) types.Tool

NewWikiRenamePageTool creates a new wiki_rename_page tool

func NewWikiReplaceTextTool

func NewWikiReplaceTextTool(
	wikiPageService interfaces.WikiPageService,
	kbIDs []string,
	knowledgeService interfaces.KnowledgeService,
	routes ...*WikiRouteResolver,
) *wikiReplaceTextTool

NewWikiReplaceTextTool creates a new wiki_replace_text tool

func NewWikiSearchTool

func NewWikiSearchTool(
	wikiService interfaces.WikiPageService,
	knowledgeService interfaces.KnowledgeService,
	scopes []WikiScope,
	routes *WikiRouteResolver,
) types.Tool

func NewWikiUpdateIssueTool

func NewWikiUpdateIssueTool(wikiService interfaces.WikiPageService, kbIDs []string) types.Tool

func NewWikiWritePageTool

func NewWikiWritePageTool(
	wikiPageService interfaces.WikiPageService,
	kbIDs []string,
	knowledgeService interfaces.KnowledgeService,
	routes ...*WikiRouteResolver,
) *wikiWritePageTool

NewWikiWritePageTool creates a new wiki_write_page tool

func NormalizeAllowedTools

func NormalizeAllowedTools(allowed []string) []string

NormalizeAllowedTools rewrites retired tool names in an allowlist to their successors and drops duplicates while preserving first-seen order.

func NormalizeToolCallID

func NormalizeToolCallID(id string, toolName string, index int) string

NormalizeToolCallID normalizes a tool call ID for cross-provider compatibility.

Different LLM providers return IDs in different formats:

  • OpenAI: "call_abc123" (well-formed)
  • Some providers: "" (empty)
  • Some providers: very long UUIDs or random strings
  • Some providers: IDs with special characters

This function ensures IDs are:

  • Non-empty (generates deterministic ID from tool name + index if empty)
  • Within length limits (truncated with hash suffix if too long)
  • Alphanumeric-safe (special characters replaced)

func OperationIdentityFromContext added in v0.9.0

func OperationIdentityFromContext(ctx context.Context) (operations.Identity, bool)

OperationIdentityFromContext returns the identity catalog operations may run as for the current request, or false when the caller is not a signed-in web user (API key, embed, IM or MCP-endpoint principals).

func OutputBudget

func OutputBudget(ctx context.Context) int

OutputBudget returns the ceiling published by the registry, in runes, falling back to DefaultMaxToolOutput for callers that execute a tool directly.

func RecoverGoroutine

func RecoverGoroutine(ctx context.Context, label string, onPanic func())

RecoverGoroutine is deferred by a goroutine that must not let a panic escape (either directly or through GoRecovered). It logs the panic with its stack, then calls onPanic — when set — on that same goroutine so the caller can mark the failed unit of work: one MCP service, one knowledge base, one retrieval call. label names that work in the log; an empty one leaves it unnamed.

onPanic deliberately receives no panic value: a recovered value carries internals (paths, addresses) that must not reach the model or the user.

func RegisterMCPTools

func RegisterMCPTools(
	ctx context.Context,
	registry *ToolRegistry,
	services []*types.MCPService,
	mcpManager *mcp.MCPManager,
	gate approval.MCPApproval,
	authWaitTimeoutSeconds int,
	lookup MCPServiceLookup,
	metadata *MCPMetadataIO,
) (int, error)

RegisterMCPTools installs a scoped directory and call proxy without connecting to MCP servers or advertising their full schemas. The count is services, not tools: discovery occurs on demand during tool execution.

func RegisteredBackgroundSubmitters added in v0.9.0

func RegisteredBackgroundSubmitters(r *ToolRegistry) []string

RegisteredBackgroundSubmitters returns the background submission tools registered in r, in declaration order.

func RepairJSON

func RepairJSON(s string) string

RepairJSON attempts to fix common JSON malformations from LLM outputs. LLMs sometimes produce:

  • Truncated JSON (missing closing brackets/braces)
  • Trailing commas before closing brackets
  • Single quotes instead of double quotes
  • Unquoted keys
  • Invalid backslash escapes inside strings (e.g. regex patterns like "C\+\+", "\d+", "\.log$") where the LLM forgot to double-escape.
  • Extra tokens after the top-level value (e.g. `{}""`, `{"a":1}{"a":1}`)

Returns the repaired JSON string. If repair is not possible, returns the original string unchanged (caller should handle parse errors).

func RepairJSONDetail

func RepairJSONDetail(s string) (string, bool)

RepairJSONDetail is RepairJSON that also reports whether the payload had to be closed off to parse — an unterminated string or an unbalanced bracket. That only happens when the provider stopped emitting mid-argument, so the values now parse but are partial: `content` holds half a file, `query` holds half a sentence. Callers must refuse such a call rather than run it. Escape and trailing-comma fixes are ordinary malformations, not truncation, and do not set the flag.

func RetiredToolReplacement

func RetiredToolReplacement(name string) string

RetiredToolReplacement tells the model how to replace a removed tool. Empty when name was never a WeKnora tool.

func SandboxFileCallProgress

func SandboxFileCallProgress(toolName string, args map[string]any) map[string]any

SandboxFileCallProgress is the UI payload for a write/edit call: path, running +/− line counts, and a short preview. File bodies stay off the wire.

func SanitizeAgentStepsForStorage

func SanitizeAgentStepsForStorage(steps []types.AgentStep) []types.AgentStep

SanitizeAgentStepsForStorage strips LLM-only payloads from persisted steps.

func SanitizeMessages

func SanitizeMessages(messages []chat.Message) []chat.Message

SanitizeMessages validates and fixes a message array for LLM compatibility. It handles common issues that cause provider API errors:

  • Ensures no consecutive same-role messages (some providers reject these)
  • Verifies tool result messages have matching tool_call in the preceding assistant message
  • Removes empty content messages that can cause API errors

Returns the sanitized message slice (may be shorter than input).

func SanitizeSandboxFileCallArgs

func SanitizeSandboxFileCallArgs(toolName string, args map[string]any) map[string]any

SanitizeSandboxFileCallArgs strips write/edit file bodies from arguments sent to the client. Live progress events already carry stats only; this covers the later "tool hint" emit that still has the full JSON.

func SanitizeToolDataForClient added in v0.9.0

func SanitizeToolDataForClient(toolName string, data map[string]interface{}) map[string]interface{}

SanitizeToolDataForClient retains transient metadata only for live clients.

func SanitizeToolDataForPersist

func SanitizeToolDataForPersist(toolName string, data map[string]interface{}) map[string]interface{}

SanitizeToolDataForPersist returns a copy of tool Data safe for DB / SSE replay.

func SanitizeToolResultForClient

func SanitizeToolResultForClient(toolName string, result *types.ToolResult) map[string]interface{}

SanitizeToolResultForClient builds stream / persistence metadata for the UI.

func SerializeMCPToolResult

func SerializeMCPToolResult(result *types.ToolResult) (string, error)

SerializeMCPToolResult serializes an MCP tool result for display

func ShouldOmitRawToolOutput

func ShouldOmitRawToolOutput(_ string, data map[string]interface{}) bool

ShouldOmitRawToolOutput reports whether the raw XML/text Output should be excluded from SSE replay and persisted agent_steps. The full Output remains available in-memory for the current agent turn.

func SplitThinkContent added in v0.9.0

func SplitThinkContent(content string) (reasoning, answer string)

SplitThinkContent reconstructs complete reasoning and answer from one response. Unlike the bounded live preview, persisted reasoning is never truncated.

func StreamContentForToolResult

func StreamContentForToolResult(toolName string, success bool, errMsg string, data map[string]interface{}) string

StreamContentForToolResult is the short SSE Content field for tool results.

func StripThinkBlocks

func StripThinkBlocks(content string) string

StripThinkBlocks removes <think>…</think> blocks from LLM output content. Some models (DeepSeek, Qwen, etc.) embed chain-of-thought reasoning inside <think> tags in the content field. These should be stripped before:

  • Displaying content to users
  • Storing content in agent state / context manager
  • Emitting content via EventBus

Returns the cleaned string, or empty string if input is empty or becomes empty.

func SuccessorToolName

func SuccessorToolName(name string) string

SuccessorToolName returns the current tool that replaces a retired allowlist entry, or name itself when it is not retired.

func SwitchManagedTools

func SwitchManagedTools() []string

SwitchManagedTools returns the tools an allowed_tools entry does not register: other agent settings register or withhold them, such as the web search, memory, skills, sandbox and MCP settings, or the built-in skill installer. registerTools either strips them from the list and re-adds them from their switch, or skips them and leaves them to the code that owns them. The agent editor uses this list to explain such stored entries instead of offering them as checkboxes.

func ToolsConsumeFiles

func ToolsConsumeFiles(allowedTools []string) bool

ToolsConsumeFiles reports whether any tool in the allowed-tools list can use user-provided file references. Used to gate the `@file` listing in the chat input (and potentially SearchKnowledge defensively on the backend). An empty allowed-tools list is treated as "unknown → permissive".

func TruncateToolOutput

func TruncateToolOutput(output string, maxChars int) string

TruncateToolOutput truncates tool output that exceeds maxChars runes, preserving the head (70%) and tail (30%) sections with a truncation marker in between. This prevents large tool results from consuming the entire LLM context window while keeping the most useful parts (headers/summaries at the start, conclusions at the end).

maxChars is counted in Unicode characters (runes), not bytes, ensuring consistent behavior across English, Chinese, and other multi-byte character sets.

If maxChars <= 0 or the output is within the limit, it is returned unchanged.

func WikiPageInScope added in v0.9.0

func WikiPageInScope(
	ctx context.Context, page *types.WikiPage, scope WikiScope, knowledgeService interfaces.KnowledgeService,
) (bool, error)

WikiPageInScope applies the same source-document and tag restrictions used by Wiki reads to page metadata surfaced outside the tool execution path.

func WithOutputBudget

func WithOutputBudget(ctx context.Context, maxChars int) context.Context

WithOutputBudget publishes the registry's output ceiling to the tool being executed. Tools that render several independent records in one result use it to shape their own output: the registry's fallback truncation keeps the head and tail of the whole blob, which for a batched result deletes the records in the middle and leaves the surviving ones cut mid-tag.

func WithToolExecContext

func WithToolExecContext(ctx context.Context, meta *ToolExecContext) context.Context

WithToolExecContext returns ctx that carries ToolExecContext for MCP approval and similar features.

func WorkWaitSeconds added in v0.9.0

func WorkWaitSeconds(arguments string) int

WorkWaitSeconds returns the wait of a work_wait call: default 60, clamped to 0–300. Malformed arguments get the default. The engine derives the tool timeout from it (D3).

Types

type AgentToolCatalog

type AgentToolCatalog struct {
	// Tools are the selectable tools, in display order.
	Tools []AgentToolInfo `json:"tools"`
	// DefaultTools apply when an agent's allowed_tools was never set (null).
	DefaultTools []string `json:"default_tools"`
	// SwitchManagedTools follow other agent settings; naming them in the list
	// does not register them.
	SwitchManagedTools []string `json:"switch_managed_tools"`
}

AgentToolCatalog is everything the agent editor needs to show an allowed_tools list the way the runtime reads it.

func BuildAgentToolCatalog

func BuildAgentToolCatalog() AgentToolCatalog

BuildAgentToolCatalog assembles the catalog from the tool definitions and the capability map, so the editor never keeps its own copy of either.

type AgentToolInfo

type AgentToolInfo struct {
	AvailableTool
	Requirement AgentToolRequirement `json:"requirement"`
}

AgentToolInfo is a selectable tool together with its capability requirement.

type AgentToolRequirement

type AgentToolRequirement struct {
	AnyOf []KBCapability `json:"any_of,omitempty"`
	AllOf []KBCapability `json:"all_of,omitempty"`
}

AgentToolRequirement is the JSON form of a tool's ToolRequirement: the knowledge base capabilities the agent's scope must expose for the tool to be registered.

type AllowedToolsCheck

type AllowedToolsCheck struct {
	// Tools is the list to store: retired names rewritten, duplicates and
	// switch-managed tools removed. Nil when the request left the list unset.
	Tools []string
	// Rejected are names no built-in tool answers to that the request adds.
	Rejected []string
	// KeptUnknown are such names that were already stored. They are kept so
	// that an agent saved before an upgrade can still be saved.
	KeptUnknown []string
	// Dropped are names removed from the list because naming them there has
	// no effect: switch-managed tools, which other agent settings decide on,
	// and retired skill tools without a successor.
	Dropped []string
}

AllowedToolsCheck is the outcome of checking an allowed_tools list on save.

func CheckAllowedTools

func CheckAllowedTools(stored, requested []string) AllowedToolsCheck

CheckAllowedTools validates a requested allowed_tools list against the selectable tools. stored is the list currently saved for the agent, nil for a new agent.

type ArtifactFileSource added in v0.9.0

type ArtifactFileSource interface {
	Read(context.Context, string) ([]byte, error)
}

ArtifactFileSource authorizes persisted files independently of sandbox paths. Implementations must restrict references to the bound conversation's outputs.

type AskUserTool added in v0.9.0

type AskUserTool struct {
	BaseTool
	// contains filtered or unexported fields
}

AskUserTool asks the user a question through a card in the conversation.

func NewAskUserTool added in v0.9.0

func NewAskUserTool(asker approval.UserAsker) *AskUserTool

NewAskUserTool builds the ask_user tool.

func (*AskUserTool) Execute added in v0.9.0

func (t *AskUserTool) Execute(ctx context.Context, args json.RawMessage) (*types.ToolResult, error)

Execute implements types.Tool.

type AvailableTool

type AvailableTool struct {
	Name        string `json:"name"`
	Label       string `json:"label"`
	Description string `json:"description"`
	Group       string `json:"group"`
	// Danger marks tools that modify content, which the editor highlights.
	Danger bool `json:"danger,omitempty"`
}

AvailableTool describes a tool an agent's allowed_tools list may select. The agent editor renders its tool checkboxes from these definitions.

func AvailableToolDefinitions

func AvailableToolDefinitions() []AvailableTool

AvailableToolDefinitions returns the tools an agent's allowed_tools list may select, in the order the agent editor shows them. Keep this in sync with registered tools in this package.

type BaseTool

type BaseTool struct {
	// contains filtered or unexported fields
}

BaseTool provides common functionality for tools

func NewBaseTool

func NewBaseTool(name, description string, schema json.RawMessage) BaseTool

NewBaseTool creates a new base tool

func (*BaseTool) Description

func (t *BaseTool) Description() string

Description returns the tool description

func (*BaseTool) Name

func (t *BaseTool) Name() string

Name returns the tool name

func (*BaseTool) Parameters

func (t *BaseTool) Parameters() json.RawMessage

Parameters returns the tool parameters schema

type BrowserSkillTool

type BrowserSkillTool struct {
	BaseTool
	// contains filtered or unexported fields
}

BrowserSkillTool binds native browser commands to one member and conversation.

func NewBrowserSkillTool

func NewBrowserSkillTool(
	manager *browserskill.Manager,
	scope browserskill.Scope,
	session string,
	searchInstructions ...string,
) *BrowserSkillTool

NewBrowserSkillTool creates a session-bound adapter to upstream RPC.

func (*BrowserSkillTool) Cleanup

func (t *BrowserSkillTool) Cleanup(ctx context.Context)

Cleanup reclaims successful temporary tasks; unfinished work retains its pages. Execute can exit with a cancelled context; cleanup must still reach the extension.

func (*BrowserSkillTool) Execute

Execute validates tool arguments and dispatches through the authorized task.

func (*BrowserSkillTool) ValidateArguments

func (t *BrowserSkillTool) ValidateArguments(args json.RawMessage) error

ValidateArguments enforces the flat schema and the selected operation's required fields before opening a browser or executing any page action.

type CollaborationTool added in v0.9.0

type CollaborationTool struct {
	BaseTool
	// contains filtered or unexported fields
}

CollaborationTool executes a collaboration command within its runtime binding.

func (*CollaborationTool) Execute added in v0.9.0

Execute validates arguments and dispatches the scoped collaboration operation.

func (*CollaborationTool) ExecutionTimeout added in v0.9.0

func (t *CollaborationTool) ExecutionTimeout() time.Duration

ExecutionTimeout allows waiting on the mailbox beyond normal tool timeouts.

type ColumnInfo

type ColumnInfo struct {
	Name     string `json:"name"`
	Type     string `json:"type"`
	Nullable string `json:"nullable"`
}

ColumnInfo represents information about a single column

type ConfirmedTool added in v0.9.0

type ConfirmedTool struct {
	// contains filtered or unexported fields
}

ConfirmedTool asks the user before running a tool that changes data, the way run_operation does for catalog operations, so the assistant's access level covers its direct tools too. A call resumed with the user's answer is honored whatever the level is now: the user may have edited it.

func NewConfirmedTool added in v0.9.0

func NewConfirmedTool(
	inner types.Tool, risk operations.Risk, access operations.Access, gate approval.BuiltinApproval,
) *ConfirmedTool

NewConfirmedTool wraps inner, whose calls carry risk.

func (*ConfirmedTool) BindSession added in v0.9.0

func (t *ConfirmedTool) BindSession(id string)

BindSession preserves the underlying sandbox tool's session-local layout.

func (*ConfirmedTool) Description added in v0.9.0

func (t *ConfirmedTool) Description() string

Description returns the wrapped tool's description.

func (*ConfirmedTool) Execute added in v0.9.0

func (t *ConfirmedTool) Execute(ctx context.Context, args json.RawMessage) (*types.ToolResult, error)

Execute runs the inner tool once the access level allows it.

func (*ConfirmedTool) Name added in v0.9.0

func (t *ConfirmedTool) Name() string

Name returns the wrapped tool's name.

func (*ConfirmedTool) Parameters added in v0.9.0

func (t *ConfirmedTool) Parameters() json.RawMessage

Parameters returns the wrapped tool's argument schema.

type DataAnalysisInput

type DataAnalysisInput struct {
	KnowledgeID string `json:"knowledge_id" jsonschema:"doc://N document handle to query"`
	SQL         string `` //nolint:lll // jsonschema tag
	/* 189-byte string literal not displayed */
}

type DataAnalysisTool

type DataAnalysisTool struct {
	BaseTool
	// contains filtered or unexported fields
}

func NewDataAnalysisTool

func NewDataAnalysisTool(
	knowledgeBaseService interfaces.KnowledgeBaseService,
	knowledgeService interfaces.KnowledgeService,
	tenantService interfaces.TenantService,
	fileService interfaces.FileService,
	db *sql.DB,
	sessionID string,
	storageResolvers ...interfaces.StorageBackendResolver,
) *DataAnalysisTool

func (*DataAnalysisTool) Cleanup

func (t *DataAnalysisTool) Cleanup(ctx context.Context)

Cleanup cleans up the session-specific schema

func (*DataAnalysisTool) Execute

Execute executes the SQL query on DuckDB (only read-only queries are allowed)

func (*DataAnalysisTool) LoadFromCSV

func (t *DataAnalysisTool) LoadFromCSV(ctx context.Context, filename string, tableName string) (*TableSchema, error)

LoadFromCSV loads data from a CSV file into a DuckDB table and returns the table schema Parameters:

  • ctx: context for cancellation and timeout
  • filename: path to the CSV file
  • tableName: name of the table to create

Returns:

  • *TableSchema: schema information of the created table
  • error: any error that occurred during the operation

func (*DataAnalysisTool) LoadFromExcel

func (t *DataAnalysisTool) LoadFromExcel(ctx context.Context, filename string, tableName string) (*TableSchema, error)

LoadFromExcel loads data from an Excel file into a DuckDB table and returns the table schema.

Multi-sheet workbooks are supported: XLSX sheets containing only formatting are skipped; rows from the remaining sheets are unioned (UNION ALL BY NAME) into a single table. A synthetic '__sheet_name' column is added so downstream SQL can filter / aggregate per sheet. If sheet enumeration fails for any reason, we fall back to reading just the first sheet (original behavior).

Parameters:

  • ctx: context for cancellation and timeout
  • filename: path to the Excel file
  • tableName: name of the table to create

Returns:

  • *TableSchema: schema information of the created table
  • error: any error that occurred during the operation

Note: requires the DuckDB 'excel' extension (for read_xlsx) and the 'spatial' extension (for st_read_meta used to enumerate sheets).

Binary BIFF .xls workbooks are converted to a temporary .xlsx before DuckDB is touched. The excel extension only reads the ZIP-based OOXML container, so a real .xls would otherwise surface as "No xl/workbook.xml found in xlsx file". A workbook that cannot be converted returns an actionable error.

func (*DataAnalysisTool) LoadFromKnowledge

func (t *DataAnalysisTool) LoadFromKnowledge(ctx context.Context, knowledge *types.Knowledge) (*TableSchema, error)

LoadFromKnowledge loads data from a Knowledge entity into a DuckDB table and returns the table schema. It automatically determines the file type and calls the appropriate loading method.

The source file is first materialized to a local temp file via FileService.GetFile so DuckDB's st_read / read_xlsx / read_csv_auto can open it directly. This side-steps provider-specific URL schemes (e.g. the local:// URL returned by the local file service) that DuckDB's extensions cannot resolve on their own.

Parameters:

  • ctx: context for cancellation and timeout
  • knowledge: the Knowledge entity containing file information

Returns:

  • *TableSchema: schema information of the created table
  • error: any error that occurred during the operation

func (*DataAnalysisTool) LoadFromKnowledgeID

func (t *DataAnalysisTool) LoadFromKnowledgeID(ctx context.Context, knowledgeID string) (*TableSchema, error)

LoadFromKnowledgeID loads data from a Knowledge ID into a DuckDB table and returns the table schema Parameters:

  • ctx: context for cancellation and timeout
  • knowledgeID: the ID of the Knowledge entity

Returns:

  • string: the name of the created table
  • *TableSchema: schema information of the created table
  • error: any error that occurred during the operation

func (*DataAnalysisTool) LoadFromTable

func (t *DataAnalysisTool) LoadFromTable(ctx context.Context, tableName string) (*TableSchema, error)

LoadFromTable retrieves the schema information of an existing table Parameters:

  • ctx: context for cancellation and timeout
  • tableName: name of the table to query

Returns:

  • *TableSchema: schema information of the table
  • error: any error that occurred during the operation

Note: This function does NOT create the table, it only retrieves schema information

func (*DataAnalysisTool) TableName

func (t *DataAnalysisTool) TableName(knowledge *types.Knowledge) string

func (*DataAnalysisTool) WithSearchTargets

func (t *DataAnalysisTool) WithSearchTargets(searchTargets types.SearchTargets) *DataAnalysisTool

WithSearchTargets enables the Agent-only authorization boundary. Other internal data-analysis callers retain their existing service-owned scope. The flag is set independently of the slice length: an Agent turn that ended up with no search target must reject every document, not fall back to unrestricted access.

type DataSchemaInput

type DataSchemaInput struct {
	KnowledgeID string `json:"knowledge_id" jsonschema:"doc://N document handle to query"`
}

type DataSchemaTool

type DataSchemaTool struct {
	BaseTool
	// contains filtered or unexported fields
}

func NewDataSchemaTool

func NewDataSchemaTool(knowledgeService interfaces.KnowledgeService, chunkRepo interfaces.ChunkRepository, targetChunkTypes ...types.ChunkType) *DataSchemaTool

func (*DataSchemaTool) Execute

func (t *DataSchemaTool) Execute(ctx context.Context, args json.RawMessage) (*types.ToolResult, error)

Execute executes the tool logic

func (*DataSchemaTool) WithSearchTargets

func (t *DataSchemaTool) WithSearchTargets(searchTargets types.SearchTargets) *DataSchemaTool

WithSearchTargets enables Agent request-scope authorization. An Agent turn with no search target must reject every document rather than fall back to the unrestricted service-owned lookup.

type DatabaseQueryInput

type DatabaseQueryInput struct {
	SQL string `` /* 138-byte string literal not displayed */
}

type DatabaseQueryTool

type DatabaseQueryTool struct {
	BaseTool
	// contains filtered or unexported fields
}

DatabaseQueryTool allows AI to query the database with auto-injected tenant_id for security

func NewDatabaseQueryTool

func NewDatabaseQueryTool(db *gorm.DB, searchTargets types.SearchTargets) *DatabaseQueryTool

NewDatabaseQueryTool creates a new database query tool

func (*DatabaseQueryTool) Execute

Execute executes the database query tool

type EditSandboxFileInput

type EditSandboxFileInput struct {
	Path  string          `json:"path" jsonschema:"Absolute or /workspace-relative sandbox path of an existing text file (not /workspace/input)."` //nolint:lll // one-line struct tag
	Edits sandboxEditList ``                                                                                                                       //nolint:lll // one-line struct tag
	/* 290-byte string literal not displayed */
}

EditSandboxFileInput defines the input parameters for edit_sandbox_file.

There is deliberately one shape. A flat old_string/new_string pair alongside edits[] would save a model a dozen bytes on a one-line fix and cost it a choice it can get wrong, plus a rule about which of the two replace_all attaches to. Every replacement goes in edits[], and a single-element array is the ordinary way to change one thing.

type EditSandboxFileTool

type EditSandboxFileTool struct {
	BaseTool
	// contains filtered or unexported fields
}

EditSandboxFileTool applies an exact string replacement to a sandbox file.

func NewEditSandboxFileTool

func NewEditSandboxFileTool(editor SandboxFileEditor) *EditSandboxFileTool

NewEditSandboxFileTool constructs the tool. `editor` MUST NOT be nil.

func (*EditSandboxFileTool) BindSession

func (s *EditSandboxFileTool) BindSession(id string)

func (*EditSandboxFileTool) Cleanup

func (t *EditSandboxFileTool) Cleanup(ctx context.Context) error

Cleanup releases any resources.

func (*EditSandboxFileTool) Description

func (t *EditSandboxFileTool) Description() string

Description is built from the session sandbox layout so host paths never hard-code /workspace.

func (*EditSandboxFileTool) Execute

Execute reads the file, applies the replacement, and writes it back.

func (*EditSandboxFileTool) Parameters

func (t *EditSandboxFileTool) Parameters() json.RawMessage

Parameters rewrites workspace paths in the schema to match the session layout.

type EditSkillFileInput

type EditSkillFileInput struct {
	Path       string `` /* 139-byte string literal not displayed */
	OldString  string `` /* 134-byte string literal not displayed */
	NewString  string `json:"new_string" jsonschema:"Replacement text. Use an empty string to delete the matched text."`
	ReplaceAll bool   `` /* 132-byte string literal not displayed */
}

EditSkillFileInput defines the input parameters for edit_skill_file.

type EditSkillFileTool

type EditSkillFileTool struct {
	BaseTool
	// contains filtered or unexported fields
}

EditSkillFileTool applies an exact string replacement inside the skill tree.

func NewEditSkillFileTool

func NewEditSkillFileTool(store SkillFileStore, skillDir string) *EditSkillFileTool

NewEditSkillFileTool constructs the tool. `store` MUST NOT be nil and `skillDir` MUST be the directory of the skill this install owns.

func (*EditSkillFileTool) Cleanup

func (t *EditSkillFileTool) Cleanup(ctx context.Context) error

Cleanup releases any resources.

func (*EditSkillFileTool) Execute

Execute reads the file, applies the replacement, and writes it back.

type FillPageTool added in v0.9.0

type FillPageTool struct {
	// contains filtered or unexported fields
}

FillPageTool fills fields of the page the user has open.

func NewFillPageTool added in v0.9.0

func NewFillPageTool(actor approval.PageActor) *FillPageTool

NewFillPageTool creates fill_page.

func (*FillPageTool) Execute added in v0.9.0

func (t *FillPageTool) Execute(ctx context.Context, args json.RawMessage) (*types.ToolResult, error)

Execute implements types.Tool.

type FindOperationsTool added in v0.9.0

type FindOperationsTool struct {
	BaseTool
	// contains filtered or unexported fields
}

FindOperationsTool lists catalog operations.

func NewFindOperationsTool added in v0.9.0

func NewFindOperationsTool(catalog *operations.Catalog, access operations.Access) *FindOperationsTool

NewFindOperationsTool creates find_operations over the full catalog, describing what access may run and why the rest is unavailable.

func (*FindOperationsTool) Execute added in v0.9.0

Execute lists the operations matching the query and domain.

type HostApproval added in v0.9.0

type HostApproval interface {
	RequestHostAndWait(ctx context.Context, req approval.HostPendingRequest) (approval.Decision, error)
}

HostApproval is the gate surface shell_exec needs on a Lite host workspace.

type KBCapability

type KBCapability string

KBCapability names the capability flags a knowledge base can expose. Values mirror the keys of `types.KBCapabilities`.

const (
	CapVector  KBCapability = "vector"
	CapKeyword KBCapability = "keyword"
	CapWiki    KBCapability = "wiki"
	CapGraph   KBCapability = "graph"
	CapFAQ     KBCapability = "faq"
)

type KBFilter

type KBFilter struct {
	AnyOf []KBCapability
}

KBFilter is the derived "KB must expose at least one of these capabilities" predicate for a set of allowed tools (see DeriveKBFilterFromTools).

func DeriveKBFilterForAgent

func DeriveKBFilterForAgent(agentMode string, allowedTools []string) KBFilter

DeriveKBFilterForAgent derives the effective KB capability filter for a given agent configuration. It combines the implicit constraint from `agentMode` (quick-answer forces vector|keyword) with the tool-derived filter (any_of capabilities required by some allowed tool).

The returned filter is the UNION of both contributions, which matches the existing any_of semantics: a KB passes iff it exposes at least one of the listed capabilities.

func DeriveKBFilterFromTools

func DeriveKBFilterFromTools(allowedTools []string) KBFilter

DeriveKBFilterFromTools derives a capability filter such that a KB passes iff at least ONE of the allowed tools has a requirement the KB satisfies. Tools without any KB requirement don't contribute — if the allowed-tools list contains only such tools, the returned filter is empty (accept all).

func (KBFilter) IsEmpty

func (f KBFilter) IsEmpty() bool

IsEmpty reports whether the filter imposes no constraint (either no capability accumulated, or explicit zero value).

type ListDocumentsInput

type ListDocumentsInput struct {
	KnowledgeBaseID string `json:"knowledge_base_id"`
	Keyword         string `json:"keyword,omitempty"`
	Page            int    `json:"page,omitempty"`
	PageSize        int    `json:"page_size,omitempty"`
}

ListDocumentsInput defines the input parameters for list_documents.

type ListDocumentsTool

type ListDocumentsTool struct {
	BaseTool
	// contains filtered or unexported fields
}

ListDocumentsTool pages through the documents of one knowledge base.

func NewListDocumentsTool

func NewListDocumentsTool(
	knowledgeService interfaces.KnowledgeService, searchTargets types.SearchTargets,
) *ListDocumentsTool

NewListDocumentsTool creates a new list_documents tool.

func (*ListDocumentsTool) Execute

Execute lists documents, honouring any document/tag scope pinned on the KB.

type ListSandboxFilesInput

type ListSandboxFilesInput struct {
	// Path is the absolute path inside the sandbox to list. When empty
	// the tool falls back to layoutDefaultListDir. Relative paths resolve
	// from the workspace root.
	Path string `` //nolint:lll // one-line struct tag
	/* 182-byte string literal not displayed */
	// MaxEntries caps the listing size to protect the LLM context.
	// Zero uses defaultListSandboxMaxEntries.
	MaxEntries int `` /* 206-byte string literal not displayed */
}

ListSandboxFilesInput defines the input parameters for list_sandbox_files.

type ListSandboxFilesTool

type ListSandboxFilesTool struct {
	BaseTool
	// contains filtered or unexported fields
}

ListSandboxFilesTool exposes SandboxFileSource.ListSessionFiles to the agent as a read-only enumeration primitive.

func NewListSandboxFilesTool

func NewListSandboxFilesTool(source SandboxFileSource) *ListSandboxFilesTool

NewListSandboxFilesTool constructs the tool. `source` MUST NOT be nil: callers should feature-gate registration in the agent bootstrap when the sandbox backend does not support per-session file inspection.

func (*ListSandboxFilesTool) BindSession

func (s *ListSandboxFilesTool) BindSession(id string)

func (*ListSandboxFilesTool) Cleanup

func (t *ListSandboxFilesTool) Cleanup(ctx context.Context) error

Cleanup releases any resources.

func (*ListSandboxFilesTool) Description

func (t *ListSandboxFilesTool) Description() string

Description is built from the session sandbox layout so host paths never hard-code /workspace.

func (*ListSandboxFilesTool) Execute

Execute enumerates files under the requested path inside the current session's sandbox.

func (*ListSandboxFilesTool) Parameters

func (t *ListSandboxFilesTool) Parameters() json.RawMessage

Parameters rewrites workspace paths in the schema to match the session layout.

type MCPCallGuard added in v0.9.0

type MCPCallGuard func(context.Context, string, string, json.RawMessage) (*types.ToolResult, error)

MCPCallGuard can return a non-nil result to decline a new MCP invocation before it opens an approval or contacts the server. It grants no authority. Identity and arguments are the resolved native target, never proxy input.

type MCPCallTool

type MCPCallTool struct {
	BaseTool
	// contains filtered or unexported fields
}

MCPCallTool resolves catalog references and invokes their MCP targets.

func (*MCPCallTool) Execute

func (t *MCPCallTool) Execute(ctx context.Context, raw json.RawMessage) (*types.ToolResult, error)

Execute revalidates the catalog target and runs the shared execution pipeline.

func (*MCPCallTool) Parameters

func (t *MCPCallTool) Parameters() json.RawMessage

Parameters advertises only references whose complete definitions are in the current function list. Execution still revalidates scope, schema and policy.

type MCPCatalog

type MCPCatalog struct {
	// contains filtered or unexported fields
}

MCPCatalog is owned by one Agent engine and one authorization principal. Only its server snapshots mutate; the executable registry stays fixed. No credential-bearing service object is serialized to the model.

type MCPDiscoverTool

type MCPDiscoverTool struct {
	BaseTool
	// contains filtered or unexported fields
}

MCPDiscoverTool exposes the authorized directory and exact tool definitions.

func (*MCPDiscoverTool) Description

func (t *MCPDiscoverTool) Description() string

Description advertises source-level guidance alongside direct tools, just as Codex's namespace/source descriptions accompany model-visible definitions. Specific tool descriptions and schemas live in their own function entries.

func (*MCPDiscoverTool) Execute

Execute lists authorized services or tools, or describes an exact tool.

func (*MCPDiscoverTool) OutputLimitChars

func (t *MCPDiscoverTool) OutputLimitChars(raw json.RawMessage) int

OutputLimitChars permits a single schema to exceed the ordinary text budget. Preserve complete JSON up to an explicit hard ceiling rather than silently truncate parameter rules.

type MCPInput

type MCPInput = map[string]any

type MCPMetadataIO

type MCPMetadataIO struct {
	Get func(context.Context, uint64, string) (*types.MCPMetadata, error)
	Put func(context.Context, uint64, string, []*types.MCPTool, string) error
}

MCPMetadataIO reads persisted directories and optionally writes a snapshot listed from an already-authorized live connection. Put must not be used to publish a partial tools/list.

type MCPOAuthSession

type MCPOAuthSession struct {
	EventBus           *event.EventBus
	SessionID          string
	AssistantMessageID string
	UserID             string
	RequestID          string
	// ApprovalCtx is the parent ctx without per-operation timeouts; when nil,
	// the caller ctx is used for the OAuth wait.
	ApprovalCtx context.Context
	// ExecTimeout, when >0, caps the retry ctx after a successful authorization.
	ExecTimeout time.Duration
	// AuthWaitTimeoutSeconds is the agent-level, user-configured number of
	// seconds to wait for in-conversation OAuth authorization. See oauthWaitTimeout.
	AuthWaitTimeoutSeconds int
}

MCPOAuthSession carries chat/session metadata so MCP connect and tool registration can pause for in-conversation OAuth. Nil disables the prompt.

type MCPRegisteredTool

type MCPRegisteredTool struct {
	*MCPTool
	// contains filtered or unexported fields
}

MCPRegisteredTool is a model-visible definition bound to one authorized catalog and schema. It must not bypass the directory's live permission and configuration checks just because its definition was advertised up front.

func (*MCPRegisteredTool) Description

func (t *MCPRegisteredTool) Description() string

Description identifies the external service and original tool.

func (*MCPRegisteredTool) Execute

Execute revalidates the catalog before invoking the bound tool.

type MCPServiceLookup

type MCPServiceLookup func(context.Context, uint64, string) (*types.MCPService, error)

MCPServiceLookup revalidates a service from the already-authorized ID set. It must preserve the application's tenant / builtin-service access rules.

type MCPTool

type MCPTool struct {
	// contains filtered or unexported fields
}

MCPTool wraps an MCP service tool to implement the Tool interface

func NewMCPTool

func NewMCPTool(
	service *types.MCPService, mcpTool *types.MCPTool,
	mcpManager *mcp.MCPManager, gate approval.MCPApproval, authWaitTimeoutSeconds int,
) *MCPTool

NewMCPTool creates a new MCP tool wrapper. authWaitTimeoutSeconds carries the agent-level OAuth wait timeout applied when a tool call triggers in-conversation auth.

func (*MCPTool) Description

func (t *MCPTool) Description() string

Description returns the tool description. Prefix indicates external/untrusted source to reduce indirect prompt injection impact.

func (*MCPTool) Execute

func (t *MCPTool) Execute(ctx context.Context, args json.RawMessage) (*types.ToolResult, error)

Execute executes the MCP tool

func (*MCPTool) Name

func (t *MCPTool) Name() string

Name returns the unique name for this tool. Format: mcp_{service_name}_{tool_name} — uses the human-readable service name so that tool names remain stable across MCP server reconnections (fixes #715).

Security: service names must be unique per tenant (enforced by DB unique index on (tenant_id, name)). The ToolRegistry uses first-wins semantics to prevent a later service from overwriting an already-registered tool (GHSA-67q9-58vj-32qx).

Note: OpenAI API requires tool names to match ^[a-zA-Z0-9_-]+$ and max 64 chars.

func (*MCPTool) Parameters

func (t *MCPTool) Parameters() json.RawMessage

Parameters returns the JSON Schema for tool parameters

func (*MCPTool) ValidateArguments

func (t *MCPTool) ValidateArguments(args json.RawMessage) error

ValidateArguments checks the complete, immutable MCP schema. Compilation is cached per tool snapshot; refreshing a definition creates a new MCPTool. Built-in tools keep their established validation and conversion semantics.

type OpenPageLink struct {
	DisplayType       string                   `json:"display_type"`
	Page              string                   `json:"page"`
	Label             string                   `json:"label"`
	Detail            string                   `json:"detail,omitempty"`
	Note              string                   `json:"note,omitempty"`
	KnowledgeBaseID   string                   `json:"knowledge_base_id,omitempty"`
	KnowledgeID       string                   `json:"knowledge_id,omitempty"`
	WikiSlug          string                   `json:"wiki_slug,omitempty"`
	AgentID           string                   `json:"agent_id,omitempty"`
	AutomationID      string                   `json:"automation_id,omitempty"`
	Section           string                   `json:"section,omitempty"`
	Panel             string                   `json:"panel,omitempty"`
	ModelID           string                   `json:"model_id,omitempty"`
	ModelDraft        *OpenPageModelDraft      `json:"model_draft,omitempty"`
	MCPServiceID      string                   `json:"mcp_service_id,omitempty"`
	MCPServiceDraft   *OpenPageMCPServiceDraft `json:"mcp_service_draft,omitempty"`
	KnowledgeBaseName string                   `json:"knowledge_base_name,omitempty"`
	// Navigated: the page was opened for the user; ReturnPath is where they were.
	Navigated  bool   `json:"navigated,omitempty"`
	ReturnPath string `json:"return_path,omitempty"`
}

OpenPageLink is what the client needs to render the button and open the page. Labels come from the target reads, not from the model.

type OpenPageMCPServiceDraft added in v0.9.0

type OpenPageMCPServiceDraft struct {
	Name              string `json:"name"`
	UsageInstructions string `json:"usage_instructions,omitempty"`
	TransportType     string `json:"transport_type"`
	URL               string `json:"url"`
	AuthType          string `json:"auth_type,omitempty"`
	APIKeyHeader      string `json:"api_key_header,omitempty"`
}

OpenPageMCPServiceDraft is a new MCP service's form, without credentials.

type OpenPageModelDraft added in v0.9.0

type OpenPageModelDraft struct {
	Type        string `json:"type"`
	Source      string `json:"source,omitempty"`
	Provider    string `json:"provider,omitempty"`
	ModelName   string `json:"model_name,omitempty"`
	DisplayName string `json:"display_name,omitempty"`
	BaseURL     string `json:"base_url,omitempty"`
}

OpenPageModelDraft is a new model's form, without credentials.

type OpenPageTool added in v0.9.0

type OpenPageTool struct {
	BaseTool
	// contains filtered or unexported fields
}

OpenPageTool checks that what it links to exists and is visible to the user, then hands the link to the client. It changes nothing. As view_page it also opens the page and reads it back.

func NewOpenPageTool added in v0.9.0

func NewOpenPageTool(rt OperationsRuntime) *OpenPageTool

NewOpenPageTool creates open_page; target reads go through rt.

func NewViewPageTool added in v0.9.0

func NewViewPageTool(rt OperationsRuntime, actor approval.PageActor) *OpenPageTool

NewViewPageTool creates view_page, which opens pages through actor.

func (*OpenPageTool) Execute added in v0.9.0

func (t *OpenPageTool) Execute(ctx context.Context, args json.RawMessage) (*types.ToolResult, error)

Execute checks the target and returns the link for the client.

type OperationsRuntime added in v0.9.0

type OperationsRuntime struct {
	Catalog    *operations.Catalog
	Dispatcher operations.Dispatcher
	Gate       approval.BuiltinApproval
	// Identity is the signed-in user the run acts for. Tools are only
	// registered when the run has one; see OperationIdentityFromContext.
	Identity operations.Identity
	// Access decides which operations run and which wait for the user.
	// Catalog is the full catalog, so a withheld operation is refused with
	// its reason rather than reported unknown.
	Access operations.Access
}

OperationsRuntime is what both operation tools need for one agent run.

type PlanStep

type PlanStep struct {
	ID          string `json:"id" jsonschema:"Unique identifier for this step (e.g., 'step1', 'step2')"`
	Description string `json:"description" jsonschema:"Clear description of what to investigate or accomplish in this step"`
	Status      string `json:"status" jsonschema:"Current status: pending (not started), in_progress (executing), completed (finished)"`
}

PlanStep represents a single step in the research plan

type ProtocolAnswerGuard added in v0.9.0

type ProtocolAnswerGuard struct {
	// contains filtered or unexported fields
}

ProtocolAnswerGuard delays only a suspicious opening, including prefixes split across chunks. Normal answers stream as before. A candidate must be validated before any of its bytes reach the UI.

func (*ProtocolAnswerGuard) Feed added in v0.9.0

func (g *ProtocolAnswerGuard) Feed(s string) string

Feed buffers suspicious prefixes and streams ordinary answer text.

func (*ProtocolAnswerGuard) Flush added in v0.9.0

func (g *ProtocolAnswerGuard) Flush() (string, error)

Flush validates and releases remaining text when the answer finishes.

type QueryKnowledgeGraphInput

type QueryKnowledgeGraphInput struct {
	KnowledgeBaseIDs []string `json:"knowledge_base_ids" jsonschema:"Array of kb://N knowledge base handles to query"`
	Query            string   `json:"query" jsonschema:"Query content (entity name or query text)"`
}

QueryKnowledgeGraphInput defines the input parameters for query knowledge graph tool

type QueryKnowledgeGraphTool

type QueryKnowledgeGraphTool struct {
	BaseTool
	// contains filtered or unexported fields
}

QueryKnowledgeGraphTool queries the knowledge graph for entities and relationships

func NewQueryKnowledgeGraphTool

func NewQueryKnowledgeGraphTool(
	knowledgeService interfaces.KnowledgeBaseService,
	searchTargets ...types.SearchTargets,
) *QueryKnowledgeGraphTool

NewQueryKnowledgeGraphTool creates a new query knowledge graph tool

func (*QueryKnowledgeGraphTool) Execute

Execute performs the knowledge graph query with concurrent KB processing

func (*QueryKnowledgeGraphTool) WithGraph

WithGraph lets the tool query the graph store for entities and relations. Without it the tool only has text search, which is what it used to do in every case: the tool never touched the graph, so a graph-only knowledge base always answered "no relevant graph information".

func (*QueryKnowledgeGraphTool) WithKnowledgeScope

func (t *QueryKnowledgeGraphTool) WithKnowledgeScope(
	knowledgeService interfaces.KnowledgeService,
) *QueryKnowledgeGraphTool

WithKnowledgeScope supplies document existence/access checks for graph evidence, as well as document/tag-level filtering for Agent calls. The graph backend queries by KB, so narrower SearchTargets must be enforced here.

type ReadDocumentInput

type ReadDocumentInput struct {
	ID      string `json:"id"`
	Offset  int    `json:"offset,omitempty"`
	Limit   int    `json:"limit,omitempty"`
	Query   string `json:"query,omitempty"`
	Regex   bool   `json:"regex,omitempty"`
	Context int    `json:"context,omitempty"`
}

ReadDocumentInput defines the input parameters for read_document.

type ReadDocumentTool

type ReadDocumentTool struct {
	BaseTool
	// contains filtered or unexported fields
}

ReadDocumentTool reads document metadata and chunks by page, by chunk handle, or by an in-document text search.

func NewReadDocumentTool

func NewReadDocumentTool(
	knowledgeService interfaces.KnowledgeService,
	chunkService interfaces.ChunkService,
	searchTargets types.SearchTargets,
) *ReadDocumentTool

NewReadDocumentTool creates a new read_document tool.

func (*ReadDocumentTool) Execute

Execute resolves the id, then dispatches to page, chunk or query reading.

type ReadFileInput

type ReadFileInput struct {
	Path string `` //nolint:lll // JSON schema tags must remain on one line.
	/* 252-byte string literal not displayed */
	LineOffset int `` //nolint:lll // JSON schema tags must remain on one line.
	/* 139-byte string literal not displayed */
	Offset   int    `json:"offset,omitempty" jsonschema:"1-based line number; continue at next_offset"`
	Limit    int    `json:"limit,omitempty" jsonschema:"Text lines (default 2000); attachment images (default 1, max 4; full always 1)"` //nolint:lll // JSON schema tags must remain on one line.
	MaxBytes int64  `json:"max_bytes,omitempty" jsonschema:"Text byte budget; at most 65536 (web: 51200)"`
	Query    string `json:"query,omitempty" jsonschema:"Find lines containing all words, case-insensitively"`
	Regex    bool   `json:"regex,omitempty" jsonschema:"Match query as one regular expression"`
	Detail   string `` //nolint:lll // JSON schema tags must remain on one line.
	/* 182-byte string literal not displayed */
	Focus string `` //nolint:lll // JSON schema tags must remain on one line.
	/* 126-byte string literal not displayed */
}

type ReadFileTool

type ReadFileTool struct {
	BaseTool
	// contains filtered or unexported fields
}

ReadFileTool exposes one read operation over capability-scoped sources. Skill resources use the manager's allowlist and bundle loader, never an arbitrary host path. Filesystem paths are resolved only inside the current session's sandbox and retain its file type, size, and output limits.

func NewReadFileTool

func NewReadFileTool(source SandboxFileSource) *ReadFileTool

func (*ReadFileTool) BindSession

func (t *ReadFileTool) BindSession(id string)

BindSession records the session so Description() and Parameters() advertise that session's workspace instead of the remote /workspace copy.

func (*ReadFileTool) Execute

func (t *ReadFileTool) Execute(ctx context.Context, args json.RawMessage) (*types.ToolResult, error)

func (*ReadFileTool) ExecutionTimeout

func (t *ReadFileTool) ExecutionTimeout() time.Duration

ExecutionTimeout gives the attachment parse wait room to return a structured result before the engine's outer tool deadline cancels the lookup.

func (*ReadFileTool) Parameters

func (t *ReadFileTool) Parameters() json.RawMessage

Parameters rewrites workspace paths in the schema to match the session layout.

func (*ReadFileTool) WithArtifacts added in v0.9.0

func (t *ReadFileTool) WithArtifacts(source ArtifactFileSource) *ReadFileTool

WithArtifacts adds authorized persisted outputs without granting sandbox access.

func (*ReadFileTool) WithAttachmentCopies

func (t *ReadFileTool) WithAttachmentCopies(copies map[string]string) *ReadFileTool

WithAttachmentCopies makes reading a staged sandbox copy of an attachment return the attachment's parsed text. The original bytes of a document are binary to read_file, and the parse may not have finished when the copy was staged, so the copy and the attachment must read the same.

func (*ReadFileTool) WithAttachments

func (t *ReadFileTool) WithAttachments(source interfaces.AttachmentReader) *ReadFileTool

WithAttachments adds the files the user attached to this conversation. The application reader owns authorization, parse waits and optional projections.

func (*ReadFileTool) WithSkills

func (t *ReadFileTool) WithSkills(manager *skills.Manager, shell bool) *ReadFileTool

func (*ReadFileTool) WithWebPages

func (t *ReadFileTool) WithWebPages(source WebPageSource) *ReadFileTool

WithWebPages adds session-scoped access to complete fetched page snapshots.

type ReadPageTool added in v0.9.0

type ReadPageTool struct {
	// contains filtered or unexported fields
}

ReadPageTool reads the page the user has open.

func NewReadPageTool added in v0.9.0

func NewReadPageTool(actor approval.PageActor) *ReadPageTool

NewReadPageTool creates read_page.

func (*ReadPageTool) Execute added in v0.9.0

func (t *ReadPageTool) Execute(ctx context.Context, args json.RawMessage) (*types.ToolResult, error)

Execute implements types.Tool.

type ReadWeKnoraDocTool added in v0.9.0

type ReadWeKnoraDocTool struct {
	BaseTool
	// contains filtered or unexported fields
}

ReadWeKnoraDocTool reads a documentation page or section.

func NewReadWeKnoraDocTool added in v0.9.0

func NewReadWeKnoraDocTool(lib *productdocs.Library) *ReadWeKnoraDocTool

NewReadWeKnoraDocTool creates read_weknora_doc over lib.

func (*ReadWeKnoraDocTool) Execute added in v0.9.0

Execute returns the page or section text, or the outline of a page too long to return whole. Text longer than one read is cut at a line break and continues from next_offset.

type ResolveDelegatedAgent added in v0.9.0

type ResolveDelegatedAgent func(context.Context, string) (string, error)

ResolveDelegatedAgent authorizes and snapshots an existing template. It must never accept a model-supplied owner, tenant, permission or session identifier.

type RunOperationTool added in v0.9.0

type RunOperationTool struct {
	BaseTool
	// contains filtered or unexported fields
}

RunOperationTool executes catalog operations through the router. One is built per run, so probes counts that run's probe operations.

func NewRunOperationTool added in v0.9.0

func NewRunOperationTool(rt OperationsRuntime) *RunOperationTool

NewRunOperationTool creates run_operation over rt's catalog and dispatcher.

func (*RunOperationTool) Execute added in v0.9.0

Execute runs one catalog operation as the user, asking for confirmation first when the access level requires it.

type SandboxCommandExecutor

type SandboxCommandExecutor interface {
	ExecShellCommand(
		ctx context.Context,
		sessionID string,
		command string,
		workDir string,
		timeout time.Duration,
		env map[string]string,
	) (*sandbox.ExecuteResult, error)
}

SandboxCommandExecutor is the narrow, tool-facing subset of a session-aware sandbox manager that supports executing arbitrary shell commands. In production it is satisfied by *sandbox.SessionBoundManager; tests can stub it with an in-memory fake. Kept local to the tools package for the same reason as SandboxFileSource — no dependency leak into higher layers.

type SandboxEdit

type SandboxEdit struct {
	OldString  string `json:"old_string" jsonschema:"Exact text to find, unique in the file and not overlapping any other edit in this call."` //nolint:lll // one-line struct tag
	NewString  string `json:"new_string" jsonschema:"Replacement text. Use an empty string to delete the matched text."`
	ReplaceAll bool   `` //nolint:lll // one-line struct tag
	/* 132-byte string literal not displayed */
}

SandboxEdit is one targeted replacement.

type SandboxFileEditor

type SandboxFileEditor interface {
	StatSessionFile(ctx context.Context, sessionID, filePath string) (*sandbox.RemoteStatEntry, error)
	ReadSessionFile(ctx context.Context, sessionID, filePath string) ([]byte, error)
	WriteSessionWorkspaceFile(ctx context.Context, sessionID, filePath string, content []byte) error
}

SandboxFileEditor reads then writes a session workspace file. Production uses *sandbox.SessionBoundManager via SessionFileStore.

type SandboxFileSink

type SandboxFileSink interface {
	StatSessionFile(ctx context.Context, sessionID, filePath string) (*sandbox.RemoteStatEntry, error)
	ReadSessionFile(ctx context.Context, sessionID, filePath string) ([]byte, error)
	WriteSessionWorkspaceFile(ctx context.Context, sessionID, filePath string, content []byte) error
}

SandboxFileSink is the file-store slice write_sandbox_file needs. Production uses *sandbox.SessionBoundManager via SessionFileStore.

It is not write-only: append mode has to see the file that is already there. The remote backends expose no atomic append, so this reads and rewrites the whole file, which is what edit_sandbox_file already does.

type SandboxFileSource

type SandboxFileSource interface {
	ListSessionFiles(ctx context.Context, sessionID, dir string) ([]sandbox.RemoteDirEntry, error)
	StatSessionFile(ctx context.Context, sessionID, path string) (*sandbox.RemoteStatEntry, error)
	ReadSessionFile(ctx context.Context, sessionID, path string) ([]byte, error)
}

SandboxFileSource is the narrow, tool-facing subset of a session-aware sandbox manager. In production it is satisfied by *sandbox.SessionBoundManager; tests can stub it with an in-memory fake.

Keeping the interface local to the tools package avoids leaking a dependency on internal/application/service (which is a higher layer) and mirrors the pattern used by ArtifactCollector.SandboxArtifactSource.

type SandboxInstallCommandExecutor

type SandboxInstallCommandExecutor interface {
	ExecShellCommandWithOptions(
		ctx context.Context,
		sessionID string,
		command string,
		opts sandbox.ShellExecOptions,
	) (*sandbox.ExecuteResult, error)
}

SandboxInstallCommandExecutor is the privileged counterpart of SandboxCommandExecutor, satisfied by *sandbox.SessionBoundManager via sandbox.SessionInstallShellExecutor. It exists as its own named type so the install privilege can only be handed over deliberately: nothing that merely implements ExecShellCommand can be mistaken for it.

type SearchConversationsInput

type SearchConversationsInput struct {
	Query string `json:"query"`
	Limit int    `json:"limit,omitempty"`
}

SearchConversationsInput defines the input parameters for the tool.

type SearchConversationsTool

type SearchConversationsTool struct {
	BaseTool
	// contains filtered or unexported fields
}

SearchConversationsTool lets the agent look things up in the user's own chat history.

A long-term memory feature that distils conversations into a few dozen sentences will always lose detail — the exact config someone was given three weeks ago is not a durable fact about them, and storing it would be the wrong shape. Keeping the transcripts searchable and letting the agent go back for them is the same division of labour MemGPT uses: a small always-present summary plus retrieval into the full history on demand.

func NewSearchConversationsTool

func NewSearchConversationsTool(
	messageService interfaces.MessageService, ownerID, currentSessionID string,
) *SearchConversationsTool

NewSearchConversationsTool creates the conversation history search tool.

func (*SearchConversationsTool) Execute

Execute searches the user's own past conversations.

type SearchKnowledgeInput

type SearchKnowledgeInput struct {
	Query            string   `json:"query"`
	Mode             string   `json:"mode,omitempty"`
	KnowledgeBaseIDs []string `json:"knowledge_base_ids,omitempty"`
	Limit            int      `json:"limit,omitempty"`
}

SearchKnowledgeInput defines the input parameters for search_knowledge.

type SearchKnowledgeTool

type SearchKnowledgeTool struct {
	BaseTool
	// contains filtered or unexported fields
}

SearchKnowledgeTool searches chunk-indexed knowledge bases in semantic, keyword or hybrid mode and returns reranked, de-duplicated chunks.

func NewSearchKnowledgeTool

func NewSearchKnowledgeTool(
	knowledgeBaseService interfaces.KnowledgeBaseService,
	knowledgeService interfaces.KnowledgeService,
	chunkService interfaces.ChunkService,
	searchTargets types.SearchTargets,
	rerankModel rerank.Reranker,
	cfg *config.Config,
) *SearchKnowledgeTool

NewSearchKnowledgeTool creates a new search_knowledge tool.

func (*SearchKnowledgeTool) Execute

Execute executes the search.

func (*SearchKnowledgeTool) WithContextImages

func (t *SearchKnowledgeTool) WithContextImages(enabled bool) *SearchKnowledgeTool

WithContextImages attaches to the result the images of the results that rest on an image matched by its own vector, at most searchutil.MaxContextImages. Enable it only for a vision model: the agent describes tool images to a model that cannot see them, and these already carry captions.

func (*SearchKnowledgeTool) WithPatternFilter

func (t *SearchKnowledgeTool) WithPatternFilter(re *regexp.Regexp) *SearchKnowledgeTool

WithPatternFilter restricts results to chunks whose text matches re. The candidate pool is widened to the maximum limit before filtering.

type SearchMemoryInput

type SearchMemoryInput struct {
	Query string `json:"query"`
	Limit int    `json:"limit,omitempty"`
}

SearchMemoryInput defines the input parameters for the tool.

type SearchMemoryTool

type SearchMemoryTool struct {
	BaseTool
	// contains filtered or unexported fields
}

SearchMemoryTool lets the agent reach into the user's long-term memory store beyond what this turn's recall injected.

Recall is computed once, before the loop starts, against the question the user opened with, and it admits five situational items inside a 600-rune budget. Both of those are the right call for something that rides in every single turn's system prompt, and both stop being the right call once an agent has spent ten iterations working its way to a sub-problem the opening question never mentioned. This is the same division of labour SearchConversationsTool describes — a small always-present summary plus retrieval on demand — applied to the memory store rather than to transcripts.

The tool takes no owner argument. Which memory space is read is derived entirely from the request context inside the service, which is what keeps "read someone else's memories" from being reachable by writing a different id into a tool call.

func NewSearchMemoryTool

func NewSearchMemoryTool(memoryService interfaces.MemoryService) *SearchMemoryTool

NewSearchMemoryTool creates the long-term memory search tool.

func (*SearchMemoryTool) Execute

func (t *SearchMemoryTool) Execute(
	ctx context.Context, args json.RawMessage,
) (*types.ToolResult, error)

Execute searches the user's own long-term memory.

type SearchWeKnoraDocsTool added in v0.9.0

type SearchWeKnoraDocsTool struct {
	BaseTool
	// contains filtered or unexported fields
}

SearchWeKnoraDocsTool searches the bundled documentation.

func NewSearchWeKnoraDocsTool added in v0.9.0

func NewSearchWeKnoraDocsTool(lib *productdocs.Library) *SearchWeKnoraDocsTool

NewSearchWeKnoraDocsTool creates search_weknora_docs over lib.

func (*SearchWeKnoraDocsTool) Execute added in v0.9.0

Execute searches sections, or lists pages when no query is given.

type SelectTabTool added in v0.9.0

type SelectTabTool struct {
	// contains filtered or unexported fields
}

SelectTabTool opens a tab of the page the user has open.

func NewSelectTabTool added in v0.9.0

func NewSelectTabTool(actor approval.PageActor) *SelectTabTool

NewSelectTabTool creates select_tab.

func (*SelectTabTool) Execute added in v0.9.0

func (t *SelectTabTool) Execute(ctx context.Context, args json.RawMessage) (*types.ToolResult, error)

Execute implements types.Tool.

type SequentialThinkingInput

type SequentialThinkingInput struct {
	Thought           string `json:"thought"`
	NextThoughtNeeded bool   `json:"next_thought_needed"`
	ThoughtNumber     int    `json:"thought_number"`
	TotalThoughts     int    `json:"total_thoughts"`
	IsRevision        bool   `json:"is_revision,omitempty"`
	RevisesThought    *int   `json:"revises_thought,omitempty"`
	BranchFromThought *int   `json:"branch_from_thought,omitempty"`
	BranchID          string `json:"branch_id,omitempty"`
	NeedsMoreThoughts bool   `json:"needs_more_thoughts,omitempty"`
}

SequentialThinkingInput defines the input parameters for sequential thinking tool

type SequentialThinkingTool

type SequentialThinkingTool struct {
	BaseTool
	// contains filtered or unexported fields
}

SequentialThinkingTool is a dynamic and reflective problem-solving tool This tool helps analyze problems through a flexible thinking process that can adapt and evolve

func NewSequentialThinkingTool

func NewSequentialThinkingTool() *SequentialThinkingTool

NewSequentialThinkingTool creates a new sequential thinking tool instance

func (*SequentialThinkingTool) Execute

Execute executes the sequential thinking tool

type ShellExecAsyncInput added in v0.9.0

type ShellExecAsyncInput struct {
	Command     string            `json:"command" jsonschema:"The shell one-liner to run"`
	WorkDir     string            `json:"work_dir,omitempty" jsonschema:"Working directory; defaults like shell_exec"`
	Stdin       string            `json:"stdin,omitempty" jsonschema:"Text written once at start, max 65536 bytes"`
	Env         map[string]string `json:"env,omitempty" jsonschema:"Extra environment variables"`
	SkillName   string            `json:"skill_name,omitempty" jsonschema:"Pull this skill's env into the command"`
	Description string            `json:"description" jsonschema:"Short label shown to the user"`
	YieldTimeMS int               `json:"yield_time_ms,omitempty" jsonschema:"Wait ms; default 10000, max 30000"`
}

ShellExecAsyncInput is the model-facing argument object.

type ShellExecAsyncTool added in v0.9.0

type ShellExecAsyncTool struct {
	BaseTool
	// contains filtered or unexported fields
}

ShellExecAsyncTool validates a command the same way shell_exec does, then hands it to ShellJobSubmitter. It does not run the command itself.

func NewShellExecAsyncTool added in v0.9.0

func NewShellExecAsyncTool(submitter ShellJobSubmitter, executor SandboxCommandExecutor,
	envResolver skills.SkillEnvResolver,
) *ShellExecAsyncTool

NewShellExecAsyncTool builds shell_exec_async. submitter starts a background job, executor runs a command that finishes inside the yield window, and envResolver supplies skill credentials.

func (*ShellExecAsyncTool) BindBackgroundRun added in v0.9.0

func (t *ShellExecAsyncTool) BindBackgroundRun(
	s interfaces.SessionRef, runID string, marks interface{ MarkStarted(string) },
)

BindBackgroundRun records the run that owns this tool. A handle that is still running is marked started on that run; a direct result is not. Cursor expiry uses the same run id at Cleanup.

func (*ShellExecAsyncTool) BindSession added in v0.9.0

func (s *ShellExecAsyncTool) BindSession(id string)

func (*ShellExecAsyncTool) Cleanup added in v0.9.0

Cleanup tells the submitter the run ended so its output cursors can expire.

func (*ShellExecAsyncTool) Execute added in v0.9.0

Execute validates the command, wraps stdin the way shell_exec does, and submits.

func (*ShellExecAsyncTool) OutputLimitChars added in v0.9.0

func (t *ShellExecAsyncTool) OutputLimitChars(json.RawMessage) int

OutputLimitChars is the rune budget for the model-facing JSON envelope.

func (*ShellExecAsyncTool) WithEnvCapture added in v0.9.0

func (t *ShellExecAsyncTool) WithEnvCapture(capture SkillEnvCapture) *ShellExecAsyncTool

WithEnvCapture attaches the same credential write-back shell_exec uses. A nil hook does nothing. Values stay in memory until the job succeeds.

func (*ShellExecAsyncTool) WithSkillEnvironment added in v0.9.0

func (t *ShellExecAsyncTool) WithSkillEnvironment(manager *skills.Manager) *ShellExecAsyncTool

WithSkillEnvironment attaches the skill runtime used by shell_exec.

type ShellExecInput

type ShellExecInput struct {
	Stdin string `` /* 200-byte string literal not displayed */
	// Command is the shell command to execute. Runs under Bash.
	Command string `json:"command" jsonschema:"Shell command to execute (single line, supports pipes and && chaining). Runs under Bash."`
	// WorkDir is the working directory for the command; defaults to /workspace.
	WorkDir string `` //nolint:lll // one-line struct tag
	/* 151-byte string literal not displayed */
	// TimeoutSec caps execution time. Zero uses the default (120s); the
	// value is hard-capped at 600s regardless of what the LLM requests.
	TimeoutSec int `json:"timeout_sec,omitempty" jsonschema:"Per-call timeout in seconds. Defaults to 120, hard-capped at 600."`
	// MaxOutputBytes caps returned stdout. Stderr has an independent smaller
	// fixed budget, and the complete model-visible output is capped at 64 KiB.
	MaxOutputBytes int `` /* 222-byte string literal not displayed */
	// MaxStderrBytes caps returned stderr independently from stdout.
	MaxStderrBytes int `json:"max_stderr_bytes,omitempty" jsonschema:"Maximum bytes returned from stderr. Defaults to 8192, hard-capped at 16384."`
	// Env carries extra environment variables merged into the shell's env.
	Env map[string]string `` /* 141-byte string literal not displayed */
	// SkillName, when set, pulls that skill's scoped environment variables
	// (API keys) into this one command's process only. Resolution
	// uses the caller-scoped SkillEnvResolver, so values
	// are per-caller (taken from ctx) and never persist. Omitting it leaves
	// shell_exec's behaviour unchanged.
	SkillName string `` //nolint:lll // JSON schema tags must remain on one line.
	/* 206-byte string literal not displayed */
}

ShellExecInput defines the input parameters for shell_exec.

type ShellExecTool

type ShellExecTool struct {
	BaseTool
	// contains filtered or unexported fields
}

ShellExecTool executes shell commands inside the session's sandbox.

func NewHostInstallShellExecTool

func NewHostInstallShellExecTool(
	executor SandboxInstallCommandExecutor, versionDir string,
) *ShellExecTool

NewHostInstallShellExecTool is the Lite installer's shell: commands run as the desktop user under an install-only OS sandbox, and versionDir is the only directory they may write.

func NewInstallShellExecTool

func NewInstallShellExecTool(
	executor SandboxInstallCommandExecutor, skillDir string,
) *ShellExecTool

NewInstallShellExecTool constructs the install-mode variant: commands run as root and may work inside the skills image root. It is registered only for the built-in skill installer agent (see AgentConfig.SkillInstallMode).

skillDir becomes the default working directory, because every command an install runs belongs there. A validated directory is required for that: an empty or unrecognised one falls back to /workspace rather than guessing.

func NewShellExecTool

func NewShellExecTool(executor SandboxCommandExecutor, envResolver skills.SkillEnvResolver) *ShellExecTool

NewShellExecTool constructs the tool. `executor` MUST NOT be nil: callers should feature-gate registration when the sandbox backend does not support ad-hoc shell execution (i.e. is not Cube).

func (*ShellExecTool) BindSession

func (s *ShellExecTool) BindSession(id string)

func (*ShellExecTool) Cleanup

func (t *ShellExecTool) Cleanup(ctx context.Context) error

Cleanup releases any resources.

func (*ShellExecTool) Description

func (t *ShellExecTool) Description() string

Description is generated from the session sandbox layout. Install mode keeps the constructor-built text.

func (*ShellExecTool) Execute

func (t *ShellExecTool) Execute(ctx context.Context, args json.RawMessage) (*types.ToolResult, error)

Execute runs the requested command inside the current session's sandbox.

func (*ShellExecTool) OutputLimitChars

func (t *ShellExecTool) OutputLimitChars(args json.RawMessage) int

OutputLimitChars lets ToolRegistry preserve shell_exec's explicitly bounded, caller-configurable output instead of applying its lower generic limit again.

func (*ShellExecTool) Parameters

func (t *ShellExecTool) Parameters() json.RawMessage

Parameters rewrites workspace paths in the schema to match the session layout.

func (*ShellExecTool) WithEnvCapture

func (t *ShellExecTool) WithEnvCapture(capture SkillEnvCapture) *ShellExecTool

WithEnvCapture attaches an optional capture hook. A nil hook is a no-op so callers can pass the wiring result through without a nil check.

func (*ShellExecTool) WithHostApproval added in v0.9.0

func (t *ShellExecTool) WithHostApproval(gate HostApproval) *ShellExecTool

WithHostApproval lets host commands wait for the session owner. Without it the host sandbox refuses anything it would have asked about.

func (*ShellExecTool) WithSkillEnvironment

func (t *ShellExecTool) WithSkillEnvironment(manager *skills.Manager) *ShellExecTool

type ShellJobSubmission added in v0.9.0

type ShellJobSubmission struct {
	Result     interfaces.WorkResult
	Background bool
}

ShellJobSubmission is the direct result of one SubmitShellJob call.

type ShellJobSubmitRequest added in v0.9.0

type ShellJobSubmitRequest struct {
	Command string
	// DisplayCommand is the original command, before stdin, cwd and skill
	// wrappers. Only this command belongs in persistent metadata and results.
	DisplayCommand  string
	WorkDir         string
	Env             map[string]string
	Description     string
	YieldTime       time.Duration
	ParentMessageID string
	ToolCallID      string
	RunID           string
	OnOutput        func(string, []byte)
	// OutputDir is the deliverable directory, same as shell_exec. OutputSeen
	// reports that OutputBefore is a complete listing taken before the command.
	OutputDir    string
	OutputSeen   bool
	OutputBefore []sandbox.OutputFileStamp
}

ShellJobSubmitRequest is the frozen submit payload shared by the remote shell-job service and the async shell tool.

func (ShellJobSubmitRequest) MaskedCommand added in v0.9.0

func (r ShellJobSubmitRequest) MaskedCommand() string

MaskedCommand keeps execution-only wrappers out of metadata. Direct service callers without a separate display command retain the existing fallback.

type ShellJobSubmitter added in v0.9.0

type ShellJobSubmitter interface {
	SubmitShellJob(ctx context.Context, s interfaces.SessionRef, req ShellJobSubmitRequest) (ShellJobSubmission, error)
}

ShellJobSubmitter starts one shell job. *service.ShellJobService implements it. EndShellJobRun is optional and checked separately at Cleanup.

type SkillEnvCapture

type SkillEnvCapture func(ctx context.Context, skillName string, pairs map[string]string)

SkillEnvCapture records NAME=value pairs a successful shell_exec already used for one skill. The tools package does not persist them; the agent service supplies the write. Values must not be logged by the caller.

type SkillFileStore

type SkillFileStore interface {
	StatSessionFile(ctx context.Context, sessionID, filePath string) (*sandbox.RemoteStatEntry, error)
	ReadSessionFile(ctx context.Context, sessionID, filePath string) ([]byte, error)
	WriteSessionFile(ctx context.Context, sessionID, filePath string, content []byte) error
}

SkillFileStore is the write surface these tools need. Production uses *sandbox.SessionBoundManager, whose WriteSessionFile already refuses any path outside the skills image root; the per-skill scope below narrows that to the one directory this install owns.

type TableSchema

type TableSchema struct {
	TableName string                 `json:"table_name"`
	Columns   []ColumnInfo           `json:"columns"`
	RowCount  int64                  `json:"row_count"`
	Metadata  map[string]interface{} `json:"metadata,omitempty"`
}

TableSchema represents the schema information of a table

func (*TableSchema) Description

func (t *TableSchema) Description() string

Description builds the model-facing schema description. It names the table as DataAnalysisTableName, the identifier the model must use in SQL; the physical TableName stays internal.

type ThinkStreamSplitter

type ThinkStreamSplitter struct {
	// contains filtered or unexported fields
}

ThinkStreamSplitter incrementally separates inline <think>…</think> reasoning from user-facing answer text as content arrives chunk-by-chunk. It is the streaming counterpart to StripThinkBlocks: where StripThinkBlocks operates on a fully-accumulated string, this splitter routes each chunk live so the thinking portion can stream into the "thought" UI area and the answer portion into the "final answer" area without waiting for the whole response.

Tag boundaries that straddle two chunks (e.g. "<thi" at the end of one chunk and "nk>" at the start of the next) are handled by buffering the trailing bytes that could still become a tag prefix until the next Feed call. Call Flush at end-of-stream to drain any buffered remainder.

The splitter is NOT safe for concurrent use; create one per stream.

func NewThinkStreamSplitter

func NewThinkStreamSplitter() *ThinkStreamSplitter

NewThinkStreamSplitter returns a splitter ready to receive content chunks.

func (*ThinkStreamSplitter) Feed

func (sp *ThinkStreamSplitter) Feed(s string) (thinkOut, answerOut string)

Feed consumes one content chunk and returns the portions that are now unambiguously thinking text and answer text respectively. Either return value may be empty. Bytes that could still be part of a tag spanning into the next chunk are buffered internally and surface on a later Feed or on Flush.

func (*ThinkStreamSplitter) Flush

func (sp *ThinkStreamSplitter) Flush() (thinkOut, answerOut string)

Flush drains any buffered remainder at end-of-stream. An unterminated <think> block is treated as thinking text; anything else is answer text.

func (*ThinkStreamSplitter) TakeAnswerReset added in v0.9.0

func (sp *ThinkStreamSplitter) TakeAnswerReset() bool

TakeAnswerReset reports that a nonce-qualified orphan closer proved the previously emitted prefix was reasoning. Consumers must replace that answer segment before appending the answer returned by the same Feed call.

type TodoWriteInput

type TodoWriteInput struct {
	Task  string     `json:"task,omitempty" jsonschema:"The complex task or question you need to create a plan for"`
	Steps []PlanStep `json:"steps" jsonschema:"Array of research plan steps with status tracking"`
}

TodoWriteInput defines the input parameters for todo_write tool

type TodoWriteTool

type TodoWriteTool struct {
	BaseTool
}

TodoWriteTool implements a planning tool for complex tasks This is an optional tool that helps organize multi-step research

func NewTodoWriteTool

func NewTodoWriteTool() *TodoWriteTool

NewTodoWriteTool creates a new todo_write tool instance

func (*TodoWriteTool) Execute

func (t *TodoWriteTool) Execute(ctx context.Context, args json.RawMessage) (*types.ToolResult, error)

Execute executes the todo_write tool

type ToolExecContext

type ToolExecContext struct {
	SessionID          string
	AssistantMessageID string
	RequestID          string
	ToolCallID         string
	UserID             string // principal storage ID of the originating session; used by HITL gates for authorization (issue #1173)
	EventBus           *event.EventBus
	// ApprovalCtx is the parent ctx WITHOUT defaultToolExecTimeout; used when the tool
	// must wait for human approval that may exceed normal tool exec timeout (issue #1173).
	// Falls back to the per-tool execCtx when nil.
	ApprovalCtx context.Context
	// ExecTimeout mirrors the per-tool exec timeout the engine applied to the
	// outer ctx. Tools that legitimately consume that ctx (e.g. MCP human
	// approval) can re-derive a fresh timeout from ApprovalCtx using this
	// value instead of hard-coding a duration. Zero means "fallback to 60s".
	ExecTimeout time.Duration
	// Snapshot, when set, captures the run so it can be resumed from this
	// call. A tool that raises a suspendable prompt passes the result along;
	// nil means the run cannot be suspended and prompts wait synchronously.
	Snapshot func() (data []byte, version int, err error)
	// Answered is set on the call a resumed run was suspended on: the prompt
	// it raised, now answered. The tool acts on the answer instead of
	// raising the prompt again.
	Answered *types.AgentPrompt
	// Mode says whether the client can show and answer prompts; IM and
	// MCP-server runs have no such surface.
	Mode types.RunMode
}

ToolExecContext is attached to context during agent tool execution (per tool call).

func ToolExecFromContext

func ToolExecFromContext(ctx context.Context) (*ToolExecContext, bool)

ToolExecFromContext returns metadata attached by the agent engine, if any.

func (*ToolExecContext) Attended added in v0.9.0

func (m *ToolExecContext) Attended() bool

Attended reports whether a client can answer prompts now.

func (*ToolExecContext) CanAsk added in v0.9.0

func (m *ToolExecContext) CanAsk() bool

CanAsk reports whether the run may raise an approval, now or by suspending until its owner answers.

type ToolExecutor

type ToolExecutor interface {
	types.Tool

	// GetContext returns any context-specific data needed for tool execution
	GetContext() map[string]interface{}
}

ToolExecutor is a helper interface for executing tools

type ToolRegistry

type ToolRegistry struct {
	// contains filtered or unexported fields
}

ToolRegistry manages the registration and retrieval of tools

func NewToolRegistry

func NewToolRegistry() *ToolRegistry

NewToolRegistry creates a new tool registry

func (*ToolRegistry) BindSession

func (r *ToolRegistry) BindSession(id string)

BindSession tells sandbox tools which session's layout to advertise in Description() and Parameters(). Host adapters refuse an empty session ID.

func (*ToolRegistry) Cleanup

func (r *ToolRegistry) Cleanup(ctx context.Context)

Cleanup cleans up all registered tools that implement types.Cleanable or errorCleanable. This is called at the end of agent sessions to release tool-specific resources, including shell-job output cursors.

func (*ToolRegistry) ExecuteTool

func (r *ToolRegistry) ExecuteTool(
	ctx context.Context,
	name string,
	args json.RawMessage,
) (*types.ToolResult, error)

ExecuteTool executes a tool by name with the given arguments

func (*ToolRegistry) GetFunctionDefinitions

func (r *ToolRegistry) GetFunctionDefinitions() []types.FunctionDefinition

GetFunctionDefinitions returns function definitions for all registered tools. The slice is sorted by tool name so the serialized payload sent to the LLM is byte-identical across requests. Providers that key prompt caching on a byte-level prefix match (e.g. Qwen explicit caching) require this — map iteration order would otherwise reshuffle the tools block and break cache hits.

func (*ToolRegistry) GetModelFunctionDefinitions

func (r *ToolRegistry) GetModelFunctionDefinitions() []types.FunctionDefinition

GetModelFunctionDefinitions is the stable model-facing projection of the registry.

func (*ToolRegistry) GetTool

func (r *ToolRegistry) GetTool(name string) (types.Tool, error)

GetTool retrieves a tool by name

func (*ToolRegistry) HasMCPServer

func (r *ToolRegistry) HasMCPServer(id string) bool

HasMCPServer lets the prompt bind an explicit service mention without requiring eager tool discovery merely to generate a tool-name prefix.

func (*ToolRegistry) ListTools

func (r *ToolRegistry) ListTools() []string

ListTools returns all registered tool names sorted alphabetically. Sorting keeps the order stable across calls — Go map iteration is intentionally randomized.

func (*ToolRegistry) MCPCallTarget

func (r *ToolRegistry) MCPCallTarget(ctx context.Context, name string, raw json.RawMessage) *types.ToolCallTarget

MCPCallTarget separates UI/audit identity from the model's proxy call. The original call name, arguments, ID and provider metadata remain replayable.

func (*ToolRegistry) MCPExposureSnapshot added in v0.9.0

func (r *ToolRegistry) MCPExposureSnapshot() []string

MCPExposureSnapshot preserves definitions that were described but have not been called yet. Call history alone cannot restore this deferred tool state. References contain a schema hash; no credentials or remote definitions are saved.

func (*ToolRegistry) PrepareMCPTools

func (r *ToolRegistry) PrepareMCPTools(ctx context.Context)

PrepareMCPTools advertises sources up front, loading full functions only after describe. This is application-level deferred loading via ordinary functions. Production readers use persisted metadata and perform no upstream discovery.

func (*ToolRegistry) PrepareMCPToolsDirect

func (r *ToolRegistry) PrepareMCPToolsDirect(ctx context.Context)

PrepareMCPToolsDirect is the full-exposure compatibility path.

func (*ToolRegistry) RefreshMCPTools

func (r *ToolRegistry) RefreshMCPTools(ctx context.Context)

RefreshMCPTools publishes ready definitions between model requests, including catalogs loaded by discovery/OAuth or refreshed after the initial request. No network discovery occurs here. Policy checks remain fresh even when the metadata snapshot is cached. Call only when parallel tool execution is idle.

func (*ToolRegistry) RegisterDeferredTool

func (r *ToolRegistry) RegisterDeferredTool(tool types.Tool)

RegisterDeferredTool retains execution capability without advertising the full definition to the model. Registration is completed before execution.

func (*ToolRegistry) RegisterTool

func (r *ToolRegistry) RegisterTool(tool types.Tool)

RegisterTool adds a tool to the registry. If a tool with the same name is already registered, the existing one is kept (first-wins) to prevent tool execution hijacking via name collision (GHSA-67q9-58vj-32qx).

func (*ToolRegistry) RememberMCPHistory

func (r *ToolRegistry) RememberMCPHistory(messages []chat.Message)

RememberMCPHistory republishes tools this session already described or called so a new engine does not require another describe round.

func (*ToolRegistry) RequireConfirmation added in v0.9.0

func (r *ToolRegistry) RequireConfirmation(
	name string, risk operations.Risk, access operations.Access, gate approval.BuiltinApproval,
) error

RequireConfirmation decorates an existing tool without permitting replacement by another implementation. Duplicate registration remains first-wins.

func (*ToolRegistry) RestoreMCPExposure added in v0.9.0

func (r *ToolRegistry) RestoreMCPExposure(refs []string)

RestoreMCPExposure restores exposure only. Refresh and execution still check the current principal, enabled policy, service configuration and schema hash.

func (*ToolRegistry) RestrictTools added in v0.9.0

func (r *ToolRegistry) RestrictTools(names []string)

RestrictTools intersects an already constructed registry with an authorized snapshot. Used by inherited children so newly available integrations cannot silently expand their parent's effective native tool set.

func (*ToolRegistry) SetExecutionGuard added in v0.9.0

func (r *ToolRegistry) SetExecutionGuard(guard func(context.Context, types.Tool) error)

SetExecutionGuard installs a runtime authority fence before any direct or deferred tool.

func (*ToolRegistry) SetMCPCallGuard added in v0.9.0

func (r *ToolRegistry) SetMCPCallGuard(guard MCPCallGuard)

SetMCPCallGuard applies only to this engine's registry, including MCP targets discovered later and direct tools rebuilt from refreshed service metadata.

func (*ToolRegistry) SetMaxToolOutputSize

func (r *ToolRegistry) SetMaxToolOutputSize(maxChars int)

SetMaxToolOutputSize sets the maximum character length for tool output. Values <= 0 will use DefaultMaxToolOutput.

type ToolRequirement

type ToolRequirement struct {
	AnyOf         []KBCapability
	AllOf         []KBCapability
	ConsumesFiles bool
	// Auxiliary tools work on any KB listed in AnyOf/AllOf but do not by
	// themselves make a KB worth selecting: a document reader can open a
	// wiki-only KB's sources, yet it should not pull wiki-only KBs into a
	// RAG agent's "all knowledge bases" scope. They contribute to the derived
	// filter only when no primary tool has a requirement.
	Auxiliary bool
}

ToolRequirement declares what a tool needs from the KB scope.

  • AnyOf: scope must expose at least ONE listed capability.
  • AllOf: scope must expose ALL listed capabilities.
  • ConsumesFiles: the tool reads user-provided file refs from `knowledge_ids`; the chat input uses this to decide whether to even offer the `@file` list to the user.

A nil/zero requirement means "no KB dependency" — the tool is always available and doesn't care about files.

type ValidationError

type ValidationError struct {
	Param   string // parameter name (or "" for top-level errors)
	Message string // human-readable error description
}

ValidationError describes a specific parameter validation failure.

func ValidateParams

func ValidateParams(args json.RawMessage, schema json.RawMessage) []ValidationError

ValidateParams checks args against the JSON Schema declared by tool.Parameters(). Returns nil if valid, or a list of validation errors.

Supported checks:

  • required: ensures all required fields are present and non-null
  • type: verifies the JSON type matches (string, number, integer, boolean, array, object)
  • enum: checks the value is in the allowed set
  • minimum / maximum: numeric bounds
  • minLength / maxLength: string length bounds

type WebFetchInput

type WebFetchInput struct {
	Items []WebFetchItem `json:"items" jsonschema:"One to eight reads with url, optional offset and limit"`
}

WebFetchInput defines the input parameters for web fetch tool.

type WebFetchItem

type WebFetchItem struct {
	URL    string `json:"url" jsonschema:"url://N page ID or absolute HTTP(S) URL"`
	Offset int    `json:"offset,omitempty" jsonschema:"Zero-based character offset; use next_offset to continue"`
	Limit  int    `json:"limit,omitempty" jsonschema:"Maximum characters to return, from 1 to 8000; default 8000"`
}

WebFetchItem represents a single web fetch task.

type WebFetchTool

type WebFetchTool struct {
	BaseTool
	// contains filtered or unexported fields
}

WebFetchTool reads page snapshots for the current Agent run.

func NewWebFetchTool

func NewWebFetchTool() *WebFetchTool

NewWebFetchTool creates a new web_fetch tool instance.

func (*WebFetchTool) Execute

func (t *WebFetchTool) Execute(ctx context.Context, args json.RawMessage) (*types.ToolResult, error)

Execute runs web_fetch and preserves successful items when a batch partially fails.

func (*WebFetchTool) WithPageSource

func (t *WebFetchTool) WithPageSource(source WebPageSource) *WebFetchTool

WithPageSource adds complete page storage independently of the in-memory cache.

type WebPageSource

type WebPageSource interface {
	Save(context.Context, string) (string, error)
	Read(context.Context, string) ([]byte, error)
}

WebPageSource stores complete pages and authorizes reads against the current session.

type WebSearchInput

type WebSearchInput struct {
	Query     string `json:"query" jsonschema:"Search query string"`
	Count     *int   `json:"count,omitempty" jsonschema:"Number of results to return (1 to the configured maximum)"`
	Country   string `json:"country,omitempty" jsonschema:"Two-letter code or ALL (Brave, Serply); omit for default"`
	Freshness string `json:"freshness,omitempty" jsonschema:"pd/pw/pm/py; Brave also accepts YYYY-MM-DDtoYYYY-MM-DD"`
	Content   bool   `json:"content,omitempty" jsonschema:"Fetch page excerpts; default false"`
}

WebSearchInput defines the input parameters for web search tool

type WebSearchTool

type WebSearchTool struct {
	BaseTool
	// contains filtered or unexported fields
}

WebSearchTool performs web searches and returns results

func NewWebSearchTool

func NewWebSearchTool(
	webSearchService interfaces.WebSearchService,
	maxResults int,
	providerID string,
) *WebSearchTool

NewWebSearchTool creates a new web search tool

func (*WebSearchTool) Execute

func (t *WebSearchTool) Execute(ctx context.Context, args json.RawMessage) (*types.ToolResult, error)

Execute executes the web search tool

func (*WebSearchTool) WithPageReader

func (t *WebSearchTool) WithPageReader(reader *WebFetchTool) *WebSearchTool

WithPageReader shares page snapshots and full-output storage with web_fetch.

type WikiRouteResolver

type WikiRouteResolver struct {
	// contains filtered or unexported fields
}

WikiRouteResolver stores request-local provenance for wiki slugs. It is server-side routing state, not a model-handle registry: only KBs already in the current WikiScope can ever be returned.

func NewWikiRouteResolver

func NewWikiRouteResolver() *WikiRouteResolver

type WikiScope

type WikiScope struct {
	KnowledgeBaseID string
	KnowledgeIDs    []string
	TagIDs          []string
}

WikiScope describes the effective retrieval scope for a single wiki knowledge base within an agent session.

  • KnowledgeBaseID: the wiki KB to search.
  • KnowledgeIDs: OPTIONAL whitelist of source knowledge (document) IDs. When non-empty, a wiki page is only surfaced if its SourceRefs intersect this set. Used to honour user-level @mentions that pin the search to specific documents inside a KB.
  • TagIDs: OPTIONAL whitelist of document tags. When non-empty, a wiki page is only surfaced if at least one of its SourceRefs belongs to any tag.

func NewWikiScopesFromKBIDs

func NewWikiScopesFromKBIDs(kbIDs []string) []WikiScope

NewWikiScopesFromKBIDs is a convenience constructor for callers that only carry plain KB IDs and don't need per-document filtering (e.g. legacy tests).

func NewWikiScopesFromSearchTargets

func NewWikiScopesFromSearchTargets(searchTargets types.SearchTargets, wikiKBIDs []string) []WikiScope

NewWikiScopesFromSearchTargets merges all targets for a Wiki KB into one scope. SearchTargets are alternatives selected by the user, so document and tag constraints are combined as a union; an unrestricted whole-KB target supersedes narrower targets for that KB.

type WorkCancelInput added in v0.9.0

type WorkCancelInput struct {
	WorkIDs []string `json:"work_ids" jsonschema:"IDs of the background work to stop"`
}

WorkCancelInput documents the work_cancel arguments for the schema.

type WorkCancelTool added in v0.9.0

type WorkCancelTool struct {
	BaseTool
	// contains filtered or unexported fields
}

WorkCancelTool stops background work of the run's session.

func NewWorkCancelTool added in v0.9.0

func NewWorkCancelTool(handler interfaces.WorkHandler, session interfaces.SessionRef, marks WorkMarks) *WorkCancelTool

NewWorkCancelTool returns work_cancel bound to one run.

func (*WorkCancelTool) Execute added in v0.9.0

Execute implements types.Tool.

type WorkMarks added in v0.9.0

type WorkMarks interface {
	MarkSeen(ids ...string)
}

WorkMarks is the run-scoped tracker the work tools report to. *background.RunNotices implements it.

type WorkWaitInput added in v0.9.0

type WorkWaitInput struct {
	WorkIDs []string `json:"work_ids" jsonschema:"IDs of the background work to wait for"`
	WaitSec int      `json:"wait_sec,omitempty" jsonschema:"Seconds to wait, default 60, max 300; 0 returns at once"`
	Mode    string   `json:"mode,omitempty" jsonschema:"all (default) waits for every ID; any returns when one ends"`
}

WorkWaitInput documents the work_wait arguments for the schema.

type WorkWaitTool added in v0.9.0

type WorkWaitTool struct {
	BaseTool
	// contains filtered or unexported fields
}

WorkWaitTool waits on background work of the run's session.

func NewWorkWaitTool added in v0.9.0

func NewWorkWaitTool(
	handler interfaces.WorkHandler, session interfaces.SessionRef, runID string,
	marks WorkMarks, pending func(context.Context) bool, submitters []string,
) *WorkWaitTool

NewWorkWaitTool returns work_wait bound to one run. runID scopes incremental output reads; pending reports a waiting user message; submitters are named in the description.

func (*WorkWaitTool) Execute added in v0.9.0

func (t *WorkWaitTool) Execute(ctx context.Context, raw json.RawMessage) (*types.ToolResult, error)

Execute implements types.Tool.

func (*WorkWaitTool) OutputLimitChars added in v0.9.0

func (t *WorkWaitTool) OutputLimitChars(json.RawMessage) int

OutputLimitChars keeps a full work_wait body, including JSON framing and escaping, inside the registry's truncation ceiling.

type WriteSandboxFileInput

type WriteSandboxFileInput struct {
	Path string `` //nolint:lll // JSON schema tags must remain on one line.
	/* 210-byte string literal not displayed */
	Content string `` //nolint:lll // one-line struct tag
	/* 242-byte string literal not displayed */
	Mode string `` //nolint:lll // one-line struct tag
	/* 198-byte string literal not displayed */
}

WriteSandboxFileInput defines the input parameters for write_sandbox_file.

The byte limit is deliberately absent from the `content` description: it depends on the agent's per-round token budget and is stated in the tool description, which is built per session.

type WriteSandboxFileTool

type WriteSandboxFileTool struct {
	BaseTool
	// contains filtered or unexported fields
}

WriteSandboxFileTool writes a text file into the session sandbox.

func NewWriteSandboxFileTool

func NewWriteSandboxFileTool(sink SandboxFileSink, completionTokens int) *WriteSandboxFileTool

NewWriteSandboxFileTool constructs the tool. `sink` MUST NOT be nil.

completionTokens is the agent's per-round completion-token budget, which is what actually bounds how much the model can emit in one call. It shapes the size guidance in the description; it is not enforced, for the reasons in Execute. Pass 0 when it is not known.

func (*WriteSandboxFileTool) BindSession

func (s *WriteSandboxFileTool) BindSession(id string)

func (*WriteSandboxFileTool) Cleanup

func (t *WriteSandboxFileTool) Cleanup(ctx context.Context) error

Cleanup releases any resources.

func (*WriteSandboxFileTool) Description

func (t *WriteSandboxFileTool) Description() string

Description is built from the session sandbox layout so host paths never hard-code /workspace.

func (*WriteSandboxFileTool) Execute

Execute writes the requested file into the current session's sandbox.

func (*WriteSandboxFileTool) Parameters

func (t *WriteSandboxFileTool) Parameters() json.RawMessage

Parameters rewrites workspace paths in the schema to match the session layout.

type WriteSkillFileInput

type WriteSkillFileInput struct {
	Path    string `` /* 136-byte string literal not displayed */
	Content string `` /* 145-byte string literal not displayed */
}

WriteSkillFileInput defines the input parameters for write_skill_file.

type WriteSkillFileTool

type WriteSkillFileTool struct {
	BaseTool
	// contains filtered or unexported fields
}

WriteSkillFileTool writes a text file into the skill directory under install.

func NewWriteSkillFileTool

func NewWriteSkillFileTool(store SkillFileStore, skillDir string) *WriteSkillFileTool

NewWriteSkillFileTool constructs the tool. `store` MUST NOT be nil and `skillDir` MUST be the directory of the skill this install owns.

func (*WriteSkillFileTool) Cleanup

func (t *WriteSkillFileTool) Cleanup(ctx context.Context) error

Cleanup releases any resources.

func (*WriteSkillFileTool) Execute

Execute writes the file after confirming it lands inside the skill directory.

Source Files

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL