P1 (part 1): move skilltools core -> tool/ (clean, verbatim)
executus CI / test (push) Successful in 36s
executus CI / test (push) Successful in 36s
The tool registry core (registry, permission model, Invocation, gated-tool wrapper, ssrf guard, hmac, encryption, argcoerce, helpers, rootrun, session_tools, webhook_rate_limit) had zero mort coupling — it imports only majordomo/llm + x/crypto/hkdf — so it moves verbatim with a package rename (skilltools -> tool). All same-package tests came along and pass; the SSRF, gated-wrapper, encryption and output-pattern invariants are re-anchored here. majordomo re-enters the module graph (now pinned to the latest, incl. the front-loaded-output fix). model/ + llmmeta + structured follow next. Docs: CLAUDE.md now requires README/examples to stay in sync with changes in the same commit; CI skips docs/example-only pushes via paths-ignore. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
package tool
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
llm "gitea.stevedudenhoeffer.com/steve/majordomo/llm"
|
||||
)
|
||||
|
||||
// AgentSession is the live-run handle a SessionToolFactory receives.
|
||||
// It is implemented by the executors (agentexec / skillexec / scaddy's
|
||||
// adapter) on top of majordomo's agent loop and exposes the one mid-run
|
||||
// mutation session tools need: feeding content back into the running
|
||||
// conversation.
|
||||
//
|
||||
// Why an interface (vs the concrete agent type): legacy agentkit handed the
|
||||
// factory a *agentkit.Agent so tools could call agent.AttachImages.
|
||||
// majordomo's *agent.Agent is deliberately immutable mid-run — message
|
||||
// injection happens through the run-scoped steer mailbox
|
||||
// (agent.WithSteer). A narrow interface lets each executor implement
|
||||
// AttachImages over its own steer queue without skilltools importing
|
||||
// the agent package, and keeps session tools testable with a two-line
|
||||
// fake.
|
||||
type AgentSession interface {
|
||||
// AttachImages queues a user-role message (text plus image parts)
|
||||
// for injection into the conversation before the agent's next
|
||||
// step. Used by tools that produce visual feedback the model must
|
||||
// see on its following turn (e.g. scaddy's rendered OpenSCAD
|
||||
// previews). Safe to call from inside a tool handler; the message
|
||||
// lands after the current step's tool results.
|
||||
AttachImages(text string, images ...llm.ImagePart)
|
||||
}
|
||||
|
||||
// SessionToolFactory builds per-session tools that close over the live
|
||||
// agent session. Called by the executor after the agent is constructed
|
||||
// but before it runs. See Invocation.SessionToolFactory for the
|
||||
// rationale (static ExtraTools cannot reach the running agent).
|
||||
type SessionToolFactory func(session AgentSession) SessionTools
|
||||
|
||||
// SessionTools carries per-session tools plus optional post-run and
|
||||
// teardown hooks. It replaces legacy agentkit's SessionTools with the same
|
||||
// three-field shape, re-based on majordomo types.
|
||||
type SessionTools struct {
|
||||
// Tools to add to the agent's toolbox for this run only.
|
||||
Tools []llm.Tool
|
||||
|
||||
// PostRun, if set, is called after the agent run completes
|
||||
// (successfully or not). It receives the full run transcript (the
|
||||
// agent Result's Messages — also populated on partial results from
|
||||
// agent.ErrMaxSteps / agent.ErrToolLoop), the agent's text output,
|
||||
// and the run error, so the hook can decide whether to attempt
|
||||
// artifact production on partial success (e.g. scaddy ships the
|
||||
// latest SCAD even when the step budget ran out). The returned
|
||||
// PostRunResult is attached to the executor's run result. Errors
|
||||
// inside PostRun must be handled by the hook itself — the executor
|
||||
// logs a nil return but never fails the run over it; the agent's
|
||||
// output is the source of truth.
|
||||
//
|
||||
// Why a transcript slice (vs the live agent): the consumers only
|
||||
// ever read the message history (thought-chain transcripts); the
|
||||
// majordomo agent exposes that on Result, not on the Agent.
|
||||
PostRun func(ctx context.Context, transcript []llm.Message, output string, runErr error) *PostRunResult
|
||||
|
||||
// Cleanup, if set, is deferred by the executor immediately after
|
||||
// the factory returns. Called even if the run fails or PostRun
|
||||
// panics. Use for temp directory removal, closing file handles,
|
||||
// etc.
|
||||
Cleanup func()
|
||||
}
|
||||
|
||||
// PostRunResult carries artifacts produced by the PostRun hook.
|
||||
// Attached to the executor's run result so callers (Discord command
|
||||
// handlers, HTTP API responses) can inspect and deliver the artifacts.
|
||||
//
|
||||
// Why a separate struct (vs returning artifacts inline): post-
|
||||
// processing may produce multiple typed artifacts (PNGs, STLs, SCAD
|
||||
// source) that the delivery layer classifies and routes differently.
|
||||
// A flat []Artifact + arbitrary Metadata covers the known use cases
|
||||
// without over-specifying the shape.
|
||||
type PostRunResult struct {
|
||||
// Artifacts are files produced during post-processing
|
||||
// (e.g., rendered PNGs, STL files, SCAD source).
|
||||
Artifacts []Artifact
|
||||
|
||||
// Metadata is arbitrary key-value data the delivery layer can
|
||||
// use for formatting (e.g., iteration count, model name, notes).
|
||||
Metadata map[string]any
|
||||
}
|
||||
|
||||
// Artifact is a named binary blob produced by post-run processing.
|
||||
//
|
||||
// Why: the delivery layer needs name + type + bytes to classify
|
||||
// each artifact (PNG → embed image, STL → filetransfer upload,
|
||||
// SCAD → paste upload). A struct with these three fields is the
|
||||
// minimal viable description.
|
||||
type Artifact struct {
|
||||
Name string // e.g., "model.stl", "preview_iso.png"
|
||||
MimeType string // e.g., "model/stl", "image/png"
|
||||
Data []byte
|
||||
}
|
||||
Reference in New Issue
Block a user