/**
* 「打开工作台」入口链接的单一事实源(飞书卡片侧)。
*
* 为什么单独一个模块:卡片按钮的链接要同时满足三件事,散落到卡片构建函数里就会
* 各写各的——
* 1. **base 跟着 Dashboard 走**:远程访问开 / 自建反代时必须是对外可达的基址,
* 不能是局域网 `host:port`。这一步复用 {@link buildDashboardUrls},和
* `botmux dashboard`、终端链接、v3 深链共用同一个开关。
* 2. **凭证是长期 token,链接常驻不过期**(产品决策,见下方小节)。
* 3. **applink host 跟着 bot 的 brand 走**:飞书 bot → applink.feishu.cn,
* Lark bot → applink.larksuite.com(见 im/lark/lark-hosts.ts)。
*
* ─── 为什么链接里是长期 token(决策反转,别照 git 历史改回去)──────────────
* 这里一度是 30 分钟 TTL 的短时票据(P2-1 / commit 9b176a87),理由是「卡片是
* 持久化载体,长期 token 不该进聊天记录」。**产品 owner 明确推翻了这条红线**:
* botmux 是自部署形态,用户就是自己实例的 owner,需要一条能收藏进书签、**永不
* 过期**的入口;短票 30 分钟即死,意味着每次进工作台都得先回飞书发一次
* `/dashboard`——入口形同虚设。
*
* 这是**有意的风险交换**,不是实现疏忽:
* · 收益:一条链接收藏即用,跨端、跨重启、跨升级都不失效。
* · 代价:链接是常驻凭证,卡片历史 / 转发 / 截图都带着它。
* · 兜底:`botmux dashboard rotate` —— 换掉 token,所有已发出的链接当场全废。
* 卡片小字里就写着这条自救路径,让 owner 知道怀疑泄漏时该做什么。
* · **门禁一层没放宽**:`/dashboard` 命令入口仍由
* `core/dashboard-command/owner-gate.ts` 拦,卡片回调仍由各 handler 的
* invoker-lock + `isDashboardAdmin` 拦,卡片仍是私信给发起人本人。渲染这条
* 链接的地方必须保持这个前提。
*
* 短时票据机制(`dashboard/workbench-ticket.ts`、兑换端点、它的全部测试)
* **原样保留、不删**:本模块只是不再调用它。将来若要回到短票形态,机制还在。
*/
/** 解析结果:链接本身 + 它到底带没带凭证(卡片据此决定小字提示的说法)。 */
export interface ResolvedWorkbenchUrl {
url: string;
/** true = `/workbench?t=`;false = 无凭证裸链接,用户需自行登录。 */
credentialed: boolean;
}
/**
* 当前这台机器的**常驻**工作台入口:`/workbench?t=<长期 token>`。
*
* token 读不到时**fail open** 成不带任何凭证的 `/#/agent-workbench`
* (用户自己走登录墙),而不是不发链接——工作台入口是锦上添花,不能因为读不到
* 一个文件就让整张 `/dashboard` 卡片发不出去。链接整体不可解析才返回 undefined。
*
* ─── token 从哪来(跨进程)────────────────────────────────────────────────
* 卡片在 **daemon** 进程构建,token 由 **dashboard** 进程落盘在
* `~/.botmux/.dashboard-token`。两个进程本来就靠这份文件交接:daemon 重启报告的
* dashboard 链接(daemon.ts:dashboardUrlForReport)走的就是同一条路,短票时代
* mint 内部算 generation 标签读的也是同一份文件。所以这里直接复用
* {@link loadPersistedToken}——它走 secure-host-file 的属主 / 0600 / 拒符号链接
* 校验,形状不安全一律 fail closed 返回 null(→ 降级无凭证链接),不需要另开
* loopback + HMAC 通道。
*
* 端口同理取 dashboard 落盘的 `.dashboard-port`(端口探测可能落在 7891 之外)。
*
* 用 `/workbench?t=` 而不是 `/?t=…#/agent-workbench`:不带 `#` 的形态复制粘贴时
* 不会被截断(见 dashboard-url.ts:workbenchEntryUrl)——这条链接除了当按钮目标,
* 还会被 owner 从工作台「常驻链接」面板 / 终端 `botmux dashboard` 里复制去收藏。
*/
export declare function resolveWorkbenchUrl(): ResolvedWorkbenchUrl | undefined;
/** 「打开工作台」按钮的一组端上目标,undefined 表示不渲染这个按钮。 */
export interface WorkbenchButtonLinks {
/** PC:appCenter AppLink(在飞书导航栏开标签页,可右键固定 → 真正的常驻入口)。 */
appLink: string;
/** 移动端的按钮目标:手机客户端不识别 applink 的 `mode`,直接给网页 URL。
* 卡片里**不**再单独渲染一行明文链接(产品试用后撤下,见
* `im/lark/overview-card.ts` 的「打开工作台」块),所以这条 URL 只出现在按钮
* 的 `multi_url` 里;owner 想拿链接本体收藏,走工作台 `⋯` 菜单的「常驻链接」
* 面板或终端 `botmux dashboard` 的输出。 */
webUrl: string;
/** 链接是否携带凭证。false 时卡片要注明「需在浏览器里登录」,别吹「常驻可收藏」。 */
credentialed: boolean;
}
/**
* PC 走 appCenter AppLink,移动端走裸 URL。brand 按 bot 取,未注册的 appId
* 归一到 feishu(见 `getBotBrand`)。两端是**同一条常驻链接**,所以同一个管理员
* 从 PC / 手机点开、或从书签进来,落到的都是同一个入口。
*/
export declare function resolveWorkbenchButtonLinks(larkAppId: string | undefined): WorkbenchButtonLinks | undefined;
//# sourceMappingURL=workbench-link.d.ts.map