Skip to content

fix(plugins): export waitForAbortSignal from plugin-sdk#30059

Closed
kevinWangSheng wants to merge 8 commits intoopenclaw:mainfrom
kevinWangSheng:fix/nextcloud-talk-abort-signal-export
Closed

fix(plugins): export waitForAbortSignal from plugin-sdk#30059
kevinWangSheng wants to merge 8 commits intoopenclaw:mainfrom
kevinWangSheng:fix/nextcloud-talk-abort-signal-export

Conversation

@kevinWangSheng
Copy link

Summary

  • Export waitForAbortSignal from the plugin SDK so extensions can import it from openclaw/plugin-sdk instead of using a relative path that breaks in the built project.

Fixes #30057

Problem

The nextcloud-talk extension fails when using the built version because it imports waitForAbortSignal from a relative path that doesn't exist in the compiled output:

Error: Cannot find module '/home/claw/.npm-global/lib/node_modules/openclaw/dist/plugin-sdk/index.js/infra/abort-signal'

Changes

  1. src/plugin-sdk/index.ts — Export waitForAbortSignal from ../infra/abort-signal.js
  2. extensions/nextcloud-talk/src/channel.ts — Import waitForAbortSignal from openclaw/plugin-sdk instead of the relative path

Test plan

  • Verified the export is added to plugin-sdk
  • Verified the import is updated in nextcloud-talk extension
  • Code compiles without errors

Kevin Shenghui and others added 8 commits February 28, 2026 09:46
Add allowMissingTarget option to assertPathSafety for write, mkdirp,
and rename operations. This fixes the regression where creating new
files fails with 'cannot create directories' error, even when the
workspace has rw access.

The issue occurs because assertPathSafety was checking for file
existence before allowing directory creation, but for new files the
parent directory may not have the target file yet.

Fixes openclaw#28734
Add allowMissingTarget option to assertPathSafety for write, mkdirp,
and rename operations. This fixes the regression where creating new
files fails with 'cannot create directories' error, even when the
workspace has rw access.

The issue occurs because assertPathSafety was checking for file
existence before allowing directory creation, but for new files the
parent directory may not have the target file yet.

Fixes openclaw#28734
Export waitForAbortSignal from the plugin SDK so extensions can import it
from 'openclaw/plugin-sdk' instead of using a relative path that breaks
in the built project.

Fixes openclaw#30057
@openclaw-barnacle openclaw-barnacle bot added channel: discord Channel integration: discord channel: nextcloud-talk Channel integration: nextcloud-talk channel: telegram Channel integration: telegram channel: whatsapp-web Channel integration: whatsapp-web gateway Gateway runtime agents Agent runtime and tooling size: M trusted-contributor labels Feb 28, 2026
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6c4053650c

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

* Response behavior when an unpaired (unauthorized) user sends a message.
* @default "silent"
*/
unpairedResponse?: UnpairedResponseMode;

Choose a reason for hiding this comment

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

P1 Badge Register unpairedResponse in config validation schemas

channels.defaults.unpairedResponse is added to the public config types here, but the runtime validator still rejects it: ChannelsSchema.defaults is .strict() and only permits groupPolicy/heartbeat in src/config/zod-schema.providers.ts:27-33. In practice, any user who sets unpairedResponse in their config will fail loadConfig with an unknown-key validation error, so the new behavior cannot be enabled in real deployments.

Useful? React with 👍 / 👎.

code,
mode: getUnpairedResponseMode(cfg),
})
: "Pairing already requested. Ask the bot owner to approve your code.";

Choose a reason for hiding this comment

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

P2 Badge Respect silent mode for repeat Discord pairing requests

When dmPolicy is pairing and a request already exists (created === false), this branch hardcodes a non-null reply string, so the later responseText !== null guard still sends a message even if unpaired response mode is silent. That means unauthorized users who message twice will still get a response, which breaks the documented "do not respond" behavior for silent mode.

Useful? React with 👍 / 👎.

const dmAuthorized = await enforceTelegramDmAccess({
isGroup: event.isGroup,
dmPolicy,
unpairedResponse: getUnpairedResponseMode(loadConfig()),

Choose a reason for hiding this comment

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

P2 Badge Honor Telegram account unpairedResponse overrides

The Telegram account type now exposes unpairedResponse, but this call site always passes getUnpairedResponseMode(loadConfig()), and that helper only reads cfg.channels.defaults.unpairedResponse (src/pairing/unpaired-response.ts:9-10). As a result, channels.telegram.accounts.<id>.unpairedResponse is never used, so per-account overrides silently do nothing.

Useful? React with 👍 / 👎.

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Feb 28, 2026

Greptile Summary

This PR exports waitForAbortSignal from the plugin SDK to fix import issues in the nextcloud-talk extension. However, the PR contains significantly more changes than described:

What's included (but not mentioned in PR description):

  • Unpaired Response Silent Mode Feature (majority of changes):

    • Adds UnpairedResponseMode type with "silent", "code-only", and "branded" options
    • Implements security feature to control responses to unauthorized users
    • Updates Telegram, Discord, and WhatsApp channels to support this mode
    • Adds test configuration to maintain backward compatibility
    • Defaults to "silent" mode for new configs (security improvement)
  • Sandbox filesystem changes: Adds allowMissingTarget parameter for write/mkdir/rename operations

  • Server cron changes: Narrows agentEntry type handling

Issues Found:

  1. Telegram account-level override not working: The TelegramAccountConfig.unpairedResponse field is defined in types with documented fallback behavior, but the implementation only reads the global default, ignoring per-account overrides (see inline comment on bot-handlers.ts:1371)

Verification:

  • waitForAbortSignal export is correct
  • ✅ Nextcloud-talk import updated properly
  • ⚠️ Unpaired response feature appears functional but has incomplete account-level override support for Telegram

Confidence Score: 3/5

  • This PR is safe to merge with minor issues that should be addressed
  • Score of 3 reflects that while the code changes are technically correct and the waitForAbortSignal export fix works as intended, there are important concerns: (1) The PR mixes multiple unrelated features making review difficult - the title/description only mention the plugin SDK export, but the PR actually includes a significant security feature (unpaired response silent mode), sandbox changes, and cron changes. (2) The Telegram account-level unpairedResponse override is defined in types but not implemented, which could confuse users trying to configure per-account behavior. The core functionality appears sound, tests are updated appropriately, and the security feature defaults to "silent" mode which is good. However, the incomplete implementation of account-level overrides and scope mismatch prevent a higher score.
  • Pay close attention to src/telegram/bot-handlers.ts and src/telegram/bot-message-context.ts where account-level unpairedResponse overrides should be implemented

Last reviewed commit: 6c40536

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

16 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

const dmAuthorized = await enforceTelegramDmAccess({
isGroup: event.isGroup,
dmPolicy,
unpairedResponse: getUnpairedResponseMode(loadConfig()),
Copy link
Contributor

Choose a reason for hiding this comment

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

Account-level unpairedResponse override not being used. The code should check telegramCfg.unpairedResponse first before falling back to the global default, similar to how dmPolicy is handled on line 616:

Suggested change
unpairedResponse: getUnpairedResponseMode(loadConfig()),
unpairedResponse: telegramCfg.unpairedResponse ?? getUnpairedResponseMode(loadConfig()),
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/telegram/bot-handlers.ts
Line: 1371

Comment:
Account-level `unpairedResponse` override not being used. The code should check `telegramCfg.unpairedResponse` first before falling back to the global default, similar to how `dmPolicy` is handled on line 616:

```suggestion
          unpairedResponse: telegramCfg.unpairedResponse ?? getUnpairedResponseMode(loadConfig()),
```

How can I resolve this? If you propose a fix, please make it concise.

!(await enforceTelegramDmAccess({
isGroup,
dmPolicy,
unpairedResponse: getUnpairedResponseMode(loadConfig()),
Copy link
Contributor

Choose a reason for hiding this comment

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

Account-level unpairedResponse override not implemented here. The Telegram config type defines this field with fallback to global defaults, but this function doesn't have access to the telegram account config to check the account-level setting. Consider passing telegramCfg to this function to support the account-level override.

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/telegram/bot-message-context.ts
Line: 281

Comment:
Account-level `unpairedResponse` override not implemented here. The Telegram config type defines this field with fallback to global defaults, but this function doesn't have access to the telegram account config to check the account-level setting. Consider passing `telegramCfg` to this function to support the account-level override.

How can I resolve this? If you propose a fix, please make it concise.

@openclaw-barnacle
Copy link

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 Mar 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling channel: discord Channel integration: discord channel: nextcloud-talk Channel integration: nextcloud-talk channel: telegram Channel integration: telegram channel: whatsapp-web Channel integration: whatsapp-web gateway Gateway runtime size: M stale Marked as stale due to inactivity

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: nextcloud-talk extension fails to load: abort-signal.js import not available in built project

2 participants