@zengxingyuan/aamp-feishu-task-bridge 0.1.1-dev.10

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 ADDED
@@ -0,0 +1,169 @@
1
+ # aamp-feishu-task-bridge
2
+
3
+ Local bridge daemon for dispatching Feishu task events to a target AAMP Agent.
4
+
5
+ ## Shape
6
+
7
+ This package is intentionally thin:
8
+
9
+ - Feishu task event -> AAMP `task.dispatch` -> target Agent
10
+ - AAMP `task.ack` -> one default Feishu task comment
11
+ - AAMP `task.help_needed` -> one Feishu task comment with the help question,
12
+ then mark the Feishu task blocked/waiting for human input
13
+ - AAMP `task.stream.opened` + selected stream events -> throttled Feishu task
14
+ steps on the parent task
15
+ - AAMP `task.result` -> parse `FEISHU_TASK_RESULT_JSON`, write a summary
16
+ comment, and complete child tasks before the parent task for success/failure
17
+ - `card.*`, cancel, and delete are not consumed by this bridge
18
+
19
+ The bridge dispatches only trusted task execution triggers from
20
+ `task.task.update_user_access_v2`:
21
+
22
+ - `task_create`
23
+ - `task_comment_create`
24
+ - `task_comment_reply`
25
+ - `task_comment_update`
26
+
27
+ Other task update event types are recorded as ignored and are not dispatched.
28
+
29
+ The dispatched prompt treats handled Feishu events as execution of an existing
30
+ Feishu task, not as a plain chat question. It carries
31
+ `source=feishu-task`, task guid/id/status, event id/types, event kind, and
32
+ whether the task has children in dispatch context. The dispatched `bodyText`
33
+ is also sent as `rawBodyText`; it contains only Feishu task context facts: the
34
+ parent task text, child task text, loaded task comments, latest effective human
35
+ comment, and event metadata. This lets the target Agent infer intent directly
36
+ without installing a Feishu task skill.
37
+
38
+ For ACP agents, the bridge also sends `promptRules` on `task.dispatch` so
39
+ `aamp-acp-bridge` replaces its default task rules with a complete Feishu task
40
+ rule prompt. Feishu execution constraints, environment-switch commands, result
41
+ schema, and deliverable rules live in `promptRules`, not in `bodyText`. This
42
+ keeps task context focused while preventing Feishu task events from being
43
+ treated as simple direct-answer questions. The target Agent should use local
44
+ `lark-cli` or `larksuite-cli` for direct Feishu task writes requested by those
45
+ rules:
46
+
47
+ - Write delivery only to the parent task when there is a concrete deliverable.
48
+ - For task execution, mark the parent task in progress before material work; child
49
+ tasks are context-tracking only and never receive steps or deliverables.
50
+ - Do not write steps directly; selected `status` / `progress` / `error` stream
51
+ events are converted by this bridge into Feishu task steps.
52
+ - Do not complete tasks directly; the bridge completes child tasks before the
53
+ parent after parsing the final result.
54
+
55
+ The final result must be an `AAMP_RESULT_JSON` object containing only `output`,
56
+ and `output` must start with `FEISHU_TASK_RESULT_JSON:` followed by compact JSON:
57
+
58
+ ```text
59
+ AAMP_RESULT_JSON: {"output":"FEISHU_TASK_RESULT_JSON: {\"status\":\"success\",\"summary\":\"...\",\"deliverable_written\":true,\"deliverable_summary\":\"...\"}"}
60
+ ```
61
+
62
+ Use `status=answered` when the agent already wrote a normal Feishu comment and
63
+ there is no separate deliverable. Use `status=success` for completed work with
64
+ a concrete deliverable, `status=failed` for execution that
65
+ ended with a blocker but should still close the Feishu task, and
66
+ `status=need_help` when human input is required before continuing.
67
+
68
+ Default ACK comments are scenario-specific:
69
+
70
+ - `task_create`: `已收到任务派发请求,正在转交智能体处理。`
71
+ - `task_comment_*`: `已收到您的回复,正在转交智能体处理。`
72
+
73
+ When the target Agent returns a `HELP:` response, `aamp-acp-bridge` converts it
74
+ to `task.help_needed`. This bridge writes the help `question` body back to the
75
+ Feishu task exactly once for the corresponding AAMP task id, then marks the
76
+ task blocked/waiting for human input. When the target Agent returns
77
+ `task.result`, successful and failed `FEISHU_TASK_RESULT_JSON` payloads are
78
+ summarized as a Feishu comment and completed by the bridge. Rejected or malformed
79
+ results are treated as failures and completed with an error summary.
80
+
81
+ ## Usage
82
+
83
+ ```bash
84
+ cd ../sdks/nodejs
85
+ npm install
86
+ npm run build
87
+
88
+ cd ../aamp-feishu-task-bridge
89
+ npm install
90
+ npm run build
91
+
92
+ node dist/index.js init \
93
+ --aamp-host https://meshmail.ai \
94
+ --target-agent agent@meshmail.ai \
95
+ --app-id cli_xxx \
96
+ --app-secret xxx
97
+ ```
98
+
99
+ For ByteDance BOE debugging, start the bridge with runtime-only overrides:
100
+
101
+ ```bash
102
+ node dist/index.js start \
103
+ --boe \
104
+ --env boe_task_event
105
+ ```
106
+
107
+ For ByteDance PRE + PPE debugging, start the bridge with runtime-only overrides:
108
+
109
+ ```bash
110
+ node dist/index.js start \
111
+ --pre \
112
+ --env ppe_task_event
113
+ ```
114
+
115
+ For PPE debugging on the normal configured domain, omit `--pre`:
116
+
117
+ ```bash
118
+ node dist/index.js start --env ppe_task_event
119
+ ```
120
+
121
+ Environment mode behavior:
122
+
123
+ - `--boe --env boe_task_event`: uses `https://open.feishu-boe.cn`, sends
124
+ `x-tt-env: boe_task_event`, and tells the target agent to run
125
+ `source ~/lark-env.sh boe --boe-env-name boe_task_event`.
126
+ - `--pre --env ppe_task_event`: uses `https://open.feishu-pre.cn`, sends
127
+ `x-use-ppe: 1` and `x-tt-env: ppe_task_event`, and tells the target agent to
128
+ run `source ~/lark-env.sh pre --ppe-env-name ppe_task_event`.
129
+ - `--env ppe_task_event`: keeps the configured/default domain, sends
130
+ `x-use-ppe: 1` and `x-tt-env: ppe_task_event`, and tells the target agent to
131
+ run `source ~/lark-env.sh --ppe-env-name ppe_task_event`.
132
+
133
+ Environment mode flags (`--domain`, `--boe`, `--pre`, `--env`) are runtime-only.
134
+ They are applied to the current `start` process but are not persisted in
135
+ `config.json`.
136
+
137
+ `init` writes the config and starts the local bridge immediately. Use
138
+ `--no-start` when you only want to write the config.
139
+
140
+ If the target Agent prints a pairing URL:
141
+
142
+ ```bash
143
+ node dist/index.js init \
144
+ --pairing-url "aamp://connect?mailbox=agent@meshmail.ai&pair_code=abc123" \
145
+ --app-id cli_xxx \
146
+ --app-secret xxx
147
+ ```
148
+
149
+ The bridge sends `pair.request` with
150
+ `dispatchContextRules={ "source": ["feishu-task"] }`.
151
+
152
+ ## Options
153
+
154
+ - `--event-name NAME`: register a Feishu event name. Can be repeated.
155
+ - `--boe`: use ByteDance BOE OpenAPI domain.
156
+ - `--pre`: use ByteDance PRE OpenAPI domain.
157
+ - `--env NAME`: add `x-tt-env: NAME` to Feishu OpenAPI requests. With `--pre`
158
+ or without `--boe`, also add `x-use-ppe: 1`.
159
+ - `--debug`: print detailed logs and write detailed ACK comments.
160
+ - `--task-api-version v1|v2`: choose Feishu task API version. Defaults to `v2`.
161
+ When v2 lookup/comment fails, the OAPI client tries the v1 task API as a
162
+ fallback because the currently generated SDK task events expose v1
163
+ `task_id`.
164
+ - `--no-ack-comment`: disable the default Feishu comment on AAMP `task.ack`.
165
+ - `--config-dir DIR`: use a custom config/state directory.
166
+
167
+ Default event name is `task.task.update_user_access_v2`. The event normalizer
168
+ requires `event_id` and accepts `task_guid`, `guid`, `task_id`, `resource_id`,
169
+ or `object_id` as the task identifier.
package/dist/ack.d.ts ADDED
@@ -0,0 +1,12 @@
1
+ import type { BridgeTaskState, FeishuTaskEventKind } from './types.js';
2
+ export interface BuildAckCommentOptions {
3
+ aampTaskId: string;
4
+ bridgeName: string;
5
+ eventKind?: FeishuTaskEventKind;
6
+ receivedAt?: Date;
7
+ debug?: boolean;
8
+ }
9
+ export declare function buildAckComment(options: BuildAckCommentOptions): string;
10
+ export declare function shouldCommentAck(state: BridgeTaskState, aampTaskId: string): boolean;
11
+ export declare function markAckCommented(state: BridgeTaskState, aampTaskId: string): BridgeTaskState;
12
+ //# sourceMappingURL=ack.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ack.d.ts","sourceRoot":"","sources":["../src/ack.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAA;AAEtE,MAAM,WAAW,sBAAsB;IACrC,UAAU,EAAE,MAAM,CAAA;IAClB,UAAU,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,mBAAmB,CAAA;IAC/B,UAAU,CAAC,EAAE,IAAI,CAAA;IACjB,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB;AAYD,wBAAgB,eAAe,CAAC,OAAO,EAAE,sBAAsB,GAAG,MAAM,CAkBvE;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAEpF;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,GAAG,eAAe,CAS5F"}
package/dist/ack.js ADDED
@@ -0,0 +1,41 @@
1
+ function ackLeadText(eventKind) {
2
+ if (eventKind === 'task_comment') {
3
+ return '已收到您的回复';
4
+ }
5
+ if (eventKind === 'task_reminder_fire') {
6
+ return '任务提醒已到期';
7
+ }
8
+ return '已收到任务派发请求';
9
+ }
10
+ export function buildAckComment(options) {
11
+ const leadText = ackLeadText(options.eventKind);
12
+ const visibleAckText = `${leadText},正在转交智能体处理。`;
13
+ if (!options.debug) {
14
+ return visibleAckText;
15
+ }
16
+ const receivedAt = (options.receivedAt ?? new Date()).toISOString();
17
+ return [
18
+ visibleAckText,
19
+ '',
20
+ `AAMP Task ID: ${options.aampTaskId}`,
21
+ `Bridge: ${options.bridgeName}`,
22
+ `事件场景: ${options.eventKind ?? 'task_create'}`,
23
+ `收到时间: ${receivedAt}`,
24
+ '',
25
+ '说明:这只表示本地 bridge 已收到 agent 的接收确认,不代表任务已正式开始执行,也不代表任务状态已经流转完成。',
26
+ ].join('\n');
27
+ }
28
+ export function shouldCommentAck(state, aampTaskId) {
29
+ return !(state.ackCommentedTaskIds ?? []).includes(aampTaskId);
30
+ }
31
+ export function markAckCommented(state, aampTaskId) {
32
+ const ackCommentedTaskIds = new Set(state.ackCommentedTaskIds ?? []);
33
+ ackCommentedTaskIds.add(aampTaskId);
34
+ return {
35
+ ...state,
36
+ status: 'acknowledged',
37
+ ackCommentedTaskIds: [...ackCommentedTaskIds],
38
+ updatedAt: new Date().toISOString(),
39
+ };
40
+ }
41
+ //# sourceMappingURL=ack.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ack.js","sourceRoot":"","sources":["../src/ack.ts"],"names":[],"mappings":"AAUA,SAAS,WAAW,CAAC,SAA0C;IAC7D,IAAI,SAAS,KAAK,cAAc,EAAE,CAAC;QACjC,OAAO,SAAS,CAAA;IAClB,CAAC;IACD,IAAI,SAAS,KAAK,oBAAoB,EAAE,CAAC;QACvC,OAAO,SAAS,CAAA;IAClB,CAAC;IACD,OAAO,WAAW,CAAA;AACpB,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,OAA+B;IAC7D,MAAM,QAAQ,GAAG,WAAW,CAAC,OAAO,CAAC,SAAS,CAAC,CAAA;IAC/C,MAAM,cAAc,GAAG,GAAG,QAAQ,aAAa,CAAA;IAC/C,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QACnB,OAAO,cAAc,CAAA;IACvB,CAAC;IAED,MAAM,UAAU,GAAG,CAAC,OAAO,CAAC,UAAU,IAAI,IAAI,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAA;IACnE,OAAO;QACL,cAAc;QACd,EAAE;QACF,iBAAiB,OAAO,CAAC,UAAU,EAAE;QACrC,WAAW,OAAO,CAAC,UAAU,EAAE;QAC/B,SAAS,OAAO,CAAC,SAAS,IAAI,aAAa,EAAE;QAC7C,SAAS,UAAU,EAAE;QACrB,EAAE;QACF,+DAA+D;KAChE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACd,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,KAAsB,EAAE,UAAkB;IACzE,OAAO,CAAC,CAAC,KAAK,CAAC,mBAAmB,IAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAA;AAChE,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,KAAsB,EAAE,UAAkB;IACzE,MAAM,mBAAmB,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,mBAAmB,IAAI,EAAE,CAAC,CAAA;IACpE,mBAAmB,CAAC,GAAG,CAAC,UAAU,CAAC,CAAA;IACnC,OAAO;QACL,GAAG,KAAK;QACR,MAAM,EAAE,cAAc;QACtB,mBAAmB,EAAE,CAAC,GAAG,mBAAmB,CAAC;QAC7C,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;KACpC,CAAA;AACH,CAAC"}
@@ -0,0 +1,41 @@
1
+ import type { BridgeConfig, BridgeState, FeishuTaskApiVersion } from './types.js';
2
+ export declare const FEISHU_BOE_DOMAIN = "https://open.feishu-boe.cn";
3
+ export declare const FEISHU_PRE_DOMAIN = "https://open.feishu-pre.cn";
4
+ export declare function getBridgeHomeDir(customDir?: string): string;
5
+ export declare function getConfigPath(customDir?: string): string;
6
+ export declare function getStatePath(customDir?: string): string;
7
+ export declare function ensureBridgeHomeDir(customDir?: string): Promise<string>;
8
+ export declare function loadBridgeConfig(customDir?: string): Promise<BridgeConfig | null>;
9
+ export declare function saveBridgeConfig(config: BridgeConfig, customDir?: string): Promise<void>;
10
+ export declare function createDefaultBridgeState(): BridgeState;
11
+ export declare function loadBridgeState(customDir?: string): Promise<BridgeState>;
12
+ export declare function saveBridgeState(state: BridgeState, customDir?: string): Promise<void>;
13
+ export declare function resetBridgeState(customDir?: string): Promise<void>;
14
+ export interface InitBridgeOptions {
15
+ configDir?: string;
16
+ aampHost?: string;
17
+ targetAgentEmail?: string;
18
+ pairingUrl?: string;
19
+ slug?: string;
20
+ appId?: string;
21
+ appSecret?: string;
22
+ domain?: string;
23
+ boe?: boolean;
24
+ pre?: boolean;
25
+ env?: string;
26
+ eventNames?: string[];
27
+ userIdType?: 'open_id' | 'user_id' | 'union_id';
28
+ taskApiVersion?: FeishuTaskApiVersion;
29
+ ackComment?: boolean;
30
+ debug?: boolean;
31
+ }
32
+ export interface FeishuRuntimeOverrides {
33
+ domain?: string;
34
+ boe?: boolean;
35
+ pre?: boolean;
36
+ env?: string;
37
+ debug?: boolean;
38
+ }
39
+ export declare function applyFeishuRuntimeOverrides(config: BridgeConfig, overrides: FeishuRuntimeOverrides): BridgeConfig;
40
+ export declare function initializeBridgeConfig(options: InitBridgeOptions): Promise<BridgeConfig>;
41
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAA;AAKjF,eAAO,MAAM,iBAAiB,+BAA+B,CAAA;AAC7D,eAAO,MAAM,iBAAiB,+BAA+B,CAAA;AAW7D,wBAAgB,gBAAgB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAI3D;AAED,wBAAgB,aAAa,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAExD;AAED,wBAAgB,YAAY,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED,wBAAsB,mBAAmB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAI7E;AAUD,wBAAsB,gBAAgB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAKvF;AAED,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,YAAY,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE9F;AAED,wBAAgB,wBAAwB,IAAI,WAAW,CAUtD;AAED,wBAAsB,eAAe,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAgB9E;AAED,wBAAsB,eAAe,CAAC,KAAK,EAAE,WAAW,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE3F;AAED,wBAAsB,gBAAgB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAIxE;AAED,MAAM,WAAW,iBAAiB;IAChC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,GAAG,CAAC,EAAE,OAAO,CAAA;IACb,GAAG,CAAC,EAAE,OAAO,CAAA;IACb,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,UAAU,CAAC,EAAE,MAAM,EAAE,CAAA;IACrB,UAAU,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,UAAU,CAAA;IAC/C,cAAc,CAAC,EAAE,oBAAoB,CAAA;IACrC,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB;AAED,MAAM,WAAW,sBAAsB;IACrC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,GAAG,CAAC,EAAE,OAAO,CAAA;IACb,GAAG,CAAC,EAAE,OAAO,CAAA;IACb,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB;AAqID,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,YAAY,EACpB,SAAS,EAAE,sBAAsB,GAChC,YAAY,CAmBd;AAED,wBAAsB,sBAAsB,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,YAAY,CAAC,CA4E9F"}
package/dist/config.js ADDED
@@ -0,0 +1,290 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { existsSync } from 'node:fs';
3
+ import { mkdir, readFile, rename, rm, writeFile } from 'node:fs/promises';
4
+ import os from 'node:os';
5
+ import path from 'node:path';
6
+ import readline from 'node:readline/promises';
7
+ import { stdin as input, stdout as output } from 'node:process';
8
+ import { AampClient, isPairingUrl, parsePairingUrl } from 'aamp-sdk';
9
+ const CONFIG_FILENAME = 'config.json';
10
+ const STATE_FILENAME = 'state.json';
11
+ const DEFAULT_BRIDGE_SLUG = 'feishu-task-bridge';
12
+ export const FEISHU_BOE_DOMAIN = 'https://open.feishu-boe.cn';
13
+ export const FEISHU_PRE_DOMAIN = 'https://open.feishu-pre.cn';
14
+ const X_TT_ENV_HEADER = 'x-tt-env';
15
+ const X_USE_PPE_HEADER = 'x-use-ppe';
16
+ const DEFAULT_EVENT_NAMES = [
17
+ 'task.task.update_user_access_v2',
18
+ ];
19
+ const LEGACY_DEFAULT_EVENT_NAMES = [
20
+ 'task.task.updated_v1',
21
+ 'task.task.update_tenant_v1',
22
+ ];
23
+ export function getBridgeHomeDir(customDir) {
24
+ return customDir
25
+ ? path.resolve(customDir)
26
+ : path.join(os.homedir(), '.aamp', 'feishu-task-bridge');
27
+ }
28
+ export function getConfigPath(customDir) {
29
+ return path.join(getBridgeHomeDir(customDir), CONFIG_FILENAME);
30
+ }
31
+ export function getStatePath(customDir) {
32
+ return path.join(getBridgeHomeDir(customDir), STATE_FILENAME);
33
+ }
34
+ export async function ensureBridgeHomeDir(customDir) {
35
+ const dir = getBridgeHomeDir(customDir);
36
+ await mkdir(dir, { recursive: true });
37
+ return dir;
38
+ }
39
+ async function writeJsonAtomic(filePath, value) {
40
+ const parentDir = path.dirname(filePath);
41
+ await mkdir(parentDir, { recursive: true });
42
+ const tempPath = path.join(parentDir, `.${path.basename(filePath)}.${randomUUID()}.tmp`);
43
+ await writeFile(tempPath, `${JSON.stringify(value, null, 2)}\n`, 'utf8');
44
+ await rename(tempPath, filePath);
45
+ }
46
+ export async function loadBridgeConfig(customDir) {
47
+ const filePath = getConfigPath(customDir);
48
+ if (!existsSync(filePath))
49
+ return null;
50
+ const raw = await readFile(filePath, 'utf8');
51
+ return normalizeBridgeConfig(JSON.parse(raw));
52
+ }
53
+ export async function saveBridgeConfig(config, customDir) {
54
+ await writeJsonAtomic(getConfigPath(customDir), config);
55
+ }
56
+ export function createDefaultBridgeState() {
57
+ return {
58
+ version: 1,
59
+ connectivity: {
60
+ feishu: 'disconnected',
61
+ aamp: 'disconnected',
62
+ },
63
+ tasks: {},
64
+ dedupEventIds: {},
65
+ };
66
+ }
67
+ export async function loadBridgeState(customDir) {
68
+ const filePath = getStatePath(customDir);
69
+ if (!existsSync(filePath))
70
+ return createDefaultBridgeState();
71
+ const raw = await readFile(filePath, 'utf8');
72
+ const parsed = JSON.parse(raw);
73
+ const defaults = createDefaultBridgeState();
74
+ return {
75
+ ...defaults,
76
+ ...parsed,
77
+ connectivity: {
78
+ ...defaults.connectivity,
79
+ ...(parsed.connectivity ?? {}),
80
+ },
81
+ tasks: parsed.tasks ?? {},
82
+ dedupEventIds: parsed.dedupEventIds ?? {},
83
+ };
84
+ }
85
+ export async function saveBridgeState(state, customDir) {
86
+ await writeJsonAtomic(getStatePath(customDir), state);
87
+ }
88
+ export async function resetBridgeState(customDir) {
89
+ const filePath = getStatePath(customDir);
90
+ if (!existsSync(filePath))
91
+ return;
92
+ await rm(filePath, { force: true });
93
+ }
94
+ async function prompt(question, defaultValue = '') {
95
+ const rl = readline.createInterface({ input, output });
96
+ try {
97
+ const suffix = defaultValue ? ` (${defaultValue})` : '';
98
+ const answer = await rl.question(`${question}${suffix}: `);
99
+ return answer.trim() || defaultValue;
100
+ }
101
+ finally {
102
+ rl.close();
103
+ }
104
+ }
105
+ function normalizeSlug(rawValue) {
106
+ return rawValue
107
+ .toLowerCase()
108
+ .replace(/[\s_]+/g, '-')
109
+ .replace(/[^a-z0-9-]/g, '')
110
+ .replace(/-+/g, '-')
111
+ .replace(/^-|-$/g, '')
112
+ .slice(0, 32) || DEFAULT_BRIDGE_SLUG;
113
+ }
114
+ function normalizeTaskApiVersion(value) {
115
+ return value === 'v1' ? 'v1' : 'v2';
116
+ }
117
+ function normalizeHeaders(headers) {
118
+ const normalized = Object.fromEntries(Object.entries(headers ?? {})
119
+ .map(([key, value]) => [key.trim(), value.trim()])
120
+ .filter(([key, value]) => Boolean(key) && Boolean(value)));
121
+ return Object.keys(normalized).length > 0 ? normalized : undefined;
122
+ }
123
+ function normalizeEnv(value) {
124
+ return value?.trim() || undefined;
125
+ }
126
+ function withoutManagedEnvHeaders(headers, removePpeHeader) {
127
+ return Object.fromEntries(Object.entries(headers ?? {}).filter(([key]) => {
128
+ const normalizedKey = key.trim().toLowerCase();
129
+ return normalizedKey !== X_TT_ENV_HEADER && (!removePpeHeader || normalizedKey !== X_USE_PPE_HEADER);
130
+ }));
131
+ }
132
+ function resolveFeishuHeaderMode(boe, pre, env) {
133
+ if (boe)
134
+ return 'boe';
135
+ if (pre)
136
+ return 'pre';
137
+ return normalizeEnv(env) ? 'ppe' : undefined;
138
+ }
139
+ function normalizeFeishuHeaders(headers, env, mode) {
140
+ const normalizedEnv = normalizeEnv(env);
141
+ const removePpeHeader = mode === 'boe' || mode === 'pre' || mode === 'ppe';
142
+ const unmanagedHeaders = withoutManagedEnvHeaders(headers, removePpeHeader);
143
+ return normalizeHeaders({
144
+ ...unmanagedHeaders,
145
+ ...(normalizedEnv && (mode === 'pre' || mode === 'ppe') ? { [X_USE_PPE_HEADER]: '1' } : {}),
146
+ ...(normalizedEnv ? { [X_TT_ENV_HEADER]: normalizedEnv } : {}),
147
+ });
148
+ }
149
+ function resolveFeishuDomain(existingDomain, overrideDomain, boe, pre) {
150
+ return (overrideDomain ?? (boe ? FEISHU_BOE_DOMAIN : pre ? FEISHU_PRE_DOMAIN : existingDomain) ?? '').trim() || undefined;
151
+ }
152
+ function normalizeEventNames(values) {
153
+ const normalized = (values ?? DEFAULT_EVENT_NAMES)
154
+ .flatMap((value) => value.split(','))
155
+ .map((value) => value.trim())
156
+ .filter(Boolean);
157
+ return normalized.length ? [...new Set(normalized)] : DEFAULT_EVENT_NAMES;
158
+ }
159
+ function hasSameEventNames(left, right) {
160
+ if (left.length !== right.length)
161
+ return false;
162
+ const rightValues = new Set(right);
163
+ return left.every((value) => rightValues.has(value));
164
+ }
165
+ function normalizeConfiguredEventNames(values) {
166
+ const normalized = normalizeEventNames(values);
167
+ return hasSameEventNames(normalized, LEGACY_DEFAULT_EVENT_NAMES)
168
+ ? DEFAULT_EVENT_NAMES
169
+ : normalized;
170
+ }
171
+ function normalizeBridgeConfig(config) {
172
+ if (!config.aampHost || !config.targetAgentEmail || !config.slug || !config.feishu || !config.mailbox) {
173
+ throw new Error('Bridge config is incomplete. Run "aamp-feishu-task-bridge init" again.');
174
+ }
175
+ return {
176
+ version: 1,
177
+ aampHost: config.aampHost,
178
+ targetAgentEmail: config.targetAgentEmail,
179
+ slug: config.slug,
180
+ feishu: {
181
+ appId: config.feishu.appId,
182
+ appSecret: config.feishu.appSecret,
183
+ userIdType: config.feishu.userIdType ?? 'open_id',
184
+ taskApiVersion: normalizeTaskApiVersion(config.feishu.taskApiVersion),
185
+ eventNames: normalizeConfiguredEventNames(config.feishu.eventNames),
186
+ },
187
+ mailbox: config.mailbox,
188
+ behavior: {
189
+ ackComment: config.behavior?.ackComment ?? true,
190
+ debug: config.behavior?.debug ?? false,
191
+ },
192
+ };
193
+ }
194
+ export function applyFeishuRuntimeOverrides(config, overrides) {
195
+ const domain = resolveFeishuDomain(undefined, overrides.domain, overrides.boe, overrides.pre);
196
+ const headerMode = resolveFeishuHeaderMode(overrides.boe, overrides.pre, overrides.env);
197
+ const headers = normalizeFeishuHeaders(undefined, overrides.env, headerMode);
198
+ const feishu = { ...config.feishu };
199
+ if (domain)
200
+ feishu.domain = domain;
201
+ else
202
+ delete feishu.domain;
203
+ if (headers)
204
+ feishu.headers = headers;
205
+ else
206
+ delete feishu.headers;
207
+ const behavior = {
208
+ ...config.behavior,
209
+ ...(overrides.debug ? { debug: true } : {}),
210
+ };
211
+ return {
212
+ ...config,
213
+ feishu,
214
+ behavior,
215
+ };
216
+ }
217
+ export async function initializeBridgeConfig(options) {
218
+ const existing = await loadBridgeConfig(options.configDir).catch(() => null);
219
+ const aampHost = (options.aampHost ?? existing?.aampHost ?? await prompt('AAMP host', 'https://meshmail.ai')).trim();
220
+ const targetInput = (options.pairingUrl ?? options.targetAgentEmail ?? existing?.targetAgentEmail ?? await prompt('Target AAMP agent email or pairing URL')).trim();
221
+ const pairing = isPairingUrl(targetInput)
222
+ ? parsePairingUrl(targetInput)
223
+ : undefined;
224
+ const targetAgentEmail = pairing?.mailbox ?? targetInput;
225
+ const appId = (options.appId ?? existing?.feishu.appId ?? await prompt('Feishu App ID')).trim();
226
+ const appSecret = (options.appSecret ?? existing?.feishu.appSecret ?? await prompt('Feishu App Secret')).trim();
227
+ const slug = normalizeSlug(options.slug ?? existing?.slug ?? DEFAULT_BRIDGE_SLUG);
228
+ const eventNames = options.eventNames
229
+ ? normalizeEventNames(options.eventNames)
230
+ : normalizeConfiguredEventNames(existing?.feishu.eventNames);
231
+ const userIdType = options.userIdType ?? existing?.feishu.userIdType ?? 'open_id';
232
+ const taskApiVersion = options.taskApiVersion ?? existing?.feishu.taskApiVersion ?? 'v2';
233
+ const ackComment = options.ackComment ?? existing?.behavior.ackComment ?? true;
234
+ const debug = options.debug ?? existing?.behavior.debug ?? false;
235
+ if (!targetAgentEmail)
236
+ throw new Error('Target AAMP agent email is required.');
237
+ if (!appId || !appSecret)
238
+ throw new Error('Feishu App ID and App Secret are required.');
239
+ const mailbox = existing?.mailbox ?? await AampClient.registerMailbox({
240
+ aampHost,
241
+ slug,
242
+ description: `Feishu task bridge for ${targetAgentEmail}`,
243
+ });
244
+ const config = {
245
+ version: 1,
246
+ aampHost,
247
+ targetAgentEmail,
248
+ slug,
249
+ feishu: {
250
+ appId,
251
+ appSecret,
252
+ userIdType,
253
+ taskApiVersion,
254
+ eventNames,
255
+ },
256
+ mailbox: {
257
+ email: mailbox.email,
258
+ mailboxToken: mailbox.mailboxToken,
259
+ smtpPassword: mailbox.smtpPassword,
260
+ baseUrl: mailbox.baseUrl,
261
+ },
262
+ behavior: {
263
+ ackComment,
264
+ debug,
265
+ },
266
+ };
267
+ await ensureBridgeHomeDir(options.configDir);
268
+ await saveBridgeConfig(config, options.configDir);
269
+ if (pairing) {
270
+ const client = AampClient.fromMailboxIdentity({
271
+ email: config.mailbox.email,
272
+ smtpPassword: config.mailbox.smtpPassword,
273
+ baseUrl: config.mailbox.baseUrl,
274
+ });
275
+ try {
276
+ await client.sendPairRequest({
277
+ to: pairing.mailbox,
278
+ pairCode: pairing.pairCode,
279
+ dispatchContextRules: pairing.dispatchContextRules ?? { source: ['feishu-task'] },
280
+ });
281
+ }
282
+ catch (error) {
283
+ throw new Error(`AAMP pair request failed for ${pairing.mailbox}: ${error.message}`, {
284
+ cause: error,
285
+ });
286
+ }
287
+ }
288
+ return config;
289
+ }
290
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import type { FeishuTaskDetails, FeishuTaskDispatch, FeishuTaskEvent, FeishuTaskEventKind } from './types.js';
2
+ export interface FeishuTaskDispatchOptions {
3
+ feishuBoe?: boolean;
4
+ feishuEnvMode?: 'boe' | 'pre' | 'ppe';
5
+ feishuEnv?: string;
6
+ }
7
+ export declare function buildFeishuTaskDispatchContext(event: FeishuTaskEvent, task: FeishuTaskDetails, eventKind: FeishuTaskEventKind): Record<string, string>;
8
+ export declare function buildFeishuTaskPromptRules(options?: FeishuTaskDispatchOptions): string;
9
+ export declare function buildFeishuTaskContext(event: FeishuTaskEvent, task: FeishuTaskDetails, eventKind: FeishuTaskEventKind): string;
10
+ export declare function buildFeishuTaskDispatch(event: FeishuTaskEvent, task: FeishuTaskDetails, eventKind: FeishuTaskEventKind, options?: FeishuTaskDispatchOptions): FeishuTaskDispatch;
11
+ //# sourceMappingURL=dispatch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dispatch.d.ts","sourceRoot":"","sources":["../src/dispatch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAA;AAK7G,MAAM,WAAW,yBAAyB;IACxC,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,aAAa,CAAC,EAAE,KAAK,GAAG,KAAK,GAAG,KAAK,CAAA;IACrC,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAWD,wBAAgB,8BAA8B,CAC5C,KAAK,EAAE,eAAe,EACtB,IAAI,EAAE,iBAAiB,EACvB,SAAS,EAAE,mBAAmB,GAC7B,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAWxB;AAoFD,wBAAgB,0BAA0B,CAAC,OAAO,CAAC,EAAE,yBAAyB,GAAG,MAAM,CAyFtF;AAED,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,eAAe,EACtB,IAAI,EAAE,iBAAiB,EACvB,SAAS,EAAE,mBAAmB,GAC7B,MAAM,CA2BR;AAED,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,eAAe,EACtB,IAAI,EAAE,iBAAiB,EACvB,SAAS,EAAE,mBAAmB,EAC9B,OAAO,CAAC,EAAE,yBAAyB,GAClC,kBAAkB,CAUpB"}