agentruncli

package
v0.0.201 Latest Latest
Warning

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

Go to latest
Published: Sep 20, 2026 License: MIT Imports: 49 Imported by: 0

README

DSH Web browser runner

agent-run run --agent-runner dsh-web hands a task to an already-running DeepSeek Harness Web server through dsh web open. The dsh executable must be on PATH and support --prompt, --prompt-file, and --no-submit. The runner does not start a server.

# Open an editable draft without starting an agent turn.
agent-run run --agent-runner dsh-web --dir /path/to/project \
  --open --no-submit '/brainstorm Implement the task'

# Submit a long prompt from a file and open the session.
agent-run run --agent-runner dsh-web --dir /path/to/project \
  --open --prompt-file /path/to/task.txt

# Pick the browser for the handoff.
agent-run run --agent-runner dsh-web --dir /path/to/project \
  --open --browser brave 'Implement the task'

# Submit without opening a browser.
agent-run run --agent-runner dsh-web --dir /path/to/project 'Implement the task'

Options and ownership

The browser runner accepts a positional prompt or --prompt-file FILE, plus --dir, --browser NAME, --open, --no-submit, and -v/--verbose. Inline and file prompts are mutually exclusive. --open opens the browser; omitting it forwards --no-open. --no-submit saves a draft and is also supported without --open. The default workspace is the caller's current directory.

--browser NAME (dsh-web only) forwards the browser to dsh web open as --browser NAME, for example brave or firefox; DSH owns the valid browser names, and an empty value forwards no browser flag. With any other --agent-runner, --browser fails before dispatch or launch: agent-run: --browser requires --agent-runner dsh-web. There is no config or persisted setting; the flag applies per invocation.

Prompt text is passed as one argument without shell evaluation or trimming. File paths are resolved against the caller's working directory and forwarded as --prompt-file; contents never expand into the child command line. DSH reads and validates the file, including UTF-8 and empty-input checks, before creating its session. Agent-run does not modify or delete the file.

DSH owns the session identity, transcript, draft, prompt admission, browser URL, and subsequent execution. Agent-run waits only for the launch command to finish and forwards its stdout/stderr. Success means the session handoff succeeded, not that the task completed. Launch failures return an error.

This is a CLI launch adapter, not a PTY provider or streaming Ask runner. The runner consumes --dir, --prompt-file, --browser NAME, --open, --no-submit, and -v/--verbose silently. Every other parsed run flag is ignored with one stderr line per flag, in command-line order: notice: dsh-web ignores --color; it only launches a DSH Web session. The notice: prefix renders gray when stderr is a terminal and NO_COLOR is unset or empty, and plain otherwise. Unregistered flags still fail at flag parse, and the --prompt-file/positional mutual exclusion still fails the run.

Agent-run session IDs, resume/send/auto-send-or-resume, JSON event streaming, model overrides, custom runner binaries/config homes, terminal flags, color, and child environment flags are meaningless for a one-shot handoff; use DSH itself for session management and server configuration. It is not a runner for the agent-run Web API or the session-oriented agentrunapi.AutoSendOrResume API.

wrk

With a compatible wrk installation:

wrk project -t 'Implement the task' --open-in-agent --agent-runner dsh-web

wrk supplies /brainstorm ${task} and the browser defaults --open --no-submit, without --color or --session-id-from-prompt. Long tasks remain file-backed through the complete handoff.

Tests

go test ./pkgs/agentruncli -run TestDSHWeb -count=1

The CLI test uses a temporary dsh executable to capture exact arguments and simulate launch failure. It makes no browser, server, or model calls and checks that no agent-run session storage is created. Actual draft rendering and prompt admission are owned by DSH's integration tests.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AppendEventBusFlags added in v0.0.112

func AppendEventBusFlags(args []string, url, token string) []string

AppendEventBusFlags appends --event-bus-url / --event-bus-token to args when URL is non-empty. Empty URL returns a copy of args unchanged (no flags added). Token is appended only when non-empty.

func ClearProcessHostDriver added in v0.0.72

func ClearProcessHostDriver()

ClearProcessHostDriver clears the process default (tests).

func Handle

func Handle(args []string) error

Handle is the full agent-run CLI entrypoint for args after the program name (os.Args[1:]). Same command surface as today's cmd/agent-run: web, run, resume, attach, send, msg, snapshot, watch, sessions, status, kill, tty, pty, top-level help, --agent-runner, and internal serve/stub paths. Success (including help) returns nil; failures return an error for the thin main to print and exit 1.

func IdlePolicyPath added in v0.0.135

func IdlePolicyPath(home, sessionID string) string

IdlePolicyPath is $home/sessions/<sessionID>/idle-policy.json.

func IdleWatchSchedule added in v0.0.138

func IdleWatchSchedule(timeout time.Duration) (first, gap time.Duration)

IdleWatchSchedule is the serve-loop sleep plan (delegates to idle.Schedule).

func LoadEnvFile added in v0.0.150

func LoadEnvFile(path string) ([]string, error)

LoadEnvFile reads KEY=VALUE lines from path for --env-file delivery. Empty / whitespace-only path → (nil, nil). Blank lines and # comments are skipped. Each non-comment line must pass validateEnvFlag.

func MergeEnvEntries added in v0.0.150

func MergeEnvEntries(fileEntries, cliEntries []string) []string

MergeEnvEntries concatenates file then CLI entries (CLI last-win per key at child apply time). Empty inputs stay nil.

func NotifyOnOpenPath added in v0.0.112

func NotifyOnOpenPath(kind string, opts EventBusOpts, sessionID, runner, workspace string)

NotifyOnOpenPath dispatches open-path publish policy:

  • "new-terminal" — after successful ForceNew / open-profile → NotifyTTYStarted once
  • "send" — live send path → no-op here (library OnTTYRestarted handles follow-up)

func NotifyTTYRestarted added in v0.0.113

func NotifyTTYRestarted(opts EventBusOpts, sessionID, runner, workspace, reason string)

NotifyTTYRestarted publishes type=agent.tty.restarted source=agent-run with payload {session_id, runner, workspace, reason}. reason should be followup|resume. No AlreadyNotified guard — each restart may re-open local attach.

func NotifyTTYStarted added in v0.0.112

func NotifyTTYStarted(opts EventBusOpts, sessionID, runner, workspace string)

NotifyTTYStarted publishes type=agent.tty.started source=agent-run with payload {session_id, runner, workspace, reason}. reason defaults to "new". Best-effort: empty URL is a no-op; publish errors write a "warning:" line. When AlreadyNotified is non-nil and *true, skips; after a non-empty-URL publish attempt, sets *true (empty URL does not set).

func NotifyTTYStartedReason added in v0.0.113

func NotifyTTYStartedReason(opts EventBusOpts, sessionID, runner, workspace, reason string)

NotifyTTYStartedReason is NotifyTTYStarted with an explicit reason field.

func ParseRunIdle added in v0.0.135

func ParseRunIdle(exitOnIdle bool, timeoutRaw string) (enabled bool, d time.Duration, err error)

ParseRunIdle interprets launch-time idle flags after the CLI reads --exit-on-idle and the raw --idle-timeout string (empty = omitted). Invalid raw → error before NormalizeIdle. !exitOnIdle → enabled=false, no error even if timeout parses (including 2s). Does not start a TTY.

func ResolveRunPrompt added in v0.0.122

func ResolveRunPrompt(positionalPrompt, promptFile string) (string, error)

ResolveRunPrompt resolves agent-run run's initial prompt from a positional string and optional --prompt-file path. Exported for L2 pure doctests; runHeadless uses the same policy after flag parse.

Policy:

  • if promptFile non-empty (TrimSpace) and positional non-empty (TrimSpace) → error (mutually exclusive)
  • if promptFile non-empty → read file UTF-8 body, TrimSpace, return
  • else return TrimSpace(positional)
  • missing/unreadable path → non-nil error

func RunFocus added in v0.0.89

func RunFocus(args []string, stdout, stderr io.Writer) error

RunFocus implements `agent-run focus` with injectable writers for L2 tests. CLI surface: focus <session-id> [--index N] [--dry-run] [--session-id ID] [-h]

func RunHelpText added in v0.0.112

func RunHelpText() string

RunHelpText returns the `agent-run run -h` help body (same text flags.Help uses). Always ends with a trailing newline.

func RunLogs added in v0.0.145

func RunLogs(args []string, store agentstorage.Store, stdout io.Writer) error

RunLogs implements `agent-run logs` with injected storage and output.

func RunSessions added in v0.0.136

func RunSessions(args []string, store agentstorage.Store, stdout, stderr io.Writer) error

RunSessions implements `agent-run sessions` with an injected store and writers. Args are the tokens after the `sessions` command name.

func SetProcessHostDriver added in v0.0.72

func SetProcessHostDriver(d agentdriver.Driver)

SetProcessHostDriver sets the default host Driver for this process when Opts leave Driver zero. Used by embedding hosts (spl agent-run); bare agent-run leaves this unset so serve falls back to agentdriver.DefaultSelf.

func WireOnTTYRestarted added in v0.0.113

func WireOnTTYRestarted(opts EventBusOpts) func(agentrunapi.TTYStartedInfo)

WireOnTTYRestarted returns a callback for agentrunapi.Opts.OnTTYRestarted. Empty URL → nil. Does not share AlreadyNotified with started.

func WireOnTTYStarted added in v0.0.113

func WireOnTTYStarted(opts EventBusOpts) func(agentrunapi.TTYStartedInfo)

WireOnTTYStarted returns a callback for agentrunapi.Opts.OnTTYStarted. Empty URL → nil. Uses info.Reason when set, else "new".

func WriteIdlePolicy added in v0.0.135

func WriteIdlePolicy(home, sessionID string, p IdlePolicy) error

WriteIdlePolicy writes compact JSON. Zero timeout + ExitOnIdle → 10m.

Types

type EventBusOpts added in v0.0.112

type EventBusOpts struct {
	URL   string
	Token string
	// PublishHook, when set, replaces the production HTTP publisher (tests).
	// Signature matches wire type/source + payload only (no eventbus import in harness).
	PublishHook func(ctx context.Context, eventType, source string, payload json.RawMessage) error
	// WarnWriter receives best-effort failure lines (prefix "warning:"). Nil → os.Stderr.
	WarnWriter io.Writer
	// AlreadyNotified, when non-nil, is an at-most-once guard for agent.tty.started only
	// (ForceNew NotifyOnOpenPath + library WireOnTTYStarted). Never used for restarted.
	// If *true, NotifyTTYStarted skips. After publishing with a non-empty URL, sets *true.
	// Empty URL does not set the flag.
	AlreadyNotified *bool
}

EventBusOpts configures best-effort publish of agent.tty.* events. Empty URL disables publish (no HTTP, no warning). PublishHook is the L2 inject seam; when nil, production uses eventbus.NewPublisher.

type FrontendSource added in v0.0.71

type FrontendSource string

FrontendSource names where the SPA tree came from.

const (
	FrontendSourceEmbed    FrontendSource = "embed"
	FrontendSourceCache    FrontendSource = "cache"
	FrontendSourceDownload FrontendSource = "download"
	FrontendSourceA1       FrontendSource = "a1"
)

type IdlePolicy added in v0.0.135

type IdlePolicy = agentstorage.IdlePolicy

IdlePolicy is the session-dir idle-exit file (not meta.json).

func ReadIdlePolicy added in v0.0.135

func ReadIdlePolicy(home, sessionID string) (p IdlePolicy, found bool, err error)

ReadIdlePolicy loads idle-policy.json. Missing file → found=false, err=nil.

type ResolvedFrontend added in v0.0.71

type ResolvedFrontend struct {
	FS       fs.FS
	Source   FrontendSource
	CacheDir string
	// EnsureErr is set when download was attempted and failed (A1 fallback).
	EnsureErr error
}

ResolvedFrontend is the result of resolveAgentRunFrontend. When Source is FrontendSourceA1, FS is nil and callers should serve the A1 shell.

type TakeoverDeps added in v0.0.112

type TakeoverDeps struct {
	ListProcs func() []procresolve.Proc
	Lsof      func(pid int) []string
	Kill      func(pid int, sig syscall.Signal) error
	WaitDead  func(pid int, timeout time.Duration) bool
	OpenIterm func(dir string, followUp string) error
	// HooksActive is true when AGENT_RUN_TAKEOVER_TEST_HOOKS was loaded (synthetic PIDs).
	HooksActive bool
	// ProcsSnapshot is the full ListProcs result used for ancestry walks.
	ProcsSnapshot []procresolve.Proc
	// KillLog path from hooks file (may be empty).
	KillLog string
}

TakeoverDeps injects process/kill/iTerm behavior for tests. When nil fields are present, production defaults are used unless hooks env is set.

Jump to

Keyboard shortcuts

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