@allbluecn/web-app 0.23.3 → 0.23.5

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.
Files changed (134) hide show
  1. package/package.json +3 -3
  2. package/src/components/ai/global-harness-sidebar/__tests__/global-ai-prompts.test.ts +2 -0
  3. package/src/components/desktop/__tests__/cloud-login-rollback.test.tsx +161 -0
  4. package/src/components/desktop/cloud-login.tsx +29 -26
  5. package/src/components/desktop-agent/__tests__/agent-chat.test.tsx +194 -0
  6. package/src/components/desktop-agent/__tests__/agent-tool-card.test.tsx +138 -0
  7. package/src/components/desktop-agent/__tests__/agent-workspace-card.test.tsx +189 -0
  8. package/src/components/desktop-agent/agent-chat.tsx +221 -0
  9. package/src/components/desktop-agent/agent-tool-card.tsx +185 -0
  10. package/src/components/desktop-agent/agent-workspace-card.tsx +176 -0
  11. package/src/components/layout/sidebar-03/app-sidebar.tsx +9 -2
  12. package/src/config/sidebar-routes.tsx +14 -1
  13. package/src/lib/changelog/sdk-versions.ts +1 -1
  14. package/src/lib/desktop-agent/__tests__/connection.test.ts +223 -0
  15. package/src/lib/desktop-agent/__tests__/errors.test.ts +43 -0
  16. package/src/lib/desktop-agent/__tests__/tool-result.test.ts +163 -0
  17. package/src/lib/desktop-agent/__tests__/use-desktop-agent-presence.test.tsx +181 -0
  18. package/src/lib/desktop-agent/availability.ts +39 -0
  19. package/src/lib/desktop-agent/connection.ts +72 -0
  20. package/src/lib/desktop-agent/errors.ts +21 -0
  21. package/src/lib/desktop-agent/tool-result.ts +170 -0
  22. package/src/lib/desktop-agent/use-desktop-agent-presence.ts +64 -0
  23. package/src/lib/desktop-bridge-types.ts +22 -1
  24. package/src/lib/hotkeys/__tests__/registry.test.ts +11 -4
  25. package/src/lib/hotkeys/registry.ts +9 -1
  26. package/src/lib/queries/README.md +1 -0
  27. package/src/lib/queries/__tests__/desktop-agent-queries.test.ts +80 -0
  28. package/src/lib/queries/desktop-agent.ts +25 -0
  29. package/src/paraglide/messages/_index.d.ts +42 -0
  30. package/src/paraglide/messages/_index.js +42 -0
  31. package/src/paraglide/messages/agent_desktop_chatcwd1.d.ts +19 -0
  32. package/src/paraglide/messages/agent_desktop_chatcwd1.js +30 -0
  33. package/src/paraglide/messages/agent_desktop_chatemptyhint2.d.ts +17 -0
  34. package/src/paraglide/messages/agent_desktop_chatemptyhint2.js +30 -0
  35. package/src/paraglide/messages/agent_desktop_chatemptytitle2.d.ts +17 -0
  36. package/src/paraglide/messages/agent_desktop_chatemptytitle2.js +30 -0
  37. package/src/paraglide/messages/agent_desktop_chatindependenthint2.d.ts +17 -0
  38. package/src/paraglide/messages/agent_desktop_chatindependenthint2.js +30 -0
  39. package/src/paraglide/messages/agent_desktop_chatnoworkspace2.d.ts +17 -0
  40. package/src/paraglide/messages/agent_desktop_chatnoworkspace2.js +30 -0
  41. package/src/paraglide/messages/agent_desktop_chatplaceholder1.d.ts +17 -0
  42. package/src/paraglide/messages/agent_desktop_chatplaceholder1.js +30 -0
  43. package/src/paraglide/messages/agent_desktop_chatsend1.d.ts +17 -0
  44. package/src/paraglide/messages/agent_desktop_chatsend1.js +30 -0
  45. package/src/paraglide/messages/agent_desktop_chatstop1.d.ts +17 -0
  46. package/src/paraglide/messages/agent_desktop_chatstop1.js +30 -0
  47. package/src/paraglide/messages/agent_desktop_chatthinking1.d.ts +17 -0
  48. package/src/paraglide/messages/agent_desktop_chatthinking1.js +30 -0
  49. package/src/paraglide/messages/agent_desktop_errorconnection1.d.ts +17 -0
  50. package/src/paraglide/messages/agent_desktop_errorconnection1.js +30 -0
  51. package/src/paraglide/messages/agent_desktop_errorforbidden1.d.ts +17 -0
  52. package/src/paraglide/messages/agent_desktop_errorforbidden1.js +30 -0
  53. package/src/paraglide/messages/agent_desktop_errorgeneric1.d.ts +19 -0
  54. package/src/paraglide/messages/agent_desktop_errorgeneric1.js +30 -0
  55. package/src/paraglide/messages/agent_desktop_errorunauthorized1.d.ts +17 -0
  56. package/src/paraglide/messages/agent_desktop_errorunauthorized1.js +30 -0
  57. package/src/paraglide/messages/agent_desktop_errorunavailable1.d.ts +17 -0
  58. package/src/paraglide/messages/agent_desktop_errorunavailable1.js +30 -0
  59. package/src/paraglide/messages/agent_desktop_pagedescription1.d.ts +17 -0
  60. package/src/paraglide/messages/agent_desktop_pagedescription1.js +30 -0
  61. package/src/paraglide/messages/agent_desktop_title.d.ts +16 -0
  62. package/src/paraglide/messages/agent_desktop_title.js +29 -0
  63. package/src/paraglide/messages/agent_desktop_toolcountfiles2.d.ts +19 -0
  64. package/src/paraglide/messages/agent_desktop_toolcountfiles2.js +30 -0
  65. package/src/paraglide/messages/agent_desktop_toolcounthits2.d.ts +19 -0
  66. package/src/paraglide/messages/agent_desktop_toolcounthits2.js +30 -0
  67. package/src/paraglide/messages/agent_desktop_toolcountlines2.d.ts +19 -0
  68. package/src/paraglide/messages/agent_desktop_toolcountlines2.js +30 -0
  69. package/src/paraglide/messages/agent_desktop_toolemptydir2.d.ts +17 -0
  70. package/src/paraglide/messages/agent_desktop_toolemptydir2.js +30 -0
  71. package/src/paraglide/messages/agent_desktop_toolerror1.d.ts +17 -0
  72. package/src/paraglide/messages/agent_desktop_toolerror1.js +30 -0
  73. package/src/paraglide/messages/agent_desktop_toolfind1.d.ts +19 -0
  74. package/src/paraglide/messages/agent_desktop_toolfind1.js +30 -0
  75. package/src/paraglide/messages/agent_desktop_toolgrep1.d.ts +19 -0
  76. package/src/paraglide/messages/agent_desktop_toolgrep1.js +30 -0
  77. package/src/paraglide/messages/agent_desktop_toolls1.d.ts +19 -0
  78. package/src/paraglide/messages/agent_desktop_toolls1.js +30 -0
  79. package/src/paraglide/messages/agent_desktop_toolmore1.d.ts +19 -0
  80. package/src/paraglide/messages/agent_desktop_toolmore1.js +30 -0
  81. package/src/paraglide/messages/agent_desktop_toolnomatches2.d.ts +17 -0
  82. package/src/paraglide/messages/agent_desktop_toolnomatches2.js +30 -0
  83. package/src/paraglide/messages/agent_desktop_toolother1.d.ts +19 -0
  84. package/src/paraglide/messages/agent_desktop_toolother1.js +30 -0
  85. package/src/paraglide/messages/agent_desktop_toolread1.d.ts +19 -0
  86. package/src/paraglide/messages/agent_desktop_toolread1.js +30 -0
  87. package/src/paraglide/messages/agent_desktop_toolrunning1.d.ts +17 -0
  88. package/src/paraglide/messages/agent_desktop_toolrunning1.js +30 -0
  89. package/src/paraglide/messages/agent_desktop_tooltruncated1.d.ts +17 -0
  90. package/src/paraglide/messages/agent_desktop_tooltruncated1.js +30 -0
  91. package/src/paraglide/messages/agent_desktop_workspaceadd1.d.ts +17 -0
  92. package/src/paraglide/messages/agent_desktop_workspaceadd1.js +30 -0
  93. package/src/paraglide/messages/agent_desktop_workspaceaddfailed2.d.ts +17 -0
  94. package/src/paraglide/messages/agent_desktop_workspaceaddfailed2.js +30 -0
  95. package/src/paraglide/messages/agent_desktop_workspacedescription1.d.ts +17 -0
  96. package/src/paraglide/messages/agent_desktop_workspacedescription1.js +30 -0
  97. package/src/paraglide/messages/agent_desktop_workspaceempty1.d.ts +17 -0
  98. package/src/paraglide/messages/agent_desktop_workspaceempty1.js +30 -0
  99. package/src/paraglide/messages/agent_desktop_workspaceemptyhint2.d.ts +17 -0
  100. package/src/paraglide/messages/agent_desktop_workspaceemptyhint2.js +30 -0
  101. package/src/paraglide/messages/agent_desktop_workspaceloadfailed2.d.ts +17 -0
  102. package/src/paraglide/messages/agent_desktop_workspaceloadfailed2.js +30 -0
  103. package/src/paraglide/messages/agent_desktop_workspaceremove1.d.ts +17 -0
  104. package/src/paraglide/messages/agent_desktop_workspaceremove1.js +30 -0
  105. package/src/paraglide/messages/agent_desktop_workspaceremovefailed2.d.ts +17 -0
  106. package/src/paraglide/messages/agent_desktop_workspaceremovefailed2.js +30 -0
  107. package/src/paraglide/messages/agent_desktop_workspacetitle1.d.ts +17 -0
  108. package/src/paraglide/messages/agent_desktop_workspacetitle1.js +30 -0
  109. package/src/paraglide/messages/agent_desktop_workspaceunsupported1.d.ts +17 -0
  110. package/src/paraglide/messages/agent_desktop_workspaceunsupported1.js +30 -0
  111. package/src/paraglide/messages/common_hotkey_desc_agentabort1.d.ts +17 -0
  112. package/src/paraglide/messages/common_hotkey_desc_agentabort1.js +30 -0
  113. package/src/paraglide/messages/sync_bind_rolled_back.d.ts +16 -0
  114. package/src/paraglide/messages/sync_bind_rolled_back.js +29 -0
  115. package/src/routeTree.gen.ts +23 -0
  116. package/src/routes/-tests/agent-gate.test.ts +45 -0
  117. package/src/routes/_nav/agent/route.lazy.tsx +63 -0
  118. package/src/routes/_nav/agent/route.tsx +21 -0
  119. package/src/routes/api/sync/account-status.ts +4 -2
  120. package/src/routes/api/sync/push.ts +11 -3
  121. package/src/server/__tests__/desktop-cloud-identity.test.ts +331 -0
  122. package/src/server/__tests__/desktop-session-merge.test.ts +42 -0
  123. package/src/server/__tests__/exchange-remote-token.test.ts +92 -10
  124. package/src/server/__tests__/remote-auth.test.ts +39 -0
  125. package/src/server/desktop-bootstrap.ts +16 -5
  126. package/src/server/desktop-cloud-identity.ts +247 -0
  127. package/src/server/remote-auth.ts +33 -1
  128. package/src/server/serverFns/auth/session.ts +27 -2
  129. package/src/server/serverFns/sync/transfer.ts +28 -27
  130. package/src/server/serverFns/workspace-kb.ts +10 -0
  131. package/src/server/sync/__tests__/ownership-transfer.test.ts +261 -48
  132. package/src/server/sync/__tests__/sync-first-push.e2e.test.ts +349 -0
  133. package/src/server/sync/account-status-cloud.ts +41 -0
  134. package/src/server/sync/ownership-transfer.ts +88 -49
@@ -0,0 +1,64 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
2
+ // AllBlue - 理想之海
3
+ // Copyright (C) 2026 AllBlue Contributors
4
+
5
+ // 本地文件助手入口门控(桌面本地优先 P3-B5):路由页(_nav/agent lazy 组件)与
6
+ // 侧栏入口共用同一判定,保证「入口可见 ⟹ 页面可达」。
7
+ //
8
+ // 判定 = 桌面构建(isDesktopEdition:VITE_DEPLOY_TARGET 构建期常量,与路由
9
+ // beforeLoad 同口径)× 存在 desktopBridge(Electron preload 注入)× agent 已装配
10
+ // (appInfo.agentPort 为数字,见 ./availability)。云 Web / OSS 构建恒 absent
11
+ // (effect 体被常量折叠);桌面构建被浏览器直开(无桥)也 absent。
12
+ //
13
+ // 有界重试(冷启动窗口):Electron 冷启动时 renderer 先挂载、backend 约 3s 后才
14
+ // 广播 agentPort——单次探测会把窗口期误判为 absent,使入口在整次会话内消失(要等
15
+ // 导航重挂载/重启)。故「桌面构建 + 有桥 + agentPort 未广播(或 appInfo 抛错)」
16
+ // 按 1s 间隔重试,累计约 20s;一旦拿到端口立即 present 并停止;到上限仍不就绪
17
+ // 才落 absent 并停止。非桌面构建 / 无桥是终态,不重试。卸载清 timer,无泄漏。
18
+ //
19
+ // mounted 模式(与 sync-indicator / cloud-login 同构):首帧恒 'pending'——SSR
20
+ // 无 window,hydration 首帧必须与服务端输出一致,挂载后再经 IPC 读桥;重试期间
21
+ // 同样保持 'pending'(消费者按加载态渲染,不提前报「不可用」)。
22
+ import { useEffect, useState } from 'react'
23
+ import { resolveDesktopAgentAvailability } from '@/lib/desktop-agent/availability'
24
+
25
+ export type DesktopAgentPresence = 'pending' | 'present' | 'absent'
26
+
27
+ /** 重试间隔与总预算(固定间隔,累计约 20s 覆盖 backend 冷启动窗口) */
28
+ export const DESKTOP_AGENT_RETRY_INTERVAL_MS = 1000
29
+ export const DESKTOP_AGENT_RETRY_BUDGET_MS = 20_000
30
+
31
+ export function useDesktopAgentPresence(): DesktopAgentPresence {
32
+ const [presence, setPresence] = useState<DesktopAgentPresence>('pending')
33
+ useEffect(() => {
34
+ let cancelled = false
35
+ let timer: ReturnType<typeof setTimeout> | null = null
36
+ let spent = 0
37
+
38
+ const probe = async () => {
39
+ const availability = await resolveDesktopAgentAvailability()
40
+ if (cancelled) return
41
+ // present / absent 都是终态(absent = 非桌面构建或无桥),停止探测
42
+ if (availability !== 'retry') {
43
+ setPresence(availability)
44
+ return
45
+ }
46
+ if (spent >= DESKTOP_AGENT_RETRY_BUDGET_MS) {
47
+ setPresence('absent')
48
+ return
49
+ }
50
+ spent += DESKTOP_AGENT_RETRY_INTERVAL_MS
51
+ timer = setTimeout(() => {
52
+ timer = null
53
+ void probe()
54
+ }, DESKTOP_AGENT_RETRY_INTERVAL_MS)
55
+ }
56
+
57
+ void probe()
58
+ return () => {
59
+ cancelled = true
60
+ if (timer !== null) clearTimeout(timer)
61
+ }
62
+ }, [])
63
+ return presence
64
+ }
@@ -5,7 +5,19 @@
5
5
  // 桌面端类型声明(迁移 P5.3/P6):desktopBridge 桥(Electron preload 暴露)。
6
6
  // 仅类型——运行时对象由 Electron preload 注入,浏览器环境无此对象。
7
7
  export interface DesktopBridgeApi {
8
- appInfo: () => Promise<{ version: string; clientId: string; platform: string; backendPort: number | null }>
8
+ /** B4 起追加 agentPort/agentToken(本地文件助手 SSE 端点;add-only,不改既有
9
+ * 字段):backend utilityProcess 装配 AgentService 后随 appInfo 广播——
10
+ * agentPort = 127.0.0.1 随机端口,agentToken = 启动时生成的访问令牌
11
+ * (请求须带 X-Desktop-Token 头)。null = agent 未装配(旧壳,或 DESKTOP_AGENT
12
+ * 门控未开/bundle 装配失败降级),renderer 据此隐藏 agent 入口。 */
13
+ appInfo: () => Promise<{
14
+ version: string
15
+ clientId: string
16
+ platform: string
17
+ backendPort: number | null
18
+ agentPort?: number | null
19
+ agentToken?: string | null
20
+ }>
9
21
  cloudLogin: (email: string, password: string) => Promise<{ ok: boolean; userId?: string; error?: string }>
10
22
  /** A10 轻量云身份激活:登录成功后取 cloud-session.json 解出的纯 session
11
23
  * token(renderer 再走 exchangeRemoteTokenFn 换权益并写 remote-auth)。 */
@@ -45,6 +57,15 @@ export interface DesktopBridgeApi {
45
57
  * 优雅降级。 */
46
58
  desktopState?: () => Promise<DesktopStatePayload>
47
59
  onDesktopState?: (cb: (payload: DesktopStatePayload) => void) => () => void
60
+ /** B1 目录授权(本地优先 P3 agent,本段为 add-only 追加,不改既有段落):
61
+ * agent 访问本地文件的授权清单(main 侧 userData/agent/workspaces.json 增删
62
+ * 查)。授权模型:renderer 不能注入任意路径——唯一添加入口是用户经原生目录
63
+ * 选择对话框拣选(pickDirectory 成功即写入清单,返回规范化绝对路径;取消返
64
+ * 回 null),removeWorkspace 撤销授权、listWorkspaces 查询。旧壳(无此三方
65
+ * 法)undefined——agent 文件面调用方 optional-chaining 优雅降级。 */
66
+ pickDirectory?: () => Promise<string | null>
67
+ listWorkspaces?: () => Promise<string[]>
68
+ removeWorkspace?: (path: string) => Promise<void>
48
69
  }
49
70
 
50
71
  /** A11 desktop-state 三态载荷(main 侧 desktop-state.json 持久化态的广播形状):
@@ -23,8 +23,8 @@ import { appHotkeys, findAppHotkeyConflicts, formatAppHotkeyForBadge, CATEGORY_O
23
23
  const DECLARED_IDS = Object.keys(appHotkeys) as AppHotkeyId[]
24
24
 
25
25
  describe("appHotkeys(defineAppHotkeys 官方声明)", () => {
26
- it("恰好 25 条声明,且 id 与迁移前注册表对齐", () => {
27
- expect(DECLARED_IDS).toHaveLength(25)
26
+ it("恰好 26 条声明,且 id 与迁移前注册表对齐(+ B5 agent-abort)", () => {
27
+ expect(DECLARED_IDS).toHaveLength(26)
28
28
  expect(DECLARED_IDS).toEqual(
29
29
  expect.arrayContaining([
30
30
  "shortcuts-panel",
@@ -34,6 +34,7 @@ describe("appHotkeys(defineAppHotkeys 官方声明)", () => {
34
34
  "copy-message",
35
35
  "chat-prev",
36
36
  "chat-next",
37
+ "agent-abort",
37
38
  "command-palette",
38
39
  "toggle-theme",
39
40
  "goto-dashboard",
@@ -82,9 +83,15 @@ describe("appHotkeys(defineAppHotkeys 官方声明)", () => {
82
83
  }
83
84
  })
84
85
 
85
- it("非序列条目为 9 条 chord(Mod+/ 等)", () => {
86
+ it("非序列条目为 10 条 chord(Mod+/ 等)", () => {
86
87
  const chords = DECLARED_IDS.map((id) => appHotkeys[id]!).filter((e) => typeof e.hotkey === "string")
87
- expect(chords).toHaveLength(9)
88
+ expect(chords).toHaveLength(10)
89
+ })
90
+
91
+ it("agent-abort(本地文件助手中止运行):Mod+. 聊天分类——输入框内同样生效(ignoreInputs auto 对 Mod 组合放行)", () => {
92
+ const entry = appHotkeys["agent-abort"]
93
+ expect(entry.hotkey).toBe("Mod+.")
94
+ expect(entry.meta).toEqual({ descriptionKey: "common_hotkey_desc_agentAbort", category: "聊天" })
88
95
  })
89
96
 
90
97
  it("现网声明零冲突(findAppHotkeyConflicts)", () => {
@@ -74,6 +74,14 @@ export const appHotkeys = defineAppHotkeys({
74
74
  hotkey: "ArrowDown",
75
75
  meta: { descriptionKey: "common_hotkey_desc_chatNext", category: "聊天" },
76
76
  },
77
+ // 本地文件助手(桌面 P3-B5)中止运行:绑定点 components/desktop-agent/agent-chat.tsx
78
+ // (仅运行中 enabled)。Mod+. 取 macOS「Command-句点 = 取消」惯例;Escape 已被
79
+ // close-panel 全局占用(同 scope 即冲突)。Mod 组合在 ignoreInputs auto 下输入框
80
+ // 内同样生效(边输入边中止)
81
+ "agent-abort": {
82
+ hotkey: "Mod+.",
83
+ meta: { descriptionKey: "common_hotkey_desc_agentAbort", category: "聊天" },
84
+ },
77
85
  "command-palette": {
78
86
  hotkey: "Mod+K",
79
87
  meta: { descriptionKey: "common_hotkey_desc_commandPalette", category: "导航" },
@@ -165,7 +173,7 @@ export interface AppHotkeyConflict {
165
173
 
166
174
  /**
167
175
  * 声明级冲突检测:用官方 AppHotkeysStore.findConflicts 的冲突语义
168
- * (scope 相同或任一为 global,且组合键相等或序列互为前缀)对全部 25 条
176
+ * (scope 相同或任一为 global,且组合键相等或序列互为前缀)对全部 26 条
169
177
  * 声明两两比对。
170
178
  *
171
179
  * 注:官方 `findHotkeyConflicts()` 检测的是**运行时注册表**(HotkeyManager
@@ -65,3 +65,4 @@ export const xxxQueryOptions = (params) =>
65
65
  | `agents.ts` | `agents` / `skills` / `agent-bindings` / `persona-hint` | 新增常量;harness 同键查询已收拢 |
66
66
  | `team.ts` | `teamMembers` / `teamInvitations` / `teamUsers` | mention-dropdown 的 `teamUsers` 是另一数据源,未动(见上第 5 条) |
67
67
  | `compliance.ts` | `compliance` / `compliance-detail` / `entity-tags` / `favorite-ids` | detail / favorite-ids 双份合并;entityTags / favoriteIds 参数化 `entityType`,`legal`(laws)/ `dictionary` 模块可渐进复用 |
68
+ | `desktop-agent.ts` | `desktop-agent` 前缀 / `desktop-agent,workspaces` | 本地文件助手(桌面 P3)授权目录清单;queryFn 走 desktopBridge.listWorkspaces(IPC,非 serverFn),无桥/旧壳降级 `[]` |
@@ -0,0 +1,80 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
2
+ // AllBlue - 理想之海
3
+ // Copyright (C) 2026 AllBlue Contributors
4
+
5
+ // desktop-agent queryOptions 工厂(桌面本地优先 P3-B5):key 结构单一来源 +
6
+ // queryFn 走 desktopBridge.listWorkspaces(main 侧 workspaces.json),非桌面 /
7
+ // 旧壳(无 listWorkspaces)降级空数组——本地桥数据,非 serverFn。
8
+ import { beforeEach, describe, expect, it, vi } from 'vitest'
9
+ import { QueryClient } from '@tanstack/react-query'
10
+
11
+ const bridgeRef: { current: unknown } = { current: null }
12
+
13
+ vi.mock('@/lib/desktop-bridge-types', () => ({
14
+ getDesktopBridge: () => bridgeRef.current,
15
+ }))
16
+
17
+ import {
18
+ DESKTOP_AGENT_QUERY_KEY,
19
+ DESKTOP_AGENT_WORKSPACES_QUERY_KEY,
20
+ desktopAgentWorkspacesQueryOptions,
21
+ } from '../desktop-agent'
22
+
23
+ beforeEach(() => {
24
+ bridgeRef.current = null
25
+ })
26
+
27
+ /** queryFn 运行时恒存在(工厂必传),类型上可选故窄化;context 形状对齐 react-query v5 调用面 */
28
+ function invokeQueryFn(
29
+ options: { queryFn?: (...args: never[]) => unknown },
30
+ queryKey: readonly unknown[],
31
+ ): Promise<unknown> {
32
+ return (options.queryFn as (c: unknown) => Promise<unknown>)({
33
+ client: new QueryClient(),
34
+ queryKey,
35
+ signal: new AbortController().signal,
36
+ meta: undefined,
37
+ })
38
+ }
39
+
40
+ describe('desktop-agent queryOptions key 结构', () => {
41
+ it('前缀常量固定段 + workspaces 子段(invalidate 前缀覆盖全部 desktop-agent 查询)', () => {
42
+ expect(DESKTOP_AGENT_QUERY_KEY).toEqual(['desktop-agent'])
43
+ expect(DESKTOP_AGENT_WORKSPACES_QUERY_KEY).toEqual(['desktop-agent', 'workspaces'])
44
+ })
45
+
46
+ it('工厂产出 workspaces 常量同一引用(invalidate 与 useQuery 同源)', () => {
47
+ expect(desktopAgentWorkspacesQueryOptions().queryKey).toBe(DESKTOP_AGENT_WORKSPACES_QUERY_KEY)
48
+ })
49
+ })
50
+
51
+ describe('desktop-agent queryOptions queryFn 接线', () => {
52
+ it('桌面壳:调 desktopBridge.listWorkspaces() 并原样返回授权清单', async () => {
53
+ const listWorkspaces = vi.fn().mockResolvedValue(['/Users/x/proj-a', '/Users/x/proj-b'])
54
+ bridgeRef.current = { listWorkspaces }
55
+ const options = desktopAgentWorkspacesQueryOptions()
56
+ await expect(invokeQueryFn(options, options.queryKey)).resolves.toEqual([
57
+ '/Users/x/proj-a',
58
+ '/Users/x/proj-b',
59
+ ])
60
+ expect(listWorkspaces).toHaveBeenCalledWith()
61
+ })
62
+
63
+ it('无桥(云 Web / OSS):返回空数组,不抛错', async () => {
64
+ bridgeRef.current = null
65
+ const options = desktopAgentWorkspacesQueryOptions()
66
+ await expect(invokeQueryFn(options, options.queryKey)).resolves.toEqual([])
67
+ })
68
+
69
+ it('旧壳(桥存在但无 listWorkspaces):返回空数组(optional-chaining 降级)', async () => {
70
+ bridgeRef.current = { appInfo: vi.fn() }
71
+ const options = desktopAgentWorkspacesQueryOptions()
72
+ await expect(invokeQueryFn(options, options.queryKey)).resolves.toEqual([])
73
+ })
74
+
75
+ it('桥 IPC 失败:错误透传给 react-query(error 态由消费方渲染,不吞成空清单)', async () => {
76
+ bridgeRef.current = { listWorkspaces: vi.fn().mockRejectedValue(new Error('ipc down')) }
77
+ const options = desktopAgentWorkspacesQueryOptions()
78
+ await expect(invokeQueryFn(options, options.queryKey)).rejects.toThrow('ipc down')
79
+ })
80
+ })
@@ -0,0 +1,25 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
2
+ // AllBlue - 理想之海
3
+ // Copyright (C) 2026 AllBlue Contributors
4
+
5
+ // desktop-agent(本地文件助手,桌面本地优先 P3-B5)queryOptions 工厂(key +
6
+ // queryFn 单一来源)。消费方(组件 useQuery / invalidate)一律从本模块取,禁止
7
+ // 再写 ['desktop-agent', ...] 内联字面量。模式说明见 ./README.md。
8
+ //
9
+ // 数据源是桌面壳桥(desktopBridge.listWorkspaces → main 侧
10
+ // userData/agent/workspaces.json),不是 serverFn:授权清单只存在于本机 main
11
+ // 进程,renderer 经 IPC 读取。非桌面(云 Web / OSS,无桥)与旧壳(无此方法)
12
+ // 降级空数组——入口本就被门控隐藏,降级只为让误用时不抛错。
13
+ import { queryOptions } from '@tanstack/react-query'
14
+ import { getDesktopBridge } from '@/lib/desktop-bridge-types'
15
+
16
+ /** desktop-agent 全域前缀:invalidate 用它即覆盖本模块全部查询 */
17
+ export const DESKTOP_AGENT_QUERY_KEY = ['desktop-agent'] as const
18
+ export const DESKTOP_AGENT_WORKSPACES_QUERY_KEY = [...DESKTOP_AGENT_QUERY_KEY, 'workspaces'] as const
19
+
20
+ /** 已授权工作目录清单(规范化绝对路径,main 侧 pickDirectory 写入顺序) */
21
+ export const desktopAgentWorkspacesQueryOptions = () =>
22
+ queryOptions({
23
+ queryKey: DESKTOP_AGENT_WORKSPACES_QUERY_KEY,
24
+ queryFn: async (): Promise<string[]> => (await getDesktopBridge()?.listWorkspaces?.()) ?? [],
25
+ })
@@ -11,6 +11,46 @@ export * from "./agent_clearconvfailed2.js";
11
11
  export * from "./agent_createfailed1.js";
12
12
  export * from "./agent_deleteconv1.js";
13
13
  export * from "./agent_deleteconvfailed2.js";
14
+ export * from "./agent_desktop_chatcwd1.js";
15
+ export * from "./agent_desktop_chatemptyhint2.js";
16
+ export * from "./agent_desktop_chatemptytitle2.js";
17
+ export * from "./agent_desktop_chatindependenthint2.js";
18
+ export * from "./agent_desktop_chatnoworkspace2.js";
19
+ export * from "./agent_desktop_chatplaceholder1.js";
20
+ export * from "./agent_desktop_chatsend1.js";
21
+ export * from "./agent_desktop_chatstop1.js";
22
+ export * from "./agent_desktop_chatthinking1.js";
23
+ export * from "./agent_desktop_errorconnection1.js";
24
+ export * from "./agent_desktop_errorforbidden1.js";
25
+ export * from "./agent_desktop_errorgeneric1.js";
26
+ export * from "./agent_desktop_errorunauthorized1.js";
27
+ export * from "./agent_desktop_errorunavailable1.js";
28
+ export * from "./agent_desktop_pagedescription1.js";
29
+ export * from "./agent_desktop_title.js";
30
+ export * from "./agent_desktop_toolcountfiles2.js";
31
+ export * from "./agent_desktop_toolcounthits2.js";
32
+ export * from "./agent_desktop_toolcountlines2.js";
33
+ export * from "./agent_desktop_toolemptydir2.js";
34
+ export * from "./agent_desktop_toolerror1.js";
35
+ export * from "./agent_desktop_toolfind1.js";
36
+ export * from "./agent_desktop_toolgrep1.js";
37
+ export * from "./agent_desktop_toolls1.js";
38
+ export * from "./agent_desktop_toolmore1.js";
39
+ export * from "./agent_desktop_toolnomatches2.js";
40
+ export * from "./agent_desktop_toolother1.js";
41
+ export * from "./agent_desktop_toolread1.js";
42
+ export * from "./agent_desktop_toolrunning1.js";
43
+ export * from "./agent_desktop_tooltruncated1.js";
44
+ export * from "./agent_desktop_workspaceadd1.js";
45
+ export * from "./agent_desktop_workspaceaddfailed2.js";
46
+ export * from "./agent_desktop_workspacedescription1.js";
47
+ export * from "./agent_desktop_workspaceempty1.js";
48
+ export * from "./agent_desktop_workspaceemptyhint2.js";
49
+ export * from "./agent_desktop_workspaceloadfailed2.js";
50
+ export * from "./agent_desktop_workspaceremove1.js";
51
+ export * from "./agent_desktop_workspaceremovefailed2.js";
52
+ export * from "./agent_desktop_workspacetitle1.js";
53
+ export * from "./agent_desktop_workspaceunsupported1.js";
14
54
  export * from "./agent_emptyexample1.js";
15
55
  export * from "./agent_emptyhint1.js";
16
56
  export * from "./agent_generatefailed1.js";
@@ -1797,6 +1837,7 @@ export * from "./common_hotkey_cat_chat.js";
1797
1837
  export * from "./common_hotkey_cat_edit.js";
1798
1838
  export * from "./common_hotkey_cat_navigation.js";
1799
1839
  export * from "./common_hotkey_cat_view.js";
1840
+ export * from "./common_hotkey_desc_agentabort1.js";
1800
1841
  export * from "./common_hotkey_desc_chatnext1.js";
1801
1842
  export * from "./common_hotkey_desc_chatprev1.js";
1802
1843
  export * from "./common_hotkey_desc_closepanel1.js";
@@ -4913,6 +4954,7 @@ export * from "./sync_bind_failed.js";
4913
4954
  export * from "./sync_bind_in_progress.js";
4914
4955
  export * from "./sync_bind_nonempty.js";
4915
4956
  export * from "./sync_bind_probe_unreachable.js";
4957
+ export * from "./sync_bind_rolled_back.js";
4916
4958
  export * from "./sync_bind_shell_unsupported.js";
4917
4959
  export * from "./sync_logout_failed.js";
4918
4960
  export * from "./sync_logout_in_progress.js";
@@ -13,6 +13,46 @@ export * from './agent_clearconvfailed2.js'
13
13
  export * from './agent_createfailed1.js'
14
14
  export * from './agent_deleteconv1.js'
15
15
  export * from './agent_deleteconvfailed2.js'
16
+ export * from './agent_desktop_chatcwd1.js'
17
+ export * from './agent_desktop_chatemptyhint2.js'
18
+ export * from './agent_desktop_chatemptytitle2.js'
19
+ export * from './agent_desktop_chatindependenthint2.js'
20
+ export * from './agent_desktop_chatnoworkspace2.js'
21
+ export * from './agent_desktop_chatplaceholder1.js'
22
+ export * from './agent_desktop_chatsend1.js'
23
+ export * from './agent_desktop_chatstop1.js'
24
+ export * from './agent_desktop_chatthinking1.js'
25
+ export * from './agent_desktop_errorconnection1.js'
26
+ export * from './agent_desktop_errorforbidden1.js'
27
+ export * from './agent_desktop_errorgeneric1.js'
28
+ export * from './agent_desktop_errorunauthorized1.js'
29
+ export * from './agent_desktop_errorunavailable1.js'
30
+ export * from './agent_desktop_pagedescription1.js'
31
+ export * from './agent_desktop_title.js'
32
+ export * from './agent_desktop_toolcountfiles2.js'
33
+ export * from './agent_desktop_toolcounthits2.js'
34
+ export * from './agent_desktop_toolcountlines2.js'
35
+ export * from './agent_desktop_toolemptydir2.js'
36
+ export * from './agent_desktop_toolerror1.js'
37
+ export * from './agent_desktop_toolfind1.js'
38
+ export * from './agent_desktop_toolgrep1.js'
39
+ export * from './agent_desktop_toolls1.js'
40
+ export * from './agent_desktop_toolmore1.js'
41
+ export * from './agent_desktop_toolnomatches2.js'
42
+ export * from './agent_desktop_toolother1.js'
43
+ export * from './agent_desktop_toolread1.js'
44
+ export * from './agent_desktop_toolrunning1.js'
45
+ export * from './agent_desktop_tooltruncated1.js'
46
+ export * from './agent_desktop_workspaceadd1.js'
47
+ export * from './agent_desktop_workspaceaddfailed2.js'
48
+ export * from './agent_desktop_workspacedescription1.js'
49
+ export * from './agent_desktop_workspaceempty1.js'
50
+ export * from './agent_desktop_workspaceemptyhint2.js'
51
+ export * from './agent_desktop_workspaceloadfailed2.js'
52
+ export * from './agent_desktop_workspaceremove1.js'
53
+ export * from './agent_desktop_workspaceremovefailed2.js'
54
+ export * from './agent_desktop_workspacetitle1.js'
55
+ export * from './agent_desktop_workspaceunsupported1.js'
16
56
  export * from './agent_emptyexample1.js'
17
57
  export * from './agent_emptyhint1.js'
18
58
  export * from './agent_generatefailed1.js'
@@ -1799,6 +1839,7 @@ export * from './common_hotkey_cat_chat.js'
1799
1839
  export * from './common_hotkey_cat_edit.js'
1800
1840
  export * from './common_hotkey_cat_navigation.js'
1801
1841
  export * from './common_hotkey_cat_view.js'
1842
+ export * from './common_hotkey_desc_agentabort1.js'
1802
1843
  export * from './common_hotkey_desc_chatnext1.js'
1803
1844
  export * from './common_hotkey_desc_chatprev1.js'
1804
1845
  export * from './common_hotkey_desc_closepanel1.js'
@@ -4915,6 +4956,7 @@ export * from './sync_bind_failed.js'
4915
4956
  export * from './sync_bind_in_progress.js'
4916
4957
  export * from './sync_bind_nonempty.js'
4917
4958
  export * from './sync_bind_probe_unreachable.js'
4959
+ export * from './sync_bind_rolled_back.js'
4918
4960
  export * from './sync_bind_shell_unsupported.js'
4919
4961
  export * from './sync_logout_failed.js'
4920
4962
  export * from './sync_logout_in_progress.js'
@@ -0,0 +1,19 @@
1
+ export { agent_desktop_chatcwd1 as "agent_desktop_chatCwd" };
2
+ export type LocalizedString = import("../runtime.js").LocalizedString;
3
+ export type Agent_Desktop_Chatcwd1Inputs = {
4
+ path: NonNullable<unknown>;
5
+ };
6
+ /**
7
+ * | output |
8
+ * | --- |
9
+ * | "Folder: {path}" |
10
+ *
11
+ * @param {Agent_Desktop_Chatcwd1Inputs} inputs
12
+ * @param {{ locale?: "zh" | "en" }} options
13
+ * @returns {LocalizedString}
14
+ */
15
+ declare const agent_desktop_chatcwd1: ((inputs: Agent_Desktop_Chatcwd1Inputs, options?: {
16
+ locale?: "zh" | "en";
17
+ }) => LocalizedString) & import("../runtime.js").MessageMetadata<Agent_Desktop_Chatcwd1Inputs, {
18
+ locale?: "zh" | "en";
19
+ }, {}>;
@@ -0,0 +1,30 @@
1
+ /* eslint-disable */
2
+ import { getLocale, experimentalStaticLocale } from '../runtime.js';
3
+
4
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
5
+
6
+ /** @typedef {{ path: NonNullable<unknown> }} Agent_Desktop_Chatcwd1Inputs */
7
+
8
+ const zh_agent_desktop_chatcwd1 = /** @type {(inputs: Agent_Desktop_Chatcwd1Inputs) => LocalizedString} */ (i) => {
9
+ return /** @type {LocalizedString} */ (`当前目录:${i?.path}`)
10
+ };
11
+
12
+ const en_agent_desktop_chatcwd1 = /** @type {(inputs: Agent_Desktop_Chatcwd1Inputs) => LocalizedString} */ (i) => {
13
+ return /** @type {LocalizedString} */ (`Folder: ${i?.path}`)
14
+ };
15
+
16
+ /**
17
+ * | output |
18
+ * | --- |
19
+ * | "Folder: {path}" |
20
+ *
21
+ * @param {Agent_Desktop_Chatcwd1Inputs} inputs
22
+ * @param {{ locale?: "zh" | "en" }} options
23
+ * @returns {LocalizedString}
24
+ */
25
+ const agent_desktop_chatcwd1 = /** @type {((inputs: Agent_Desktop_Chatcwd1Inputs, options?: { locale?: "zh" | "en" }) => LocalizedString) & import('../runtime.js').MessageMetadata<Agent_Desktop_Chatcwd1Inputs, { locale?: "zh" | "en" }, {}>} */ ((inputs, options = {}) => {
26
+ const locale = experimentalStaticLocale ?? options.locale ?? getLocale()
27
+ if (locale === "en") return en_agent_desktop_chatcwd1(inputs)
28
+ return zh_agent_desktop_chatcwd1(inputs)
29
+ });
30
+ export { agent_desktop_chatcwd1 as "agent_desktop_chatCwd" }
@@ -0,0 +1,17 @@
1
+ export { agent_desktop_chatemptyhint2 as "agent_desktop_chatEmptyHint" };
2
+ export type LocalizedString = import("../runtime.js").LocalizedString;
3
+ export type Agent_Desktop_Chatemptyhint2Inputs = {};
4
+ /**
5
+ * | output |
6
+ * | --- |
7
+ * | "For example: summarize this project's structure, or find all TODOs" |
8
+ *
9
+ * @param {Agent_Desktop_Chatemptyhint2Inputs} inputs
10
+ * @param {{ locale?: "zh" | "en" }} options
11
+ * @returns {LocalizedString}
12
+ */
13
+ declare const agent_desktop_chatemptyhint2: ((inputs?: Agent_Desktop_Chatemptyhint2Inputs, options?: {
14
+ locale?: "zh" | "en";
15
+ }) => LocalizedString) & import("../runtime.js").MessageMetadata<Agent_Desktop_Chatemptyhint2Inputs, {
16
+ locale?: "zh" | "en";
17
+ }, {}>;
@@ -0,0 +1,30 @@
1
+ /* eslint-disable */
2
+ import { getLocale, experimentalStaticLocale } from '../runtime.js';
3
+
4
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
5
+
6
+ /** @typedef {{}} Agent_Desktop_Chatemptyhint2Inputs */
7
+
8
+ const zh_agent_desktop_chatemptyhint2 = /** @type {(inputs: Agent_Desktop_Chatemptyhint2Inputs) => LocalizedString} */ () => {
9
+ return /** @type {LocalizedString} */ (`例如:总结这个项目的结构,或找出所有 TODO`)
10
+ };
11
+
12
+ const en_agent_desktop_chatemptyhint2 = /** @type {(inputs: Agent_Desktop_Chatemptyhint2Inputs) => LocalizedString} */ () => {
13
+ return /** @type {LocalizedString} */ (`For example: summarize this project's structure, or find all TODOs`)
14
+ };
15
+
16
+ /**
17
+ * | output |
18
+ * | --- |
19
+ * | "For example: summarize this project's structure, or find all TODOs" |
20
+ *
21
+ * @param {Agent_Desktop_Chatemptyhint2Inputs} inputs
22
+ * @param {{ locale?: "zh" | "en" }} options
23
+ * @returns {LocalizedString}
24
+ */
25
+ const agent_desktop_chatemptyhint2 = /** @type {((inputs?: Agent_Desktop_Chatemptyhint2Inputs, options?: { locale?: "zh" | "en" }) => LocalizedString) & import('../runtime.js').MessageMetadata<Agent_Desktop_Chatemptyhint2Inputs, { locale?: "zh" | "en" }, {}>} */ ((inputs = {}, options = {}) => {
26
+ const locale = experimentalStaticLocale ?? options.locale ?? getLocale()
27
+ if (locale === "en") return en_agent_desktop_chatemptyhint2(inputs)
28
+ return zh_agent_desktop_chatemptyhint2(inputs)
29
+ });
30
+ export { agent_desktop_chatemptyhint2 as "agent_desktop_chatEmptyHint" }
@@ -0,0 +1,17 @@
1
+ export { agent_desktop_chatemptytitle2 as "agent_desktop_chatEmptyTitle" };
2
+ export type LocalizedString = import("../runtime.js").LocalizedString;
3
+ export type Agent_Desktop_Chatemptytitle2Inputs = {};
4
+ /**
5
+ * | output |
6
+ * | --- |
7
+ * | "Ask about your local files" |
8
+ *
9
+ * @param {Agent_Desktop_Chatemptytitle2Inputs} inputs
10
+ * @param {{ locale?: "zh" | "en" }} options
11
+ * @returns {LocalizedString}
12
+ */
13
+ declare const agent_desktop_chatemptytitle2: ((inputs?: Agent_Desktop_Chatemptytitle2Inputs, options?: {
14
+ locale?: "zh" | "en";
15
+ }) => LocalizedString) & import("../runtime.js").MessageMetadata<Agent_Desktop_Chatemptytitle2Inputs, {
16
+ locale?: "zh" | "en";
17
+ }, {}>;
@@ -0,0 +1,30 @@
1
+ /* eslint-disable */
2
+ import { getLocale, experimentalStaticLocale } from '../runtime.js';
3
+
4
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
5
+
6
+ /** @typedef {{}} Agent_Desktop_Chatemptytitle2Inputs */
7
+
8
+ const zh_agent_desktop_chatemptytitle2 = /** @type {(inputs: Agent_Desktop_Chatemptytitle2Inputs) => LocalizedString} */ () => {
9
+ return /** @type {LocalizedString} */ (`向本地文件提问`)
10
+ };
11
+
12
+ const en_agent_desktop_chatemptytitle2 = /** @type {(inputs: Agent_Desktop_Chatemptytitle2Inputs) => LocalizedString} */ () => {
13
+ return /** @type {LocalizedString} */ (`Ask about your local files`)
14
+ };
15
+
16
+ /**
17
+ * | output |
18
+ * | --- |
19
+ * | "Ask about your local files" |
20
+ *
21
+ * @param {Agent_Desktop_Chatemptytitle2Inputs} inputs
22
+ * @param {{ locale?: "zh" | "en" }} options
23
+ * @returns {LocalizedString}
24
+ */
25
+ const agent_desktop_chatemptytitle2 = /** @type {((inputs?: Agent_Desktop_Chatemptytitle2Inputs, options?: { locale?: "zh" | "en" }) => LocalizedString) & import('../runtime.js').MessageMetadata<Agent_Desktop_Chatemptytitle2Inputs, { locale?: "zh" | "en" }, {}>} */ ((inputs = {}, options = {}) => {
26
+ const locale = experimentalStaticLocale ?? options.locale ?? getLocale()
27
+ if (locale === "en") return en_agent_desktop_chatemptytitle2(inputs)
28
+ return zh_agent_desktop_chatemptytitle2(inputs)
29
+ });
30
+ export { agent_desktop_chatemptytitle2 as "agent_desktop_chatEmptyTitle" }
@@ -0,0 +1,17 @@
1
+ export { agent_desktop_chatindependenthint2 as "agent_desktop_chatIndependentHint" };
2
+ export type LocalizedString = import("../runtime.js").LocalizedString;
3
+ export type Agent_Desktop_Chatindependenthint2Inputs = {};
4
+ /**
5
+ * | output |
6
+ * | --- |
7
+ * | "Each question runs independently; earlier turns are not remembered" |
8
+ *
9
+ * @param {Agent_Desktop_Chatindependenthint2Inputs} inputs
10
+ * @param {{ locale?: "zh" | "en" }} options
11
+ * @returns {LocalizedString}
12
+ */
13
+ declare const agent_desktop_chatindependenthint2: ((inputs?: Agent_Desktop_Chatindependenthint2Inputs, options?: {
14
+ locale?: "zh" | "en";
15
+ }) => LocalizedString) & import("../runtime.js").MessageMetadata<Agent_Desktop_Chatindependenthint2Inputs, {
16
+ locale?: "zh" | "en";
17
+ }, {}>;
@@ -0,0 +1,30 @@
1
+ /* eslint-disable */
2
+ import { getLocale, experimentalStaticLocale } from '../runtime.js';
3
+
4
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
5
+
6
+ /** @typedef {{}} Agent_Desktop_Chatindependenthint2Inputs */
7
+
8
+ const zh_agent_desktop_chatindependenthint2 = /** @type {(inputs: Agent_Desktop_Chatindependenthint2Inputs) => LocalizedString} */ () => {
9
+ return /** @type {LocalizedString} */ (`每次提问独立执行,不保留多轮上下文`)
10
+ };
11
+
12
+ const en_agent_desktop_chatindependenthint2 = /** @type {(inputs: Agent_Desktop_Chatindependenthint2Inputs) => LocalizedString} */ () => {
13
+ return /** @type {LocalizedString} */ (`Each question runs independently; earlier turns are not remembered`)
14
+ };
15
+
16
+ /**
17
+ * | output |
18
+ * | --- |
19
+ * | "Each question runs independently; earlier turns are not remembered" |
20
+ *
21
+ * @param {Agent_Desktop_Chatindependenthint2Inputs} inputs
22
+ * @param {{ locale?: "zh" | "en" }} options
23
+ * @returns {LocalizedString}
24
+ */
25
+ const agent_desktop_chatindependenthint2 = /** @type {((inputs?: Agent_Desktop_Chatindependenthint2Inputs, options?: { locale?: "zh" | "en" }) => LocalizedString) & import('../runtime.js').MessageMetadata<Agent_Desktop_Chatindependenthint2Inputs, { locale?: "zh" | "en" }, {}>} */ ((inputs = {}, options = {}) => {
26
+ const locale = experimentalStaticLocale ?? options.locale ?? getLocale()
27
+ if (locale === "en") return en_agent_desktop_chatindependenthint2(inputs)
28
+ return zh_agent_desktop_chatindependenthint2(inputs)
29
+ });
30
+ export { agent_desktop_chatindependenthint2 as "agent_desktop_chatIndependentHint" }
@@ -0,0 +1,17 @@
1
+ export { agent_desktop_chatnoworkspace2 as "agent_desktop_chatNoWorkspace" };
2
+ export type LocalizedString = import("../runtime.js").LocalizedString;
3
+ export type Agent_Desktop_Chatnoworkspace2Inputs = {};
4
+ /**
5
+ * | output |
6
+ * | --- |
7
+ * | "Add and select an authorized folder first" |
8
+ *
9
+ * @param {Agent_Desktop_Chatnoworkspace2Inputs} inputs
10
+ * @param {{ locale?: "zh" | "en" }} options
11
+ * @returns {LocalizedString}
12
+ */
13
+ declare const agent_desktop_chatnoworkspace2: ((inputs?: Agent_Desktop_Chatnoworkspace2Inputs, options?: {
14
+ locale?: "zh" | "en";
15
+ }) => LocalizedString) & import("../runtime.js").MessageMetadata<Agent_Desktop_Chatnoworkspace2Inputs, {
16
+ locale?: "zh" | "en";
17
+ }, {}>;