Files
hapi/shared/package.json
T
7f5d6b17f3 feat(peer): spawn-peer remit + rename-proof Parent UUID stamps (#1922)
* feat(cli): spawn-peer with required remit and MCP spawn_peer

Machine spawn creates an empty composer; stuffing message into that
JSON is stripped. Add hapi spawn-peer and MCP spawn_peer that spawn,
rename, deliver via the ping-peer path, and fail closed unless the
remit is on the new session. Reject message/prompt/text on machine
spawn with 400. Do not auto-approve spawn_peer in default/read-only.

Fixes #1509

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(cli): reject overlong spawn-peer names before spawn

Hub rename max is 255; continuing past PATCH 400 left a live session under a different title. MCP/steer copy now says the hub 400s a spawn-body remit instead of stripping it.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(cli): wait for fresh spawn-peer child instead of resuming it

Machine spawn can return while the hub row is still inactive. ping-peer then POSTed /resume, which can launch a second agent because the original spawn has no existingSessionId for runner dedupe.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(cli): reject flavor-illegal permissionMode before spawn-peer

Codex + bypassPermissions (and Pi + any mode) used to reach the runner and fail after a child existed, or silently drop the mode. Check isPermissionModeAllowedForFlavor when both agent and mode are explicit.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(cli): treat omitted spawn-peer agent as Claude for permissionMode

Hub and runner default agent to claude when spawn omits it. Validate permissionMode against that effective flavor so yolo/read-only fail closed before a child starts.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(cli): resolve spawn-peer dir locally and archive failed children

Relative --dir values were forwarded unchanged, so the runner resolved them against daemon cwd. Remit delivery failures also left the new session running, so a retry spawned a duplicate. Resolve in the caller and best-effort archive the child before rethrowing.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(cli): verify remit before archiving a failed spawn-peer child

A timed-out ping-peer POST can still land the remit. Check the transcript before archive, and only say the child was archived when the hub returns ok.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(cli): swallow spawn-peer transcript GET errors and skip unapplied names

A thrown messages GET after spawn skipped archive and leaked a live child. Treat transport errors as a miss so the verify loop can retry, then clean up. Also do not return a requested name the hub never applied.

Co-authored-by: Cursor <cursoragent@cursor.com>

* feat(spawn-peer): hub peerSpawnDefaults + model/effort spawn surface

Add hub settings peerSpawnDefaults (agent, permissionMode, per-flavor models)
with stock claude/yolo/sonnet fallbacks. spawnPeer resolves explicit args →
hub settings → stock, maps yolo to flavor equivalents, and forwards model/effort
into machine spawn. Settings UI under General → Agents; MCP/CLI optional overrides.

Co-authored-by: Cursor <cursoragent@cursor.com>

* test(hub): use cursor-valid permission mode in peer spawn defaults test

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(cli): teach spawn_peer that omit permissionMode means yolo

MCP copy said "pass permissionMode only when the operator asked", so agents
omitted it and got hub/stock whatever was stored — often approval-gated
default. Clarify omit = yolo via peerSpawnDefaults/stock; pass only to tighten.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(hub,web): apply peerSpawnDefaults to machine spawn and New Session

POST /api/machines/:id/spawn now resolves omitted agent/permissionMode/model
from hub Settings, and New Session seeds from the same peerSpawnDefaults so
UI create and peer spawn share one authoritative default (stock yolo).

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(web): NewSession hub seed respects sticky prefs + QueryClient in tests

Sticky localStorage last-used agent wins over hub seed; machine spawn still
applies peerSpawnDefaults server-side. Tests provide QueryClientProvider.

Co-authored-by: Cursor <cursoragent@cursor.com>

* test(web): mock CREATABLE_AGENT_FLAVORS for settings general peerSpawn UI

Co-authored-by: Cursor <cursoragent@cursor.com>

* test(web): stabilize NewSession tests after hub peerSpawnDefaults seed

Wrap remaining mounts in QueryClientProvider, pre-seed hub settings so a
late useQuery resolve cannot wipe in-test model picks, and use neutral
stock permission defaults in the fixture.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(spawn-peer): address tip Codex Majors for peerSpawnDefaults

Preserve explicit yolo booleans on machine spawn, fail closed when hub
defaults cannot load, validate permission modes against the resolved
agent, remap auto-approval across flavors, and stop late hub settings
from wiping New Session edits. Reject retired agents in spawn defaults
and restore the CLI executable build docs.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(spawn-peer): address follow-up tip Codex Majors

Stop absent Yolo localStorage from beating hub defaults, track New Session
edits before late hub seed, reject incompatible machine-spawn permissions,
resolve MCP spawn_peer paths against the session working directory, and
hide unsupported Codex safe-yolo from Settings spawn defaults.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(spawn-peer): clear tip-2 CI and follow-up Codex Majors

Omit permissionMode for Pi/DSH, preserve explicit Yolo-off across delayed
hub seed, fix settings test mocks for launch permission helpers, and
restore unrelated CLI README lifecycle/ACP docs.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(spawn-peer): tip-3 Majors for seed edits and launchable modes

Skip hub agent seed after permission edits, resolve inherited modes via
the launch catalog (AGY request-review fallback), preserve hub Cursor
models through preference restore, and restore Codex auth README nuance.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(web): tip Minors for Cursor/Grok hub permission seeding

Give Cursor the native permission select so Plan/Ask survive machine
spawn, and re-apply Grok hub permissions after agent-init resets.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(spawn-peer): tip Minors for Cursor select and hub seed remap

Map hub permission through resolvePermissionModeForFlavor, keep native
Default when agent is explicit without a model, and assert Cursor Plan/Ask Mode labels.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(web): tip Minors for delayed hub seed and Default model

Apply hub permission/model to unset fields even with a sticky agent,
preserve explicitly saved auto models, and seed OpenCode/AGY selectors
from hub defaults.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(spawn-peer): tip Minors for model edit sticky and clear override

Mark OpenCode/AGY model picks as edited so delayed hub seed cannot
overwrite them, and treat empty hub model values as clear sentinels.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(spawn-peer): tip Majors for models patch typing and remit page scan

Type the models patch as NonNullable and paginate transcript verification
oldest-ward so a busy child is not archived when the remit leaves page 1.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(web): tip Minor — keep agent after explicit model pick

Do not apply a late hub default agent when the operator already chose a
model; otherwise preference restore drops that selection.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(spawn-peer): tip Cursor YOLO migrate and Codex effort map

Bridge Cursor's saved YOLO toggle (incl. false) into native Default over
hub yolo, and send Codex/OpenCode --effort as modelReasoningEffort.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(web): tip Majors — scoped YOLO bridge and catalog fallback

Keep unsupported saved permission modes at Default instead of hub yolo,
and apply delayed YOLO migration only when the sticky bridge agent matches.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(cli): drop rebase conflict markers in startHappyServer

Both sessionDisplayRename and spawnPeer imports are required after
rebasing onto upstream rename work; markers had slipped into tip.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(web): wrap Kimi NewSession tests in QueryClientProvider

Hub settings useQuery requires a provider; upstream Kimi catalog tests
rendered bare and broke after the spawn-peer rebase onto main.

Co-authored-by: Cursor <cursoragent@cursor.com>

* feat(peer): rename-proof Parent UUID stamp on spawn remits

Orchestrated spawn_peer / spawn-peer remits now auto-stamp a durable
[title](/sessions/<uuid>) Parent chip (fail-closed in-session). MCP copy
forbids inventing titles; UUID stays identity after parent rename.

Refs heavygee/hapi#175

Co-authored-by: Cursor <cursoragent@cursor.com>

* style(peer): plain hyphen in Parent-stamp warning and test comment

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(peer): reject blank remit before Parent stamp

Codex review on #1922: stamping first turned empty remits non-empty and
bypassed the idle-session guard. Also only treat ## Parent blocks as
already-present so bare /sessions citations still get the chip.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(peer): gate New Session Create on hub defaults; require Parent chip

Codex tip review on #1922: block Create while getHubSettings is pending so
stock mount defaults cannot bypass restrictive hub peerSpawnDefaults; skip
Parent stamp only when ## Parent already has a markdown session chip; clarify
codex resume takes a native thread id.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(peer): resolve MCP spawn cwd; Agents settings section

Codex Major on #1922: spawn_peer relative directories now prefer the
launcher cwd (Codex --cd), then skillLookup, then session metadata.path.
Move peerSpawnDefaults UI into the unused Agents settings section.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(peer): pass session cwd to MCP spawn_peer; Agents settings section

Codex tip review on #1922: resolve relative spawn_peer directories from the
launcher working directory (Codex --cd), skillLookup, then metadata.path;
move peerSpawnDefaults UI into the Agents settings section.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(peer): skip archive on unread transcript; validate startingMode after hub agent

Codex tip review: do not archive a child when remit verification cannot read
the transcript; run AGY/DSH remote-only startingMode checks against the
resolved hub agent; update MCP bridge test expectations for workingDirectory.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(peer): treat exhausted remit pagination as unverifiable

Hitting the messages page cap with hasMore still true must not count as an
observed-empty transcript — that would archive a child whose remit may still
exist on older pages.

Co-authored-by: Cursor <cursoragent@cursor.com>

* docs(cli): list HAPI_API_URL as optional with localhost default

Codex tip review: the README had moved HAPI_API_URL under Required even
though configuration defaults it to http://localhost:3006 (and settings can
supply a URL). Also drop trailing whitespace flagged by git diff --check.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(peer): re-verify empty transcript before archiving failed spawn

An earlier observed-absent page plus later unread GETs must not archive a
child whose remit may have landed after the first empty read.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(peer): never auto-archive on spawnPeer failure path

Timed-out remit POSTs and empty-read/archive TOCTOU races can still land
work on the child. Leave the session running with its id for inspection
instead of terminating an in-flight peer.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(peer): classify empty_session from final remit verify

An earlier empty transcript read must not stick as empty_session once
later message GETs become unavailable — report verify_failed instead.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(peer): recognize escaped brackets in Parent chip labels

Titles with ] were escaped in the chip label but the idempotency regex
stopped at the first raw bracket and re-stamped a second Parent block.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(peer): avoid Parent chip regex backtracking on backslashes

Exclude \\ from the single-char label alternative so escaped pairs have
one parse path — long nonmatching backslash runs no longer explode.

Co-authored-by: Cursor <cursoragent@cursor.com>

* feat(cli): MCP/CLI spawn_peer --machine for cross-host remits

Wire optional machine (UUID or hostname via GET /api/machines) through
MCP spawn_peer and hapi spawn-peer into existing spawnPeer({ machineId }).
Skip local directory existence checks for cross-host targets to match the
estate wrapper; keep fail-closed remit verify.

Fixes tiann/hapi#1931

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(peer): reject ambiguous spawn --machine label matches

Tip bot Major on #1922: hostname/displayName selectors that match more
than one online runner now fail closed with ambiguous + UUID guidance.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(peer): preserve cross-OS absolute dirs for spawn --machine

path.resolve on the caller OS was rewriting foreign absolute roots
(C:\… on Linux, /srv/… on Windows) before the hub spawn POST. Detect
POSIX or Windows absolute paths and only resolve relative directories.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(peer): resolve spawn dirs after local vs remote is known

Defer directory resolution until the target machine is selected. Remote
spawns still preserve foreign absolute roots; local spawns use native
path.resolve so Windows drive-less paths like \repo bind to the caller
drive.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(web): apply delayed DSH model defaults without replacing edits

* fix(web): preserve hub permission defaults across form remounts

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: weishu <twsxtd@gmail.com>
2026-11-02 13:17:22 +08:00

44 lines
1.5 KiB
JSON

{
"name": "@hapi/protocol",
"private": true,
"version": "0.1.0",
"type": "module",
"main": "./src/index.ts",
"types": "./src/index.ts",
"exports": {
".": "./src/index.ts",
"./apiTypes": "./src/apiTypes.ts",
"./messages": "./src/messages.ts",
"./slashCommands": "./src/slashCommands.ts",
"./buildInfo": "./src/buildInfo.ts",
"./conversationHistory": "./src/conversationHistory.ts",
"./modes": "./src/modes.ts",
"./peerSpawnDefaults": "./src/peerSpawnDefaults.ts",
"./rpcMethods": "./src/rpcMethods.ts",
"./runnerCapabilities": "./src/runnerCapabilities.ts",
"./schemas": "./src/schemas.ts",
"./sessionCitation": "./src/sessionCitation.ts",
"./peerParentStamp": "./src/peerParentStamp.ts",
"./sessionExport": "./src/sessionExport.ts",
"./sessionLifecycle": "./src/sessionLifecycle.ts",
"./types": "./src/types.ts",
"./voice": "./src/voice.ts",
"./voicePickerCatalog": "./src/voicePickerCatalog.ts",
"./voice-personality": "./src/voicePersonality.ts",
"./usage": "./src/usage.ts",
"./settingsFileLock": "./src/settingsFileLock.ts",
"./agentCliSpawnLease": "./src/agentCliSpawnLease.ts"
},
"sideEffects": false,
"scripts": {
"test": "bun test"
},
"dependencies": {
"proper-lockfile": "^4.1.2",
"zod": "^4.2.1"
},
"devDependencies": {
"@types/proper-lockfile": "^4.1.4"
}
}