docs: add plugin core and Telegram/OpenClaw adapter skeleton / 補 reply-end-controls 核心與 Telegram/OpenClaw 設計骨架
This commit is contained in:
34
adapters/openclaw.md
Normal file
34
adapters/openclaw.md
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
# OpenClaw Adapter Design
|
||||||
|
|
||||||
|
## Goal
|
||||||
|
|
||||||
|
Describe how reply-end-controls should connect to OpenClaw without baking all logic directly into Telegram-specific code.
|
||||||
|
|
||||||
|
## Adapter responsibilities
|
||||||
|
|
||||||
|
### Outbound integration
|
||||||
|
|
||||||
|
- detect final assistant reply payloads
|
||||||
|
- append Telegram buttons
|
||||||
|
|
||||||
|
### Callback integration
|
||||||
|
|
||||||
|
- receive Telegram callback query events from OpenClaw's Telegram plugin layer
|
||||||
|
- normalize callback payload
|
||||||
|
- pass normalized event to reply-end-controls core
|
||||||
|
|
||||||
|
### State integration
|
||||||
|
|
||||||
|
- store reply-end state in OpenClaw conversation/session state
|
||||||
|
- expose the state to later assistant turns
|
||||||
|
|
||||||
|
### Policy integration
|
||||||
|
|
||||||
|
- before later assistant output generation, expose `lastChoice`
|
||||||
|
- if `stop`, suppress proactive continuation behavior
|
||||||
|
|
||||||
|
## V1 expectation
|
||||||
|
|
||||||
|
The OpenClaw adapter is the first concrete runtime adapter for the project.
|
||||||
|
|
||||||
|
Even though Telegram is the only supported channel, the logic should still be split so the reusable core is not trapped inside one Telegram-only handler implementation.
|
||||||
37
core/callback-contract.md
Normal file
37
core/callback-contract.md
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
# Callback Contract
|
||||||
|
|
||||||
|
## Goal
|
||||||
|
|
||||||
|
Define a stable callback payload contract between channel-specific button handlers and the reusable reply-end-controls core.
|
||||||
|
|
||||||
|
## Telegram V1 callback values
|
||||||
|
|
||||||
|
- `rec:continue`
|
||||||
|
- `rec:stop`
|
||||||
|
|
||||||
|
## Optional message-scoped extension
|
||||||
|
|
||||||
|
If V1 needs tighter message binding later, extend to:
|
||||||
|
|
||||||
|
- `rec:continue:<messageId>`
|
||||||
|
- `rec:stop:<messageId>`
|
||||||
|
|
||||||
|
## Normalized internal event
|
||||||
|
|
||||||
|
Suggested normalized structure after channel parsing:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"choice": "continue | stop",
|
||||||
|
"conversationId": "string",
|
||||||
|
"sessionKey": "string | null",
|
||||||
|
"sourceMessageId": "string",
|
||||||
|
"sourceCallbackId": "string",
|
||||||
|
"channel": "telegram",
|
||||||
|
"timestamp": "ISO timestamp"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Why normalize
|
||||||
|
|
||||||
|
The Telegram parser should convert platform-specific callback payloads into one internal structure, so the reusable policy/state layer does not need to know Telegram details.
|
||||||
29
core/policy.md
Normal file
29
core/policy.md
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
# Policy
|
||||||
|
|
||||||
|
## Goal
|
||||||
|
|
||||||
|
Define how reply-end choices influence later assistant behavior.
|
||||||
|
|
||||||
|
## Policy rules
|
||||||
|
|
||||||
|
### If `lastChoice = continue`
|
||||||
|
|
||||||
|
- assistant/runtime may continue normal follow-up behavior
|
||||||
|
- assistant may keep short-term task momentum
|
||||||
|
|
||||||
|
### If `lastChoice = stop`
|
||||||
|
|
||||||
|
- assistant should not proactively extend the previous thread
|
||||||
|
- assistant should avoid unnecessary follow-up prompts
|
||||||
|
- assistant should treat the prior exchange as closed
|
||||||
|
|
||||||
|
### If user types a new message
|
||||||
|
|
||||||
|
- typed input takes priority over button state
|
||||||
|
- the new message may implicitly reopen the interaction
|
||||||
|
|
||||||
|
## V1 constraint
|
||||||
|
|
||||||
|
V1 only needs to influence continuation behavior.
|
||||||
|
|
||||||
|
It does not need to redesign routing, tool permissions, or long-term memory behavior.
|
||||||
49
core/state-model.md
Normal file
49
core/state-model.md
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
# State Model
|
||||||
|
|
||||||
|
## Goal
|
||||||
|
|
||||||
|
Define the agent-neutral state model for reply-end controls.
|
||||||
|
|
||||||
|
This state should be reusable across multiple agents, while Telegram remains the first delivery channel.
|
||||||
|
|
||||||
|
## Core state
|
||||||
|
|
||||||
|
Suggested canonical structure:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"replyEndControls": {
|
||||||
|
"lastChoice": "continue | stop",
|
||||||
|
"lastChoiceAt": "ISO timestamp",
|
||||||
|
"sourceMessageId": "string",
|
||||||
|
"sourceCallbackId": "string",
|
||||||
|
"active": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Field meanings
|
||||||
|
|
||||||
|
- `lastChoice`
|
||||||
|
- the latest explicit user choice
|
||||||
|
- `lastChoiceAt`
|
||||||
|
- when the choice was made
|
||||||
|
- `sourceMessageId`
|
||||||
|
- the assistant message whose buttons were clicked
|
||||||
|
- `sourceCallbackId`
|
||||||
|
- the callback event id from the channel
|
||||||
|
- `active`
|
||||||
|
- whether the latest state should still affect later assistant behavior
|
||||||
|
|
||||||
|
## Semantics
|
||||||
|
|
||||||
|
- `continue`
|
||||||
|
- the conversation should remain open to follow-up handling
|
||||||
|
- `stop`
|
||||||
|
- the conversation should be treated as closed unless the user explicitly types a new instruction
|
||||||
|
|
||||||
|
## Reset rules
|
||||||
|
|
||||||
|
- A new typed user message overrides prior button state.
|
||||||
|
- A later `continue` click overrides an earlier `stop` click.
|
||||||
|
- The system may optionally expire stale button state in a later version, but V1 does not require timeout expiry.
|
||||||
20
telegram/callback-handler.md
Normal file
20
telegram/callback-handler.md
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
# Telegram Callback Handler
|
||||||
|
|
||||||
|
## Responsibility
|
||||||
|
|
||||||
|
Receive Telegram callback queries, parse reply-end button clicks, normalize them, and hand them off to the reusable state/policy layer.
|
||||||
|
|
||||||
|
## V1 actions
|
||||||
|
|
||||||
|
- parse `rec:continue`
|
||||||
|
- parse `rec:stop`
|
||||||
|
- map into normalized callback event
|
||||||
|
- write updated state
|
||||||
|
- update original message buttons to show resolved choice
|
||||||
|
|
||||||
|
## V1 UI behavior after click
|
||||||
|
|
||||||
|
Suggested resolved button state:
|
||||||
|
|
||||||
|
- selected option gains a clear marker
|
||||||
|
- the message should not remain indefinitely clickable as if no decision happened
|
||||||
22
telegram/reply-decorator.md
Normal file
22
telegram/reply-decorator.md
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
# Telegram Reply Decorator
|
||||||
|
|
||||||
|
## Responsibility
|
||||||
|
|
||||||
|
Append inline keyboard controls to every assistant reply sent to Telegram.
|
||||||
|
|
||||||
|
## Required controls
|
||||||
|
|
||||||
|
- `A. 繼續`
|
||||||
|
- `B. 就這樣吧,不需要額外處理`
|
||||||
|
|
||||||
|
## Output shape
|
||||||
|
|
||||||
|
The Telegram outbound payload should include:
|
||||||
|
|
||||||
|
- normal reply text
|
||||||
|
- inline keyboard markup
|
||||||
|
|
||||||
|
## V1 behavior
|
||||||
|
|
||||||
|
- every assistant reply gets the two buttons
|
||||||
|
- no conditional rendering in V1
|
||||||
Reference in New Issue
Block a user