feat(cli): add Codex-aware auto peer delivery

Default peer CLI and MCP messages to auto, steering eligible Codex turns and queueing otherwise. Preserve explicit delivery modes and uncertain-send safety, and clarify steer guidance for important time-sensitive findings.
This commit is contained in:
weishu
2026-10-29 22:02:43 +08:00
parent f48a6696cf
commit 9384ce031b
13 changed files with 270 additions and 84 deletions
+20
View File
@@ -1,6 +1,8 @@
import { describe, expect, it } from 'bun:test'
import {
SESSION_REFERENCE_STEER_SUFFIX,
PEER_DELIVERY_MODE_DESCRIPTION,
PING_PEER_TOOL_DESCRIPTION,
buildSessionCitationSteerInstruction,
extractSessionCitationIds,
normalizeSessionIdPrefix,
@@ -98,6 +100,24 @@ describe('normalizeSessionIdPrefix', () => {
})
describe('buildSessionCitationSteerInstruction', () => {
it('guides collaboration toward auto and preserves explicit modes and retry safety', () => {
const text = buildSessionCitationSteerInstruction({ inspectTool: 'inspect_peer', pingTool: 'ping_peer' })
expect(text).toContain(PEER_DELIVERY_MODE_DESCRIPTION)
expect(PING_PEER_TOOL_DESCRIPTION).toContain(PEER_DELIVERY_MODE_DESCRIPTION)
expect(text).toContain('auto (default)')
expect(text).toContain('active Codex turn')
expect(text).toContain('Auto currently queues for other agent flavors')
expect(text).toContain('Prefer auto for routine collaboration when queueing is an acceptable fallback')
expect(text).toContain('queue: explicitly defer non-urgent updates')
expect(text).toContain('steer: use for important, time-sensitive findings the peer needs to know now')
expect(text).toContain('not after finishing its current turn')
expect(text).toContain('State why the finding matters now and what the peer should adjust')
expect(text).toContain('Steer requires insertion')
expect(text).toContain('does not abort the current turn or guarantee an immediate response')
expect(text).toContain('do not resend automatically')
expect(text).toContain('hapi ping-peer <id> <message> --delivery-mode auto')
})
it('mentions both citation forms and forbids local FS search', () => {
const text = buildSessionCitationSteerInstruction({
inspectTool: 'mcp__hapi__inspect_peer',
+16 -2
View File
@@ -24,12 +24,25 @@ export const INSPECT_PEER_TOOL_DESCRIPTION =
'Extract <id> and pass it as sessionIdPrefix. /sessions/<id> is a hub path - do NOT Grep, Glob, or Read it as a local filesystem path. ' +
'Read-only: does not resume. Prefer this (or `hapi inspect-peer`) over JWT+curl.'
/** Shared delivery guidance for the peer MCP schemas, descriptions, and prompts. */
export const PEER_DELIVERY_MODE_DESCRIPTION =
'auto (default): steer an active Codex turn when steering is available; otherwise queue, resuming inactive peers. ' +
'Auto currently queues for other agent flavors. Prefer auto for routine collaboration when queueing is an acceptable fallback. ' +
'queue: explicitly defer non-urgent updates that can wait instead of steering. ' +
'steer: use for important, time-sensitive findings the peer needs to know now, not after finishing its current turn ' +
'(e.g. a correction that invalidates its assumptions, a blocker, or a result that changes its next action). ' +
'State why the finding matters now and what the peer should adjust. ' +
'Steer requires insertion into an active Pi, Codex, or Cursor ACP turn; unsupported, idle, or inactive targets are rejected before sending. ' +
'Steering does not abort the current turn or guarantee an immediate response. ' +
'If send or steer is unconfirmed after submission, inspect the target before retrying; do not resend automatically.'
/** MCP `ping_peer` tool description (same citation forms as inspect_peer). */
export const PING_PEER_TOOL_DESCRIPTION =
'Send a message to another HAPI session (peer handoff / nudge). Resolves by session id prefix, resumes if inactive, then POSTs on the same hub/namespace. ' +
'When the user cites a peer via [title](/sessions/<id>), Copy-reference prose See session "…" (/sessions/<id>) for context, or a bare /sessions/<id>, ' +
'extract <id> and pass it as sessionIdPrefix. /sessions/<id> is a hub path - do NOT search the local filesystem for it. ' +
'Prefer this (or `hapi ping-peer`) over reinventing JWT+curl. Targets another session - not the current chat.'
'Prefer this (or `hapi ping-peer`) over reinventing JWT+curl. Targets another session - not the current chat. ' +
`Select deliveryMode: ${PEER_DELIVERY_MODE_DESCRIPTION}`
/** Zod `.describe` for sessionIdPrefix on inspect_peer / ping_peer. */
export const SESSION_ID_PREFIX_PARAM_DESCRIPTION =
@@ -158,7 +171,8 @@ export function buildSessionCitationSteerInstruction(tools: SessionCitationSteer
`/sessions/<id> is a HAPI hub path, not a local filesystem path - do not Grep, Glob, or Read it as a file. ` +
`Call "${tools.inspectTool}" with sessionIdPrefix=<id> to read metadata and recent messages; ` +
`call "${tools.pingTool}" with sessionIdPrefix=<id> and a message to nudge or hand off. ` +
`Prefer these over JWT+curl. Shell fallbacks: hapi inspect-peer <id> / hapi ping-peer <id> <message>.`
`Select deliveryMode: ${PEER_DELIVERY_MODE_DESCRIPTION} ` +
`Prefer these over JWT+curl. Shell fallbacks: hapi inspect-peer <id> / hapi ping-peer <id> <message> --delivery-mode auto.`
if (tools.listPeersTool) {
text +=
` To discover peers without a citation, call "${tools.listPeersTool}" ` +