Skip to content

Commit 1507a97

Browse files
authored
refactor: centralize inbound supplemental context
* refactor: centralize inbound supplemental context * refactor: trim supplemental finalizer typing * docs: clarify supplemental context projection * refactor: move inbound finalization into core * refactor: simplify channel inbound facts * refactor: fold supplemental media into inbound finalizer * refactor: migrate channel inbound callers to builder * docs: mark inbound finalizer compat types deprecated * refactor: wire runtime turn context builder * refactor: replace channel turn runtime API * fix: respect discord quote visibility * fix: avoid deprecated line dispatch helper * refactor: deprecate channel message SDK seams * docs: trim channel outbound SDK page * test: migrate irc inbound assertion * refactor: deprecate outbound SDK facades * refactor: deprecate channel helper SDK facades * refactor: deprecate channel streaming SDK facade * refactor: move direct dm helpers into inbound SDK * chore: mark legacy test-utils SDK alias deprecated * refactor: remove unused allow-from read helper * refactor: route remaining channel dispatch through core * refactor: enforce modern extension SDK imports * test: give slow image root tests more time * ci: support node fallback on windows * fix: add transcripts tool display metadata * refactor: trim legacy channel test seams * fix: preserve channel compat after rebase * fix: keep deprecated channel inbound aliases * fix: preserve discord thread context visibility * fix: clean final rebase conflicts * fix: preserve channel message dispatch aliases * fix: sync channel refactor after rebase * fix: sync channel refactor after latest main * fix: dedupe memory-core subagent mock * test: align clickclack inbound dispatch assertions * fix: sync plugin sdk api hash after rebase * fix: sync channel refactor after latest main * fix: sync plugin sdk api hash after rebase * fix: sync plugin sdk api hash after latest main * test: remove stale inbound context awaits
1 parent ad3d197 commit 1507a97

321 files changed

Lines changed: 5451 additions & 5411 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/actions/setup-pnpm-store-cache/ensure-node.sh

Lines changed: 37 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -53,14 +53,16 @@ openclaw_active_node_version() {
5353

5454
openclaw_prepend_node_bin() {
5555
local node_bin_dir="$1"
56+
local github_path_dir="${2:-$node_bin_dir}"
5657
local shell_node_bin_dir="$node_bin_dir"
5758
if command -v cygpath >/dev/null 2>&1; then
5859
shell_node_bin_dir="$(cygpath -u "$node_bin_dir" 2>/dev/null || printf '%s' "$node_bin_dir")"
5960
fi
6061
export PATH="$shell_node_bin_dir:$PATH"
6162
if [[ -n "${GITHUB_PATH:-}" ]]; then
62-
local github_node_bin_dir="$shell_node_bin_dir"
63-
if command -v cygpath >/dev/null 2>&1; then
63+
local github_node_bin_dir="$github_path_dir"
64+
if [[ $# -lt 2 ]] && command -v cygpath >/dev/null 2>&1; then
65+
github_node_bin_dir="$shell_node_bin_dir"
6466
github_node_bin_dir="$(cygpath -w "$shell_node_bin_dir" 2>/dev/null || printf '%s' "$shell_node_bin_dir")"
6567
fi
6668
echo "$github_node_bin_dir" >> "$GITHUB_PATH"
@@ -139,6 +141,7 @@ openclaw_node_download_platform() {
139141
MINGW*:x86_64 | MSYS*:x86_64 | CYGWIN*:x86_64 | MINGW*:AMD64 | MSYS*:AMD64 | CYGWIN*:AMD64)
140142
printf 'win-x64\n'
141143
;;
144+
MINGW*:aarch64 | MINGW*:arm64 | MSYS*:aarch64 | MSYS*:arm64 | CYGWIN*:aarch64 | CYGWIN*:arm64) printf 'win-arm64\n' ;;
142145
*)
143146
return 1
144147
;;
@@ -147,31 +150,47 @@ openclaw_node_download_platform() {
147150

148151
openclaw_download_node() {
149152
local requested_node="$1"
150-
local version platform archive_url install_root
153+
local version platform archive_url install_root temp_root
151154
version="$(openclaw_resolve_node_download_version "$requested_node")"
152155
platform="$(openclaw_node_download_platform)" || return 1
153-
install_root="${RUNNER_TEMP:-/tmp}/openclaw-node-${version}-${platform}"
154-
mkdir -p "$install_root"
156+
temp_root="${RUNNER_TEMP:-/tmp}"
157+
if command -v cygpath >/dev/null 2>&1; then
158+
temp_root="$(cygpath -u "$temp_root" 2>/dev/null || printf '%s\n' "$temp_root")"
159+
fi
160+
install_root="${temp_root}/openclaw-node-${version}-${platform}"
155161
if [[ "$platform" == win-* ]]; then
156-
local archive_path
162+
local archive_path ps_archive_path ps_install_root ps_bin_dir node_bin_dir
163+
archive_path="${temp_root}/node-${version}-${platform}.zip"
157164
archive_url="https://nodejs.org/dist/${version}/node-${version}-${platform}.zip"
158-
archive_path="${RUNNER_TEMP:-/tmp}/node-${version}-${platform}.zip"
165+
rm -rf "$install_root"
166+
mkdir -p "$install_root"
159167
echo "Downloading Node ${version} from ${archive_url}"
160-
curl -fsSL "$archive_url" -o "$archive_path"
161-
if command -v powershell.exe >/dev/null 2>&1 && command -v cygpath >/dev/null 2>&1; then
162-
powershell.exe -NoLogo -NoProfile -Command \
163-
"Expand-Archive -LiteralPath '$(cygpath -w "$archive_path")' -DestinationPath '$(cygpath -w "$install_root")' -Force"
168+
curl -fsSL -o "$archive_path" "$archive_url"
169+
ps_archive_path="$archive_path"
170+
ps_install_root="$install_root"
171+
if command -v cygpath >/dev/null 2>&1; then
172+
ps_archive_path="$(cygpath -w "$archive_path")"
173+
ps_install_root="$(cygpath -w "$install_root")"
174+
fi
175+
ps_bin_dir="$ps_install_root\\node-${version}-${platform}"
176+
node_bin_dir="$install_root/node-${version}-${platform}"
177+
if command -v pwsh >/dev/null 2>&1; then
178+
pwsh -NoLogo -NoProfile -Command "Expand-Archive -LiteralPath '${ps_archive_path}' -DestinationPath '${ps_install_root}' -Force"
179+
openclaw_prepend_node_bin "$node_bin_dir" "$ps_bin_dir"
180+
elif command -v powershell.exe >/dev/null 2>&1; then
181+
powershell.exe -NoLogo -NoProfile -Command "Expand-Archive -LiteralPath '${ps_archive_path}' -DestinationPath '${ps_install_root}' -Force"
182+
openclaw_prepend_node_bin "$node_bin_dir" "$ps_bin_dir"
164183
else
165184
unzip -q "$archive_path" -d "$install_root"
185+
openclaw_prepend_node_bin "$node_bin_dir"
166186
fi
167-
openclaw_prepend_node_bin "$install_root/node-${version}-${platform}"
168-
return 0
187+
else
188+
archive_url="https://nodejs.org/dist/${version}/node-${version}-${platform}.tar.xz"
189+
mkdir -p "$install_root"
190+
echo "Downloading Node ${version} from ${archive_url}"
191+
curl -fsSL "$archive_url" | tar -xJ -C "$install_root" --strip-components=1
192+
openclaw_prepend_node_bin "$install_root/bin"
169193
fi
170-
171-
archive_url="https://nodejs.org/dist/${version}/node-${version}-${platform}.tar.xz"
172-
echo "Downloading Node ${version} from ${archive_url}"
173-
curl -fsSL "$archive_url" | tar -xJ -C "$install_root" --strip-components=1
174-
openclaw_prepend_node_bin "$install_root/bin"
175194
}
176195

177196
openclaw_ensure_node() {

apps/shared/OpenClawKit/Sources/OpenClawKit/Resources/tool-display.json

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -448,12 +448,13 @@
448448
"start": {
449449
"label": "start",
450450
"detailKeys": [
451-
"providerId",
452451
"sessionId",
453452
"title",
454-
"meetingUrl",
453+
"providerId",
454+
"accountId",
455455
"guildId",
456-
"channelId"
456+
"channelId",
457+
"meetingUrl"
457458
]
458459
},
459460
"stop": {
@@ -468,10 +469,11 @@
468469
"import": {
469470
"label": "import",
470471
"detailKeys": [
471-
"providerId",
472472
"sessionId",
473473
"title",
474-
"meetingUrl"
474+
"providerId",
475+
"meetingUrl",
476+
"speakerLabel"
475477
]
476478
},
477479
"summarize": {
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
1818f0bf7e1f19917074efbeb8d6627e799f0909d019681cd8e184244de0641f plugin-sdk-api-baseline.json
2-
49dcff59d33606b9675962183b3e5bc10c09141ca9c75db609401efffcacf291 plugin-sdk-api-baseline.jsonl
1+
ad0244c9ea86a2c2b3f43f285b066c1ec8e0969dbcce87dd848a33442712db13 plugin-sdk-api-baseline.json
2+
b21846ef642b66f7af8439724424abbced35bd0b51b6ecdab90db75c44bbc516 plugin-sdk-api-baseline.jsonl

docs/channels/bot-loop-protection.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ OpenClaw can accept messages written by other bots on channels that support `all
1313
When that path is enabled, pair loop protection prevents two bot identities from
1414
replying to each other indefinitely.
1515

16-
The guard is enforced by the core channel-turn kernel. Each supporting channel
16+
The guard is enforced by the core inbound reply runner. Each supporting channel
1717
maps its own inbound event into generic facts: account or scope, conversation id,
1818
sender bot id, and receiver bot id. Core then tracks the participant pair in both
1919
directions, applies a sliding-window budget, and suppresses the pair during a

docs/concepts/message-lifecycle-refactor.md

Lines changed: 30 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@
22
summary: "Design plan for the unified durable message receive, send, preview, edit, and streaming lifecycle"
33
read_when:
44
- Refactoring channel send or receive behavior
5-
- Changing channel turn, reply dispatch, outbound queue, preview streaming, or plugin SDK message APIs
5+
- Changing channel inbound, reply dispatch, outbound queue, preview streaming, or plugin SDK message APIs
66
- Designing a new channel plugin that needs durable sends, receipts, previews, edits, or retries
77
title: "Message lifecycle refactor"
88
---
99

10-
This page is the target design for replacing scattered channel turn, reply
10+
This page is the target design for replacing scattered channel inbound, reply
1111
dispatch, preview streaming, and outbound delivery helpers with one durable
1212
message lifecycle.
1313

@@ -20,14 +20,14 @@ The short version:
2020
commit, fail.
2121
- Receiving must be context based too: normalize, dedupe, route, record,
2222
dispatch, platform ack, fail.
23-
- The public plugin SDK should collapse to one small channel-message surface.
23+
- The public plugin SDK should collapse to one small channel-outbound surface.
2424

2525
## Problems
2626

2727
The current channel stack grew from several valid local needs:
2828

29-
- Simple inbound adapters use `runtime.channel.turn.run`.
30-
- Rich adapters use `runtime.channel.turn.runPrepared`.
29+
- Simple inbound adapters use `runtime.channel.inbound.run`.
30+
- Rich adapters use `runtime.channel.inbound.runPreparedReply`.
3131
- Legacy helpers use `dispatchInboundReplyWithBase`,
3232
`recordInboundSessionAndDispatchReply`, reply payload helpers, reply chunking,
3333
reply references, and outbound runtime helpers.
@@ -67,7 +67,7 @@ non-durable policy.
6767
- Shared preview, edit, stream, finalization, retry, recovery, and receipt
6868
semantics.
6969
- A small plugin SDK surface that third-party plugins can learn and maintain.
70-
- Compatibility for existing `channel.turn` callers during migration.
70+
- Compatibility for existing inbound reply compatibility callers during migration.
7171
- Clear extension points for new channel capabilities.
7272
- No platform-specific branches in core.
7373
- No token-delta channel messages. Channel streaming remains message preview,
@@ -77,7 +77,7 @@ non-durable policy.
7777

7878
## Non goals
7979

80-
- Do not remove `runtime.channel.turn.*` in the first phase.
80+
- Do not force every existing channel onto durable message delivery in the first phase.
8181
- Do not force every channel into the same native transport behavior.
8282
- Do not teach core Telegram topics, Slack native streams, Matrix redactions,
8383
Feishu cards, QQ voice, or Teams activities.
@@ -557,7 +557,7 @@ This should cover current behavior:
557557
The public SDK target should be one subpath:
558558

559559
```typescript
560-
import { defineChannelMessageAdapter } from "openclaw/plugin-sdk/channel-message";
560+
import { defineChannelMessageAdapter } from "openclaw/plugin-sdk/channel-outbound";
561561
```
562562

563563
Target shape:
@@ -670,22 +670,22 @@ should not need them.
670670

671671
Bundled plugins may keep internal helper imports through reserved runtime
672672
subpaths while migrating. Public docs should steer plugin authors to
673-
`plugin-sdk/channel-message` once it exists.
673+
`plugin-sdk/channel-outbound` once it exists.
674674

675-
## Relationship to channel turn
675+
## Relationship to channel inbound
676676

677-
`runtime.channel.turn.*` should stay during migration.
677+
`runtime.channel.inbound.*` is the runtime bridge during migration.
678678

679679
It should become a compatibility adapter:
680680

681681
```text
682-
channel.turn.run
682+
channel.inbound.run
683683
-> messages.receive context
684684
-> session dispatch
685685
-> messages.send context for visible output
686686
```
687687

688-
`channel.turn.runPrepared` should also remain initially:
688+
`channel.inbound.runPreparedReply` should also remain initially:
689689

690690
```text
691691
channel-owned dispatcher
@@ -694,10 +694,8 @@ channel-owned dispatcher
694694
-> messages.send for final delivery
695695
```
696696

697-
After all bundled plugins and known third-party compatibility paths are bridged,
698-
`channel.turn` can be deprecated. It should not be removed until there is a
699-
published SDK migration path and contract tests proving old plugins still work
700-
or fail with a clear version error.
697+
The old `channel.turn` runtime surface remains a deprecated alias only. New code
698+
uses inbound/message nouns.
701699

702700
## Compatibility guardrails
703701

@@ -706,10 +704,10 @@ existing delivery callback has side effects beyond "send this payload".
706704

707705
Legacy entry points are non-durable by default:
708706

709-
- `channel.turn.run` and `dispatchAssembledChannelTurn` use the channel's
707+
- `channel.inbound.run` and `dispatchChannelInboundReply` use the channel's
710708
delivery callback unless that channel explicitly supplies an audited durable
711709
policy/options object.
712-
- `channel.turn.runPrepared` stays channel-owned until the prepared dispatcher
710+
- `channel.inbound.runPreparedReply` stays channel-owned until the prepared dispatcher
713711
explicitly calls the send context.
714712
- Public compatibility helpers such as `recordInboundSessionAndDispatchReply`,
715713
`dispatchInboundReplyWithBase`, and direct-DM helpers never inject generic
@@ -902,17 +900,17 @@ Core policy:
902900
- Make `deliverOutboundPayloads` call `messages.send`.
903901
- Make final-send durability the default and fail closed when the durable intent
904902
cannot be written in the new message lifecycle, after the adapter declares
905-
replay safety. Existing channel-turn and SDK compatibility paths remain
903+
replay safety. Existing inbound runner and SDK compatibility paths remain
906904
direct-send by default during this phase.
907905
- Record receipts consistently.
908906
- Return receipts and delivery results to the original dispatcher caller instead
909907
of treating durable send as a terminal side effect.
910908
- Persist message origin through durable send intents so recovery, replay, and
911909
chunked sends preserve OpenClaw operational provenance.
912910

913-
### Phase 3: Channel Turn Bridge
911+
### Phase 3: Channel Inbound Bridge
914912

915-
- Reimplement `channel.turn.run` and `dispatchAssembledChannelTurn` on top of
913+
- Reimplement `channel.inbound.run` and `dispatchChannelInboundReply` on top of
916914
`messages.receive` and `messages.send`.
917915
- Keep current fact types stable.
918916
- Keep legacy behavior by default. An assembled-turn channel becomes durable
@@ -950,12 +948,12 @@ Core policy:
950948

951949
### Phase 6: Public SDK
952950

953-
- Add `openclaw/plugin-sdk/channel-message`.
951+
- Add `openclaw/plugin-sdk/channel-outbound`.
954952
- Document it as the preferred channel plugin API.
955953
- Update package exports, entrypoint inventory, generated API baselines, and
956954
plugin SDK docs.
957955
- Include `MessageOrigin`, origin encode/decode hooks, and the shared
958-
`shouldDropOpenClawEcho` predicate in the channel-message SDK surface.
956+
`shouldDropOpenClawEcho` predicate in the channel-outbound SDK surface.
959957
- Keep compatibility wrappers for old subpaths.
960958
- Mark reply-named SDK helpers as deprecated in docs after bundled plugins are
961959
migrated.
@@ -976,9 +974,9 @@ Move all non-reply outbound producers onto `messages.send`:
976974
This is where the model stops being "agent replies" and becomes "OpenClaw sends
977975
messages".
978976

979-
### Phase 8: Deprecate Turn
977+
### Phase 8: Remove Turn-Named Compatibility
980978

981-
- Keep `channel.turn` as a wrapper for at least one compatibility window.
979+
- Keep inbound/message-named wrappers as the compatibility window.
982980
- Publish migration notes.
983981
- Run plugin SDK compatibility tests against old imports.
984982
- Remove or hide old internal helpers only after no bundled plugin needs them
@@ -1002,10 +1000,10 @@ Unit tests:
10021000

10031001
Integration tests:
10041002

1005-
- `channel.turn.run` simple adapter still records and sends.
1003+
- `channel.inbound.run` simple adapter still records and sends.
10061004
- Legacy assembled-event delivery does not become durable unless the channel
10071005
explicitly opts in.
1008-
- `channel.turn.runPrepared` bridge still records and finalizes.
1006+
- `channel.inbound.runPreparedReply` bridge still records and finalizes.
10091007
- Public compatibility helpers call caller-owned delivery callbacks by default
10101008
and do not generic-send before those callbacks.
10111009
- Durable fallback delivery replays the whole projected payload array after
@@ -1075,7 +1073,7 @@ Validation:
10751073
- Whether durable live preview state should be stored in the same queue record
10761074
as the final send intent or in a sibling live-state store.
10771075
- How long compatibility wrappers stay documented after
1078-
`plugin-sdk/channel-message` ships.
1076+
`plugin-sdk/channel-outbound` ships.
10791077
- Whether third-party plugins should implement receive adapters directly or only
10801078
provide normalize/send/live hooks through `defineChannelMessageAdapter`.
10811079
- Which receipt fields are safe to expose in public SDK versus internal runtime
@@ -1094,15 +1092,15 @@ Validation:
10941092
documented compatibility wrapper.
10951093
- Every preview/edit/stream channel uses `messages.live` for draft state and
10961094
finalization.
1097-
- `channel.turn` is only a wrapper.
1095+
- `channel.inbound` is only a wrapper.
10981096
- Reply-named SDK helpers are compatibility exports, not the recommended path.
10991097
- Durable recovery can replay pending final sends after restart without losing
11001098
the final response or duplicating already committed sends; sends whose
11011099
platform outcome is unknown are reconciled before replay or documented as
11021100
at-least-once for that adapter.
11031101
- Durable final sends fail closed when the durable intent cannot be written,
11041102
unless a caller explicitly selected a documented non-durable mode.
1105-
- Legacy channel-turn and SDK compatibility helpers default to direct
1103+
- Legacy SDK compatibility helpers default to direct
11061104
channel-owned delivery; generic durable send is explicit opt-in only.
11071105
- Receipts preserve all platform message ids for multi-part deliveries and a
11081106
primary id for threading/edit convenience.
@@ -1125,4 +1123,4 @@ Validation:
11251123
- [Streaming and chunking](/concepts/streaming)
11261124
- [Progress drafts](/concepts/progress-drafts)
11271125
- [Retry policy](/concepts/retry)
1128-
- [Channel turn kernel](/plugins/sdk-channel-turn)
1126+
- [Channel inbound API](/plugins/sdk-channel-inbound)

docs/docs.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1743,8 +1743,8 @@
17431743
"plugins/architecture-internals",
17441744
"plugins/sdk-migration",
17451745
"plugins/compatibility",
1746-
"plugins/sdk-channel-message",
1747-
"plugins/sdk-channel-turn",
1746+
"plugins/sdk-channel-outbound",
1747+
"plugins/sdk-channel-inbound",
17481748
"plugins/sdk-channel-ingress",
17491749
"plugins/message-presentation"
17501750
]

docs/plugins/architecture-internals.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -665,8 +665,8 @@ barrel when authoring new plugins. Core subpaths:
665665

666666
Channel plugins pick from a family of narrow seams — `channel-setup`,
667667
`setup-runtime`, `setup-tools`, `channel-pairing`,
668-
`channel-contract`, `channel-feedback`, `channel-inbound`, `channel-lifecycle`,
669-
`channel-reply-pipeline`, `command-auth`, `secret-input`, `webhook-ingress`,
668+
`channel-contract`, `channel-feedback`, `channel-inbound`, `channel-outbound`,
669+
`command-auth`, `secret-input`, `webhook-ingress`,
670670
`channel-targets`, and `channel-actions`. Approval behavior should consolidate
671671
on one `approvalCapability` contract rather than mixing across unrelated
672672
plugin fields. See [Channel plugins](/plugins/sdk-channel-plugins).
@@ -679,7 +679,9 @@ Runtime and config helpers live under matching focused `*-runtime` subpaths
679679
instead of the broad `config-runtime` compatibility barrel.
680680

681681
<Info>
682-
`openclaw/plugin-sdk/channel-runtime`, `openclaw/plugin-sdk/config-runtime`,
682+
`openclaw/plugin-sdk/channel-runtime`, `openclaw/plugin-sdk/channel-lifecycle`,
683+
small channel helper facades, `openclaw/plugin-sdk/outbound-runtime`,
684+
`openclaw/plugin-sdk/outbound-send-deps`, `openclaw/plugin-sdk/config-runtime`,
683685
and `openclaw/plugin-sdk/infra-runtime` are deprecated compatibility shims for
684686
older plugins. New code should import narrower generic primitives instead.
685687
</Info>

0 commit comments

Comments
 (0)