Skip to content

feat(agent): send to and list sessions by the agent's own session name - #29

Merged
tak-bro merged 7 commits into
mainfrom
feat/agent-target-handle
Oct 31, 2026
Merged

tak-bro merged 7 commits into
mainfrom
feat/agent-target-handle

Conversation

@tak-bro

@tak-bro tak-bro commented Oct 31, 2026 •

Copy link
Copy Markdown
Member

Summary

다른 세션의 에이전트가 사용자가 부르는 Claude Code 세션 이름(ko-qmd-70 같은 cwd 기반 derived 이름, /rename 이름)으로 다른 머신의 세션에 hwip_agent_send 할 수 있게 한다. 지금은 리스너가 derived 이름을 서버에 올리지 않아 UNKNOWN_TARGET 이 난다. 보내기 전에 전 머신 세션을 조회하는 hwip_agent_list {all:true} · hwip agent list --all 도 더한다.

이 변경은 레포 4개에 걸친다 — 배포 순서 server → cli → mcp-server(plugin 은 문서). 새 필드는 양쪽 다 optional 이라 어느 순서로 가도 깨지지 않지만, server 가 먼저여야 handle 이 저장된다.

관련 PR (배포 순서): 1. hwipit/hwip#662 (server) → 2. #29 → 3. hwipit/mcp-server#7 · 문서 hwipit/plugin#5

Changes

  • src/remote-agents.ts — detectClaudeSessionHandle: Claude 세션 레코드의 이름(derived 포함)을 그대로 handle 로. claude 행에 resolveSessionHandle
  • src/listener.ts — 세션 행에 providerSessionHandle, sessionsFingerprint 에 포함(handle 만 바뀌어도 바로 리포트)
  • src/agent-target.ts — handle 매칭, AMBIGUOUS 후보에 handle·state, 공용 listAgentTargets
  • src/agent-list.ts · src/cli.ts · src/args.ts — hwip agent list --all [--json](API 키 필요, 실패 시 LIST_FAILED exit 1). 표의 모든 칸에서 제어문자·bidi·zero-width 문자를 지움
  • src/agent-read.ts — 후보에 handle·state, --all 거부
  • src/usage.ts · README.md — 사용법

How to Test

npx tsc --noEmit && npx vitest run --exclude src/http-proxy.test.ts
hwip agent list --all

Evidence

agent-target.test.ts 의 handle 매칭 테스트: 구현 전 UNKNOWN_TARGET 으로 red → green. --turns 거부·bidi 제거 테스트는 조건을 빼는 mutation 으로 red 확인.

Risks

  • src/http-proxy.test.ts 8건은 main 에서도 로컬 프록시 환경 때문에 실패 — 이 PR 과 무관해 verify 에서 제외했다.
  • 미룸: describeCandidate 에러 문구의 원격 label·alias escape(기존 경로, 이번에 더한 handle·state 는 서버가 정규화).

Merge danger

Door: two-way · Blast radius: cli agent commands
agent list JSON 행에 handle 필드 추가, agent read·agent send 가 --all(send 는 --turns 도) 를 exit 2 로 거부 — 전에는 조용히 무시했다.

Alternatives considered

  • providerSessionName 에 derived 이름도 싣기 — 앱 표시 정책(auto-name 숨김)을 깨서 버림. 매칭 전용 필드를 따로 둔다(D1, 사용자 결정).
  • 새 CLI hwip sessions 명령·새 MCP 툴 — 기존 agent list 에 all 옵션 하나로 충분(D3, 사용자 결정).
  • cwd 를 서버로 올려 후보에 표시 — 올리지 않는다(D2, 사용자 결정).

Auto-decided

  • handle 대상 에이전트: Claude 만 — 다른 에이전트는 사용자 이름이 이미 providerSessionName 으로 매칭됨
  • --all JSON 모양: {v:1, all:true, sessions} — 로컬 행의 상위 집합(host·online·handle·alias 추가)
  • MCP all 경로: MCP 클라이언트가 GET /devices 직접 + 공용 listAgentTargets — send 와 같은 기기 목록·키, 구버전 CLI 에 --all 이 없을 때의 실패 경로가 사라짐
  • 배포 순서: server → cli → mcp
  • handle 길이 상한: 200자(KNOWN_RUN_TITLE_MAX 관례)

Acceptance

  • AC-1 · PASS · 서버 ingest 가 handle 을 한 줄·200자로 정규화해 저장, 비문자열·빈 값은 버림
  • AC-2 · PASS · 리스너가 derived Claude 이름을 providerSessionHandle 에 싣고 providerSessionName 은 지금처럼 비움(앱 표시 불변)
  • AC-3 · PASS · resolveAgentTarget(cli·mcp 두 사본)이 handle 로 풀고, 여럿이면 AMBIGUOUS_TARGET 후보에 handle·host·state
  • AC-4 · PASS · hwip agent list --all --json · hwip_agent_list {all:true} 가 전 머신 세션을 반환
  • AC-5 · PASS · 세 레포 기존 suite·typecheck 초록
  • verify-check: 8/8 green · audit: ok (5 checked rows at 7a01332)

Checklist

  • /review --full(opus fork + sonnet 교차, 형제 레포 별도) — Critical·Important 0
  • /security-scan(변경분) — SECURE, Low 2(기존 경로) 중 1건 수정
  • 문서(README·SKILL) 갱신

🤖 Generated with Claude Code

Claude Code names every session, from the cwd (ko-qmd-70) or by
/rename. The listener withholds a cwd-derived name from display, so
another agent told to send to that name got UNKNOWN_TARGET. Each session
row now carries providerSessionHandle, the record name whoever chose
it, and the change fingerprint includes it so a rename is reported at
once. Display naming is unchanged.
hwip agent send and hwip agent read now match a session by
providerSessionHandle, the name Claude Code shows for it (ko-qmd-70), as
well as by tmux name, alias, label and shown name. One match is still
required. AMBIGUOUS_TARGET and UNKNOWN_TARGET list each candidate with
its handle and state so same-named sessions can be told apart.
hwip agent list --all [--json] lists the sessions agent send can reach
on every machine of the account, read from the server's device list:
key, host, online, agent, state, alias, shown name and handle. Every
table cell is stripped of control characters. Local agent list rows
gain handle too. agent read and agent send refuse --all instead of
ignoring it, since the agent flag table is shared.
The send branch already refused --turns; a test now pins it. The handle
is shown by agent list, so its comments say it is kept out of the app
rather than never shown.
The --all table prints names other machines report. Strip the same
characters the server's oneLine does, so a key cannot read as another.
@tak-bro

tak-bro commented Oct 31, 2026

Copy link
Copy Markdown
Member Author

/review — #29 @7a01332

Verdict: Approve (Critical 0, Important 0, Nice-to-have 1)

Scope: 18 files (+482/-25) · CI: pass · Risk: Low · 반박됨 0
test-check: n_logic=8 n_test=9 n_new=0 verdict=pass
weaken-check: n=3 verdict=justified
routing: tests errors security
axis-a: README agent list 칸의 "never exits 3" 문장이 --all 의 exit 3 과 한 칸 안에서 어긋남(문서)
axis-b: as planned

Scope Check: CLEAN
Intent: 리스너가 Claude 세션 이름을 providerSessionHandle 로 올리고, send·read 가 handle 로 대상을 풀고, agent list --all 로 전 머신 세션을 본다 (AC-2·AC-3·AC-4, cli 몫)
Delivered: 플랜 Files 표의 cli 파일 전부 + Outcome 에 divergence 로 기록된 session-name-source.test.ts·args.ts·cli.ts·agent-read.ts(--all 거부)

Findings

  • README.md:1324 · [Nice-to-have] · A · agent list 칸이 "no API key (it never exits 3)" 라고 쓴 뒤 같은 칸에서 --all 이 "exit 3 without" 이라 함 — 앞 문장을 "Without --all …" 으로 한정 · confidence 9/10 · code-confirmed

확인한 것 (finding 아님)

  • handle 감지는 pid 일치만 쓴다(src/remote-agents.ts:581 → detectClaudeSessionByPid, mtime 폴백 없음) — 같은 디렉터리의 다른 claude 이름이 handle 로 실려 오송신될 경로 없음.
  • collectDescendantPids 는 캐시(src/remote-agents.ts:493)라 행당 조회가 하나 늘어도 ps 는 늘지 않음.
  • agent send 메시지 안의 --all 은 sendArgv 로 분리돼(src/args.ts:136) 새 거부 분기에 걸리지 않음.
  • printable 의 문자 집합 = 서버 oneLine 의 UNPRINTABLE(hwip server/src/lib/one-line.ts:3)과 같음.
  • weaken 3건(agent-list-cli.test.ts:66·agent-list-usage.test.ts:18·usage.test.ts:42)은 --all 추가로 바뀐 usage 문자열·flag 표 — AC-4 가 정한 변경.
  • 변경 테스트 파일 9개 로컬 실행: 214 passed. codegraph impact resolveAgentTarget 호출자 = send·agent-read·agent-list(테스트 포함), 모두 diff 안에서 handle·state 를 넘김.

pre-existing: src/agent-target.ts:137 · describeCandidate 가 원격 label·alias 를 escape 하지 않고 에러 문구에 넣음 (PR 본문 Risks 에 미룸으로 기록됨)

reviewer fork (opus) · 단일 리뷰어 — 교차 모델 파인더는 --full 에서만

@tak-bro
tak-bro marked this pull request as ready for review October 31, 2026 09:15
@tak-bro
tak-bro merged commit 3c3389b into main Oct 31, 2026
4 checks passed
@tak-bro
tak-bro deleted the feat/agent-target-handle branch October 31, 2026 09:24
@github-actions

github-actions Bot commented Nov 1, 2026

Copy link
Copy Markdown

🎉 This PR is included in version 0.1.14 🎉

The release is available on:

Your semantic-release bot 📦🚀

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant