@sleep2agi/agent-network 2.3.0-preview.16 → 2.3.0-preview.160
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 +35 -324
- package/dist/bin/anet.cjs +101 -0
- package/dist/bin/cli.d.ts +1 -0
- package/dist/bin/cli.js +20 -1
- package/dist/bin/goal-wake-log-render.d.ts +31 -0
- package/dist/src/active-network-task.d.ts +28 -0
- package/dist/src/batch-workdir.d.ts +9 -0
- package/dist/src/bootstrap-password-db.d.ts +13 -0
- package/dist/src/channel-attachments.d.ts +29 -0
- package/dist/src/channel-inbox-wake.d.ts +21 -0
- package/dist/src/channel-meta.d.ts +10 -0
- package/dist/src/channel-peer-reply.d.ts +41 -0
- package/dist/src/channel-task-trace.d.ts +14 -0
- package/dist/src/claude-vendor-env.d.ts +28 -0
- package/dist/src/cli-args.d.ts +8 -0
- package/dist/src/cli-auth-session.d.ts +47 -0
- package/dist/src/cli-errors.d.ts +41 -0
- package/dist/src/cli-exit.d.ts +11 -0
- package/dist/src/cli-help.d.ts +10 -0
- package/dist/src/cli-version-display.d.ts +16 -0
- package/dist/src/client-task-trace.d.ts +9 -0
- package/dist/src/client.js +1 -1
- package/dist/src/codex-adopt.d.ts +46 -0
- package/dist/src/codex-auth-fingerprint.d.ts +211 -0
- package/dist/src/codex-bin-pin.d.ts +23 -0
- package/dist/src/codex-commhub-mcp.d.ts +22 -0
- package/dist/src/codex-copresence-bridge-log.d.ts +44 -0
- package/dist/src/codex-copresence-env.d.ts +5 -0
- package/dist/src/codex-copresence-login-gate.d.ts +16 -0
- package/dist/src/codex-copresence-model.d.ts +23 -0
- package/dist/src/codex-copresence-preflight.d.ts +78 -0
- package/dist/src/codex-copresence-profile.d.ts +125 -0
- package/dist/src/codex-copresence-recovery.d.ts +67 -0
- package/dist/src/codex-copresence-resume-timeout.d.ts +28 -0
- package/dist/src/codex-copresence-rollout-guard.d.ts +36 -0
- package/dist/src/codex-copresence-rpc.d.ts +15 -0
- package/dist/src/codex-copresence-thread.d.ts +13 -0
- package/dist/src/codex-external-appserver.d.ts +128 -0
- package/dist/src/codex-fork-recovery.d.ts +47 -0
- package/dist/src/codex-home-enforce.d.ts +88 -0
- package/dist/src/codex-lifecycle-account.d.ts +104 -0
- package/dist/src/codex-lifecycle-canary.d.ts +20 -0
- package/dist/src/codex-lifecycle-facts.d.ts +53 -0
- package/dist/src/codex-lifecycle-fork.d.ts +91 -0
- package/dist/src/codex-lifecycle-preflight.d.ts +77 -0
- package/dist/src/codex-lifecycle-receipt.d.ts +53 -0
- package/dist/src/codex-lifecycle-restart.d.ts +88 -0
- package/dist/src/codex-login-share-guard.d.ts +146 -0
- package/dist/src/codex-menu.d.ts +99 -0
- package/dist/src/codex-model-default.d.ts +6 -0
- package/dist/src/codex-node-login.d.ts +98 -0
- package/dist/src/codex-pending-thread-restart.d.ts +69 -0
- package/dist/src/codex-recovery-lease.d.ts +39 -0
- package/dist/src/codex-recovery-resource-gate.d.ts +15 -0
- package/dist/src/codex-resume.d.ts +89 -0
- package/dist/src/codex-rollout-history-guard.d.ts +84 -0
- package/dist/src/codex-tui-client-health.d.ts +30 -0
- package/dist/src/commhub-response.d.ts +1 -0
- package/dist/src/controlled-upload.d.ts +83 -0
- package/dist/src/copresence-deps.d.ts +22 -0
- package/dist/src/copresence-identity.d.ts +363 -0
- package/dist/src/copresence-startup-diagnosis.d.ts +17 -0
- package/dist/src/daemon-adopt.d.ts +14 -0
- package/dist/src/daemon-anet-bin.d.ts +32 -0
- package/dist/src/daemon-capability-display.d.ts +110 -0
- package/dist/src/daemon-capability-display.js +21 -0
- package/dist/src/daemon-inherited-env.d.ts +9 -0
- package/dist/src/daemon-runtime-path-preflight.d.ts +22 -0
- package/dist/src/daemon-runtime-staleness.d.ts +13 -0
- package/dist/src/dashboard-managed-process.d.ts +35 -0
- package/dist/src/display-width.d.ts +27 -0
- package/dist/src/doctor-node-count.d.ts +28 -0
- package/dist/src/environ-alias.d.ts +14 -0
- package/dist/src/grok-attach-client.d.ts +129 -0
- package/dist/src/grok-build-drift.d.ts +15 -0
- package/dist/src/grok-copresence-disclosure.d.ts +11 -0
- package/dist/src/grok-copresence-orchestration.d.ts +75 -0
- package/dist/src/grok-copresence-profile.d.ts +65 -0
- package/dist/src/grok-create-mode.d.ts +19 -0
- package/dist/src/host-telemetry.d.ts +14 -0
- package/dist/src/hub-health-timeout.d.ts +4 -0
- package/dist/src/hub-server-version.d.ts +64 -0
- package/dist/src/hub-stop.d.ts +74 -0
- package/dist/src/hub-time-display.d.ts +20 -0
- package/dist/src/hub-version-skew.d.ts +19 -0
- package/dist/src/im/correlation-store.d.ts +34 -0
- package/dist/src/im/feishu/adapter.d.ts +54 -0
- package/dist/src/im/feishu/bridge.d.ts +78 -14
- package/dist/src/im/feishu/hub-upload.d.ts +1 -1
- package/dist/src/im/feishu/outbound-route.d.ts +62 -0
- package/dist/src/im/feishu/worker-lifecycle.d.ts +13 -0
- package/dist/src/im/feishu/worker.js +180 -153
- package/dist/src/inbox-drain.d.ts +20 -0
- package/dist/src/local-process-state.d.ts +12 -0
- package/dist/src/locale-diagnostic.d.ts +12 -0
- package/dist/src/login-client-label.d.ts +6 -0
- package/dist/src/ls-columns.d.ts +15 -0
- package/dist/src/mock-llm.d.ts +12 -0
- package/dist/src/node-activity-log.d.ts +4 -0
- package/dist/src/node-clone.d.ts +134 -0
- package/dist/src/node-delete-hub.d.ts +42 -0
- package/dist/src/node-files.d.ts +62 -0
- package/dist/src/node-locate.d.ts +60 -0
- package/dist/src/node-ls-all.d.ts +80 -0
- package/dist/src/node-menu.d.ts +40 -0
- package/dist/src/node-not-found.d.ts +1 -0
- package/dist/src/node-remote.d.ts +180 -0
- package/dist/src/node-running-guard.d.ts +9 -0
- package/dist/src/node-server-identity.d.ts +35 -0
- package/dist/src/node-server-payload.d.ts +66 -0
- package/dist/src/node-server-rules-file.d.ts +14 -0
- package/dist/src/node-server-version.d.ts +39 -0
- package/dist/src/node-server.js +8 -1
- package/dist/src/node-skills.d.ts +57 -0
- package/dist/src/normalize-runtime.d.ts +29 -2
- package/dist/src/offline-age.d.ts +29 -0
- package/dist/src/one-line-cell.d.ts +20 -0
- package/dist/src/opencode-agent-node-pair.d.ts +28 -0
- package/dist/src/opencode-auth-login.d.ts +43 -0
- package/dist/src/opencode-free-tier.d.ts +27 -0
- package/dist/src/opencode-generation-create.d.ts +27 -0
- package/dist/src/opencode-generation-record.d.ts +24 -0
- package/dist/src/opencode-launch-env.d.ts +13 -0
- package/dist/src/opencode-owner-mode.d.ts +6 -0
- package/dist/src/opencode-package-binary.d.ts +44 -0
- package/dist/src/opencode-pin.d.ts +61 -0
- package/dist/src/opencode-preset.d.ts +73 -0
- package/dist/src/opencode-runtime-binding.d.ts +30 -0
- package/dist/src/opencode-safe-root.d.ts +36 -0
- package/dist/src/opencode-smoke-env.d.ts +1 -0
- package/dist/src/opencode-versions.d.ts +44 -0
- package/dist/src/outbound-attachments.d.ts +60 -0
- package/dist/src/outbound-tool-names.d.ts +1 -0
- package/dist/src/owned-roots.d.ts +58 -0
- package/dist/src/owner-env-file.d.ts +2 -0
- package/dist/src/package-mode-preflight.d.ts +41 -0
- package/dist/src/posix-codex-copresence.d.ts +33 -0
- package/dist/src/posix-modes.d.ts +36 -0
- package/dist/src/primary-network.d.ts +23 -0
- package/dist/src/private-state.d.ts +10 -0
- package/dist/src/process-telemetry.d.ts +12 -0
- package/dist/src/profile-serialize.d.ts +1 -0
- package/dist/src/project-key.d.ts +1 -0
- package/dist/src/reply-local-links.d.ts +47 -0
- package/dist/src/reply-originator.d.ts +20 -0
- package/dist/src/resume-runtime-infer.d.ts +18 -0
- package/dist/src/rules-file.d.ts +53 -0
- package/dist/src/secret-shell-guidance.d.ts +4 -0
- package/dist/src/session-status-class.d.ts +48 -0
- package/dist/src/shared/reserved-env.d.ts +3 -0
- package/dist/src/sibling-agent-node.d.ts +23 -0
- package/dist/src/stale-socket.d.ts +118 -0
- package/dist/src/start-resource-gate.d.ts +146 -0
- package/dist/src/stopped-receipt.d.ts +8 -0
- package/dist/src/subcommand-redirect.d.ts +26 -0
- package/dist/src/task-trace.d.ts +33 -0
- package/dist/src/tmux-attach.d.ts +11 -0
- package/dist/src/tmux-capability.d.ts +58 -0
- package/dist/src/tmux-exact-target.d.ts +36 -0
- package/dist/src/tmux-format.d.ts +20 -0
- package/dist/src/tmux-pane-prompt.d.ts +22 -0
- package/dist/src/tmux.d.ts +44 -0
- package/dist/src/token-cli.d.ts +13 -0
- package/dist/src/tool-allowlist.d.ts +28 -0
- package/dist/src/unsafe-package-path-reason.d.ts +31 -0
- package/dist/src/upgrade-channel.d.ts +31 -0
- package/dist/src/win-launcher.d.ts +20 -0
- package/dist/src/windows-codex-copresence.d.ts +60 -0
- package/package.json +14 -7
|
@@ -1,5 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RFC-020 §3.1 — Feishu (Lark) adapter for the IM compatibility layer.
|
|
3
|
+
*
|
|
4
|
+
* Uses `@larksuiteoapi/node-sdk` in WebSocket long-connection mode (WSClient).
|
|
5
|
+
* No public IP / no domain verification / no webhook signature decryption —
|
|
6
|
+
* the three biggest 飞书 接入 risks all live in the HTTP event-callback path,
|
|
7
|
+
* not in WSClient mode.
|
|
8
|
+
*
|
|
9
|
+
* Milestones:
|
|
10
|
+
* M1: contract scaffold.
|
|
11
|
+
* M2 (this file): WSClient init + EventDispatcher for `im.message.receive_v1`
|
|
12
|
+
* + event normalization + access whitelist gate + audit log.
|
|
13
|
+
* M3: outbound `im.message.create` (text), edit support (≤20/msg).
|
|
14
|
+
* M5: image upload / download (`im.image.create` / `im.messageResource.get`)
|
|
15
|
+
* + group @bot detection refined to match the bot's own open_id.
|
|
16
|
+
*/
|
|
17
|
+
import * as lark from "@larksuiteoapi/node-sdk";
|
|
1
18
|
import type { IMAdapter, IMAdapterHealth, IMChannelConfig, IMConversationRef, IMIngressMode, NormalizedIMEvent, NormalizedIMMessage } from "../types.js";
|
|
2
19
|
type OnEventHandler = (event: NormalizedIMEvent) => Promise<void>;
|
|
20
|
+
export type FeishuWsClientLike = Pick<lark.WSClient, "start" | "close">;
|
|
21
|
+
export type FeishuWsClientFactory = (params: ConstructorParameters<typeof lark.WSClient>[0]) => FeishuWsClientLike;
|
|
22
|
+
type FeishuInboundHandler = (rawEvent: unknown) => Promise<unknown>;
|
|
23
|
+
export interface FeishuEventDispatcherLike {
|
|
24
|
+
register(handlers: Record<string, FeishuInboundHandler>): unknown;
|
|
25
|
+
}
|
|
26
|
+
export interface FeishuAdapterOptions {
|
|
27
|
+
/** @internal Avoids real bot-info HTTP calls in lifecycle tests. */
|
|
28
|
+
createClient?: (params: ConstructorParameters<typeof lark.Client>[0]) => lark.Client;
|
|
29
|
+
/** @internal Test seam; production uses the pinned Lark SDK WSClient. */
|
|
30
|
+
createWsClient?: FeishuWsClientFactory;
|
|
31
|
+
/** @internal Test seam; production uses the pinned Lark SDK dispatcher. */
|
|
32
|
+
createEventDispatcher?: () => FeishuEventDispatcherLike;
|
|
33
|
+
/** Independent outer bound in case the SDK promise/callback path stalls. */
|
|
34
|
+
wsReadyTimeoutMs?: number;
|
|
35
|
+
/** Called once when an already-ready socket exhausts reconnect attempts. */
|
|
36
|
+
onTerminalError?: (error: Error) => void;
|
|
37
|
+
}
|
|
3
38
|
export declare class FeishuAdapter implements IMAdapter {
|
|
4
39
|
readonly platform = "feishu";
|
|
5
40
|
readonly ingressMode: IMIngressMode;
|
|
@@ -7,6 +42,8 @@ export declare class FeishuAdapter implements IMAdapter {
|
|
|
7
42
|
private connectionName_;
|
|
8
43
|
private client;
|
|
9
44
|
private wsClient;
|
|
45
|
+
private lifecycleGeneration;
|
|
46
|
+
private readonly options;
|
|
10
47
|
/**
|
|
11
48
|
* The bot's own open_id, resolved at init() via /open-apis/bot/v3/info.
|
|
12
49
|
* Used to detect real @bot mentions (vs any mention) in group messages.
|
|
@@ -17,6 +54,7 @@ export declare class FeishuAdapter implements IMAdapter {
|
|
|
17
54
|
/** Where to persist downloaded inbound media (M5c). */
|
|
18
55
|
private mediaDir;
|
|
19
56
|
private health_;
|
|
57
|
+
constructor(options?: FeishuAdapterOptions);
|
|
20
58
|
/**
|
|
21
59
|
* Snapshot of the current `access.allowFrom` list (from access.json).
|
|
22
60
|
* Used by the bridge's rate-limiter to exempt operator-vouched explicit
|
|
@@ -94,6 +132,17 @@ export declare function parsePostContent(rawJson: string): string;
|
|
|
94
132
|
* @internal exported for unit tests.
|
|
95
133
|
*/
|
|
96
134
|
export declare function extractPostImageKeys(rawJson: string): string[];
|
|
135
|
+
/**
|
|
136
|
+
* Sanitize a Feishu-supplied `file_name` so it's safe to append to a
|
|
137
|
+
* filesystem path. Strips `/`, `\`, `..`, control characters, and NUL
|
|
138
|
+
* bytes. Empty / all-stripped input falls back to a placeholder that
|
|
139
|
+
* uses the message id, so a hostile client can never write outside the
|
|
140
|
+
* conversation's `<mediaDir>/<convKey>/` directory.
|
|
141
|
+
*
|
|
142
|
+
* NOT a full display-safety pass — the LLM still sees the sanitized
|
|
143
|
+
* bytes and shouldn't render them as HTML/etc. That's a Layer above.
|
|
144
|
+
*/
|
|
145
|
+
export declare function sanitizeFileName(raw: string, fallback: string): string;
|
|
97
146
|
/**
|
|
98
147
|
* Feishu text-message practical chunk threshold (RFC-020 §16).
|
|
99
148
|
*
|
|
@@ -120,4 +169,9 @@ export declare const FEISHU_TEXT_SINGLE_LIMIT = 4000;
|
|
|
120
169
|
* If the input is already short enough, returns a single-element array.
|
|
121
170
|
*/
|
|
122
171
|
export declare function splitTextForFeishu(text: string, maxChars: number): string[];
|
|
172
|
+
/**
|
|
173
|
+
* Lark errors may echo request/config values. Keep worker logs actionable while
|
|
174
|
+
* ensuring credentials and multiline payloads never cross the process boundary.
|
|
175
|
+
*/
|
|
176
|
+
export declare function sanitizeFeishuWsError(rawError: unknown, appId: string, appSecret: string): Error;
|
|
123
177
|
export {};
|
|
@@ -2,22 +2,36 @@
|
|
|
2
2
|
* RFC-020 §2.5 / RFC-002 §2.2 — Feishu bridge worker.
|
|
3
3
|
*
|
|
4
4
|
* Entry point spawned by agent-node when a node profile has `channels.feishu`
|
|
5
|
-
* enabled.
|
|
6
|
-
* "agent-node direct bridge" model, not the full commhub-gateway:
|
|
5
|
+
* enabled. This worker owns the FeishuAdapter and its WSClient connection.
|
|
7
6
|
*
|
|
8
|
-
*
|
|
9
|
-
* - Inbound IM event → access whitelist gate → forward to agent-node's main
|
|
10
|
-
* `think()` via parent IPC.
|
|
11
|
-
* - think() result → adapter.send() back to the originating conversation.
|
|
7
|
+
* 🔴 There are TWO outbound paths, and which one runs is decided at line ~445:
|
|
12
8
|
*
|
|
13
|
-
*
|
|
9
|
+
* const client = commhubClient ?? createEnvCommHubClient();
|
|
10
|
+
* if (client) return createCommHubEventHandler(...); // (A)
|
|
11
|
+
* if (typeof process.send === "function") ... // (B)
|
|
12
|
+
*
|
|
13
|
+
* (A) CommHub task dispatch — **the default on any real node.**
|
|
14
|
+
* `createEnvCommHubClient()` returns null only when neither COMMHUB_URL
|
|
15
|
+
* nor ANET_HUB_URL is set, and every provisioned node has one. Replies
|
|
16
|
+
* carry `in_reply_to`, and the correlation store tracks task status.
|
|
17
|
+
* (B) parent IPC → agent-node's `think()` — the fallback when there is no
|
|
18
|
+
* hub URL in env (standalone / test harness).
|
|
19
|
+
*
|
|
20
|
+
* Both paths end at adapter.send() back to the originating conversation.
|
|
21
|
+
*
|
|
22
|
+
* 🔴 This block used to say the opposite —— verbatim:
|
|
23
|
+
* "IM messages do NOT pass through commhub task dispatch."
|
|
24
|
+
* That was true of the 2026-06-24 first cut, and stayed in the file after
|
|
25
|
+
* the commhub path landed (#1252, merged 2026-08-27). It is the first thing
|
|
26
|
+
* anyone reads in this file, so it mis-answered the question "does Feishu go
|
|
27
|
+
* through CommHub" for at least one reader before being caught. If you change
|
|
28
|
+
* which path is default, change these lines in the same commit.
|
|
29
|
+
*
|
|
30
|
+
* Still true of both paths (unchanged from the first cut):
|
|
14
31
|
* - No separate gateway ntok_ / dedicated commhub alias.
|
|
15
|
-
* - IM messages do NOT pass through commhub task dispatch.
|
|
16
|
-
* - Feishu messages do NOT appear in Dashboard topology / Chat.
|
|
17
32
|
*
|
|
18
|
-
* The
|
|
19
|
-
*
|
|
20
|
-
* — tracked in #182.
|
|
33
|
+
* The remaining §2.9 work (meta_json columns, SSE passthrough, Dashboard
|
|
34
|
+
* topology / Chat visibility for Feishu conversations) is tracked in #182.
|
|
21
35
|
*
|
|
22
36
|
* Milestones:
|
|
23
37
|
* M1: worker entry scaffold.
|
|
@@ -29,8 +43,29 @@
|
|
|
29
43
|
* M4: agent-node spawn integration (fork(this) wired by agent-node).
|
|
30
44
|
* M5: group @bot trigger refinement, image up/down, Docker smoke.
|
|
31
45
|
*/
|
|
32
|
-
import type { NormalizedIMEvent } from "../types.js";
|
|
46
|
+
import type { IMCorrelationStore, NormalizedIMEvent } from "../types.js";
|
|
33
47
|
import { FeishuAdapter } from "./adapter.js";
|
|
48
|
+
export type IMBridgeCommHubInboxMessage = {
|
|
49
|
+
id: string;
|
|
50
|
+
type?: string;
|
|
51
|
+
content: string;
|
|
52
|
+
from_session?: string;
|
|
53
|
+
in_reply_to?: string;
|
|
54
|
+
meta?: unknown;
|
|
55
|
+
};
|
|
56
|
+
export interface IMBridgeCommHubClient {
|
|
57
|
+
sendTask(args: {
|
|
58
|
+
alias: string;
|
|
59
|
+
task: string;
|
|
60
|
+
priority?: "high" | "normal" | "low";
|
|
61
|
+
ttlSeconds?: number;
|
|
62
|
+
meta?: unknown;
|
|
63
|
+
}): Promise<{
|
|
64
|
+
taskId: string;
|
|
65
|
+
}>;
|
|
66
|
+
getInbox(alias: string): Promise<IMBridgeCommHubInboxMessage[]>;
|
|
67
|
+
ackInbox(alias: string, messageId: string): Promise<void>;
|
|
68
|
+
}
|
|
34
69
|
export interface FeishuBridgeOptions {
|
|
35
70
|
/** Absolute path to `.anet/nodes/<node>/channels/feishu/`. */
|
|
36
71
|
channelDir: string;
|
|
@@ -44,6 +79,16 @@ export interface FeishuBridgeOptions {
|
|
|
44
79
|
* - stderr logger otherwise (standalone smoke debugging).
|
|
45
80
|
*/
|
|
46
81
|
onEvent?: (event: NormalizedIMEvent) => Promise<void>;
|
|
82
|
+
/** Fatal WS failure after initial readiness (for worker lifecycle ownership). */
|
|
83
|
+
onTerminalError?: (error: Error) => void;
|
|
84
|
+
/** Persistent task/message correlation state. Defaults to channelDir/state.json. */
|
|
85
|
+
correlationStore?: IMCorrelationStore;
|
|
86
|
+
/** CommHub task transport. Defaults to COMMHUB_URL/COMMHUB_TOKEN when available. */
|
|
87
|
+
commhubClient?: IMBridgeCommHubClient;
|
|
88
|
+
/** Poll interval for CommHub replies. Defaults to 1500ms. */
|
|
89
|
+
commhubPollMs?: number;
|
|
90
|
+
/** 出站传输模式。省略时按 ANET_FEISHU_BRIDGE_MODE,再省略则 "direct"。 */
|
|
91
|
+
bridgeMode?: FeishuBridgeMode;
|
|
47
92
|
}
|
|
48
93
|
/** Bridge → parent: inbound IM event ready for think(). */
|
|
49
94
|
export interface BridgeIncomingEnvelope {
|
|
@@ -101,6 +146,24 @@ export type WithRateLimitHandle = {
|
|
|
101
146
|
floodKeyCount: number;
|
|
102
147
|
};
|
|
103
148
|
};
|
|
149
|
+
/**
|
|
150
|
+
* 出站传输模式。**显式声明,不靠环境变量在场与否去猜。**
|
|
151
|
+
*
|
|
152
|
+
* direct — parent IPC → agent-node 的 think()。**默认。**
|
|
153
|
+
* 2026-06-24 的第一版路径,飞书消息不进 CommHub 任务分发,
|
|
154
|
+
* 也不出现在 Dashboard 拓扑 / Chat 里。
|
|
155
|
+
* commhub — 入站事件变成一个 CommHub task,回复带 in_reply_to,
|
|
156
|
+
* correlation store 跟踪状态。**必须显式打开。**
|
|
157
|
+
*
|
|
158
|
+
* 🔴 为什么要显式:在此之前是 `commhubClient ?? createEnvCommHubClient()` ——
|
|
159
|
+
* 有 COMMHUB_URL 就走 commhub、没有就悄悄回落 IPC。两条路径的可观测性、
|
|
160
|
+
* Dashboard 可见性、失败语义完全不同,而**运维看不出自己在哪条上**,
|
|
161
|
+
* 文件头注释也因此和代码说了相反的话长达一次发布。
|
|
162
|
+
*/
|
|
163
|
+
export type FeishuBridgeMode = "commhub" | "direct";
|
|
164
|
+
export declare const DEFAULT_FEISHU_BRIDGE_MODE: FeishuBridgeMode;
|
|
165
|
+
/** 解析模式。优先级:显式入参 > 环境变量 > 默认。非法值直接抛,不静默取默认。 */
|
|
166
|
+
export declare function resolveFeishuBridgeMode(explicit?: FeishuBridgeMode, env?: NodeJS.ProcessEnv): FeishuBridgeMode;
|
|
104
167
|
/**
|
|
105
168
|
* IPC handler — forwards inbound events to the parent agent-node and routes
|
|
106
169
|
* the parent's reply back to Feishu via the adapter. The parent contract is
|
|
@@ -125,7 +188,8 @@ export type WithRateLimitHandle = {
|
|
|
125
188
|
* the agent-node.log (closes the prior silent-success blindspot).
|
|
126
189
|
*/
|
|
127
190
|
/** @internal exported for test harness; not intended for production callers. */
|
|
128
|
-
export declare function createIPCEventHandler(adapter: FeishuAdapter, ttlMs: number, ackPlaceholder: boolean): (event: NormalizedIMEvent) => Promise<void>;
|
|
191
|
+
export declare function createIPCEventHandler(adapter: FeishuAdapter, ttlMs: number, ackPlaceholder: boolean, correlationStore?: IMCorrelationStore): (event: NormalizedIMEvent) => Promise<void>;
|
|
192
|
+
export declare function createCommHubEventHandler(nodeAlias: string, adapter: FeishuAdapter, ttlMs: number, ackPlaceholder: boolean, correlationStore: IMCorrelationStore | undefined, commhubClient: IMBridgeCommHubClient, pollMs?: number): (event: NormalizedIMEvent) => Promise<void>;
|
|
129
193
|
export { FeishuAdapter } from "./adapter.js";
|
|
130
194
|
export { loadFeishuChannelConfig } from "./config.js";
|
|
131
195
|
export type { FeishuAccessList, FeishuChannelConfig, FeishuChannelEnv, } from "./config.js";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* RFC-020 §17 — feishu inbound bridge → hub `/api/upload` integration.
|
|
3
3
|
*
|
|
4
|
-
* Vincent 2026-06-30: cross-machine agents (e.g.
|
|
4
|
+
* Vincent 2026-06-30: cross-machine agents (e.g. a partner-team node on a partner-team host)
|
|
5
5
|
* delegated by the feishu-local bot can't read inbound attachments
|
|
6
6
|
* because the only thing they get is a host-local path that doesn't
|
|
7
7
|
* exist on the receiver's filesystem. #351 already wired agent-node's
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RFC-020 §16.1 — feishu outbound route decision (pure helper).
|
|
3
|
+
*
|
|
4
|
+
* Single source of truth for the `adapter.send` decision tree that
|
|
5
|
+
* picks among text / interactive card / image (rendered PNG) / file /
|
|
6
|
+
* imagePath outputs. Extracted into a pure module so the production
|
|
7
|
+
* call site AND the unit tests can bind the same function — previously
|
|
8
|
+
* the test mirrored the decision tree in a sibling `pickRoute` helper,
|
|
9
|
+
* which would drift silently if the production tree changed.
|
|
10
|
+
*
|
|
11
|
+
* Inputs are the minimal data the decision needs:
|
|
12
|
+
*
|
|
13
|
+
* - `text` / `imagePath` / `files` — payload from `NormalizedIMMessage`
|
|
14
|
+
* - `forceTextOnly` — caption-mode hint (RFC-020 §15.2)
|
|
15
|
+
* - `mode` — channel-config `outboundRender` (`"plain"` / `"card"` /
|
|
16
|
+
* `"auto"`, RFC-020 §16)
|
|
17
|
+
*
|
|
18
|
+
* Outputs the chosen `route` plus a short `reason` string for log /
|
|
19
|
+
* debug. The CALLER (adapter.send) actually performs the upload /
|
|
20
|
+
* render side-effects keyed on the route — this function does no I/O.
|
|
21
|
+
*
|
|
22
|
+
* Behavior contract (mirrors adapter.send line-for-line, locked by
|
|
23
|
+
* `feishu-outbound-render-mode.test.ts`):
|
|
24
|
+
*
|
|
25
|
+
* 1. `imagePath` set → `image_upload`
|
|
26
|
+
* 2. `files[0].path` set → `file_upload`
|
|
27
|
+
* 3. `forceTextOnly` true → `text`
|
|
28
|
+
* 4. mode "plain" → `text` (always)
|
|
29
|
+
* 5. mode "card" → `card_short_md` iff `looksLikeMarkdown(text)` AND
|
|
30
|
+
* NOT `shouldRenderAsImage(text)`; else `text`
|
|
31
|
+
* 6. mode "auto" → `image_render` iff `shouldRenderAsImage(text)`;
|
|
32
|
+
* else `card_short_md` iff `looksLikeMarkdown(text)`; else `text`
|
|
33
|
+
* 7. unknown mode (defensive default-default) → `text`
|
|
34
|
+
*
|
|
35
|
+
* The production switch in adapter.send may add the actual upload /
|
|
36
|
+
* render / lark API calls keyed on the route, but the route itself
|
|
37
|
+
* is decided HERE. To change the decision, change this file.
|
|
38
|
+
*/
|
|
39
|
+
export type OutboundRoute = "image_upload" | "file_upload" | "text" | "card_short_md" | "image_render";
|
|
40
|
+
export interface RouteInput {
|
|
41
|
+
text?: string;
|
|
42
|
+
imagePath?: string;
|
|
43
|
+
files?: {
|
|
44
|
+
name: string;
|
|
45
|
+
path?: string;
|
|
46
|
+
}[];
|
|
47
|
+
forceTextOnly?: boolean;
|
|
48
|
+
/** `outboundRender` from the channel config. Defaults to "plain" when
|
|
49
|
+
* absent so a caller that doesn't read the config still gets the
|
|
50
|
+
* "Vincent default" behavior. */
|
|
51
|
+
mode?: "plain" | "card" | "auto";
|
|
52
|
+
}
|
|
53
|
+
export interface RouteDecision {
|
|
54
|
+
route: OutboundRoute;
|
|
55
|
+
reason: string;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Decide the outbound route for a `NormalizedIMMessage` (or a subset
|
|
59
|
+
* of its fields). Pure — no I/O, no SDK calls; safe to call from tests
|
|
60
|
+
* directly.
|
|
61
|
+
*/
|
|
62
|
+
export declare function resolveOutboundRoute(input: RouteInput): RouteDecision;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
interface WorkerProcessBoundary {
|
|
2
|
+
stderr: {
|
|
3
|
+
write(message: string): unknown;
|
|
4
|
+
};
|
|
5
|
+
exit(code: number): unknown;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* A terminal WS error means this worker no longer owns a live ingress path.
|
|
9
|
+
* Exit non-zero so the parent/supervisor cannot continue advertising it as
|
|
10
|
+
* healthy. Kept separate from worker.ts so the real exit contract is testable.
|
|
11
|
+
*/
|
|
12
|
+
export declare function exitFeishuWorker(error: Error, boundary?: WorkerProcessBoundary): void;
|
|
13
|
+
export {};
|