Commit ac43ef4
feat(harness-driver): add lifecycle-aware SpawnedAgentHandle (#1050)
* ci(publish): publish @agent-relay/harnesses on release
@agent-relay/harnesses was set up as a public package (no private flag,
publishConfig.access public, versioned in lockstep) but was never wired
into the publish workflow, so it never reached npm. External SDK
consumers (e.g. relayflows) need it for the prebuilt PTY harnesses and
the definePtyHarness/createHuman author helpers.
Add a publish-harnesses job to the package=all path. It runs after
publish-packages — where its exact-version workspace deps
(@agent-relay/sdk, @agent-relay/harness-driver) land on the registry —
so an external `npm install @agent-relay/harnesses@<v>` can always
resolve its dependencies. Mirrors the existing provenance +
skip-if-exists publish pattern.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* ci(publish): gate release on publish-harnesses; trim changelog
Address PR review: publish-harnesses ran outside the release gate, so a
tag/release could be cut even if harness publishing failed.
- create-release now needs publish-harnesses and its `if` requires the
job to not have failed. It tolerates `skipped` so package=main
releases (where publish-harnesses does not run) are not blocked.
- summary job lists the harness publish result.
- Trim the changelog bullet to impact-first per the repo changelog rule.
Leaving the new job's actions on @v4 tags to match the rest of the
workflow (the repo uses tag refs throughout; SHA-pinning would be
inconsistent and is not the enforced policy here).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* feat(harness-driver): add lifecycle-aware SpawnedAgentHandle
`spawnPty`/`spawnCli`/`spawnHeadless` now return a `SpawnedAgentHandle`
instead of a bare `SpawnAgentResult`. The handle is a structural superset
(still carries name/runtime/sessionId/pid) so existing callers are
unaffected, and it adds the promise-based lifecycle operations consumers
previously had to reconstruct from the raw broker event stream:
- waitForExit() -> { reason, code, signal }
- waitForIdle() -> { reason, idleSecs }
- exit / exitCode / exitSignal (synchronous view of a prior exit)
- release()
All operations are backed by the client's broker event stream and its
event history, so they are replay-correct: awaiting after the agent has
already exited resolves immediately from history rather than hanging.
Typechecks clean; harness-driver tests pass; dependents (harnesses, sdk)
unaffected.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(harness-driver): source waitForIdle from broker event stream
The client `eventBus` only carries call-site hook events; broker events
like `agentIdle` are never emitted onto it in direct-client usage, so
`addListener('agentIdle', ...)` never fired and `waitForIdle()` could
hang. Match the `agent_idle` BrokerEvent on the transport stream via
`onEvent` instead — consistent with how `waitForExit()` already works.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(harness-driver): ensure broker event stream is live in handle waits
`transport.onEvent()` only registers a listener; events arrive only once
the stream is connected. Call the idempotent `connectEvents()` at the
start of `waitForExit`/`waitForIdle` so they receive events even if the
consumer never connected the stream, instead of hanging until timeout.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>1 parent a14f65f commit ac43ef4
3 files changed
Lines changed: 170 additions & 8 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
43 | 43 | | |
44 | 44 | | |
45 | 45 | | |
| 46 | + | |
46 | 47 | | |
47 | 48 | | |
48 | 49 | | |
| |||
621 | 622 | | |
622 | 623 | | |
623 | 624 | | |
624 | | - | |
| 625 | + | |
625 | 626 | | |
626 | 627 | | |
627 | 628 | | |
| |||
638 | 639 | | |
639 | 640 | | |
640 | 641 | | |
641 | | - | |
| 642 | + | |
642 | 643 | | |
643 | 644 | | |
644 | 645 | | |
645 | 646 | | |
646 | 647 | | |
647 | 648 | | |
648 | | - | |
| 649 | + | |
649 | 650 | | |
650 | 651 | | |
651 | 652 | | |
| |||
659 | 660 | | |
660 | 661 | | |
661 | 662 | | |
662 | | - | |
| 663 | + | |
663 | 664 | | |
664 | 665 | | |
665 | 666 | | |
| |||
680 | 681 | | |
681 | 682 | | |
682 | 683 | | |
683 | | - | |
| 684 | + | |
684 | 685 | | |
685 | 686 | | |
686 | 687 | | |
687 | 688 | | |
688 | 689 | | |
689 | 690 | | |
690 | | - | |
| 691 | + | |
691 | 692 | | |
692 | 693 | | |
693 | 694 | | |
| |||
699 | 700 | | |
700 | 701 | | |
701 | 702 | | |
702 | | - | |
| 703 | + | |
703 | 704 | | |
704 | 705 | | |
705 | 706 | | |
706 | | - | |
| 707 | + | |
707 | 708 | | |
708 | 709 | | |
709 | 710 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
| 2 | + | |
2 | 3 | | |
3 | 4 | | |
4 | 5 | | |
| |||
0 commit comments