Skip to content

feat(agents): add kiro adapter#135

Closed
yyovil wants to merge 1 commit into
agents/15-kimifrom
agents/16-kiro
Closed

feat(agents): add kiro adapter#135
yyovil wants to merge 1 commit into
agents/15-kimifrom
agents/16-kiro

Conversation

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Jun 6, 2026

Greptile Summary

Adds the Kiro (AWS) agent adapter, following the same structure as the existing copilot and goose adapters: a Plugin struct implementing adapters.Adapter and ports.Agent, workspace-local hook install/uninstall via .kiro/agents/ao.json, an activity state deriver, and registration in both the adapter registry and the activity dispatch table.

  • kiro/hooks.go: Reads and merges into the ao.json agent file using raw-JSON preservation so unmanaged top-level keys survive round-trips; writes atomically via temp-file + rename.
  • kiro/kiro.go: Resolves the kiro-cli binary with platform-aware PATH search (Windows .cmd/.exe fallbacks + well-known install dirs), maps AO permission modes to Kiro's --trust-all-tools / --trust-tools=fs_read,fs_write flags, and exposes --resume-id for session restore.
  • kiro/activity.go: Maps the four managed hook sub-commands (session-start, user-prompt-submit, permission-request, stop) to the corresponding ActivityState values.

Confidence Score: 4/5

Safe to merge after addressing the nil-map panic in hooks.go; all other paths are straightforward additions that follow established patterns.

The readKiroHooks function can return a nil topLevel map when the ao.json file contains bare JSON null — a valid but unusual state that any failed-write or manual edit could produce. GetAgentHooks then panics on the map assignment in writeKiroHooks. A one-line nil guard after the unmarshal call fixes it. Everything else — binary resolution, launch/restore command building, hook idempotency, uninstall, and the wiring registration — looks correct and well-tested.

backend/internal/adapters/agent/kiro/hooks.go — specifically the readKiroHooks function and its interaction with writeKiroHooks when the config file is malformed.

Important Files Changed

Filename Overview
backend/internal/adapters/agent/kiro/hooks.go Hook install/uninstall for .kiro/agents/ao.json with atomic writes and raw-JSON preservation; readKiroHooks can return a nil topLevel when the file contains bare null, leading to a panic in GetAgentHooks.
backend/internal/adapters/agent/kiro/kiro.go Main Kiro adapter: Plugin struct, binary resolution with platform-aware PATH search, launch/restore command building, session info. Well-structured and follows existing adapter patterns.
backend/internal/adapters/agent/kiro/activity.go Activity state deriver mapping AO hook sub-commands to domain states; mirrors the copilot adapter pattern exactly.
backend/internal/adapters/agent/kiro/kiro_test.go Good coverage of launch/restore commands, approval mode flags, hooks install/uninstall/idempotency, and activity state derivation.
backend/internal/adapters/agent/activitydispatch/dispatch.go Registers kiro.DeriveActivityState in the Derivers map under the "kiro" key; consistent with other adapters.
backend/internal/adapters/agent/registry/registry.go Adds kiro.New() to the Constructors() slice; no issues.
backend/internal/daemon/wiring_test.go Adds {domain.HarnessKiro, "kiro"} to the resolver table test; correct and consistent with other harness entries.

Sequence Diagram

sequenceDiagram
    participant AO as AO Daemon
    participant Plugin as kiro.Plugin
    participant FS as .kiro/agents/ao.json
    participant CLI as kiro-cli

    AO->>Plugin: GetAgentHooks(cfg)
    Plugin->>FS: readKiroHooks (preserve unmanaged keys)
    FS-->>Plugin: topLevel + rawHooks
    Plugin->>Plugin: merge kiroManagedHooks (deduplicate)
    Plugin->>FS: writeKiroHooks (atomic temp+rename)

    AO->>Plugin: GetLaunchCommand(cfg)
    Plugin->>Plugin: kiroBinary() [cached resolve]
    Plugin-->>AO: [kiro-cli, chat, --no-interactive, (trust flags), --, prompt]
    AO->>CLI: exec

    CLI->>AO: hook: ao hooks kiro session-start
    AO->>AO: DeriveActivityState("session-start") → Active
    CLI->>AO: hook: ao hooks kiro permission-request
    AO->>AO: DeriveActivityState("permission-request") → WaitingInput
    CLI->>AO: hook: ao hooks kiro stop
    AO->>AO: DeriveActivityState("stop") → Idle

    AO->>Plugin: GetRestoreCommand(cfg)
    Plugin-->>AO: [kiro-cli, chat, --no-interactive, --resume-id, id, (trust flags)]
Loading

Reviews (2): Last reviewed commit: "feat(agents): add kiro adapter" | Re-trigger Greptile

Registers the kiro harness, stacked on the agent platform. Includes its own activity deriver.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Comment on lines +196 to +198
if err := json.Unmarshal(data, &topLevel); err != nil {
return nil, nil, fmt.Errorf("parse %s: %w", hooksPath, err)
}
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.

P1 readKiroHooks can return a nil topLevel map when the ao.json file contains the literal JSON value null. json.Unmarshal([]byte("null"), &topLevel) succeeds in Go but silently sets topLevel to nil. A subsequent call to GetAgentHooks — which adds entries to rawHooks and then reaches topLevel["hooks"] = hooksJSON in writeKiroHooks — will panic with "assignment to entry in nil map". This can be triggered by any tool (including a failed earlier write) that leaves the config file as bare null.

Suggested change
if err := json.Unmarshal(data, &topLevel); err != nil {
return nil, nil, fmt.Errorf("parse %s: %w", hooksPath, err)
}
if err := json.Unmarshal(data, &topLevel); err != nil {
return nil, nil, fmt.Errorf("parse %s: %w", hooksPath, err)
}
if topLevel == nil {
topLevel = map[string]json.RawMessage{}
}

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.

2 participants