eve-lark 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +155 -23
- package/README.zh-CN.md +153 -28
- package/dist/card.d.ts +167 -0
- package/dist/card.d.ts.map +1 -0
- package/dist/channel.d.ts +28 -0
- package/dist/channel.d.ts.map +1 -0
- package/dist/crypto.d.ts +31 -0
- package/dist/crypto.d.ts.map +1 -0
- package/dist/dedup.d.ts +28 -0
- package/dist/dedup.d.ts.map +1 -0
- package/dist/errors.d.ts +31 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/event-policy.d.ts +29 -0
- package/dist/event-policy.d.ts.map +1 -0
- package/dist/feishu-emoji.d.ts +16 -0
- package/dist/feishu-emoji.d.ts.map +1 -0
- package/dist/index.d.ts +24 -399
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2860 -190
- package/dist/index.js.map +1 -1
- package/dist/lark-client.d.ts +220 -0
- package/dist/lark-client.d.ts.map +1 -0
- package/dist/long-connection.d.ts +98 -0
- package/dist/long-connection.d.ts.map +1 -0
- package/dist/options.d.ts +4 -0
- package/dist/options.d.ts.map +1 -0
- package/dist/outbound.d.ts +90 -0
- package/dist/outbound.d.ts.map +1 -0
- package/dist/parse.d.ts +8 -0
- package/dist/parse.d.ts.map +1 -0
- package/dist/streaming-controller.d.ts +201 -0
- package/dist/streaming-controller.d.ts.map +1 -0
- package/dist/target.d.ts +31 -0
- package/dist/target.d.ts.map +1 -0
- package/dist/types.d.ts +521 -0
- package/dist/types.d.ts.map +1 -0
- package/package.json +6 -4
package/dist/card.d.ts
ADDED
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import type { LarkCard, LarkCardV1, LarkInputRequest } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* One tool call's renderable state. Mirror of the same name in
|
|
4
|
+
* streaming-controller.ts to avoid a circular import (controller imports
|
|
5
|
+
* card builders, not vice versa).
|
|
6
|
+
*/
|
|
7
|
+
export interface ToolCallEntry {
|
|
8
|
+
name: string;
|
|
9
|
+
state: "running" | "done" | "failed";
|
|
10
|
+
}
|
|
11
|
+
export interface LarkCardFooterMetrics {
|
|
12
|
+
elapsedMs?: number | undefined;
|
|
13
|
+
tokens?: number | undefined;
|
|
14
|
+
cachedTokens?: number | undefined;
|
|
15
|
+
contextTokens?: number | undefined;
|
|
16
|
+
model?: string | undefined;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Render tool calls as a single grey-on-grey lark_md block above the answer
|
|
20
|
+
* buffer. Running tools get `⏳`, completed get `✓` (green), failed get `✗`
|
|
21
|
+
* (red). One line per tool so the user can see the full call history even
|
|
22
|
+
* after the turn ends. Returns undefined when there are no tool calls so
|
|
23
|
+
* callers can skip pushing an empty line.
|
|
24
|
+
*/
|
|
25
|
+
export declare function renderToolCalls(calls: readonly ToolCallEntry[]): string | undefined;
|
|
26
|
+
export declare function splitReasoningText(text?: string): {
|
|
27
|
+
reasoningText?: string;
|
|
28
|
+
answerText?: string;
|
|
29
|
+
};
|
|
30
|
+
export declare function stripReasoningTags(text: string): string;
|
|
31
|
+
/**
|
|
32
|
+
* Build a Feishu interactive card that surfaces an eve `authorization.required`
|
|
33
|
+
* event: the agent needs the user to sign in to an external service. Renders
|
|
34
|
+
* the connection's display name, a URL button that opens the auth URL, and
|
|
35
|
+
* the user code (if present) so the user can copy-paste it.
|
|
36
|
+
*/
|
|
37
|
+
export declare function buildAuthCard(opts: {
|
|
38
|
+
displayName: string;
|
|
39
|
+
url: string;
|
|
40
|
+
userCode?: string | undefined;
|
|
41
|
+
}): LarkCardV1;
|
|
42
|
+
/**
|
|
43
|
+
* Build the "post-authorization" card that replaces the auth card once the
|
|
44
|
+
* user completes (or declines, or fails) the external sign-in.
|
|
45
|
+
*/
|
|
46
|
+
export declare function buildAuthCompletedCard(opts: {
|
|
47
|
+
displayName: string;
|
|
48
|
+
outcome: "authorized" | "declined" | "failed" | "timed-out" | string;
|
|
49
|
+
reason?: string | undefined;
|
|
50
|
+
}): LarkCardV1;
|
|
51
|
+
/**
|
|
52
|
+
* Build a simple single-shot card with the given markdown text. Renders via
|
|
53
|
+
* `div` + `lark_md` so the font size is close to a native chat message
|
|
54
|
+
* (the bare `markdown` element renders noticeably smaller).
|
|
55
|
+
*/
|
|
56
|
+
export declare function buildTextCard(text: string): LarkCardV1;
|
|
57
|
+
/**
|
|
58
|
+
* Build a streaming card with optional status prefix, tool-call history,
|
|
59
|
+
* answer buffer, and inline ask UI. Tool calls render first (so the user
|
|
60
|
+
* sees what the agent is doing / has done), then status, then the streamed
|
|
61
|
+
* text. If `askRequest` is set, the prompt renders below the text and an
|
|
62
|
+
* `action` row of option buttons is appended so the user can answer inline
|
|
63
|
+
* on the SAME card — no separate ask-card, no separate reply card.
|
|
64
|
+
*/
|
|
65
|
+
export declare function buildStreamingCard(opts: {
|
|
66
|
+
buffer: string;
|
|
67
|
+
status?: string | undefined;
|
|
68
|
+
toolCalls?: readonly ToolCallEntry[] | undefined;
|
|
69
|
+
askRequest?: LarkInputRequest | null | undefined;
|
|
70
|
+
reasoningText?: string | undefined;
|
|
71
|
+
footerMetrics?: LarkCardFooterMetrics | undefined;
|
|
72
|
+
}): LarkCardV1;
|
|
73
|
+
/**
|
|
74
|
+
* Build an error card displayed when a turn fails.
|
|
75
|
+
*/
|
|
76
|
+
export declare function buildErrorCard(message: string): LarkCardV1;
|
|
77
|
+
/** Marker placed in every ask-card button value so the card-action handler
|
|
78
|
+
* can recognise our own callbacks (and ignore card actions from other
|
|
79
|
+
* sources on the same message). */
|
|
80
|
+
export declare const ASK_BUTTON_VALUE_MARKER = "__eveLarkAsk";
|
|
81
|
+
export declare const ASK_FORM_VALUE_MARKER = "__eveLarkAskForm";
|
|
82
|
+
/**
|
|
83
|
+
* Build a Feishu interactive card that surfaces an eve `ask_question`
|
|
84
|
+
* input request.
|
|
85
|
+
*
|
|
86
|
+
* Render choice:
|
|
87
|
+
* - `display === "select"` OR options > {@link ASK_OPTIONS_BUTTON_MAX}:
|
|
88
|
+
* a single `select_static` dropdown. The selected optionId comes back in
|
|
89
|
+
* `action.option` (Feishu's select callback shape).
|
|
90
|
+
* - Otherwise (display "confirmation" or short option list): one button per
|
|
91
|
+
* option. Each button's `value` carries `{__eveLarkAsk, requestId,
|
|
92
|
+
* optionId}`; Feishu returns it via `action.value` on click.
|
|
93
|
+
*
|
|
94
|
+
* For `allowFreeform: true` with no options, renders just the prompt (the
|
|
95
|
+
* user replies with a normal chat message, which the channel intercepts).
|
|
96
|
+
* For `allowFreeform: true` WITH options, renders the picker AND a footer
|
|
97
|
+
* hint that the user can also type a reply.
|
|
98
|
+
*/
|
|
99
|
+
export declare function buildAskCard(request: LarkInputRequest): LarkCardV1;
|
|
100
|
+
export declare function buildAskFormCard(requests: readonly LarkInputRequest[]): LarkCard;
|
|
101
|
+
export declare function buildAskProcessingCard(requests: readonly LarkInputRequest[]): LarkCardV1;
|
|
102
|
+
export declare function buildAskFormProcessingCard(requests: readonly LarkInputRequest[]): LarkCard;
|
|
103
|
+
export declare function buildAskRejectedCard(request: LarkInputRequest, reason: string): LarkCardV1;
|
|
104
|
+
export declare function buildAskFormRejectedCard(requests: readonly LarkInputRequest[], reason: string): LarkCard;
|
|
105
|
+
export declare function buildAskExpiredCard(requests: readonly LarkInputRequest[]): LarkCardV1;
|
|
106
|
+
export declare function buildAskFormExpiredCard(requests: readonly LarkInputRequest[]): LarkCard;
|
|
107
|
+
/**
|
|
108
|
+
* Build the "post-click" card body that replaces the ask-card once the user
|
|
109
|
+
* has answered. Disables further clicks by removing the action row and
|
|
110
|
+
* appending a "✓ <selected label>" line.
|
|
111
|
+
*
|
|
112
|
+
* `priorBuffer` is optional streaming text from the controller when the ask
|
|
113
|
+
* was rendered inline on a streaming card — preserves the prior turn's text
|
|
114
|
+
* above the answered prompt instead of wiping it.
|
|
115
|
+
*/
|
|
116
|
+
export declare function buildAskAnsweredCard(request: LarkInputRequest, selected: {
|
|
117
|
+
kind: "option";
|
|
118
|
+
label: string;
|
|
119
|
+
} | {
|
|
120
|
+
kind: "freeform";
|
|
121
|
+
text: string;
|
|
122
|
+
}, priorBuffer?: string | undefined): LarkCardV1;
|
|
123
|
+
export declare function buildAskFormAnsweredCard(requests: readonly LarkInputRequest[], text?: string): LarkCard;
|
|
124
|
+
export declare const CARDKIT_STREAMING_ELEMENT_ID = "eve_lark_answer";
|
|
125
|
+
export interface CardKitV2Card {
|
|
126
|
+
schema: "2.0";
|
|
127
|
+
config: {
|
|
128
|
+
streaming_mode: boolean;
|
|
129
|
+
wide_screen_mode?: boolean;
|
|
130
|
+
update_multi?: boolean;
|
|
131
|
+
};
|
|
132
|
+
body: {
|
|
133
|
+
elements: Array<{
|
|
134
|
+
tag: string;
|
|
135
|
+
text?: {
|
|
136
|
+
tag: string;
|
|
137
|
+
content: string;
|
|
138
|
+
};
|
|
139
|
+
[k: string]: unknown;
|
|
140
|
+
}>;
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Build a CardKit v2 card body for streaming. `streamingMode: true` for
|
|
145
|
+
* intermediate patches, `false` for the final card.
|
|
146
|
+
*
|
|
147
|
+
* Uses the v2 `markdown` element (not `div+lark_md`) because CardKit v2
|
|
148
|
+
* renders `markdown` at native chat-message size, while `div+lark_md` in v2
|
|
149
|
+
* defaults to a larger / "card-like" size that looks unnatural in a chat
|
|
150
|
+
* thread. (v1 interactive cards render `div+lark_md` at native size; v2
|
|
151
|
+
* flips the defaults — pick the element that gives the look you want.)
|
|
152
|
+
*/
|
|
153
|
+
export declare function buildCardKitStreamingCard(opts: {
|
|
154
|
+
buffer: string;
|
|
155
|
+
status?: string | undefined;
|
|
156
|
+
streamingMode: boolean;
|
|
157
|
+
toolCalls?: readonly ToolCallEntry[] | undefined;
|
|
158
|
+
askRequest?: LarkInputRequest | null | undefined;
|
|
159
|
+
reasoningText?: string | undefined;
|
|
160
|
+
footerMetrics?: LarkCardFooterMetrics | undefined;
|
|
161
|
+
}): CardKitV2Card;
|
|
162
|
+
/**
|
|
163
|
+
* Build a non-streaming CardKit v2 card with the final text. Used as the
|
|
164
|
+
* terminal patch when the turn completes.
|
|
165
|
+
*/
|
|
166
|
+
export declare function buildCardKitFinalCard(text: string, toolCalls?: readonly ToolCallEntry[] | undefined, askRequest?: LarkInputRequest | null | undefined, reasoningText?: string | undefined, footerMetrics?: LarkCardFooterMetrics | undefined): CardKitV2Card;
|
|
167
|
+
//# sourceMappingURL=card.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"card.d.ts","sourceRoot":"","sources":["../src/card.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { type Channel } from "eve/channels";
|
|
2
|
+
import type { LarkChannelOptions, LarkContinuationToken } from "./types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Continuation token format: `${chatId}:${rootMessageId ?? "_"}`.
|
|
5
|
+
* The framework prepends the channel file stem before handing the token to
|
|
6
|
+
* the runtime; consumers should call this helper rather than concatenate.
|
|
7
|
+
*/
|
|
8
|
+
export declare function larkContinuationToken(chatId: string, rootMessageId: string | null): LarkContinuationToken;
|
|
9
|
+
/**
|
|
10
|
+
* Create a Lark/Feishu channel for the eve agent framework.
|
|
11
|
+
*
|
|
12
|
+
* The channel mounts a single POST webhook that verifies the request,
|
|
13
|
+
* decrypts the body when an encrypt key is configured, deduplicates events
|
|
14
|
+
* by id, parses the inbound message, and starts or resumes an eve session.
|
|
15
|
+
*
|
|
16
|
+
* Streaming happens via eve's native channel events: `message.appended`
|
|
17
|
+
* drives live card patches, `message.completed` finalizes the card, and
|
|
18
|
+
* `turn.failed` aborts it. In `replyMode: "static"` the controller is
|
|
19
|
+
* skipped and `message.completed` delivers a single card.
|
|
20
|
+
*
|
|
21
|
+
* **Delivery guarantee**: every terminal event (`message.completed` or
|
|
22
|
+
* `turn.failed`) delivers *something* to the user. If the streaming card
|
|
23
|
+
* path fails, we fall back to a fresh card; if that fails, plain text; if
|
|
24
|
+
* even that fails, the error is logged. The user is never left looking at
|
|
25
|
+
* a typing-emoji reaction with no reply.
|
|
26
|
+
*/
|
|
27
|
+
export declare function createLarkChannel(optionsInput: LarkChannelOptions): Channel<undefined, Record<string, unknown>, Record<string, unknown>>;
|
|
28
|
+
//# sourceMappingURL=channel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../src/channel.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,OAAO,EAEb,MAAM,cAAc,CAAC;AAoCtB,OAAO,KAAK,EAEV,kBAAkB,EAClB,qBAAqB,EAUtB,MAAM,YAAY,CAAC;AA2GpB;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,MAAM,GAAG,IAAI,GAC3B,qBAAqB,CAEvB;AAoZD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,iBAAiB,CAC/B,YAAY,EAAE,kBAAkB,GAC/B,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAusDtE"}
|
package/dist/crypto.d.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Verify an `X-Lark-Signature` header against the raw webhook body.
|
|
3
|
+
*
|
|
4
|
+
* Feishu computes: `sha256(timestamp + nonce + encrypt_key + body)` and ships
|
|
5
|
+
* the hex digest (optionally prefixed with `sha256=`) in `X-Lark-Signature`.
|
|
6
|
+
* We concatenate the string parts first, then the raw bytes of the body, to
|
|
7
|
+
* avoid a UTF-8 round-trip on the request body.
|
|
8
|
+
*
|
|
9
|
+
* Constant-time compare. Returns false on length mismatch instead of throwing.
|
|
10
|
+
*/
|
|
11
|
+
export declare function verifySignature(opts: {
|
|
12
|
+
timestamp: string;
|
|
13
|
+
nonce: string;
|
|
14
|
+
encryptKey: string;
|
|
15
|
+
rawBody: Buffer;
|
|
16
|
+
signatureHeader: string;
|
|
17
|
+
}): boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Decrypt the `encrypt` field from a Feishu webhook body.
|
|
20
|
+
*
|
|
21
|
+
* Layout:
|
|
22
|
+
* key = SHA256(encrypt_key) // 32 bytes → AES-256
|
|
23
|
+
* buf = base64decode(encrypt_field)
|
|
24
|
+
* iv = buf[0:16]
|
|
25
|
+
* ct = buf[16:] // AES-256-CBC ciphertext
|
|
26
|
+
* plaintext = AES_256_CBC_decrypt(key, iv, ct) // PKCS#7 unpadded
|
|
27
|
+
*
|
|
28
|
+
* Returns the raw plaintext bytes. The caller is expected to JSON.parse them.
|
|
29
|
+
*/
|
|
30
|
+
export declare function decryptPayload(encryptB64: string, encryptKey: string): Buffer;
|
|
31
|
+
//# sourceMappingURL=crypto.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../src/crypto.ts"],"names":[],"mappings":"AAGA;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,eAAe,EAAE,MAAM,CAAC;CACzB,GAAG,OAAO,CASV;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CA0B7E"}
|
package/dist/dedup.d.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-process deduplication for Feishu webhook events.
|
|
3
|
+
*
|
|
4
|
+
* Feishu retries delivery on non-2xx responses and during brief outage windows,
|
|
5
|
+
* so consumers must idempotently ack events they've already seen. We key by
|
|
6
|
+
* `header.event_id` (or `message.message_id` as a fallback) and remember each
|
|
7
|
+
* key for the TTL window.
|
|
8
|
+
*
|
|
9
|
+
* Backed by an insertion-ordered Map so FIFO eviction is O(1) at the front.
|
|
10
|
+
* Lazy sweep on every insert prevents unbounded growth of expired entries;
|
|
11
|
+
* no `setInterval` so this is safe in serverless.
|
|
12
|
+
*/
|
|
13
|
+
export declare class DedupMap {
|
|
14
|
+
private readonly entries;
|
|
15
|
+
private readonly ttlMs;
|
|
16
|
+
private readonly maxEntries;
|
|
17
|
+
private insertsSinceSweep;
|
|
18
|
+
constructor(ttlMs: number, maxEntries: number);
|
|
19
|
+
has(key: string): boolean;
|
|
20
|
+
set(key: string): void;
|
|
21
|
+
/**
|
|
22
|
+
* Walk the insertion-ordered map from the front and drop expired entries.
|
|
23
|
+
* Stops at the first non-expired entry since events arrive roughly in time
|
|
24
|
+
* order. Called on every set, so cost is amortized.
|
|
25
|
+
*/
|
|
26
|
+
private maybeSweep;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=dedup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dedup.d.ts","sourceRoot":"","sources":["../src/dedup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,qBAAa,QAAQ;IACnB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA6B;IACrD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,iBAAiB,CAAK;IAE9B,YAAY,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAG5C;IAED,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAQxB;IAED,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAWrB;IAED;;;;OAIG;IACH,OAAO,CAAC,UAAU;CAYnB"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed error hierarchy for eve-lark.
|
|
3
|
+
*
|
|
4
|
+
* All errors extend a common base so consumers can `instanceof LarkChannelError`
|
|
5
|
+
* to catch anything thrown by the channel.
|
|
6
|
+
*/
|
|
7
|
+
export declare class LarkChannelError extends Error {
|
|
8
|
+
constructor(message: string, options?: ErrorOptions);
|
|
9
|
+
}
|
|
10
|
+
export declare class LarkConfigError extends LarkChannelError {
|
|
11
|
+
}
|
|
12
|
+
export declare class LarkSignatureError extends LarkChannelError {
|
|
13
|
+
}
|
|
14
|
+
export declare class LarkDecryptError extends LarkChannelError {
|
|
15
|
+
}
|
|
16
|
+
export interface LarkApiErrorBody {
|
|
17
|
+
code?: number | undefined;
|
|
18
|
+
msg?: string | undefined;
|
|
19
|
+
}
|
|
20
|
+
export declare class LarkApiError extends LarkChannelError {
|
|
21
|
+
readonly code: number | undefined;
|
|
22
|
+
readonly body: LarkApiErrorBody | undefined;
|
|
23
|
+
readonly status: number | undefined;
|
|
24
|
+
constructor(message: string, opts?: {
|
|
25
|
+
code?: number | undefined;
|
|
26
|
+
body?: LarkApiErrorBody | undefined;
|
|
27
|
+
status?: number | undefined;
|
|
28
|
+
cause?: unknown;
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,YAAY,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,EAGlD;CACF;AAED,qBAAa,eAAgB,SAAQ,gBAAgB;CAAG;AAExD,qBAAa,kBAAmB,SAAQ,gBAAgB;CAAG;AAE3D,qBAAa,gBAAiB,SAAQ,gBAAgB;CAAG;AAEzD,MAAM,WAAW,gBAAgB;IAC/B,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC1B;AAED,qBAAa,YAAa,SAAQ,gBAAgB;IAChD,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,QAAQ,CAAC,IAAI,EAAE,gBAAgB,GAAG,SAAS,CAAC;IAC5C,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAEpC,YACE,OAAO,EAAE,MAAM,EACf,IAAI,CAAC,EAAE;QACL,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QAC1B,IAAI,CAAC,EAAE,gBAAgB,GAAG,SAAS,CAAC;QACpC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QAC5B,KAAK,CAAC,EAAE,OAAO,CAAC;KACjB,EAMF;CACF"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { LarkChatType, LarkEventHeader } from "./types.js";
|
|
2
|
+
export declare function isEventOwnedByApp(header: Pick<LarkEventHeader, "app_id"> | undefined, appId: string): boolean;
|
|
3
|
+
export declare function isEventExpired(header: Pick<LarkEventHeader, "create_time"> | undefined, nowMs: number, ttlMs: number): boolean;
|
|
4
|
+
export declare function isAbortText(text: string): boolean;
|
|
5
|
+
export declare class ChatTaskQueue {
|
|
6
|
+
private readonly chains;
|
|
7
|
+
enqueue<T>(key: string, task: () => Promise<T>): Promise<T>;
|
|
8
|
+
has(key: string): boolean;
|
|
9
|
+
}
|
|
10
|
+
export declare class BotLoopGuard {
|
|
11
|
+
private readonly maxBotTurns;
|
|
12
|
+
private readonly counts;
|
|
13
|
+
constructor(opts: {
|
|
14
|
+
maxBotTurns: number;
|
|
15
|
+
});
|
|
16
|
+
record(key: string, senderType: "user" | "app"): boolean;
|
|
17
|
+
}
|
|
18
|
+
export interface ParsedReactionCreated {
|
|
19
|
+
sourceMessageId: string;
|
|
20
|
+
chatId: string | null;
|
|
21
|
+
chatType: LarkChatType | null;
|
|
22
|
+
messageId: string;
|
|
23
|
+
senderOpenId: string;
|
|
24
|
+
text: string;
|
|
25
|
+
rootId: string | null;
|
|
26
|
+
parentId: string | null;
|
|
27
|
+
}
|
|
28
|
+
export declare function parseReactionCreatedEvent(event: unknown): ParsedReactionCreated | null;
|
|
29
|
+
//# sourceMappingURL=event-policy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-policy.d.ts","sourceRoot":"","sources":["../src/event-policy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAEhE,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,IAAI,CAAC,eAAe,EAAE,QAAQ,CAAC,GAAG,SAAS,EACnD,KAAK,EAAE,MAAM,GACZ,OAAO,CAGT;AAED,wBAAgB,cAAc,CAC5B,MAAM,EAAE,IAAI,CAAC,eAAe,EAAE,aAAa,CAAC,GAAG,SAAS,EACxD,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,GACZ,OAAO,CAKT;AA0BD,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAOjD;AAED,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAoC;IAE3D,OAAO,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAc1D;IAED,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAExB;CACF;AAED,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA6B;IAEpD,YAAY,IAAI,EAAE;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE,EAExC;IAED,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,KAAK,GAAG,OAAO,CAQvD;CACF;AAED,MAAM,WAAW,qBAAqB;IACpC,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,QAAQ,EAAE,YAAY,GAAG,IAAI,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,OAAO,GAAG,qBAAqB,GAAG,IAAI,CA0CtF"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Valid Feishu emoji type strings for the message-reactions API.
|
|
3
|
+
*
|
|
4
|
+
* Feishu emoji types are case-sensitive and inconsistent: most are uppercase
|
|
5
|
+
* (`THUMBSUP`, `OK`), but a meaningful subset is CamelCase (`Typing`,
|
|
6
|
+
* `CrossMark`, `EatingFood`, `Drumstick`, …). Passing the wrong case fails
|
|
7
|
+
* with HTTP 400 code=231001 "reaction type is invalid" — silent unless the
|
|
8
|
+
* caller is watching logs.
|
|
9
|
+
*
|
|
10
|
+
* Source: openclaw-lark's `VALID_FEISHU_EMOJI_TYPES` (which references the
|
|
11
|
+
* official Feishu emoji doc).
|
|
12
|
+
*/
|
|
13
|
+
export declare const VALID_FEISHU_EMOJI_TYPES: ReadonlySet<string>;
|
|
14
|
+
/** Returns true iff `s` is a valid Feishu emoji type string (case-sensitive). */
|
|
15
|
+
export declare function isValidFeishuEmojiType(s: string): boolean;
|
|
16
|
+
//# sourceMappingURL=feishu-emoji.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"feishu-emoji.d.ts","sourceRoot":"","sources":["../src/feishu-emoji.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,wBAAwB,EAAE,WAAW,CAAC,MAAM,CA8BvD,CAAC;AAEH,iFAAiF;AACjF,wBAAgB,sBAAsB,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAEzD"}
|