Skip to content

feat(plugin-sdk): export transcript.runtime subpath#80208

Closed
clriesco wants to merge 1 commit into
openclaw:mainfrom
clriesco:feat/plugin-sdk-transcript-runtime-export
Closed

feat(plugin-sdk): export transcript.runtime subpath#80208
clriesco wants to merge 1 commit into
openclaw:mainfrom
clriesco:feat/plugin-sdk-transcript-runtime-export

Conversation

@clriesco

@clriesco clriesco commented May 10, 2026

Copy link
Copy Markdown

Summary

  • Problem: Channel plugins that need to record outbound assistant turns to a session transcript have no public API. recordInboundSession covers user turns only; appendAssistantMessageToSessionTranscript already exists in the source tree but is not exported via package.json.
  • Why it matters: Plugin authors either reach into internal paths (fragile across openclaw versions) or duplicate runtime logic the helper already implements correctly.
  • What changed: Exposes the existing helpers via openclaw/plugin-sdk/transcript.runtime — one new re-export file, one entry in scripts/lib/plugin-sdk-entrypoints.json, four lines in package.json exports auto-generated by scripts/sync-plugin-sdk-exports.mjs.
  • What did NOT change (scope boundary): No runtime behavior change. No new functions added; the helpers already shipped, only the public surface is updated.

Change Type

  • Feature (new public SDK surface)

Scope

  • API / contracts

Linked Issue/PR

  • Closes #
  • Related #
  • This PR fixes a bug or regression

N/A — small DX gap discovered while building a third-party agent-link channel plugin that needs to persist a sender's outbound assistant turn into its own session transcript when the send is issued from a different session than where the peer's reply will land.

Real behavior proof (required for external PRs)

  • Behavior or issue addressed: await import("openclaw/plugin-sdk/transcript.runtime") cannot resolve in published builds because the subpath is missing from package.json exports, even though appendAssistantMessageToSessionTranscript exists in the source tree at src/config/sessions/transcript.runtime.ts.

  • Real environment tested: Linux x86_64, Node v25, pnpm 10.33.2. Local clone of this branch. No mocks — the proof is a real node --import tsx invocation against the actual source file the new subpath re-exports, plus an inspection of the generated .d.ts artifact.

  • Exact steps or command run after this patch:

    cd ~/code/openclaw                # branch: feat/plugin-sdk-transcript-runtime-export
    pnpm install --frozen-lockfile
    pnpm build:plugin-sdk:strict-smoke
    ls dist/plugin-sdk/transcript.runtime.d.ts
    cat dist/plugin-sdk/transcript.runtime.d.ts
    node --import tsx --eval "
      import('./src/plugin-sdk/transcript.runtime.ts').then(m => {
        console.log('keys:', Object.keys(m).sort());
        console.log('append type:', typeof m.appendAssistantMessageToSessionTranscript);
        console.log('appendExact type:', typeof m.appendExactAssistantMessageToSessionTranscript);
      });
    "
    
  • Evidence after fix (terminal output, copied live):

    $ ls dist/plugin-sdk/transcript.runtime.d.ts
    dist/plugin-sdk/transcript.runtime.d.ts
    
    $ cat dist/plugin-sdk/transcript.runtime.d.ts
    export * from "./src/plugin-sdk/transcript.runtime.js";
    
    $ node --import tsx --eval "..."
    keys: [ 'appendAssistantMessageToSessionTranscript',
            'appendExactAssistantMessageToSessionTranscript' ]
    append type: function
    appendExact type: function
    

    Same node --import tsx invocation against the linuxbrew-installed [email protected] (without this patch) fails with ERR_MODULE_NOT_FOUND for the openclaw/plugin-sdk/transcript.runtime specifier, confirming the gap this PR closes.

  • Observed result after fix: The new subpath resolves through Node's source-level resolver. The strict-smoke build emits dist/plugin-sdk/transcript.runtime.d.ts whose body matches the export * from "./src/..." shape used by existing public entries (e.g. session-store-runtime.d.ts). Both appendAssistantMessageToSessionTranscript and appendExactAssistantMessageToSessionTranscript are reachable as functions through the new public surface.

  • What was not tested: The full pnpm build (tsdown), full pnpm check, and full pnpm test lanes were not exercised in my local environment because tsdown is killed by SIGKILL on this 3.8 GB host after several minutes of progress-less heap growth. Repo CI is the source of truth for those lanes. The mechanical change is isomorphic to existing entries, so a mismatch would surface in scripts/check-plugin-sdk-subpath-exports.mjs, pnpm plugin-sdk:check-exports, or the strict-smoke lane — all three are green locally.

  • Before evidence (optional but encouraged): Same node --import tsx invocation pointing the specifier at the linuxbrew-installed [email protected] returns:

    Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'openclaw/plugin-sdk/transcript.runtime' ...
    

Root Cause (if applicable)

N/A — this is an exposure gap, not a regression. The helpers existed; the export entry was missing.

Regression Test Plan (if applicable)

  • Coverage level that should have caught this:
    • Unit test
    • Seam / integration test
    • End-to-end test
    • Existing coverage already sufficient
  • Target test or file: scripts/check-plugin-sdk-subpath-exports.mjs, scripts/sync-plugin-sdk-exports.mjs --check, pnpm build:plugin-sdk:strict-smoke.
  • Scenario the test should lock in: Every openclaw/plugin-sdk/<subpath> referenced in source is listed in plugin-sdk-entrypoints.json and package.json exports.
  • Why this is the smallest reliable guardrail: The existing scripts already enforce subpath/exports parity once an entry is added. The same scripts are run as part of this PR and report no drift.
  • Existing test that already covers this (if any): The two scripts above.
  • If no new test is added, why not: No new behavior; only a re-export of existing helpers. Adding a unit test would only assert the re-export shape, which the strict-smoke lane and the subpath-exports check already cover.

User-visible / Behavior Changes

None. New public subpath; existing imports unchanged.

Diagram (if applicable)

N/A.

Security Impact (required)

  • New permissions/capabilities? No
  • Secrets/tokens handling changed? No
  • New/changed network calls? No
  • Command/tool execution surface changed? No
  • Data access scope changed? No

Repro + Verification

Environment

  • OS: Linux x86_64
  • Runtime/container: Node v25, pnpm 10.33.2
  • Model/provider: N/A
  • Integration/channel (if any): consumer is a third-party agent-link plugin
  • Relevant config (redacted): N/A

Steps

  1. Clone this branch.
  2. pnpm install --frozen-lockfile
  3. pnpm build:plugin-sdk:strict-smoke
  4. node --import tsx --eval "import('./src/plugin-sdk/transcript.runtime.ts').then(m => console.log(Object.keys(m).sort()))"

Expected

[ 'appendAssistantMessageToSessionTranscript', 'appendExactAssistantMessageToSessionTranscript' ]

Actual

Matches expected; see evidence block above.

Evidence

  • Trace/log snippets (terminal output copied above)

Human Verification (required)

  • Verified scenarios: source-level resolution of the new subpath; correct shape of the generated .d.ts; mechanical isomorphism with existing entries (the subpath-exports check, the sync check, and the strict-smoke build all green); negative case against the published linuxbrew install reproduces ERR_MODULE_NOT_FOUND.
  • Edge cases checked: pnpm plugin-sdk:check-exports confirms package.json exports are in sync with the entrypoint list; pnpm lint:extensions:no-plugin-sdk-wildcard-reexports confirms the new file uses named exports, not wildcards; boundary report (scripts/check-sdk-package-extension-import-boundary.mjs --json) returns [].
  • What I did not verify: full tsdown build, full pnpm check, full pnpm test lanes (local RAM constraint). Repo CI is authoritative there.

Review Conversations

  • I will reply to or resolve every bot review conversation I address in this PR.
  • I will leave open only conversations that need maintainer or reviewer judgment.

Compatibility / Migration

  • Backward compatible? Yes (additive)
  • Config/env changes? No
  • Migration needed? No

Risks and Mitigations

  • Risk: Public SDK surface grows by two function exports.
    • Mitigation: Functions are existing implementations exercised by the runtime today. This PR only updates the published surface; no new behavior.

AI-assisted

This PR was prepared with Claude Code (claude-opus-4.7) assistance. Reviewed and authored by @clriesco.

Adds a new `openclaw/plugin-sdk/transcript.runtime` public subpath
re-exporting `appendAssistantMessageToSessionTranscript` and
`appendExactAssistantMessageToSessionTranscript` from the existing
internal `src/config/sessions/transcript.runtime.ts` module.

Channel plugins that need to record outbound assistant messages
directly into a session transcript (e.g. agent-link, where the
sender's outbound is initiated from a session distinct from the
one the reply will be delivered to) currently have no public way
to do so. Existing `recordInboundSession` only covers user turns.

The new entry follows the existing plugin-sdk subpath conventions:
listed in scripts/lib/plugin-sdk-entrypoints.json and synced into
package.json exports via scripts/sync-plugin-sdk-exports.mjs.
@openclaw-barnacle openclaw-barnacle Bot added scripts Repository scripts size: XS labels May 10, 2026
@clawsweeper

clawsweeper Bot commented May 10, 2026

Copy link
Copy Markdown
Contributor

Thanks for the context here. I swept through the related work, and this is now duplicate or superseded.

Close: merged #95030 supersedes this narrower raw helper export with the documented openclaw/plugin-sdk/session-transcript-runtime contract on current main, including append, publish, target, lock, docs, and tests.

Canonical path: Keep the merged openclaw/plugin-sdk/session-transcript-runtime API as the canonical transcript plugin surface and close this narrower raw-helper export branch.

So I’m closing this here and keeping the remaining discussion on #95030.

Review details

Best possible solution:

Keep the merged openclaw/plugin-sdk/session-transcript-runtime API as the canonical transcript plugin surface and close this narrower raw-helper export branch.

Do we have a high-confidence way to reproduce the issue?

Not applicable. This is a public SDK surface PR rather than a bug report; source inspection and the merged replacement PR establish the current behavior.

Is this the best way to solve the issue?

No, this PR is no longer the best path. Current main uses a documented session-transcript-runtime API that covers identity, target, append, publish, and locking semantics instead of exporting raw internal helpers.

Security review:

Security review needs attention: The diff has no supply-chain change, but the proposed raw public transcript writer subpath would expand durable plugin write authority after a structured replacement exists.

  • [medium] Raw transcript writer becomes public SDK — src/plugin-sdk/transcript.runtime.ts:7
    Publishing appendAssistantMessageToSessionTranscript directly would expose persistent session transcript writes through a raw helper surface rather than the documented identity, target, and write-lock contract now on current main.
    Confidence: 0.84

AGENTS.md: found and applied where relevant.

What I checked:

  • Root policy read: Root AGENTS.md was read fully and applied; it treats plugin APIs, session state, persisted preferences, migrations, and security boundaries as compatibility-sensitive review surfaces. (AGENTS.md:26, ad304e790d0c)
  • Scoped SDK policy read: The scoped Plugin SDK policy defines this directory as the public contract between plugins and core and requires narrow, aligned public subpaths. (src/plugin-sdk/AGENTS.md:1, ad304e790d0c)
  • Current main exports canonical subpath: Current main publishes ./plugin-sdk/session-transcript-runtime in package.json and lists session-transcript-runtime in the SDK entrypoint registry. (package.json:978, ad304e790d0c)
  • Current main implements append-capable SDK API: appendSessionTranscriptMessageByIdentity is implemented in the canonical SDK module and routes through the session accessor append path rather than exposing the raw internal helper name. (src/plugin-sdk/session-transcript-runtime.ts:121, ad304e790d0c)
  • Current docs point plugins to replacement API: The SDK runtime docs direct plugin authors to import openclaw/plugin-sdk/session-transcript-runtime for transcript identity, target, read, append, publish, and write-lock workflows. Public docs: docs/plugins/sdk-runtime.md. (docs/plugins/sdk-runtime.md:169, ad304e790d0c)
  • Replacement tests cover the behavior: The current-main tests cover durable assistant-message append through the canonical SDK module, along with identity, active-target binding, publish, and write-lock behavior. (src/plugin-sdk/session-transcript-runtime.test.ts:147, ad304e790d0c)

Likely related people:

  • jalehman: Authored the merged replacement PR that added the documented structured transcript runtime SDK subpath, tests, docs, and export metadata. (role: canonical implementation author; confidence: high; commits: 7a0d36f3d0e1, 1125743c7023; files: src/plugin-sdk/session-transcript-runtime.ts, src/plugin-sdk/session-transcript-runtime.test.ts, docs/plugins/sdk-runtime.md)
  • vincentkoc: Current checkout blame attributes the present replacement SDK export, package export, and docs snapshot to recent main integration commits, so this is a routing signal for current-main state rather than original authorship. (role: recent current-main provenance signal; confidence: medium; commits: 8c0767ffa4de, 2800ce4e28bf; files: src/plugin-sdk/session-transcript-runtime.ts, package.json, docs/plugins/sdk-runtime.md)
  • shakkernerd: History shows the internal transcript runtime facade and outbound transcript mirroring path were refactored in related work before the public SDK replacement landed. (role: adjacent transcript runtime contributor; confidence: medium; commits: 4a81771290a8; files: src/config/sessions/transcript.runtime.ts, src/config/sessions/transcript.ts, src/infra/outbound/deliver.ts)
  • steipete: History shows delivered outbound message mirroring originally added the internal assistant transcript append behavior that this PR wanted to expose. (role: introduced adjacent behavior; confidence: medium; commits: fdaeada3ec76; files: src/config/sessions/transcript.ts, src/infra/outbound/deliver.ts)

Codex review notes: model internal, reasoning high; reviewed against ad304e790d0c; fix evidence: commit 7a0d36f3d0e1, main fix timestamp 2026-06-20T21:01:07Z.

@openclaw-barnacle openclaw-barnacle Bot added the proof: supplied External PR includes structured after-fix real behavior proof. label May 10, 2026
@clriesco

Copy link
Copy Markdown
Author

The five red checks (check, check-additional, check-additional-extension-bundled, check-dependencies, check-lint) are all pre-existing failures on main, unrelated to this PR. The first two are aggregator jobs that simply propagate the other three.

Concretely, each of the three underlying failures reproduces on main right now:

Error Reproduces on main
Prefer String#slice() over String#substring() (in scripts/) run 25625451283 — same line in check-lint
'fetchImpl.mock.calls[1]?.[1]?.body' may use Object's default stringification (in a test mock) run 25625451283 — same line in check-lint and check-additional-extension-bundled
Unexpected unused files: extensions/qa-lab/src/live-transports/telegram/telegram-user-credential.runtime.ts runs 25625557384 and 25625451283 — same path in check-dependencies

None of these touch the files this PR modifies (src/plugin-sdk/transcript.runtime.ts, scripts/lib/plugin-sdk-entrypoints.json, package.json exports). Per CONTRIBUTING.md (> Do not submit test or CI-config fixes for failures already red on main CI), this PR does not address them.

The relevant gates for this change are green:

  • Critical Quality (plugin-sdk-package-contract) — pass
  • Critical Quality (plugin-boundary) — pass
  • check-strict-smoke — pass
  • check-additional-extension-package-boundary — pass
  • checks-fast-contracts-plugins-{a,b,c,d} — pass
  • Real behavior proof — pass

@openclaw-barnacle

Copy link
Copy Markdown

This pull request has been automatically marked as stale due to inactivity.
Please add updates or it will be closed.

@openclaw-barnacle openclaw-barnacle Bot added the stale Marked as stale due to inactivity label Jun 1, 2026
@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P2 Normal backlog priority with limited blast radius. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 session-state 🚨 May lose, corrupt, stale, or mis-associate session, agent, or context state. merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. labels Jun 1, 2026
@openclaw-barnacle openclaw-barnacle Bot removed the stale Marked as stale due to inactivity label Jun 2, 2026
@clawsweeper clawsweeper Bot added rating: 🌊 off-meta tidepool PR readiness rating does not apply to this item. and removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Jun 2, 2026
@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. and removed rating: 🌊 off-meta tidepool PR readiness rating does not apply to this item. labels Jun 14, 2026
@clawsweeper clawsweeper Bot added rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. and removed rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. labels Jun 19, 2026
@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. and removed rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. labels Jun 20, 2026
@clawsweeper clawsweeper Bot added the rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. label Jun 22, 2026
@clawsweeper

clawsweeper Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

ClawSweeper applied the proposed close for this PR.

  • Action: closed this PR.
  • Close reason: duplicate or superseded.
  • Evidence: durable ClawSweeper review.
  • Coverage proof: PR B clearly carries PR A's useful intent in a stronger canonical API, and the only omitted piece is PR A's exact transcript.runtime alias/raw helper shape, which the source report treats as a competing surface that should not be landed independently. Covering PR: refactor: add SDK transcript identity target API #95030.

@clawsweeper clawsweeper Bot closed this Jun 22, 2026
@clriesco
clriesco deleted the feat/plugin-sdk-transcript-runtime-export branch June 22, 2026 06:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. merge-risk: 🚨 session-state 🚨 May lose, corrupt, stale, or mis-associate session, agent, or context state. P2 Normal backlog priority with limited blast radius. proof: supplied External PR includes structured after-fix real behavior proof. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. scripts Repository scripts size: XS status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant