Skip to content

experiment(cli): evaluate AgentENV-owned completion hook - #164

Open
NickNYU wants to merge 2 commits into
kvcache-ai:mainfrom
NickNYU:experiment/completion-agentenv-hook
Open

experiment(cli): evaluate AgentENV-owned completion hook#164
NickNYU wants to merge 2 commits into
kvcache-ai:mainfrom
NickNYU:experiment/completion-agentenv-hook

Conversation

@NickNYU

@NickNYU NickNYU commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Summary

This is the second parallel experiment for #37. It keeps the static completion generator and appends Bash/Zsh/Fish adapters that call an AgentENV-owned internal protocol: aenv __complete.

What it adds

  • Hidden aenv __complete --index ... -- <shell words...> entry point.
  • Dynamic candidates backed by the existing sandbox list API.
  • State-aware candidates for running, paused, and active sandbox IDs.
  • Short completion-specific network timeouts and silent failure behavior.
  • Focused tests and a design note.

Trade-off

The protocol is owned by AgentENV and does not depend on clap_complete unstable-dynamic, but AgentENV must maintain cursor parsing plus three shell adapters. Clap still includes the hidden hook in generated command metadata, which is a small maintenance detail to discuss. The companion PR evaluates the upstream unstable dynamic engine. These are alternatives; please review and choose one direction rather than merging both.

Verification

  • cargo fmt --all
  • cargo check -p aenv --bin aenv
  • focused completion tests (15 passed)
  • generated Bash script and no-credential hook invocation

nzhu added 2 commits August 8, 2026 11:45
Captures the sandbox-ID-only design, its short-timeout failure behavior, shell-adapter boundary, and verification plan before implementation begins.

Constraint: PR kvcache-ai#89 provides static completion but no stable dynamic hook\nRejected: Use clap_complete unstable-dynamic API | maintainer identified the surface as unstable\nConfidence: high\nScope-risk: narrow\nDirective: Keep dynamic lookup silent and separate from normal CLI timeouts\nTested: Design self-review and git diff --check\nNot-tested: CLI behavior; implementation has not started
Evaluate a stable AgentENV-owned completion protocol alongside the static shell generator, using a hidden command for dynamic sandbox IDs.

Constraint: The experiment must preserve the existing clap-generated scripts and keep completion failures silent
Rejected: Depend on clap_complete unstable-dynamic | leaves the protocol and shell adapter contract outside AgentENV
Confidence: medium
Scope-risk: moderate
Directive: Treat __complete as an internal protocol and coordinate any future changes with all three shell adapters
Tested: cargo fmt --all; cargo check -p aenv --bin aenv; focused completion tests (15 passed); generated Bash script; no-credential hook invocation
Not-tested: Full workspace test suite and live API-backed candidate lookup
@github-actions

github-actions Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

🔍 OpenCodeReview found 5 issue(s) in this PR.

  • ✅ Successfully posted inline: 5 comment(s)

Comment on lines +101 to +104
"pause" | "exec" | "upload" | "download" | "timeout" if index == 2 => {
SandboxStateFilter::Running
}
"resume" if index == 2 => SandboxStateFilter::Paused,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[bug · medium]
The fixed cursor index assumes the sandbox ID immediately follows the subcommand, but Clap permits options before positional arguments. For example, the documented aenv upload --user app <TAB>, aenv download --force <TAB>, and aenv resume --timeout 300 <TAB> forms reach indices greater than 2 and receive no dynamic candidates. Determine the active positional after skipping each command's options (including option values), rather than keying solely on index == 2.

Comment on lines +109 to +112
"snapshot"
if words.get(2).map(String::as_str) == Some("list")
&& index > 3
&& words[..index].last().map(String::as_str) == Some("--sandbox-id") =>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[bug · medium]
This excludes the declared visible alias snapshot ls, even though the command's own examples use aenv snapshot ls --sandbox-id <sandbox-id>. Accept both list and ls here so the documented form receives sandbox completion.

Comment on lines +112 to +115
&& words[..index].last().map(String::as_str) == Some("--sandbox-id") =>
{
SandboxStateFilter::Active
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[bug · medium]
Only the separated --sandbox-id <value> form is recognized. Clap also accepts --sandbox-id=<value>, for which the current token contains the option and prefix and this branch returns None (notably in shells that preserve = in the word). Handle the attached form and emit candidates with the --sandbox-id= prefix so completion does not replace the entire option token with a bare ID.

fi
_aenv "$@"
}
complete -o nospace -o bashdefault -o nosort -F _aenv_dynamic aenv

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[bug · medium]
-o nospace applies to every result from this wrapper, including the fallback _aenv static completions. Consequently Bash no longer appends a space after completing ordinary subcommands, options, or their values, and the next token can be concatenated to the completion. Preserve the options from the generated _aenv registration (or conditionally manage spacing only for dynamic results) instead of globally enabling nospace.

Comment on lines +183 to +185
set -l words (commandline -opc)
set -a words (commandline -ct)
command aenv __complete --index (math (count $words) - 1) -- $words 2>/dev/null

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[bug · medium]
When the cursor is immediately after a space, commandline -ct is empty and its unquoted command substitution appends no array element. The calculated index then points at the preceding subcommand (for example pause) rather than an empty sandbox argument, so Fish offers no IDs until the user types a prefix. Store the current token separately and append it as a quoted value so the empty element is preserved.

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