Skip to content

Align Linq messaging with the OpenClaw channel runtime - #10

Open
RomneyDa wants to merge 2 commits into
linq-team:mainfrom
RomneyDa:linq-sdk-runtime-alignment
Open

Align Linq messaging with the OpenClaw channel runtime#10
RomneyDa wants to merge 2 commits into
linq-team:mainfrom
RomneyDa:linq-sdk-runtime-alignment

Conversation

@RomneyDa

@RomneyDa RomneyDa commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Summary

  • route Linq inbound messages through the shared channel ingress, pairing, context, and inbound-turn runtime
  • add normalized message receipts and canonical outbound session routing so current OpenClaw hosts can resume the matching phone session
  • split gateway transport from inbound policy/dispatch and expose strict, recursive SDK/manifest channel config schemas
  • retain OpenClaw 2026.6.1 compatibility while supplying the exact-recipient and account-scoping hints consumed by OpenClaw 2026.7.1+
  • split setup discovery from runtime channel loading and type-check the setup adapter against the public wizard contract

Validation

  • clean install against OpenClaw 2026.7.1: typecheck and 11 files / 41 tests pass
  • isolated install against the minimum OpenClaw 2026.6.1 peer: typecheck and 11 files / 41 tests pass
  • actual OpenClaw 2026.6.1 runtime loader: plugin status loaded, Linq channel registered, strict recursive account schema exposed, and plugins doctor reports no issues
  • complete live sandbox inbound/reply/restart test on OpenClaw 2026.6.1, detailed below
  • two independent Codex review passes; all findings addressed, including reply prefixes, pairing account scope, nested schema parity, and non-blocking best-effort presence calls

Live OpenClaw 2026.6.1 proof

  • started the plugin under the published OpenClaw 2026.6.1 package and confirmed the gateway identified itself as 2026.6.1
  • created a temporary active, phone-scoped message.received subscription targeting a public tunnel
  • confirmed the public route returned 405 for GET and 401 for an unsigned POST
  • received the real provider-signed hello61 message from the sandbox sender
  • routed the event through OpenClaw, ran the configured agent, and delivered Hey Dallin — I’m here. to the same Linq chat; the provider API recorded both messages
  • verified session metadata persisted lastChannel: linq, the account, and the exact linq:chat:<chat_id> delivery target
  • fully stopped and restarted the 2026.6.1 gateway
  • delivered Linq 6.1 restart route verified. from the stored session; OpenClaw reported deliverySucceeded: true and Linq recorded the message
  • deleted the temporary subscription, stopped the gateway and tunnel, and removed temporary configs/signing-secret state

No sandbox token, phone number, signing secret, chat ID, or tunnel URL is included in this PR.

Compatibility notes

  • the peer requirement is openclaw >=2026.6.1; OpenClaw 7.1 is not a prerequisite
  • preserves the existing Linq dmPolicy: open behavior while using shared ingress
  • chat targets remain account-scoped; canonical phone targets include the 7.1 exact-recipient hint
  • OpenClaw 6.1 supports inbound sessions, persisted replies, message-tool sends, receipts, setup, and restart-safe delivery; it ignores the newer optional hints
  • recipient-aware session selection for one-shot openclaw agent --channel linq --to ... runs is a host capability added in OpenClaw 7.1
  • configured response prefixes and model-dependent prefix context flow through the shared reply pipeline

Next phases

This completes messaging runtime alignment. The stacked #12 handles webhook onboarding correctness next; structured status and guided smoke diagnostics follow in Phase 2. FaceTime Audio work remains gated on a supported Linq call-control and duplex-media contract; once available, the planned sequence is voice config/security, call lifecycle, authenticated media transport, shared OpenClaw realtime-voice bridging, and production hardening.

@RomneyDa
RomneyDa force-pushed the linq-sdk-runtime-alignment branch from 26dd4d3 to c98e1a6 Compare July 14, 2026 20:19
@RomneyDa

Copy link
Copy Markdown
Contributor Author

Compatibility correction after auditing the host-version boundary:

  • Restored the peer floor to openclaw >=2026.6.1. The plugin loads, typechecks, and passes all 39 tests against that release.
  • OpenClaw 2026.7.1 introduced core recipient-aware session selection for one-shot openclaw agent --channel linq --to ... runs and account IDs in pairing-request hook payloads. Those are optional host enhancements, not prerequisites for Linq messaging.
  • Linq now returns the 7.1 exact-recipient hint and supplies pairing account scope in a forward-compatible shape. OpenClaw 6.1 ignores those extra fields while retaining inbound routing, persisted chat replies, message-tool sends, receipts, and setup behavior.
  • Revalidated separately against 2026.6.1 and 2026.7.1: typecheck and 10 test files / 39 tests pass on both.

The PR description has been updated to make this boundary explicit.

@RomneyDa
RomneyDa force-pushed the linq-sdk-runtime-alignment branch from c98e1a6 to d3fd2d3 Compare July 14, 2026 20:45
@RomneyDa

Copy link
Copy Markdown
Contributor Author

Follow-up proof on head d3fd2d3:

I tested more than compilation against the minimum host. OpenClaw 2026.6.1 loaded the plugin runtime from an isolated state/config, registered the linq channel, exposed the strict recursive account schema, and openclaw plugins doctor reported no issues.

That loader test caught one real omission: openclaw.plugin.json still had the old permissive accounts.additionalProperties: true schema even though the runtime schema had been corrected. The manifest and runtime schemas now both recursively validate nested accounts, with a regression test covering both manifest surfaces.

Current matrix:

  • OpenClaw 2026.6.1: typecheck, 10 files / 40 tests, runtime plugin load, plugin doctor
  • OpenClaw 2026.7.1: typecheck, 10 files / 40 tests

The remaining version distinction is deliberate and documented: 7.1 adds recipient-aware session selection for one-shot CLI agent runs; it is not required for the rest of the Linq channel to operate.

@RomneyDa

Copy link
Copy Markdown
Contributor Author

Full minimum-version E2E is now complete. This was run with the published OpenClaw 2026.6.1 package, not the current host:

  • real signed sandbox hello61 inbound reached the plugin
  • OpenClaw ran the agent and Linq recorded the reply
  • session metadata persisted the linq:chat:<chat_id> target
  • after a full 6.1 gateway restart, delivery from that stored session reported deliverySucceeded: true and Linq recorded the restart-verification message
  • temporary subscription, gateway, tunnel, config, and signing-secret state were removed

The peer requirement remains openclaw >=2026.6.1; 7.1 is explicitly documented as an optional host enhancement only for recipient-aware one-shot CLI session selection. The PR description now contains the detailed proof.

@RomneyDa

Copy link
Copy Markdown
Contributor Author

Setup/runtime follow-up added on the current head (a1dcbbf):

  • setup-entry.ts now loads a dedicated setup plugin built from a shared setup/config/security base instead of importing the full runtime channel.
  • The full channel spreads the same base, preventing setup/runtime config drift.
  • Removed @ts-nocheck and corrected the adapter to the public ChannelSetupWizardAdapter contract.
  • Added an import-boundary regression test that fails if setup discovery loads the Linq gateway, outbound sender, or runtime module.
  • OpenClaw 2026.6.1 and 2026.7.1 both pass typecheck and 11 files / 41 tests.

This is the architecture finding assigned to #10; token prompting and provider-mutation guards remain on stacked #12.

@ghsmc ghsmc left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

solid refactor — approving. ran the suite against both openclaw 2026.7.1 and the 2026.6.1 minimum peer: typecheck clean and 41/41 tests pass on both, and every plugin-sdk import used here exists in 6.1, so the compat claim holds. also nice catch moving read receipts/typing behind sender authorization — the old monitor leaked presence to unauthorized senders.

a few comments, none blocking:

  1. src/linq/ingress.tsnormalizeLinqSender strips dots (plus spaces/parens/hyphens) and lowercases before allowlist/pairing matching. fine for phone formatting, but imessage handles can be emails, so j.doe@example.com and jdoe@example.com collide into one identity on the auth surface. i'd restrict the dot-stripping to phone-shaped senders. this is the one i'd like addressed before or shortly after merge.

  2. src/linq/inbound.ts — context extra hardcodes WasMentioned: true, CommandAuthorized: true. equivalent today since dispatch only happens post-authorization, but it throws away any finer-grained authorization.senderAccess the shared ingress result carries.

  3. src/linq/inbound.test.ts — one test uses dmPolicy: "allowlist", which isn't a legal value in the plugin's own config schema (pairing|open|disabled). it only compiles because tests are excluded from typecheck. either add allowlist to the enum if that's the intent, or point the test at a reachable policy.

  4. fyi: reply context moved from the visible [Replying to message <id>] body suffix to extra.ReplyToId — if the shared context builder doesn't render that, agents lose visible reply context.

  5. fyi, pre-existing not a regression: with no webhookSecret configured and the default dmPolicy: open, an unsigned POST to the webhook path dispatches the agent fully command-authorized. carried over unchanged (hmac + 300s replay window intact when a secret is set) but deserves a startup warning at some point.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants