Skip to content

Add a file mission input type#112

Open
mlund01 wants to merge 1 commit into
mainfrom
feature/file-inputs
Open

Add a file mission input type#112
mlund01 wants to merge 1 commit into
mainfrom
feature/file-inputs

Conversation

@mlund01

@mlund01 mlund01 commented Jun 13, 2026

Copy link
Copy Markdown
Owner

Implements #111.

Summary

Adds a new file mission input type. A mission can declare an input as a file, and the caller supplies it at run time as either a project-relative path or a base64 {filename, content_base64} upload. The file is exposed to agents as a read-only, text-only input.<name> slot — a runtime-supplied, single-file analog of a packet — read via the existing file_read / file_grep / file_search tools, rather than inlined into objectives.

mission "analyze" {
  inputs = {
    document = file("The document to analyze", true)
  }
  task "summarize" {
    objective = "Summarize the contents of slot input.document"
  }
}
squadron mission analyze -c ./config --input document=./report.md

Design

A file input reuses the packet slot machinery instead of inventing a parallel one. Both supply forms flow through the existing map[string]string input plumbing and converge on the same materialized slot:

  • Path — resolved relative to the project root and containment-checked (files outside the project must use the base64 form). Copied in.
  • Base64 upload — for callers with no host path (command center, webhooks, MCP run_mission). Decoded in, with the filename sanitized to a bare basename.

Each input is materialized into its own per-run directory under <squadron_home>/inputs/<mission>/<run_id>/<name>/, so the slot has no sibling leak without any pinned-file machinery. Single-file size is capped at 10 MB. Staging reuses the scratchpad sidecar + sweep model (SweepExpiredInputs, sharing a sweepExpiredRuns core). Raw values are persisted and an already-staged dir is reused, so resume works without the original source path.

File inputs are always required and reject default / protected. They interpolate into objectives as their slot name (input.<name>), not their contents.

The MCP host's run_mission now JSON-encodes structured input values instead of fmt.Sprintf("%v", …), so a base64 envelope (and any list/object/map input) round-trips intact — fixing a latent bug for structured inputs generally.

Tests

go build, go vet, and the full go test ./... pass. New coverage: materialization (both forms), filename sanitization, path-escape rejection, bad base64, size cap, missing-required, resume reuse, read-only/text-only slot enforcement, the input sweep, plus config-layer schema-parse / validation / ResolveInputValues tests. Also smoke-tested via squadron verify on a real file-input config.

Docs

Updated docs/content/missions/overview.mdx, docs/content/config/functions.mdx, and CLAUDE.md.

🤖 Generated with Claude Code

Add a `file` mission input so a mission can be handed a document to work
on. The file is exposed to agents as a read-only, text-only `input.<name>`
slot — a runtime-supplied, single-file analog of a packet — rather than
inlined into objectives.

Two supply forms, both flowing through the existing map[string]string input
plumbing and converging on the same isolated, materialized slot:
  - path: a project-relative path (CLI / schedule), containment-checked
  - base64: a {filename, content_base64} envelope (command center,
    webhooks, MCP run_mission) for callers with no host path

Each input is materialized into its own per-run directory under
<squadron_home>/inputs/<mission>/<run_id>/<name>/, so the slot has no
sibling leak without pinned-file machinery. Path forms are copied
(10 MB cap); base64 forms are decoded with a sanitized basename. Staging
reuses the scratchpad sidecar + sweep model (SweepExpiredInputs). Raw
values are persisted and already-staged dirs are reused, so resume works
without the original source path.

File inputs are always required and reject default/protected. The MCP
host's run_mission now JSON-encodes structured input values instead of
fmt.Sprintf("%v", ...), so base64 envelopes (and list/object/map inputs)
round-trip intact.

Implements #111.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant