Documentation
¶
Overview ¶
Package im contains the Feishu adapter.
Feishu Developer Console Setup ¶
To enable interactive card callbacks (e.g. ask_user buttons), the following must be configured in the Feishu Developer Console (开发者后台):
Under "Events & Callbacks" (事件与回调), set the connection mode to "Long Connection / WebSocket" (长连接).
Under "Events & Callbacks" → "Callback Configuration" (回调配置), add the callback: card.action.trigger (卡片回传交互回调).
IMPORTANT: This is in the "Callback Configuration" (回调配置) section, NOT in "Event Subscription" (事件订阅). Card callbacks and event subscriptions are separate sections. Without this step, card buttons will render but clicking them will produce error 200340 (card callback not configured).
The adapter uses the official Feishu Go SDK's larkws.NewClient for the WebSocket connection, which registers the callback capability with the Feishu platform so card.action.trigger events are delivered over the long connection.
Index ¶
- Constants
- Variables
- func BuildAskUserResponse(req toolpkg.AskUserRequest, parsed []ParsedQuestionAnswer) toolpkg.AskUserResponse
- func DefaultBindingsPath() (string, error)
- func DefaultPCSessionStorePath() (string, error)
- func DefaultPairingStatePath() (string, error)
- func EscapeMarkdownV2(text string) string
- func FormatAskUserPrompt(lang string, req toolpkg.AskUserRequest) string
- func FormatIMStatus(lang ToolLanguage, activity, toolName, toolArg string) string
- func FormatToolInline(name, detail string) string
- func HasWechatAdapter(mgr *Manager) bool
- func IsLocalFilePath(s string) bool
- func LastMessageID(b ChannelBinding) string
- func LocalizeIMProgress(lang ToolLanguage, text string) string
- func PCEncodeInviteToURI(invite PCInvite) (string, error)
- func ParseRemoteQuestionnaireAnswer(raw string, question toolpkg.AskUserQuestion) (selected map[string]struct{}, freeform string, err error)
- func SplitMessage(text string, maxLen int) []string
- func SplitMessageForPlatform(text string, p Platform) []string
- func SplitNonEmptyLines(text string) []string
- func StartNamedAdapter(parent context.Context, cfg config.IMConfig, name string, mgr *Manager) error
- type AdapterController
- func StartConfiguredAdapters(parent context.Context, cfg config.IMConfig, mgr *Manager) (*AdapterController, error)
- func StartCurrentBindingAdapter(parent context.Context, cfg config.IMConfig, mgr *Manager) (*AdapterController, error)
- func StartPCAdapterOnly(parent context.Context, cfg config.IMConfig, mgr *Manager) (*AdapterController, error)
- type AdapterDescriptor
- type AdapterState
- type ApprovalRequest
- type ApprovalResponse
- type ApprovalResult
- type ApprovalState
- type Attachment
- type AttachmentKind
- type BindingStore
- type Bridge
- type ChannelBinding
- type Closer
- type DaemonBridge
- func (b *DaemonBridge) ConsumeRestartDebug() bool
- func (b *DaemonBridge) HandleAskUser(ctx context.Context, req toolpkg.AskUserRequest) (toolpkg.AskUserResponse, error)
- func (b *DaemonBridge) Messages() []provider.Message
- func (b *DaemonBridge) SendUserMessage(content []provider.ContentBlock)
- func (b *DaemonBridge) SetActivityHook(fn func())
- func (b *DaemonBridge) SetFollowSink(sink daemon.FollowSink)
- func (b *DaemonBridge) SetHarnessConfig(mode string, autoInit bool, workingDir string)
- func (b *DaemonBridge) SetProviderSwitchHook(fn func(vendor, endpoint, model string) (string, error))
- func (b *DaemonBridge) SetRestartHook(fn func())
- func (b *DaemonBridge) SubmitInboundMessage(ctx context.Context, msg InboundMessage) error
- func (b *DaemonBridge) Subscribe(fn func(provider.StreamEvent)) func()
- type Envelope
- type EvalMetrics
- type ExtractedImage
- type IMEmitter
- func (e *IMEmitter) EmitAskUser(text string)
- func (e *IMEmitter) EmitAskUserInteractive(title string, q toolpkg.AskUserQuestion, fallbackText string) map[string]string
- func (e *IMEmitter) EmitEvent(event OutboundEvent)
- func (e *IMEmitter) EmitKnightReport(report string)
- func (e *IMEmitter) EmitRoundSummary(text string, toolCalls, toolSuccesses, toolFailures int)
- func (e *IMEmitter) EmitStatus(status string)
- func (e *IMEmitter) EmitText(text string)
- func (e *IMEmitter) EmitToolStatus(toolName, rawArgs string)
- func (e *IMEmitter) EmitUserText(text string)
- func (e *IMEmitter) EmitUserTextExcept(text, excludeAdapter string)
- func (e *IMEmitter) FormatAskUserPrompt(rawArgs string) string
- func (e *IMEmitter) HasTargets() bool
- func (e *IMEmitter) Language() string
- func (e *IMEmitter) Manager() *Manager
- func (e *IMEmitter) OutputMode() string
- func (e *IMEmitter) SetOutputMode(mode string)
- func (e *IMEmitter) TriggerTyping()
- type InboundMessage
- type InstanceDetect
- func (d *InstanceDetect) Info() InstanceInfo
- func (d *InstanceDetect) IsPrimary() bool
- func (d *InstanceDetect) IsRegistered() bool
- func (d *InstanceDetect) ListInstances() []InstanceInfo
- func (d *InstanceDetect) Register() ([]InstanceInfo, error)
- func (d *InstanceDetect) Unregister()
- func (d *InstanceDetect) UpdateHasActiveChannels(active bool) error
- type InstanceInfo
- type InteractiveButton
- type InteractiveCallback
- type InteractiveMessage
- type InteractiveSender
- type JSONFileBindingStore
- func (s *JSONFileBindingStore) Delete(workspace, adapter string) error
- func (s *JSONFileBindingStore) List() ([]ChannelBinding, error)
- func (s *JSONFileBindingStore) ListByAdapter(adapter string) ([]ChannelBinding, error)
- func (s *JSONFileBindingStore) ListByWorkspace(workspace string) ([]ChannelBinding, error)
- func (s *JSONFileBindingStore) Save(binding ChannelBinding) error
- type JSONFilePCSessionStore
- type JSONFilePairingStore
- type Manager
- func (m *Manager) ActiveSession() *SessionBinding
- func (m *Manager) AllPersistedBindings() []ChannelBinding
- func (m *Manager) BindChannel(binding ChannelBinding) (ChannelBinding, error)
- func (m *Manager) BindSession(binding SessionBinding)
- func (m *Manager) ClearChannel(workspace string) error
- func (m *Manager) ClearChannelByAdapter(adapterName string) error
- func (m *Manager) ClearReplyWindow(workspace string) error
- func (m *Manager) CurrentBinding() *ChannelBinding
- func (m *Manager) CurrentBindings() []ChannelBinding
- func (m *Manager) DeleteBinding(adapter, workspace string) error
- func (m *Manager) DisableAll() (int, error)
- func (m *Manager) DisableBinding(adapterName string) error
- func (m *Manager) DisabledBindings() []ChannelBinding
- func (m *Manager) Emit(ctx context.Context, event OutboundEvent) error
- func (m *Manager) EmitExcept(ctx context.Context, event OutboundEvent, excludeAdapter string) error
- func (m *Manager) EmitExceptAdapters(ctx context.Context, event OutboundEvent, excludeSet map[string]bool) error
- func (m *Manager) EmitToNonInteractive(ctx context.Context, event OutboundEvent) error
- func (m *Manager) EnableAll() (int, error)
- func (m *Manager) EnableBinding(adapterName string) error
- func (m *Manager) GenerateShareLink(ctx context.Context, adapter, callbackData string) (string, error)
- func (m *Manager) GetBindingContextToken(adapter string) string
- func (m *Manager) HandleInbound(ctx context.Context, msg InboundMessage) error
- func (m *Manager) HandleInteractiveCallback(cb InteractiveCallback)
- func (m *Manager) HandlePairingInbound(msg InboundMessage) (PairingResult, error)
- func (m *Manager) HasActiveBindings() bool
- func (m *Manager) HasNonInteractiveBindings(sentAdapters map[string]string) bool
- func (m *Manager) InstanceDetect() *InstanceDetect
- func (m *Manager) IsBindingDisabled(adapterName string) bool
- func (m *Manager) IsBindingMuted(adapterName string) bool
- func (m *Manager) IsPrimary() bool
- func (m *Manager) ListBindings() ([]ChannelBinding, error)
- func (m *Manager) MuteAll() (int, error)
- func (m *Manager) MuteAllExcept(exclude string) (int, error)
- func (m *Manager) MuteBinding(adapterName string) error
- func (m *Manager) MutedBindings() []ChannelBinding
- func (m *Manager) PCAdapter() PCAdapterAPI
- func (m *Manager) PublishAdapterState(state AdapterState)
- func (m *Manager) RecordOutboundMessage(workspace, adapter, messageID string) error
- func (m *Manager) RecordPassiveReply(workspace, messageID string, sentAt time.Time) error
- func (m *Manager) RegisterAdapterCancel(adapterName string, cancel context.CancelFunc)
- func (m *Manager) RegisterApproval(req ApprovalRequest) (ApprovalRequest, <-chan permission.Decision)
- func (m *Manager) RegisterInstance(workspace string) (*InstanceDetect, []InstanceInfo, error)
- func (m *Manager) RegisterSink(sink Sink)
- func (m *Manager) RejectPendingPairing() (*PairingChallenge, bool, error)
- func (m *Manager) ResolveApproval(resp ApprovalResponse) (ApprovalResult, bool, error)
- func (m *Manager) ResolveOutputMode(adapterName, globalMode string) string
- func (m *Manager) SendDirect(ctx context.Context, binding ChannelBinding, event OutboundEvent) error
- func (m *Manager) SendInteractive(ctx context.Context, msg InteractiveMessage) map[string]string
- func (m *Manager) SetBindingStore(store BindingStore) error
- func (m *Manager) SetBridge(bridge Bridge)
- func (m *Manager) SetInteractiveCallback(fn func(InteractiveCallback))
- func (m *Manager) SetOnRestart(fn func(adapterName string) error)
- func (m *Manager) SetOnUpdate(cb func(StatusSnapshot))
- func (m *Manager) SetPairingStore(store PairingStateStore) error
- func (m *Manager) Snapshot() StatusSnapshot
- func (m *Manager) StopAdapter(adapterName string)
- func (m *Manager) SyncSessionHistory(ctx context.Context, binding ChannelBinding, messages []provider.Message) error
- func (m *Manager) TriggerTyping(ctx context.Context)
- func (m *Manager) UnbindAdapter(adapterName string) error
- func (m *Manager) UnbindChannel(workspace string) error
- func (m *Manager) UnbindSession()
- func (m *Manager) UnmuteAll() (int, error)
- func (m *Manager) UnmuteBinding(adapterName string) error
- func (m *Manager) UnregisterInstance()
- func (m *Manager) UnregisterSink(name string)
- func (m *Manager) UpdateBindingContextToken(adapter, token string)
- func (m *Manager) WechatAdapter() *WechatAdapter
- type MemoryBindingStore
- func (s *MemoryBindingStore) Delete(workspace, adapter string) error
- func (s *MemoryBindingStore) List() ([]ChannelBinding, error)
- func (s *MemoryBindingStore) ListByAdapter(adapter string) ([]ChannelBinding, error)
- func (s *MemoryBindingStore) ListByWorkspace(workspace string) ([]ChannelBinding, error)
- func (s *MemoryBindingStore) Save(binding ChannelBinding) error
- type MemoryPCSessionStore
- type MemoryPairingStore
- type OutboundEvent
- type OutboundEventKind
- type PCAdapterAPI
- type PCInvite
- type PCSessionInfo
- type PCSessionStore
- type PairingChallenge
- type PairingChannelState
- type PairingKind
- type PairingResult
- type PairingStateStore
- type ParsedQuestionAnswer
- type Platform
- type SessionBinding
- type ShareLinkProvider
- type Sink
- type StatusSnapshot
- type ToolCallInfo
- type ToolLanguage
- type ToolPresentation
- type ToolResultInfo
- type TypingIndicator
- type WechatAdapter
- func (a *WechatAdapter) AuthenticateQRCode(ctx context.Context) (qrcode string, imgBase64 string, err error)
- func (a *WechatAdapter) Close() error
- func (a *WechatAdapter) GetState() AdapterState
- func (a *WechatAdapter) Name() string
- func (a *WechatAdapter) PollQRCodeStatus(ctx context.Context, qrcode string) (status string, botToken string, err error)
- func (a *WechatAdapter) Send(ctx context.Context, binding ChannelBinding, event OutboundEvent) error
- func (a *WechatAdapter) SetBotToken(token string)
- func (a *WechatAdapter) Start(ctx context.Context)
Constants ¶
const PCInviteURIPrefix = "privateclaw://connect?payload="
const WechatDefaultOutputMode = "summary"
WechatDefaultOutputMode is the recommended output mode for WeChat IM channels. WeChat iLink passive reply has a ~5 second context_token expiry and a 5-message limit per inbound. Summary mode ensures only one combined reply is sent.
Variables ¶
var ( ErrNoSessionBound = errors.New("no active session bound") ErrNoChannelBound = errors.New("no channel bound for active workspace") ErrNoBridge = errors.New("no IM bridge configured") ErrApprovalNotFound = errors.New("approval not found") ErrAdapterAlreadyBound = errors.New("adapter already bound to another workspace") ErrInboundChannelDenied = errors.New("inbound message does not match active binding") ErrNoPendingPairing = errors.New("no pending pairing challenge") )
var PlatformLimits = map[Platform]int{
PlatformDiscord: 2000,
PlatformSlack: 4000,
PlatformDingTalk: 4000,
PlatformTelegram: 4096,
PlatformQQ: 3000,
PlatformFeishu: 4000,
PlatformDummy: 50000,
}
PlatformLimits defines the maximum message length for each IM platform. These limits are based on official API documentation as of 2025.
Functions ¶
func BuildAskUserResponse ¶ added in v1.1.34
func BuildAskUserResponse(req toolpkg.AskUserRequest, parsed []ParsedQuestionAnswer) toolpkg.AskUserResponse
BuildAskUserResponse builds an AskUserResponse from parsed per-question answers. This is the shared implementation used by daemon (and can be used by TUI).
func DefaultBindingsPath ¶
func DefaultPCSessionStorePath ¶ added in v1.1.34
func DefaultPairingStatePath ¶
func EscapeMarkdownV2 ¶ added in v1.1.34
EscapeMarkdownV2 converts plain or markdown text to Telegram MarkdownV2 safe text.
It preserves markdown formatting structures (bold, italic, strikethrough, code, code blocks, links, images) while escaping all other MarkdownV2 special characters.
func FormatAskUserPrompt ¶ added in v1.1.34
func FormatAskUserPrompt(lang string, req toolpkg.AskUserRequest) string
FormatAskUserPrompt formats an AskUserRequest into an IM-friendly prompt with per-question-type reply guidance. Shared by TUI and daemon modes.
func FormatIMStatus ¶ added in v1.1.34
func FormatIMStatus(lang ToolLanguage, activity, toolName, toolArg string) string
FormatIMStatus produces the final status string for IM delivery, mirroring the TUI's formatIMStatus pipeline:
describeTool → formatToolInline → localizeIMProgress
func FormatToolInline ¶ added in v1.1.34
FormatToolInline formats a tool name and detail as an inline status string, e.g. "读 chart.html" or just "编辑" if detail is trivial.
func HasWechatAdapter ¶ added in v1.1.82
HasWechatAdapter returns true if the manager has any active WeChat adapter.
func IsLocalFilePath ¶ added in v1.1.34
IsLocalFilePath checks if a string looks like a local file path.
func LastMessageID ¶ added in v1.1.34
func LastMessageID(b ChannelBinding) string
LastMessageID returns the most recent message ID for typing reaction targeting: prefers the user's inbound message, falls back to the bot's last outbound message.
func LocalizeIMProgress ¶ added in v1.1.34
func LocalizeIMProgress(lang ToolLanguage, text string) string
LocalizeIMProgress applies language-specific localization to an IM progress string, mirroring the TUI's localizeIMProgress function.
func PCEncodeInviteToURI ¶ added in v1.1.34
PCEncodeInviteToURI encodes an invite into a privateclaw:// URI (exported for TUI).
func ParseRemoteQuestionnaireAnswer ¶ added in v1.1.34
func ParseRemoteQuestionnaireAnswer(raw string, question toolpkg.AskUserQuestion) (selected map[string]struct{}, freeform string, err error)
ParseRemoteQuestionnaireAnswer parses a raw IM text reply against a single question definition. It returns the selected choice IDs (for single/multi), a freeform text (for text or unmatched input), and whether parsing succeeded.
This is the shared implementation used by both TUI and daemon modes.
func SplitMessage ¶ added in v1.1.45
SplitMessage splits a long message into chunks that fit within the platform's message length limit. It tries to split at line boundaries to preserve readability.
The splitting strategy:
- If the message fits within maxLen, return it as a single chunk.
- Otherwise, try to find the last newline before maxLen.
- If no newline found, split at maxLen (hard cut).
- Repeat until the entire message is processed.
Each chunk is guaranteed to be at most maxLen bytes long.
func SplitMessageForPlatform ¶ added in v1.1.45
SplitMessageForPlatform is a convenience wrapper that looks up the platform's limit and calls SplitMessage.
func SplitNonEmptyLines ¶ added in v1.1.34
SplitNonEmptyLines splits text into non-empty trimmed lines.
Types ¶
type AdapterController ¶
type AdapterController struct {
// contains filtered or unexported fields
}
func StartConfiguredAdapters ¶
func StartPCAdapterOnly ¶ added in v1.1.34
func StartPCAdapterOnly(parent context.Context, cfg config.IMConfig, mgr *Manager) (*AdapterController, error)
StartPCAdapterOnly starts only the built-in PrivateClaw adapter. Used when IM is not explicitly enabled but PC should still be available.
func (*AdapterController) Stop ¶
func (c *AdapterController) Stop()
type AdapterDescriptor ¶
type AdapterState ¶
type ApprovalRequest ¶
type ApprovalResponse ¶
type ApprovalResult ¶
type ApprovalResult struct {
Request ApprovalRequest
Decision permission.Decision
RespondedBy string
RespondedAt time.Time
}
type ApprovalState ¶
type ApprovalState struct {
Request ApprovalRequest
Resolved bool
Decision permission.Decision
RespondedBy string
RespondedAt time.Time
}
type Attachment ¶
type AttachmentKind ¶
type AttachmentKind string
const ( AttachmentImage AttachmentKind = "image" AttachmentVoice AttachmentKind = "voice" AttachmentAudio AttachmentKind = "audio" AttachmentFile AttachmentKind = "file" )
type BindingStore ¶
type BindingStore interface {
Save(binding ChannelBinding) error
Delete(workspace, adapter string) error
List() ([]ChannelBinding, error)
ListByWorkspace(workspace string) ([]ChannelBinding, error)
ListByAdapter(adapter string) ([]ChannelBinding, error)
}
BindingStore persists channel bindings keyed by (workspace, adapter).
type Bridge ¶
type Bridge interface {
SubmitInboundMessage(ctx context.Context, msg InboundMessage) error
}
type ChannelBinding ¶
type ChannelBinding struct {
Workspace string
Platform Platform
Adapter string
TargetID string
ChannelID string
ThreadID string
LastInboundMessageID string
LastOutboundMessageID string
LastInboundAt time.Time
PassiveReplyCount int
PassiveReplyStartedAt time.Time
BoundAt time.Time
Muted bool
ContextToken string // WeChat iLink: latest context_token for reply routing
ContextTokenUpdatedAt time.Time // When ContextToken was last refreshed by an inbound message
}
type Closer ¶ added in v1.1.45
type Closer interface {
Close() error
}
Closer is an optional interface that adapters implement to close their underlying network connections. Called by Manager when an adapter is muted or disabled to physically disconnect.
type DaemonBridge ¶ added in v1.1.34
type DaemonBridge struct {
// contains filtered or unexported fields
}
func NewDaemonBridge ¶ added in v1.1.34
func NewDaemonBridge(mgr *Manager, ag *agent.Agent, emitter *IMEmitter, store session.Store, sess *session.Session) *DaemonBridge
NewDaemonBridge creates a bridge that submits IM messages directly to the agent.
func (*DaemonBridge) ConsumeRestartDebug ¶ added in v1.1.51
func (b *DaemonBridge) ConsumeRestartDebug() bool
ConsumeRestartDebug returns whether /restart debug was requested and resets the flag.
func (*DaemonBridge) HandleAskUser ¶ added in v1.1.34
func (b *DaemonBridge) HandleAskUser(ctx context.Context, req toolpkg.AskUserRequest) (toolpkg.AskUserResponse, error)
HandleAskUser is the AskUserHandler for daemon mode — sends questions to IM one at a time and collects answers interactively. For single-choice questions, it first attempts to send native interactive buttons. If the adapter supports it, the user clicks a button instead of typing a number. The answer is routed back through the same pendingAsk mechanism — either from a text reply or a button callback.
func (*DaemonBridge) Messages ¶ added in v1.1.51
func (b *DaemonBridge) Messages() []provider.Message
Messages returns the current agent conversation history.
func (*DaemonBridge) SendUserMessage ¶ added in v1.1.51
func (b *DaemonBridge) SendUserMessage(content []provider.ContentBlock)
SendUserMessage injects a user message into the agent conversation. If the agent is currently running, the message is queued as an interruption (same mechanism as IM mid-run messages). If the agent is idle, a new run is started.
func (*DaemonBridge) SetActivityHook ¶ added in v1.1.43
func (b *DaemonBridge) SetActivityHook(fn func())
SetActivityHook installs a callback fired when an inbound IM message counts as real user activity. Daemon mode uses this to keep Knight's idle timer honest.
func (*DaemonBridge) SetFollowSink ¶ added in v1.1.34
func (b *DaemonBridge) SetFollowSink(sink daemon.FollowSink)
SetFollowSink sets or clears the follow-mode display sink.
func (*DaemonBridge) SetHarnessConfig ¶ added in v1.1.66
func (b *DaemonBridge) SetHarnessConfig(mode string, autoInit bool, workingDir string)
SetHarnessConfig configures auto-run routing for daemon mode.
func (*DaemonBridge) SetProviderSwitchHook ¶ added in v1.1.82
func (b *DaemonBridge) SetProviderSwitchHook(fn func(vendor, endpoint, model string) (string, error))
SetProviderSwitchHook installs a callback to switch provider/model. The callback receives (vendor, endpoint, model) — any may be empty to mean "keep current". It returns a human-readable summary string.
func (*DaemonBridge) SetRestartHook ¶ added in v1.1.46
func (b *DaemonBridge) SetRestartHook(fn func())
SetRestartHook installs a callback to trigger daemon process restart.
func (*DaemonBridge) SubmitInboundMessage ¶ added in v1.1.34
func (b *DaemonBridge) SubmitInboundMessage(ctx context.Context, msg InboundMessage) error
SubmitInboundMessage handles an inbound IM message by submitting it to the agent.
func (*DaemonBridge) Subscribe ¶ added in v1.1.51
func (b *DaemonBridge) Subscribe(fn func(provider.StreamEvent)) func()
Subscribe registers a callback for agent streaming events. All events from the agent loop are forwarded to all subscribers via buffered channels to avoid blocking the agent. Returns an unsubscribe function.
type EvalMetrics ¶ added in v1.1.43
type EvalMetrics struct {
SessionStart time.Time
SessionEnd time.Time
UserMessages int
AskUserCount int
AskUserLatencyMs map[string]int64 // question_id → latency
ToolCalls map[string]int // tool_name → count
TotalToolCalls int
ToolErrors int
ToolErrorsByTool map[string]int // tool_name → error count
ReworkCount int
Rounds int
InputTokens int
OutputTokens int
KnightReports int
StagedSkills int
ElapsedMs int64
// contains filtered or unexported fields
}
EvalMetrics collects quantitative metrics during an evaluation session.
func NewEvalMetrics ¶ added in v1.1.43
func NewEvalMetrics() *EvalMetrics
NewEvalMetrics creates a new metrics collector.
func (*EvalMetrics) RecordEvent ¶ added in v1.1.43
func (m *EvalMetrics) RecordEvent(event OutboundEvent)
RecordEvent updates metrics based on an outbound event.
func (*EvalMetrics) Reset ¶ added in v1.1.43
func (m *EvalMetrics) Reset()
Reset clears all per-task metrics while keeping session-level fields.
func (*EvalMetrics) Snapshot ¶ added in v1.1.43
func (m *EvalMetrics) Snapshot() map[string]interface{}
Snapshot returns a copy of current metrics as a map.
func (*EvalMetrics) WriteCSV ¶ added in v1.1.43
func (m *EvalMetrics) WriteCSV(path string, runID, phase, mode string) error
WriteCSV appends a metrics row to a CSV file.
func (*EvalMetrics) WriteJSON ¶ added in v1.1.43
func (m *EvalMetrics) WriteJSON(path string) error
WriteJSON writes the metrics snapshot to a JSON file.
type ExtractedImage ¶ added in v1.1.34
type ExtractedImage struct {
Kind string // "url", "data_url", "local_path"
Data string // URL, base64 data URL, or local file path
}
ExtractedImage represents an image found in message text.
func ExtractImagesFromText ¶ added in v1.1.34
func ExtractImagesFromText(text string) ([]ExtractedImage, string)
ExtractImagesFromText finds markdown images, bare image URLs, and data URLs in text. Returns extracted images and the text with image references replaced by their alt text (for markdown images) or removed (for bare URLs and data URLs). Line breaks are preserved.
type IMEmitter ¶ added in v1.1.34
type IMEmitter struct {
// contains filtered or unexported fields
}
IMEmitter handles asynchronous outbound IM event emission with typing keepalive. It is framework-agnostic and can be used by both TUI and daemon modes.
func NewIMEmitter ¶ added in v1.1.34
NewIMEmitter creates a new IM emitter for the given manager, language, and working directory.
func (*IMEmitter) EmitAskUser ¶ added in v1.1.34
EmitAskUser sends an ask_user prompt to IM.
func (*IMEmitter) EmitAskUserInteractive ¶ added in v1.1.51
func (e *IMEmitter) EmitAskUserInteractive(title string, q toolpkg.AskUserQuestion, fallbackText string) map[string]string
EmitAskUserInteractive sends an ask_user question to IM, preferring interactive buttons for adapters that support them (Discord, Telegram, Feishu). Text fallback is only sent to adapters that did NOT receive an interactive message (e.g. QQ, DingDing). If the question has no choices, falls back to EmitAskUser for all adapters.
func (*IMEmitter) EmitEvent ¶ added in v1.1.34
func (e *IMEmitter) EmitEvent(event OutboundEvent)
EmitEvent sends a raw outbound event to all bound IM channels.
func (*IMEmitter) EmitKnightReport ¶ added in v1.1.43
EmitKnightReport sends a Knight status report to IM.
func (*IMEmitter) EmitRoundSummary ¶ added in v1.1.34
EmitRoundSummary sends the final round text to IM.
func (*IMEmitter) EmitStatus ¶ added in v1.1.34
EmitStatus sends a status update to IM. Duplicate consecutive statuses are suppressed.
func (*IMEmitter) EmitToolStatus ¶ added in v1.1.34
EmitToolStatus formats and sends a tool execution status using the shared DescribeTool pipeline.
func (*IMEmitter) EmitUserText ¶ added in v1.1.34
EmitUserText sends a user echo message to IM.
func (*IMEmitter) EmitUserTextExcept ¶ added in v1.1.34
EmitUserTextExcept sends a user echo message to all bound IM channels except the originating adapter. This prevents the user from seeing their own message echoed back on the channel they sent from.
func (*IMEmitter) FormatAskUserPrompt ¶ added in v1.1.34
FormatAskUserPrompt formats an ask_user request as an IM-friendly prompt string. Delegates to the shared FormatAskUserPrompt in ask_user_format.go.
func (*IMEmitter) HasTargets ¶ added in v1.1.43
HasTargets returns true if at least one IM channel is bound. Uses a lightweight check that avoids copying the bindings list.
func (*IMEmitter) Manager ¶ added in v1.1.51
Manager returns the underlying Manager. Returns nil if the emitter is nil.
func (*IMEmitter) OutputMode ¶ added in v1.1.45
OutputMode returns the current output mode.
func (*IMEmitter) SetOutputMode ¶ added in v1.1.45
SetOutputMode sets the IM output mode: verbose, quiet, or summary.
func (*IMEmitter) TriggerTyping ¶ added in v1.1.34
func (e *IMEmitter) TriggerTyping()
TriggerTyping sends typing indicators to all bound adapters with keepalive throttling.
type InboundMessage ¶
type InboundMessage struct {
Envelope Envelope
Text string
Attachments []Attachment
Metadata map[string]string
}
func (InboundMessage) ProviderContent ¶
func (m InboundMessage) ProviderContent() []provider.ContentBlock
type InstanceDetect ¶ added in v1.1.45
type InstanceDetect struct {
// contains filtered or unexported fields
}
InstanceDetect manages per-directory instance registration and discovery. It uses PID files under .ggcode/instances/ to track running instances.
func NewInstanceDetect ¶ added in v1.1.45
func NewInstanceDetect(workspace string) *InstanceDetect
NewInstanceDetect creates a new instance detector for the given workspace. workspace is the project root directory (where .ggcode/ lives).
func (*InstanceDetect) Info ¶ added in v1.1.45
func (d *InstanceDetect) Info() InstanceInfo
Info returns this instance's info.
func (*InstanceDetect) IsPrimary ¶ added in v1.1.45
func (d *InstanceDetect) IsPrimary() bool
IsPrimary checks if this instance is the oldest among all running instances in the same directory. Must be called after Register().
func (*InstanceDetect) IsRegistered ¶ added in v1.1.45
func (d *InstanceDetect) IsRegistered() bool
IsRegistered returns whether Register() has been called successfully.
func (*InstanceDetect) ListInstances ¶ added in v1.1.45
func (d *InstanceDetect) ListInstances() []InstanceInfo
ListInstances returns all live instances in the directory, including self. Sorted by StartedAt ascending (oldest first).
func (*InstanceDetect) Register ¶ added in v1.1.45
func (d *InstanceDetect) Register() ([]InstanceInfo, error)
Register writes this instance's PID file and cleans up stale entries. Returns a list of other live instances (sorted by StartedAt ascending) and an error if file operations fail.
func (*InstanceDetect) Unregister ¶ added in v1.1.45
func (d *InstanceDetect) Unregister()
Unregister removes this instance's PID file. Call on graceful shutdown.
func (*InstanceDetect) UpdateHasActiveChannels ¶ added in v1.1.45
func (d *InstanceDetect) UpdateHasActiveChannels(active bool) error
UpdateHasActiveChannels updates the hasActiveChannels flag in the PID file.
type InstanceInfo ¶ added in v1.1.45
type InstanceInfo struct {
PID int `json:"pid"`
UUID string `json:"uuid"`
StartedAt time.Time `json:"startedAt"`
HasActiveChannels bool `json:"hasActiveChannels"`
}
InstanceInfo describes a running ggcode instance in the same directory.
type InteractiveButton ¶ added in v1.1.51
type InteractiveButton struct {
// Label is the button text shown to the user.
Label string
// Value is the opaque value sent back when the button is clicked.
// For ask_user, this is the choice number (e.g. "1", "2").
Value string
// Style hints (optional): "primary", "danger", "default".
Style string
}
InteractiveButton represents a single clickable option.
type InteractiveCallback ¶ added in v1.1.51
type InteractiveCallback struct {
// MessageID is the platform message ID of the original interactive message.
MessageID string
// Values are the selected button values (one for single, multiple for multi-select).
Values []string
// Adapter is the adapter name that received the callback.
Adapter string
// Envelope carries the standard sender/channel info.
Envelope Envelope
}
InteractiveCallback represents a user's response to an interactive element. Adapters translate platform-specific callbacks into this common type.
type InteractiveMessage ¶ added in v1.1.51
type InteractiveMessage struct {
// ID is a unique identifier for correlating callbacks.
ID string
// Text is the main message body (markdown).
Text string
// Buttons is a list of clickable options presented to the user.
// Each button has a label and a value that gets sent back on click.
Buttons []InteractiveButton
// MultiSelect allows selecting multiple buttons (for multi-question ask_user).
MultiSelect bool
// Placeholder is shown in select menus (Slack, DingTalk).
Placeholder string
}
InteractiveMessage describes a message with interactive elements. Used for ask_user questions with choices, approval actions, etc.
type InteractiveSender ¶ added in v1.1.51
type InteractiveSender interface {
SendInteractive(ctx context.Context, binding ChannelBinding, msg InteractiveMessage) (string, error)
}
InteractiveSender is an optional interface that adapters implement to send messages with native interactive elements (buttons, select menus). Adapters that don't implement this fall back to text-based interaction.
type JSONFileBindingStore ¶
type JSONFileBindingStore struct {
// contains filtered or unexported fields
}
JSONFileBindingStore persists bindings to a JSON file with atomic writes.
func NewJSONFileBindingStore ¶
func NewJSONFileBindingStore(path string) (*JSONFileBindingStore, error)
func (*JSONFileBindingStore) Delete ¶
func (s *JSONFileBindingStore) Delete(workspace, adapter string) error
func (*JSONFileBindingStore) List ¶
func (s *JSONFileBindingStore) List() ([]ChannelBinding, error)
func (*JSONFileBindingStore) ListByAdapter ¶ added in v1.1.34
func (s *JSONFileBindingStore) ListByAdapter(adapter string) ([]ChannelBinding, error)
func (*JSONFileBindingStore) ListByWorkspace ¶ added in v1.1.34
func (s *JSONFileBindingStore) ListByWorkspace(workspace string) ([]ChannelBinding, error)
func (*JSONFileBindingStore) Save ¶
func (s *JSONFileBindingStore) Save(binding ChannelBinding) error
type JSONFilePCSessionStore ¶ added in v1.1.34
type JSONFilePCSessionStore struct {
// contains filtered or unexported fields
}
JSONFilePCSessionStore persists PC sessions to a JSON file.
func NewJSONFilePCSessionStore ¶ added in v1.1.34
func NewJSONFilePCSessionStore(path string) (*JSONFilePCSessionStore, error)
func (*JSONFilePCSessionStore) LoadAll ¶ added in v1.1.34
func (s *JSONFilePCSessionStore) LoadAll() ([]pcPersistedSession, error)
func (*JSONFilePCSessionStore) SaveAll ¶ added in v1.1.34
func (s *JSONFilePCSessionStore) SaveAll(sessions []pcPersistedSession) error
type JSONFilePairingStore ¶
type JSONFilePairingStore struct {
// contains filtered or unexported fields
}
func NewJSONFilePairingStore ¶
func NewJSONFilePairingStore(path string) (*JSONFilePairingStore, error)
func (*JSONFilePairingStore) LoadAll ¶
func (s *JSONFilePairingStore) LoadAll() (map[string]PairingChannelState, error)
func (*JSONFilePairingStore) SaveAll ¶
func (s *JSONFilePairingStore) SaveAll(states map[string]PairingChannelState) error
type Manager ¶
type Manager struct {
// contains filtered or unexported fields
}
func NewManager ¶
func NewManager() *Manager
func (*Manager) ActiveSession ¶
func (m *Manager) ActiveSession() *SessionBinding
func (*Manager) AllPersistedBindings ¶ added in v1.1.46
func (m *Manager) AllPersistedBindings() []ChannelBinding
AllPersistedBindings returns all persisted bindings from the store, including bindings for other workspaces not currently active.
func (*Manager) BindChannel ¶
func (m *Manager) BindChannel(binding ChannelBinding) (ChannelBinding, error)
func (*Manager) BindSession ¶
func (m *Manager) BindSession(binding SessionBinding)
func (*Manager) ClearChannel ¶
func (*Manager) ClearChannelByAdapter ¶ added in v1.1.34
func (*Manager) ClearReplyWindow ¶
func (*Manager) CurrentBinding ¶
func (m *Manager) CurrentBinding() *ChannelBinding
func (*Manager) CurrentBindings ¶ added in v1.1.34
func (m *Manager) CurrentBindings() []ChannelBinding
func (*Manager) DeleteBinding ¶ added in v1.1.46
DeleteBinding removes a specific persisted binding by adapter and workspace.
func (*Manager) DisableAll ¶ added in v1.1.45
DisableAll disables all active (non-muted, non-disabled) bindings.
func (*Manager) DisableBinding ¶ added in v1.1.35
DisableBinding temporarily disables an adapter's binding for the current session. The binding is moved from currentBindings to disabledBindings, so it will no longer receive outbound messages and inbound messages will be rejected. The persistent binding is NOT deleted, so it can be re-enabled later.
func (*Manager) DisabledBindings ¶ added in v1.1.35
func (m *Manager) DisabledBindings() []ChannelBinding
DisabledBindings returns a snapshot of currently disabled bindings.
func (*Manager) EmitExcept ¶ added in v1.1.34
EmitExcept sends an event to all bound channels except those matching excludeAdapter. This is used to suppress user mirror echo on the originating IM channel while still delivering it to other bound channels.
func (*Manager) EmitExceptAdapters ¶ added in v1.1.51
func (m *Manager) EmitExceptAdapters(ctx context.Context, event OutboundEvent, excludeSet map[string]bool) error
EmitExceptAdapters sends an event to all bound channels except those in excludeSet.
func (*Manager) EmitToNonInteractive ¶ added in v1.1.51
func (m *Manager) EmitToNonInteractive(ctx context.Context, event OutboundEvent) error
EmitToNonInteractive sends an event only to adapters that do NOT implement InteractiveSender. Used for ask_user text fallback — adapters that already received interactive buttons should not get the duplicate text version.
func (*Manager) EnableBinding ¶ added in v1.1.35
EnableBinding re-enables a previously disabled adapter binding. The binding is moved back to currentBindings so it resumes receiving messages.
func (*Manager) GenerateShareLink ¶
func (*Manager) GetBindingContextToken ¶ added in v1.1.83
GetBindingContextToken returns the persisted ContextToken for the given adapter.
func (*Manager) HandleInbound ¶
func (m *Manager) HandleInbound(ctx context.Context, msg InboundMessage) error
func (*Manager) HandleInteractiveCallback ¶ added in v1.1.51
func (m *Manager) HandleInteractiveCallback(cb InteractiveCallback)
HandleInteractiveCallback is called by adapters when a user clicks an interactive button. It dispatches to the registered callback handler.
func (*Manager) HandlePairingInbound ¶
func (m *Manager) HandlePairingInbound(msg InboundMessage) (PairingResult, error)
HandlePairingInbound processes an inbound IM message for pairing. If the adapter has no binding with a ChannelID, it creates a pairing challenge (4-digit code displayed on screen). The user must enter the code in the IM channel to complete binding and obtain the ChannelID/TargetID.
func (*Manager) HasActiveBindings ¶ added in v1.1.43
HasActiveBindings returns true if there is at least one active channel binding. Lighter than ListBindings — no allocation or copying.
func (*Manager) HasNonInteractiveBindings ¶ added in v1.1.51
HasNonInteractiveBindings returns true if there is at least one bound adapter that did NOT receive an interactive message (i.e. doesn't implement InteractiveSender or wasn't in the sentAdapters set). Used to decide whether to send text fallback.
func (*Manager) InstanceDetect ¶ added in v1.1.45
func (m *Manager) InstanceDetect() *InstanceDetect
InstanceDetect returns the instance detector (nil if not registered).
func (*Manager) IsBindingDisabled ¶ added in v1.1.35
IsBindingDisabled returns true if the given adapter's binding is currently disabled.
func (*Manager) IsBindingMuted ¶ added in v1.1.45
IsBindingMuted returns true if the given adapter's binding is currently muted.
func (*Manager) IsPrimary ¶ added in v1.1.45
IsPrimary returns true if this instance is the oldest running instance in the workspace (or no detector is set).
func (*Manager) ListBindings ¶
func (m *Manager) ListBindings() ([]ChannelBinding, error)
func (*Manager) MuteAll ¶ added in v1.1.45
MuteAll mutes all currently active bindings for this process. Returns the number of adapters that were muted.
func (*Manager) MuteAllExcept ¶ added in v1.1.46
MuteAllExcept mutes all currently active bindings except the named adapter. If exclude is empty, all bindings are muted. Returns the number muted.
func (*Manager) MuteBinding ¶ added in v1.1.45
MuteBinding mutes an adapter for this process only. The binding stays in currentBindings (so the UI still shows it as bound) but is marked Muted. The connection is dropped so inbound/outbound messages stop.
func (*Manager) MutedBindings ¶ added in v1.1.45
func (m *Manager) MutedBindings() []ChannelBinding
MutedBindings returns a snapshot of currently muted bindings.
func (*Manager) PCAdapter ¶ added in v1.1.34
func (m *Manager) PCAdapter() PCAdapterAPI
PCAdapter returns the first registered PrivateClaw adapter, or nil.
func (*Manager) PublishAdapterState ¶
func (m *Manager) PublishAdapterState(state AdapterState)
func (*Manager) RecordOutboundMessage ¶ added in v1.1.34
RecordOutboundMessage records the message ID of a bot reply so that typing indicator reactions can target it when no inbound message exists.
func (*Manager) RecordPassiveReply ¶
func (*Manager) RegisterAdapterCancel ¶ added in v1.1.45
func (m *Manager) RegisterAdapterCancel(adapterName string, cancel context.CancelFunc)
RegisterAdapterCancel registers a cancel function for an adapter. When the adapter is muted or disabled, the cancel is called to stop its goroutine and drop the connection.
func (*Manager) RegisterApproval ¶
func (m *Manager) RegisterApproval(req ApprovalRequest) (ApprovalRequest, <-chan permission.Decision)
func (*Manager) RegisterInstance ¶ added in v1.1.45
func (m *Manager) RegisterInstance(workspace string) (*InstanceDetect, []InstanceInfo, error)
RegisterInstance creates an InstanceDetect for the given workspace, registers this process as a running instance, and stores it on the Manager. If other instances are already running in the same workspace, this instance is auto-muted (non-primary). Returns the detector and any other live instances.
func (*Manager) RegisterSink ¶
func (*Manager) RejectPendingPairing ¶
func (m *Manager) RejectPendingPairing() (*PairingChallenge, bool, error)
func (*Manager) ResolveApproval ¶
func (m *Manager) ResolveApproval(resp ApprovalResponse) (ApprovalResult, bool, error)
func (*Manager) ResolveOutputMode ¶ added in v1.1.82
ResolveOutputMode returns the effective output mode for the given adapter. If the adapter's platform has a recommended default (e.g. WeChat → summary), and the global mode is "verbose" (the default), the platform default is used.
func (*Manager) SendDirect ¶
func (m *Manager) SendDirect(ctx context.Context, binding ChannelBinding, event OutboundEvent) error
func (*Manager) SendInteractive ¶ added in v1.1.51
SendInteractive sends an interactive message to all bound adapters that support it. Returns a map of adapter name → platform message ID for callback correlation. Adapters that don't support interactive messages are skipped (caller should fall back to text).
func (*Manager) SetBindingStore ¶
func (m *Manager) SetBindingStore(store BindingStore) error
func (*Manager) SetInteractiveCallback ¶ added in v1.1.51
func (m *Manager) SetInteractiveCallback(fn func(InteractiveCallback))
SetInteractiveCallback registers a handler for interactive button/menu callbacks from adapters. When a user clicks a button, the adapter calls Manager.HandleInteractiveCallback which dispatches to this handler.
func (*Manager) SetOnRestart ¶ added in v1.1.45
SetOnRestart sets a callback invoked by UnmuteBinding/EnableBinding to restart a previously stopped adapter. The caller (TUI/daemon) provides this because it has access to the IM config needed to start adapters.
func (*Manager) SetOnUpdate ¶
func (m *Manager) SetOnUpdate(cb func(StatusSnapshot))
func (*Manager) SetPairingStore ¶
func (m *Manager) SetPairingStore(store PairingStateStore) error
func (*Manager) Snapshot ¶
func (m *Manager) Snapshot() StatusSnapshot
func (*Manager) StopAdapter ¶ added in v1.1.45
StopAdapter stops a running adapter by name. This is the public version of stopAdapter, used for hot-reloading config changes without altering binding state.
func (*Manager) SyncSessionHistory ¶
func (*Manager) TriggerTyping ¶ added in v1.1.34
TriggerTyping sends a typing indicator to all bound adapters that implement the TypingIndicator interface.
func (*Manager) UnbindAdapter ¶ added in v1.1.34
UnbindAdapter removes the binding for whatever workspace has the given adapter name. This is needed when unbinding from a panel where the current session workspace may differ from the workspace that originally bound the adapter. Returns ErrNoChannelBound if no binding uses this adapter.
func (*Manager) UnbindChannel ¶
func (*Manager) UnbindSession ¶
func (m *Manager) UnbindSession()
func (*Manager) UnmuteAll ¶ added in v1.1.45
UnmuteAll unmutes all muted bindings for this process. Returns the number of adapters that were unmuted.
func (*Manager) UnmuteBinding ¶ added in v1.1.45
UnmuteBinding unmutes a previously muted adapter and restarts it.
func (*Manager) UnregisterInstance ¶ added in v1.1.45
func (m *Manager) UnregisterInstance()
UnregisterInstance removes this process's instance registration (PID file). Call on graceful shutdown.
func (*Manager) UnregisterSink ¶
func (*Manager) UpdateBindingContextToken ¶ added in v1.1.83
UpdateBindingContextToken updates the ContextToken (and ContextTokenUpdatedAt) on the binding for the given adapter. The token is persisted to disk so it survives restarts. WeChat iLink requires context_token for every sendmessage; without it only ~2 messages succeed before the server stops responding. Tokens expire after ~24 hours.
func (*Manager) WechatAdapter ¶ added in v1.1.82
func (m *Manager) WechatAdapter() *WechatAdapter
WechatAdapter returns the first wechat adapter sink from the manager, or nil.
type MemoryBindingStore ¶
type MemoryBindingStore struct {
// contains filtered or unexported fields
}
MemoryBindingStore is an in-memory BindingStore for tests.
func NewMemoryBindingStore ¶
func NewMemoryBindingStore() *MemoryBindingStore
func (*MemoryBindingStore) Delete ¶
func (s *MemoryBindingStore) Delete(workspace, adapter string) error
func (*MemoryBindingStore) List ¶
func (s *MemoryBindingStore) List() ([]ChannelBinding, error)
func (*MemoryBindingStore) ListByAdapter ¶ added in v1.1.34
func (s *MemoryBindingStore) ListByAdapter(adapter string) ([]ChannelBinding, error)
func (*MemoryBindingStore) ListByWorkspace ¶ added in v1.1.34
func (s *MemoryBindingStore) ListByWorkspace(workspace string) ([]ChannelBinding, error)
func (*MemoryBindingStore) Save ¶
func (s *MemoryBindingStore) Save(binding ChannelBinding) error
type MemoryPCSessionStore ¶ added in v1.1.34
type MemoryPCSessionStore struct {
// contains filtered or unexported fields
}
MemoryPCSessionStore is an in-memory PC session store for testing.
func NewMemoryPCSessionStore ¶ added in v1.1.34
func NewMemoryPCSessionStore() *MemoryPCSessionStore
func (*MemoryPCSessionStore) LoadAll ¶ added in v1.1.34
func (s *MemoryPCSessionStore) LoadAll() ([]pcPersistedSession, error)
func (*MemoryPCSessionStore) SaveAll ¶ added in v1.1.34
func (s *MemoryPCSessionStore) SaveAll(sessions []pcPersistedSession) error
type MemoryPairingStore ¶
type MemoryPairingStore struct {
// contains filtered or unexported fields
}
func NewMemoryPairingStore ¶
func NewMemoryPairingStore() *MemoryPairingStore
func (*MemoryPairingStore) LoadAll ¶
func (s *MemoryPairingStore) LoadAll() (map[string]PairingChannelState, error)
func (*MemoryPairingStore) SaveAll ¶
func (s *MemoryPairingStore) SaveAll(states map[string]PairingChannelState) error
type OutboundEvent ¶
type OutboundEvent struct {
Kind OutboundEventKind
Text string
Status string
ToolCall *ToolCallInfo
ToolRes *ToolResultInfo
Approval *ApprovalRequest
Result *ApprovalResult
CreatedAt time.Time
}
func SessionHistoryEvents ¶
func SessionHistoryEvents(messages []provider.Message) []OutboundEvent
type OutboundEventKind ¶
type OutboundEventKind string
const ( OutboundEventText OutboundEventKind = "text" OutboundEventStatus OutboundEventKind = "status" OutboundEventToolCall OutboundEventKind = "tool_call" OutboundEventToolResult OutboundEventKind = "tool_result" OutboundEventApprovalRequest OutboundEventKind = "approval_request" OutboundEventApprovalResult OutboundEventKind = "approval_result" )
type PCAdapterAPI ¶ added in v1.1.34
type PCAdapterAPI interface {
CreateSession(ctx context.Context, label string, groupMode bool) (*PCInvite, string, error)
ListSessions() []PCSessionInfo
GetSession(sessionID string) (*pcSession, bool)
CloseSession(sessionID string) error
RenewSession(ctx context.Context, sessionID string) error
GetInviteURI(sessionID string) (string, error)
KickParticipant(sessionID, appID string) error
}
PCAdapterAPI is the exported interface for PrivateClaw adapter operations (used by TUI).
type PCInvite ¶ added in v1.1.34
type PCInvite struct {
Version int `json:"version"`
SessionID string `json:"sessionId"`
SessionKey string `json:"sessionKey"`
AppWsURL string `json:"appWsUrl"`
ExpiresAt string `json:"expiresAt"`
GroupMode bool `json:"groupMode,omitempty"`
ProviderLabel string `json:"providerLabel,omitempty"`
RelayLabel string `json:"relayLabel,omitempty"`
}
type PCSessionInfo ¶ added in v1.1.34
type PCSessionInfo struct {
SessionID string
State string
GroupMode bool
Label string
ParticipantCount int
ExpiresAt time.Time
}
PCSessionInfo is a summary of a session for TUI display.
type PCSessionStore ¶ added in v1.1.34
type PCSessionStore interface {
LoadAll() ([]pcPersistedSession, error)
SaveAll(sessions []pcPersistedSession) error
}
PCSessionStore persists PC session data across restarts.
type PairingChallenge ¶
type PairingChallenge struct {
Kind PairingKind
Workspace string
Adapter string
Platform Platform
ChannelID string
ThreadID string
SenderID string
SenderName string
Code string
RequestedAt time.Time
LastInboundMessageID string
LastInboundAt time.Time
ExistingBinding *ChannelBinding
}
func (PairingChallenge) ReplyBinding ¶
func (c PairingChallenge) ReplyBinding() ChannelBinding
type PairingChannelState ¶
type PairingChannelState struct {
Adapter string
Platform Platform
ChannelID string
RejectCount int
BlacklistedAt time.Time
UpdatedAt time.Time
}
func (PairingChannelState) IsBlacklisted ¶
func (s PairingChannelState) IsBlacklisted() bool
type PairingKind ¶
type PairingKind string
const ( PairingKindBind PairingKind = "bind" PairingKindRebind PairingKind = "rebind" )
type PairingResult ¶
type PairingResult struct {
Consumed bool
Kind PairingKind
ReplyText string
Bound bool
PreviousBinding *ChannelBinding
NewBinding *ChannelBinding
}
type PairingStateStore ¶
type PairingStateStore interface {
LoadAll() (map[string]PairingChannelState, error)
SaveAll(map[string]PairingChannelState) error
}
type ParsedQuestionAnswer ¶ added in v1.1.34
type ParsedQuestionAnswer struct {
QuestionIndex int
Selected map[string]struct{}
Freeform string
Error error
}
ParsedQuestionAnswer holds the result of parsing a single question's reply.
func ParseMultiQuestionReply ¶ added in v1.1.34
func ParseMultiQuestionReply(raw string, questions []toolpkg.AskUserQuestion) []ParsedQuestionAnswer
ParseMultiQuestionReply splits a multi-line IM reply into per-question answers and parses each one. It returns a slice of results in the same order as the questions slice. If there are fewer lines than questions, remaining questions are left unanswered (empty results).
This is the shared implementation used by both TUI and daemon modes.
type Platform ¶
type Platform string
const ( PlatformUnknown Platform = "" PlatformQQ Platform = "qq" PlatformTelegram Platform = "telegram" PlatformDiscord Platform = "discord" PlatformFeishu Platform = "feishu" PlatformDingTalk Platform = "dingtalk" PlatformSlack Platform = "slack" PlatformDummy Platform = "dummy" PlatformWechat Platform = "wechat" )
const PlatformPrivateClaw Platform = "privateclaw"
type SessionBinding ¶
type ShareLinkProvider ¶
type ShareLinkProvider interface {
}
type Sink ¶
type Sink interface {
Name() string
Send(context.Context, ChannelBinding, OutboundEvent) error
}
type StatusSnapshot ¶
type StatusSnapshot struct {
ActiveSession *SessionBinding
CurrentBindings []ChannelBinding
DisabledBindings []ChannelBinding
MutedBindings []ChannelBinding
PendingPairing *PairingChallenge
Adapters []AdapterState
PendingApprovals []ApprovalState
}
func (StatusSnapshot) BindingByAdapter ¶ added in v1.1.82
func (s StatusSnapshot) BindingByAdapter(adapter string) *ChannelBinding
BindingByAdapter returns the first current binding matching the given adapter name.
type ToolCallInfo ¶ added in v1.1.34
type ToolLanguage ¶ added in v1.1.34
type ToolLanguage string
ToolLanguage represents the language for tool status formatting.
const ( ToolLangZhCN ToolLanguage = "zh-CN" ToolLangEn ToolLanguage = "en" )
type ToolPresentation ¶ added in v1.1.34
type ToolPresentation struct {
DisplayName string // e.g. "读", "编辑", "执行"
Detail string // e.g. file path, command preview
Activity string // e.g. "读取 chart.html", "执行 npm test"
}
ToolPresentation holds the formatted display information for a tool call.
func DescribeTool ¶ added in v1.1.34
func DescribeTool(lang ToolLanguage, toolName, rawArgs string) ToolPresentation
DescribeTool produces a human-readable presentation of a tool call, mirroring the TUI's describeTool pipeline (tool_labels.go).
type ToolResultInfo ¶ added in v1.1.34
type TypingIndicator ¶ added in v1.1.34
type TypingIndicator interface {
TriggerTyping(ctx context.Context, binding ChannelBinding) error
}
TypingIndicator is an optional interface that adapters can implement to show a native "bot is typing" indicator on the IM platform.
type WechatAdapter ¶ added in v1.1.82
type WechatAdapter struct {
// contains filtered or unexported fields
}
func (*WechatAdapter) AuthenticateQRCode ¶ added in v1.1.82
func (a *WechatAdapter) AuthenticateQRCode(ctx context.Context) (qrcode string, imgBase64 string, err error)
AuthenticateQRCode requests a QR code from iLink for the user to scan. Returns the qrcode token (for status polling) and base64-encoded PNG image.
func (*WechatAdapter) Close ¶ added in v1.1.82
func (a *WechatAdapter) Close() error
func (*WechatAdapter) GetState ¶ added in v1.1.82
func (a *WechatAdapter) GetState() AdapterState
GetAdapterState returns the current adapter state for the TUI panel.
func (*WechatAdapter) Name ¶ added in v1.1.82
func (a *WechatAdapter) Name() string
func (*WechatAdapter) PollQRCodeStatus ¶ added in v1.1.82
func (a *WechatAdapter) PollQRCodeStatus(ctx context.Context, qrcode string) (status string, botToken string, err error)
PollQRCodeStatus checks the QR code scan status. Returns status string and the bot_token when confirmed.
func (*WechatAdapter) Send ¶ added in v1.1.82
func (a *WechatAdapter) Send(ctx context.Context, binding ChannelBinding, event OutboundEvent) error
Send sends an outbound message to the bound WeChat channel. Per iLink protocol spec: context_token is NOT optional — every sendmessage must carry the latest context_token from an inbound message, keyed by userID. Without it, WeChat cannot route the reply to the correct conversation.
func (*WechatAdapter) SetBotToken ¶ added in v1.1.82
func (a *WechatAdapter) SetBotToken(token string)
SetBotToken updates the bot token (after QR scan) and starts the message loop.
func (*WechatAdapter) Start ¶ added in v1.1.82
func (a *WechatAdapter) Start(ctx context.Context)
Source Files
¶
- adapters.go
- ask_user_format.go
- ask_user_parse.go
- bindings.go
- daemon_bridge.go
- dingtalk_adapter.go
- discord_adapter.go
- dummy_adapter.go
- dummy_metrics.go
- dummy_server.go
- emitter.go
- feishu_adapter.go
- history.go
- image_extract.go
- instance_detect.go
- message_split.go
- pairing.go
- pc_adapter.go
- pc_crypto.go
- pc_invite.go
- pc_protocol.go
- pc_relay_client.go
- pc_session.go
- pc_session_store.go
- qq_adapter.go
- runtime.go
- slack_adapter.go
- stt_helpers.go
- tg_adapter.go
- tg_markdown.go
- tool_format.go
- tool_status.go
- types.go
- wechat_adapter.go