kiro: wire session CWD through to EnvState; o: add new command
- backend: add CWD field to GenerationParams for environment state - kiro: pass session CWD to kiroCurrentEnvState instead of hardcoded '/' - agent/runtime: set GenParams.CWD from session cwd in BuildRuntime - o new: create sessions and agents via 9P filesystem - o prompt: support piped stdin for non-interactive use
This commit is contained in:
parent
fbe8059cf5
commit
46524d37dd
|
|
@ -174,6 +174,7 @@ func BuildRuntime(cfg *AgentConfig, srv *toolsrv.Conn, cwd string, env []string,
|
|||
genParams = cfg.GenerationParams
|
||||
maxSteps = cfg.MaxSteps
|
||||
}
|
||||
genParams.CWD = cwd
|
||||
|
||||
exec := func(ctx context.Context, name string, args json.RawMessage) (string, []backend.ContentBlock, error) {
|
||||
if srv == nil {
|
||||
|
|
|
|||
|
|
@ -140,6 +140,10 @@ type GenerationParams struct {
|
|||
IncludeReasoning *bool `json:"includeReasoning,omitempty"`
|
||||
ResponseFormat string `json:"responseFormat,omitempty"`
|
||||
Stop []string `json:"stop,omitempty"`
|
||||
|
||||
// Environment state for backends that support it (e.g., Kiro).
|
||||
// These are passed through to the backend API but not used for sampling.
|
||||
CWD string `json:"-"` // Current working directory
|
||||
}
|
||||
|
||||
// Backend is the interface all LLM providers must implement.
|
||||
|
|
|
|||
|
|
@ -315,7 +315,7 @@ func buildKiroRequest(model string, messages []Message, tools []Tool, profileARN
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
current = kiroChatMessage{UserInputMessage: encodeKiroUserMessage(messages[len(messages)-1], model, encodedTools, nil, true)}
|
||||
current = kiroChatMessage{UserInputMessage: encodeKiroUserMessage(messages[len(messages)-1], model, encodedTools, nil, params.CWD)}
|
||||
|
||||
case "tool":
|
||||
// Find the last non-tool message.
|
||||
|
|
@ -328,7 +328,7 @@ func buildKiroRequest(model string, messages []Message, tools []Tool, profileARN
|
|||
return nil, err
|
||||
}
|
||||
toolResults, images := encodeKiroToolResults(messages[cutoff+1:])
|
||||
current = kiroChatMessage{UserInputMessage: emptyKiroUserMessage(model, encodedTools, toolResults, images, true)}
|
||||
current = kiroChatMessage{UserInputMessage: emptyKiroUserMessage(model, encodedTools, toolResults, images, params.CWD)}
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf("last message role %q is not supported (expected user, system, or tool)", lastRole)
|
||||
|
|
@ -363,7 +363,7 @@ func encodeKiroHistory(messages []Message) ([]kiroChatMessage, error) {
|
|||
m := messages[i]
|
||||
switch strings.ToLower(strings.TrimSpace(m.Role)) {
|
||||
case "user", "system":
|
||||
out = append(out, kiroChatMessage{UserInputMessage: encodeKiroUserMessage(m, "", nil, nil, false)})
|
||||
out = append(out, kiroChatMessage{UserInputMessage: encodeKiroUserMessage(m, "", nil, nil, "")})
|
||||
case "assistant":
|
||||
out = append(out, kiroChatMessage{AssistantResponseMessage: encodeKiroAssistantMessage(m)})
|
||||
case "tool":
|
||||
|
|
@ -373,13 +373,13 @@ func encodeKiroHistory(messages []Message) ([]kiroChatMessage, error) {
|
|||
i++
|
||||
}
|
||||
results, imgs := encodeKiroToolResults(messages[start : i+1])
|
||||
out = append(out, kiroChatMessage{UserInputMessage: emptyKiroUserMessage("", nil, results, imgs, false)})
|
||||
out = append(out, kiroChatMessage{UserInputMessage: emptyKiroUserMessage("", nil, results, imgs, "")})
|
||||
}
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func encodeKiroUserMessage(m Message, modelID string, tools []kiroTool, toolResults []kiroToolResult, includeEnvState bool) *kiroUserInputMessage {
|
||||
func encodeKiroUserMessage(m Message, modelID string, tools []kiroTool, toolResults []kiroToolResult, cwd string) *kiroUserInputMessage {
|
||||
msg := &kiroUserInputMessage{
|
||||
Content: kiroExtractTextContent(m),
|
||||
Origin: kiroDefaultOrigin,
|
||||
|
|
@ -393,8 +393,8 @@ func encodeKiroUserMessage(m Message, modelID string, tools []kiroTool, toolResu
|
|||
if len(toolResults) > 0 {
|
||||
ctx.ToolResults = toolResults
|
||||
}
|
||||
if includeEnvState {
|
||||
ctx.EnvState = kiroCurrentEnvState()
|
||||
if cwd != "" {
|
||||
ctx.EnvState = kiroCurrentEnvState(cwd)
|
||||
}
|
||||
if len(ctx.Tools) > 0 || len(ctx.ToolResults) > 0 || ctx.EnvState != nil {
|
||||
msg.UserInputMessageContext = ctx
|
||||
|
|
@ -402,7 +402,7 @@ func encodeKiroUserMessage(m Message, modelID string, tools []kiroTool, toolResu
|
|||
return msg
|
||||
}
|
||||
|
||||
func emptyKiroUserMessage(modelID string, tools []kiroTool, toolResults []kiroToolResult, images []kiroImageBlock, includeEnvState bool) *kiroUserInputMessage {
|
||||
func emptyKiroUserMessage(modelID string, tools []kiroTool, toolResults []kiroToolResult, images []kiroImageBlock, cwd string) *kiroUserInputMessage {
|
||||
msg := &kiroUserInputMessage{
|
||||
Content: "",
|
||||
Origin: kiroDefaultOrigin,
|
||||
|
|
@ -416,8 +416,8 @@ func emptyKiroUserMessage(modelID string, tools []kiroTool, toolResults []kiroTo
|
|||
if len(toolResults) > 0 {
|
||||
ctx.ToolResults = toolResults
|
||||
}
|
||||
if includeEnvState {
|
||||
ctx.EnvState = kiroCurrentEnvState()
|
||||
if cwd != "" {
|
||||
ctx.EnvState = kiroCurrentEnvState(cwd)
|
||||
}
|
||||
if len(ctx.Tools) > 0 || len(ctx.ToolResults) > 0 || ctx.EnvState != nil {
|
||||
msg.UserInputMessageContext = ctx
|
||||
|
|
@ -564,10 +564,10 @@ func kiroExtractImages(m Message) []kiroImageBlock {
|
|||
return images
|
||||
}
|
||||
|
||||
func kiroCurrentEnvState() *kiroEnvState {
|
||||
func kiroCurrentEnvState(cwd string) *kiroEnvState {
|
||||
return &kiroEnvState{
|
||||
OperatingSystem: runtime.GOOS,
|
||||
CurrentWorkingDirectory: "/",
|
||||
CurrentWorkingDirectory: cwd,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
# read <path> Read a file (-l to loop)
|
||||
# write <path> [data] Write to a file (args or stdin)
|
||||
# ls [path] List namespace entries
|
||||
# new <session> [agent] [cwd] Create a new session or agent
|
||||
# ctl <command> Send a control command (stop, compact, kill, ...)
|
||||
# prompt Interactive REPL for submitting prompts (requires agent)
|
||||
# chatstream Stream chat output (requires agent)
|
||||
|
|
@ -280,6 +281,13 @@ cmd_prompt() {
|
|||
fi
|
||||
local path="session/$s/agent/$a"
|
||||
|
||||
# If stdin is not a terminal, read it all and send as a single prompt
|
||||
if [[ ! -t 0 ]]; then
|
||||
cat | ollie-9p write "$path/prompt"
|
||||
return
|
||||
fi
|
||||
|
||||
# Interactive REPL mode
|
||||
echo "[$s/$a]"
|
||||
echo "Type . on a blank line to send, Ctrl+D to exit."
|
||||
echo "/ prefix runs ctl: /stop, /compact, /model X, /inject X"
|
||||
|
|
@ -386,6 +394,30 @@ cmd_env() {
|
|||
fi
|
||||
}
|
||||
|
||||
cmd_new() {
|
||||
if [[ $# -lt 1 ]]; then
|
||||
echo "usage: o new <session> [agent] [cwd]" >&2
|
||||
echo " o new myproject Create a new session named 'myproject'" >&2
|
||||
echo " o new myproject coding /path Create agent 'coding' in session 'myproject'" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
local session_name="$1"
|
||||
shift
|
||||
|
||||
if [[ $# -eq 0 ]]; then
|
||||
# Create new session
|
||||
printf 'name=%s\ncwd=%s\n' "$session_name" "$PWD" | ollie-9p write "session/new"
|
||||
echo "created session: $session_name"
|
||||
else
|
||||
# Create new agent in existing session
|
||||
local agent_name="$1"
|
||||
local agent_cwd="${2:-$PWD}"
|
||||
printf 'name=%s\ncwd=%s\n' "$agent_name" "$agent_cwd" | ollie-9p write "session/$session_name/agent/new"
|
||||
echo "created agent: $session_name/$agent_name"
|
||||
fi
|
||||
}
|
||||
|
||||
cmd_tui() {
|
||||
local tmux_session="${session:-}"
|
||||
local s a
|
||||
|
|
@ -483,6 +515,9 @@ Commands:
|
|||
write <path> [data] Write to a file (args or stdin)
|
||||
ls [path] List namespace entries
|
||||
|
||||
new <session> Create a new session
|
||||
new <session> <agent> [cwd] Create an agent in a session
|
||||
|
||||
generate <prompt> One-shot generation (no session needed)
|
||||
|
||||
ctl <cmd> [args] Send control command (rdwr: gets response)
|
||||
|
|
@ -506,6 +541,8 @@ Examples:
|
|||
o read -l statewait # block-loop on state changes
|
||||
o read chat # stream chat (filtered text)
|
||||
o read chat.raw # stream chat (full markup)
|
||||
o new myproject # create session 'myproject' in current dir
|
||||
o new myproject coding # create agent 'coding' in 'myproject'
|
||||
o generate "explain monads" # one-shot, no session
|
||||
o ctl stop # stop agent (uses $session/$agent)
|
||||
o ctl kill mysession # kill session by name
|
||||
|
|
@ -529,6 +566,7 @@ case "$subcmd" in
|
|||
ctl) cmd_ctl "$@" ;;
|
||||
prompt) cmd_prompt "$@" ;;
|
||||
log) cmd_log "$@" ;;
|
||||
new) cmd_new "$@" ;;
|
||||
tui) cmd_tui "$@" ;;
|
||||
env) cmd_env "$@" ;;
|
||||
help|-h|--help) cmd_help ;;
|
||||
|
|
|
|||
Loading…
Reference in New Issue