@rexvane/piweb 0.3.16 → 0.3.17

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 (288) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/app-path-routes-manifest.json +8 -11
  3. package/.next/build-manifest.json +3 -3
  4. package/.next/prerender-manifest.json +6 -6
  5. package/.next/react-loadable-manifest.json +4 -16
  6. package/.next/required-server-files.js +1 -3
  7. package/.next/required-server-files.json +1 -3
  8. package/.next/routes-manifest.json +0 -20
  9. package/.next/server/app/_global-error/page.js +2 -2
  10. package/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  11. package/.next/server/app/_global-error.html +1 -1
  12. package/.next/server/app/_global-error.rsc +1 -1
  13. package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  14. package/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  15. package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  16. package/.next/server/app/_not-found/page.js +1 -1
  17. package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  18. package/.next/server/app/_not-found.html +1 -1
  19. package/.next/server/app/_not-found.rsc +4 -7
  20. package/.next/server/app/_not-found.segments/_full.segment.rsc +4 -7
  21. package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -5
  22. package/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -5
  23. package/.next/server/app/api/agent/[id]/events/route.js +2 -2
  24. package/.next/server/app/api/agent/[id]/events/route.js.nft.json +1 -1
  25. package/.next/server/app/api/agent/[id]/route.js +1 -1
  26. package/.next/server/app/api/agent/[id]/route.js.nft.json +1 -1
  27. package/.next/server/app/api/agent/[id]/tree/route.js +1 -1
  28. package/.next/server/app/api/agent/[id]/tree/route.js.nft.json +1 -1
  29. package/.next/server/app/api/agent/new/route.js +1 -1
  30. package/.next/server/app/api/agent/new/route.js.nft.json +1 -1
  31. package/.next/server/app/api/config/route.js +1 -1
  32. package/.next/server/app/api/config/route.js.nft.json +1 -1
  33. package/.next/server/app/api/files/route.js +1 -1
  34. package/.next/server/app/api/files/route.js.nft.json +1 -1
  35. package/.next/server/app/api/git/route.js +2 -2
  36. package/.next/server/app/api/git/route.js.nft.json +1 -1
  37. package/.next/server/app/api/growth/route.js +1 -1
  38. package/.next/server/app/api/growth/route.js.nft.json +1 -1
  39. package/.next/server/app/api/health/route.js +1 -1
  40. package/.next/server/app/api/models/route.js +1 -1
  41. package/.next/server/app/api/models/route.js.nft.json +1 -1
  42. package/.next/server/app/api/pi-settings/route.js +1 -1
  43. package/.next/server/app/api/pi-settings/route.js.nft.json +1 -1
  44. package/.next/server/app/api/plugins/route.js +1 -1
  45. package/.next/server/app/api/plugins/route.js.nft.json +1 -1
  46. package/.next/server/app/api/prompts/route.js +1 -1
  47. package/.next/server/app/api/prompts/route.js.nft.json +1 -1
  48. package/.next/server/app/api/security/route.js +1 -1
  49. package/.next/server/app/api/security/route.js.nft.json +1 -1
  50. package/.next/server/app/api/sessions/[id]/export/route.js +1 -1
  51. package/.next/server/app/api/sessions/[id]/export/route.js.nft.json +1 -1
  52. package/.next/server/app/api/sessions/[id]/route.js +1 -1
  53. package/.next/server/app/api/sessions/[id]/route.js.nft.json +1 -1
  54. package/.next/server/app/api/sessions/import/route.js +3 -3
  55. package/.next/server/app/api/sessions/import/route.js.nft.json +1 -1
  56. package/.next/server/app/api/sessions/route.js +1 -1
  57. package/.next/server/app/api/sessions/route.js.nft.json +1 -1
  58. package/.next/server/app/api/skills/route.js +2 -2
  59. package/.next/server/app/api/skills/route.js.nft.json +1 -1
  60. package/.next/server/app/api/update/route.js +2 -2
  61. package/.next/server/app/api/update/route.js.nft.json +1 -1
  62. package/.next/server/app/api/version/route.js +1 -1
  63. package/.next/server/app/api/version/route.js.nft.json +1 -1
  64. package/.next/server/app/api/web-auth/route.js +1 -1
  65. package/.next/server/app/api/workspaces/route.js +1 -1
  66. package/.next/server/app/api/workspaces/route.js.nft.json +1 -1
  67. package/.next/server/app/icon.svg/route.js +1 -1
  68. package/.next/server/app/index.html +1 -1
  69. package/.next/server/app/index.rsc +6 -9
  70. package/.next/server/app/index.segments/__PAGE__.segment.rsc +4 -7
  71. package/.next/server/app/index.segments/_full.segment.rsc +6 -9
  72. package/.next/server/app/index.segments/_tree.segment.rsc +2 -5
  73. package/.next/server/app/login/page.js +1 -1
  74. package/.next/server/app/login/page_client-reference-manifest.js +1 -1
  75. package/.next/server/app/login.html +1 -1
  76. package/.next/server/app/login.rsc +5 -8
  77. package/.next/server/app/login.segments/_full.segment.rsc +5 -8
  78. package/.next/server/app/login.segments/_tree.segment.rsc +2 -5
  79. package/.next/server/app/login.segments/login/__PAGE__.segment.rsc +3 -6
  80. package/.next/server/app/page.js +1 -1
  81. package/.next/server/app/page_client-reference-manifest.js +1 -1
  82. package/.next/server/app-paths-manifest.json +8 -11
  83. package/.next/server/chunks/496.js +1 -1
  84. package/.next/server/chunks/532.js +1 -1
  85. package/.next/server/chunks/686.js +4 -8
  86. package/.next/server/middleware-build-manifest.js +1 -1
  87. package/.next/server/middleware-react-loadable-manifest.js +1 -1
  88. package/.next/server/pages/404.html +1 -1
  89. package/.next/server/pages/500.html +1 -1
  90. package/.next/server/server-reference-manifest.json +1 -1
  91. package/.next/static/chunks/2608.ec8ff1f5767c9056.js +1 -0
  92. package/.next/static/chunks/2716.93be8ad5c970c516.js +1 -0
  93. package/.next/static/chunks/4632.112d2e893d48d188.js +1 -0
  94. package/.next/static/chunks/4673.c1fb1580efc6ace7.js +1 -0
  95. package/.next/static/chunks/4686-f4a037d609cea3f2.js +1 -0
  96. package/.next/static/chunks/app/_global-error/page-f77e9ede9808b18e.js +1 -0
  97. package/.next/static/chunks/app/api/agent/[id]/events/route-f77e9ede9808b18e.js +1 -0
  98. package/.next/static/chunks/app/api/agent/[id]/route-f77e9ede9808b18e.js +1 -0
  99. package/.next/static/chunks/app/api/agent/[id]/tree/route-f77e9ede9808b18e.js +1 -0
  100. package/.next/static/chunks/app/api/agent/new/route-f77e9ede9808b18e.js +1 -0
  101. package/.next/static/chunks/app/api/config/route-f77e9ede9808b18e.js +1 -0
  102. package/.next/static/chunks/app/api/files/route-f77e9ede9808b18e.js +1 -0
  103. package/.next/static/chunks/app/api/git/route-f77e9ede9808b18e.js +1 -0
  104. package/.next/static/chunks/app/api/growth/route-f77e9ede9808b18e.js +1 -0
  105. package/.next/static/chunks/app/api/health/route-f77e9ede9808b18e.js +1 -0
  106. package/.next/static/chunks/app/api/models/route-f77e9ede9808b18e.js +1 -0
  107. package/.next/static/chunks/app/api/pi-settings/route-f77e9ede9808b18e.js +1 -0
  108. package/.next/static/chunks/app/api/plugins/route-f77e9ede9808b18e.js +1 -0
  109. package/.next/static/chunks/app/api/prompts/route-f77e9ede9808b18e.js +1 -0
  110. package/.next/static/chunks/app/api/security/route-f77e9ede9808b18e.js +1 -0
  111. package/.next/static/chunks/app/api/sessions/[id]/export/route-f77e9ede9808b18e.js +1 -0
  112. package/.next/static/chunks/app/api/sessions/[id]/route-f77e9ede9808b18e.js +1 -0
  113. package/.next/static/chunks/app/api/sessions/import/route-f77e9ede9808b18e.js +1 -0
  114. package/.next/static/chunks/app/api/sessions/route-f77e9ede9808b18e.js +1 -0
  115. package/.next/static/chunks/app/api/skills/route-f77e9ede9808b18e.js +1 -0
  116. package/.next/static/chunks/app/api/update/route-f77e9ede9808b18e.js +1 -0
  117. package/.next/static/chunks/app/api/version/route-f77e9ede9808b18e.js +1 -0
  118. package/.next/static/chunks/app/api/web-auth/route-f77e9ede9808b18e.js +1 -0
  119. package/.next/static/chunks/app/api/workspaces/route-f77e9ede9808b18e.js +1 -0
  120. package/.next/static/chunks/app/page-b51087831582ee37.js +1 -0
  121. package/.next/static/chunks/next/dist/client/components/builtin/app-error-f77e9ede9808b18e.js +1 -0
  122. package/.next/static/chunks/next/dist/client/components/builtin/forbidden-f77e9ede9808b18e.js +1 -0
  123. package/.next/static/chunks/next/dist/client/components/builtin/not-found-f77e9ede9808b18e.js +1 -0
  124. package/.next/static/chunks/next/dist/client/components/builtin/unauthorized-f77e9ede9808b18e.js +1 -0
  125. package/.next/static/chunks/webpack-c31263fd83d75ce6.js +1 -0
  126. package/.next/static/css/850c2fd130ffa2fc.css +1 -0
  127. package/.next/static/zsynuO_9Kx6nrXgkTUJ04/_buildManifest.js +1 -0
  128. package/.next/types/routes.d.ts +1 -4
  129. package/.next/types/validator.ts +0 -27
  130. package/README.md +17 -29
  131. package/assets/archive.jpg +0 -0
  132. package/assets/growth-1.jpg +0 -0
  133. package/assets/growth-2.jpg +0 -0
  134. package/assets/import.jpg +0 -0
  135. package/assets/main.jpg +0 -0
  136. package/assets/outline.jpg +0 -0
  137. package/assets/prompts-1.jpg +0 -0
  138. package/assets/prompts-2.jpg +0 -0
  139. package/assets/providers-1.jpg +0 -0
  140. package/assets/providers-2.jpg +0 -0
  141. package/assets/providers-3.jpg +0 -0
  142. package/assets/trace-1.jpg +0 -0
  143. package/assets/trace-2.png +0 -0
  144. package/assets/trace-3.png +0 -0
  145. package/assets/trace-4.png +0 -0
  146. package/assets/viewer-1.jpg +0 -0
  147. package/assets/viewer-2.jpg +0 -0
  148. package/bin/pi.js +50 -0
  149. package/next.config.ts +32 -7
  150. package/package.json +4 -9
  151. package/scripts/launcher.mjs +1 -1
  152. package/scripts/pick-folder.ps1 +2 -11
  153. package/scripts/release.mjs +31 -11
  154. package/scripts/verify-package.mjs +0 -53
  155. package/src/app/api/config/route.ts +1 -4
  156. package/src/app/api/growth/route.ts +14 -14
  157. package/src/app/api/models/route.ts +2 -1
  158. package/src/app/api/security/route.ts +3 -8
  159. package/src/app/api/update/route.ts +2 -8
  160. package/src/app/globals.css +90 -777
  161. package/src/app/layout.tsx +6 -13
  162. package/src/components/AppShell.tsx +229 -521
  163. package/src/components/ChatInput.tsx +26 -153
  164. package/src/components/ChatWindow.tsx +231 -51
  165. package/src/components/ContextMeter.tsx +17 -11
  166. package/src/components/FileViewer.tsx +11 -10
  167. package/src/components/GitPanel.tsx +11 -13
  168. package/src/components/ModelSelector.tsx +6 -19
  169. package/src/components/PiMark.tsx +38 -5
  170. package/src/components/ProjectPanel.tsx +111 -95
  171. package/src/components/PromptPanel.tsx +51 -132
  172. package/src/components/SessionImportSection.tsx +37 -53
  173. package/src/components/SessionSidebar.tsx +57 -159
  174. package/src/components/SettingsPanel.tsx +193 -330
  175. package/src/components/icons.tsx +0 -23
  176. package/src/hooks/useGrowth.ts +123 -156
  177. package/src/hooks/usePiWeb.ts +15 -122
  178. package/src/i18n.tsx +42 -98
  179. package/src/lib/agent-manager.ts +21 -187
  180. package/src/lib/command-validation.ts +1 -9
  181. package/src/lib/growth-service.ts +390 -166
  182. package/src/lib/growth-tracker.ts +64 -264
  183. package/src/lib/growth-turns.ts +31 -1
  184. package/src/lib/models/model-scope.ts +15 -0
  185. package/src/lib/models-service.ts +16 -0
  186. package/src/lib/pi-settings.ts +7 -0
  187. package/src/lib/pi.ts +2 -3
  188. package/src/lib/session-import/claude.ts +2 -13
  189. package/src/lib/session-import/codex.ts +8 -44
  190. package/src/lib/session-import/files.ts +0 -14
  191. package/src/lib/session-import/grok.ts +24 -54
  192. package/src/lib/session-import/index.ts +0 -5
  193. package/src/lib/session-import/types.ts +0 -12
  194. package/src/lib/session-import/writer.ts +3 -8
  195. package/src/lib/skills-service.ts +9 -16
  196. package/src/lib/theme.ts +1 -68
  197. package/src/lib/trajectory.ts +0 -1
  198. package/src/lib/types.ts +27 -36
  199. package/tsconfig.json +2 -1
  200. package/.next/server/app/api/swarm/[id]/route.js +0 -1
  201. package/.next/server/app/api/swarm/[id]/route.js.nft.json +0 -1
  202. package/.next/server/app/api/swarm/[id]/route_client-reference-manifest.js +0 -1
  203. package/.next/server/app/api/swarm/route.js +0 -1
  204. package/.next/server/app/api/swarm/route.js.nft.json +0 -1
  205. package/.next/server/app/api/swarm/route_client-reference-manifest.js +0 -1
  206. package/.next/server/app/api/tests/route.js +0 -2
  207. package/.next/server/app/api/tests/route.js.nft.json +0 -1
  208. package/.next/server/app/api/tests/route_client-reference-manifest.js +0 -1
  209. package/.next/server/chunks/757.js +0 -1
  210. package/.next/server/chunks/775.js +0 -3
  211. package/.next/static/0t1jBUAuVaTFTXxRyIo3q/_buildManifest.js +0 -1
  212. package/.next/static/chunks/2608.43c58236c9cce8e6.js +0 -1
  213. package/.next/static/chunks/2716.4ec42df1d51354c9.js +0 -1
  214. package/.next/static/chunks/4632.62139b565b657aac.js +0 -1
  215. package/.next/static/chunks/4673.7796104395deb8d7.js +0 -1
  216. package/.next/static/chunks/4686-17f21a006739a596.js +0 -1
  217. package/.next/static/chunks/7577.10af9bb661652da8.js +0 -1
  218. package/.next/static/chunks/8866.38ec4ac4ee5a1b74.js +0 -1
  219. package/.next/static/chunks/app/_global-error/page-5148173b3f55e415.js +0 -1
  220. package/.next/static/chunks/app/api/agent/[id]/events/route-5148173b3f55e415.js +0 -1
  221. package/.next/static/chunks/app/api/agent/[id]/route-5148173b3f55e415.js +0 -1
  222. package/.next/static/chunks/app/api/agent/[id]/tree/route-5148173b3f55e415.js +0 -1
  223. package/.next/static/chunks/app/api/agent/new/route-5148173b3f55e415.js +0 -1
  224. package/.next/static/chunks/app/api/config/route-5148173b3f55e415.js +0 -1
  225. package/.next/static/chunks/app/api/files/route-5148173b3f55e415.js +0 -1
  226. package/.next/static/chunks/app/api/git/route-5148173b3f55e415.js +0 -1
  227. package/.next/static/chunks/app/api/growth/route-5148173b3f55e415.js +0 -1
  228. package/.next/static/chunks/app/api/health/route-5148173b3f55e415.js +0 -1
  229. package/.next/static/chunks/app/api/models/route-5148173b3f55e415.js +0 -1
  230. package/.next/static/chunks/app/api/pi-settings/route-5148173b3f55e415.js +0 -1
  231. package/.next/static/chunks/app/api/plugins/route-5148173b3f55e415.js +0 -1
  232. package/.next/static/chunks/app/api/prompts/route-5148173b3f55e415.js +0 -1
  233. package/.next/static/chunks/app/api/security/route-5148173b3f55e415.js +0 -1
  234. package/.next/static/chunks/app/api/sessions/[id]/export/route-5148173b3f55e415.js +0 -1
  235. package/.next/static/chunks/app/api/sessions/[id]/route-5148173b3f55e415.js +0 -1
  236. package/.next/static/chunks/app/api/sessions/import/route-5148173b3f55e415.js +0 -1
  237. package/.next/static/chunks/app/api/sessions/route-5148173b3f55e415.js +0 -1
  238. package/.next/static/chunks/app/api/skills/route-5148173b3f55e415.js +0 -1
  239. package/.next/static/chunks/app/api/swarm/[id]/route-5148173b3f55e415.js +0 -1
  240. package/.next/static/chunks/app/api/swarm/route-5148173b3f55e415.js +0 -1
  241. package/.next/static/chunks/app/api/tests/route-5148173b3f55e415.js +0 -1
  242. package/.next/static/chunks/app/api/update/route-5148173b3f55e415.js +0 -1
  243. package/.next/static/chunks/app/api/version/route-5148173b3f55e415.js +0 -1
  244. package/.next/static/chunks/app/api/web-auth/route-5148173b3f55e415.js +0 -1
  245. package/.next/static/chunks/app/api/workspaces/route-5148173b3f55e415.js +0 -1
  246. package/.next/static/chunks/app/page-14379b8060d5cf07.js +0 -1
  247. package/.next/static/chunks/next/dist/client/components/builtin/app-error-5148173b3f55e415.js +0 -1
  248. package/.next/static/chunks/next/dist/client/components/builtin/forbidden-5148173b3f55e415.js +0 -1
  249. package/.next/static/chunks/next/dist/client/components/builtin/not-found-5148173b3f55e415.js +0 -1
  250. package/.next/static/chunks/next/dist/client/components/builtin/unauthorized-5148173b3f55e415.js +0 -1
  251. package/.next/static/chunks/webpack-d1a69ad9edb38b11.js +0 -1
  252. package/.next/static/css/d0a0162cb481abe8.css +0 -1
  253. package/.next/types/app/api/swarm/[id]/route.ts +0 -353
  254. package/.next/types/app/api/swarm/route.ts +0 -353
  255. package/.next/types/app/api/tests/route.ts +0 -353
  256. package/assets/archive.png +0 -0
  257. package/assets/growth-1.png +0 -0
  258. package/assets/growth-2.png +0 -0
  259. package/assets/import.png +0 -0
  260. package/assets/main.png +0 -0
  261. package/assets/outline.png +0 -0
  262. package/assets/prompts-1.png +0 -0
  263. package/assets/prompts-2.png +0 -0
  264. package/assets/providers-1.png +0 -0
  265. package/assets/providers-2.png +0 -0
  266. package/assets/providers-3.png +0 -0
  267. package/assets/trace-1.png +0 -0
  268. package/assets/viewer-1.png +0 -0
  269. package/assets/viewer-2.png +0 -0
  270. package/scripts/managed-niubash-assets.mjs +0 -146
  271. package/scripts/prepare-niubash-packages.mjs +0 -182
  272. package/scripts/run-test-file.mjs +0 -34
  273. package/scripts/smoke-managed-niubash.mjs +0 -62
  274. package/scripts/verify-release-config.mjs +0 -24
  275. package/src/app/api/swarm/[id]/route.ts +0 -28
  276. package/src/app/api/swarm/route.ts +0 -24
  277. package/src/app/api/tests/route.ts +0 -27
  278. package/src/components/SwarmCoordinatorPod.tsx +0 -1021
  279. package/src/components/TestInspectorPod.tsx +0 -549
  280. package/src/lib/delegation.ts +0 -93
  281. package/src/lib/growth-rounds.ts +0 -84
  282. package/src/lib/managed-niubash.ts +0 -231
  283. package/src/lib/runtime-activity.ts +0 -27
  284. package/src/lib/session-import/lock.ts +0 -25
  285. package/src/lib/swarm-service.ts +0 -371
  286. package/src/lib/test-run-service.ts +0 -122
  287. package/src/lib/workflow.ts +0 -55
  288. /package/.next/static/{0t1jBUAuVaTFTXxRyIo3q → zsynuO_9Kx6nrXgkTUJ04}/_ssgManifest.js +0 -0
@@ -8,22 +8,16 @@
8
8
  */
9
9
  import { useEffect, useRef, useState } from "react";
10
10
  import {
11
- IconCheckOutline14,
12
- IconChevronRight14,
13
- IconCloseOutline14,
14
11
  IconFileOutline16,
15
12
  IconSendArrowUp14,
16
13
  IconStopFill16,
17
14
  IconTerminalOutline14,
18
- IconWorkflowAgent16,
19
- IconWorkflowGoal16,
20
- IconWorkflowPlan16,
21
15
  } from "@/components/icons";
22
16
  import { ContextMeter } from "@/components/ContextMeter";
23
17
  import { ModelSelector, type ModelChoice } from "@/components/ModelSelector";
24
18
  import { useI18n } from "@/i18n";
25
19
  import { otherBehavior, useEnterBehavior } from "@/lib/enter-behavior";
26
- import type { ImageAttachment, WorkflowMode, WorkflowState } from "@/lib/types";
20
+ import type { ImageAttachment } from "@/lib/types";
27
21
 
28
22
  export interface SlashCommand {
29
23
  name: string;
@@ -62,9 +56,6 @@ export function ChatInput({
62
56
  thinkingLevel,
63
57
  thinkingLevels,
64
58
  models,
65
- modelLoading,
66
- modelLoadError,
67
- onRetryModels,
68
59
  providerNames,
69
60
  authByProvider,
70
61
  queue,
@@ -77,9 +68,6 @@ export function ChatInput({
77
68
  onSelectModel,
78
69
  onSelectLevel,
79
70
  onClearQueue,
80
- workflow,
81
- onWorkflowModeChange,
82
- onApprovePlan,
83
71
  draft,
84
72
  initialDraft,
85
73
  onDraftChange,
@@ -107,9 +95,6 @@ export function ChatInput({
107
95
  thinkingLevel?: string;
108
96
  thinkingLevels: string[];
109
97
  models: ModelChoice[];
110
- modelLoading?: boolean;
111
- modelLoadError?: string | null;
112
- onRetryModels?: () => void;
113
98
  providerNames: Record<string, string>;
114
99
  authByProvider: Record<string, boolean>;
115
100
  queue: { steering: string[]; followUp: string[] };
@@ -124,9 +109,6 @@ export function ChatInput({
124
109
  onSelectLevel: (level: string) => void;
125
110
  /** 清空队列并返回被清掉的文本(取回编辑 / 丢弃都走它) */
126
111
  onClearQueue?: () => Promise<QueueResult | void> | void;
127
- workflow?: WorkflowState;
128
- onWorkflowModeChange?: (mode: WorkflowMode) => void | Promise<{ success?: boolean } | void>;
129
- onApprovePlan?: () => void | Promise<{ success?: boolean; error?: string } | void>;
130
112
  /** Parent-owned, session-scoped draft. Async work always updates this same target. */
131
113
  draft?: ChatDraft;
132
114
  initialDraft?: ChatDraft;
@@ -164,70 +146,15 @@ export function ChatInput({
164
146
  const [dragActive, setDragActive] = useState(false);
165
147
  const dragDepth = useRef(0);
166
148
  const [modelOpen, setModelOpen] = useState(false);
167
- const [workflowOpen, setWorkflowOpen] = useState(false);
168
- const [pendingWorkflowMode, setPendingWorkflowMode] = useState<WorkflowMode | null>(null);
169
- const [approvalPending, setApprovalPending] = useState(false);
170
- const [approvalError, setApprovalError] = useState("");
171
- const approvalInFlightRef = useRef(false);
172
- const workflowRequestRef = useRef(0);
173
- const workflowInFlightRef = useRef(false);
174
- const queuedWorkflowRef = useRef<{ mode: WorkflowMode; request: number } | null>(null);
175
149
  const [cmdIdx, setCmdIdx] = useState(0);
176
150
  const [cmdDismissed, setCmdDismissed] = useState(false);
177
151
  const taRef = useRef<HTMLTextAreaElement>(null);
178
152
  const wrapRef = useRef<HTMLDivElement>(null);
179
- const workflowRef = useRef<HTMLDivElement>(null);
180
153
  const { t } = useI18n();
181
154
  const isBlocked = !model?.id;
182
155
  const enterBehavior = useEnterBehavior();
183
156
  const queuedCount = queue.steering.length + queue.followUp.length;
184
157
  const [restoreTick, setRestoreTick] = useState(0);
185
- const activeWorkflowMode = pendingWorkflowMode ?? workflow?.mode ?? "agent";
186
-
187
- useEffect(() => {
188
- if (pendingWorkflowMode !== null && workflow?.mode === pendingWorkflowMode) setPendingWorkflowMode(null);
189
- }, [workflow?.mode, pendingWorkflowMode]);
190
- useEffect(() => { setApprovalError(""); }, [workflow?.mode, workflow?.planStatus, workflow?.planId]);
191
-
192
- const approvePlan = async () => {
193
- if (!onApprovePlan || approvalInFlightRef.current || isStreaming || disabled) return;
194
- approvalInFlightRef.current = true;
195
- setApprovalPending(true);
196
- setApprovalError("");
197
- try {
198
- const result = await onApprovePlan();
199
- if (result && result.success === false && mountedRef.current) setApprovalError(result.error || t.planApprovalFailed);
200
- } catch (error) {
201
- if (mountedRef.current) setApprovalError(error instanceof Error ? error.message : t.planApprovalFailed);
202
- } finally {
203
- approvalInFlightRef.current = false;
204
- if (mountedRef.current) setApprovalPending(false);
205
- }
206
- };
207
-
208
- const flushWorkflowMode = async () => {
209
- if (workflowInFlightRef.current || !queuedWorkflowRef.current || !onWorkflowModeChange) return;
210
- const { mode, request } = queuedWorkflowRef.current;
211
- queuedWorkflowRef.current = null;
212
- workflowInFlightRef.current = true;
213
- try {
214
- const result = await onWorkflowModeChange(mode);
215
- if (mountedRef.current && request === workflowRequestRef.current && result && result.success === false) setPendingWorkflowMode(null);
216
- } catch {
217
- if (mountedRef.current && request === workflowRequestRef.current) setPendingWorkflowMode(null);
218
- } finally {
219
- workflowInFlightRef.current = false;
220
- if (mountedRef.current && queuedWorkflowRef.current) void flushWorkflowMode();
221
- }
222
- };
223
-
224
- const selectWorkflowMode = (mode: WorkflowMode) => {
225
- if (!onWorkflowModeChange) return;
226
- const request = ++workflowRequestRef.current;
227
- setPendingWorkflowMode(mode);
228
- queuedWorkflowRef.current = { mode, request };
229
- void flushWorkflowMode();
230
- };
231
158
 
232
159
  useEffect(() => {
233
160
  mountedRef.current = true;
@@ -236,23 +163,6 @@ export function ChatInput({
236
163
  useEffect(() => {
237
164
  setAttachmentError(uploadFailure ?? "");
238
165
  }, [uploadFailure]);
239
- useEffect(() => {
240
- if (!workflowOpen) return;
241
- const closeOnPointer = (event: PointerEvent) => {
242
- if (!workflowRef.current?.contains(event.target as Node)) setWorkflowOpen(false);
243
- };
244
- const closeOnEscape = (event: KeyboardEvent) => {
245
- if (event.key !== "Escape") return;
246
- setWorkflowOpen(false);
247
- workflowRef.current?.querySelector<HTMLButtonElement>(".pw-workflow-add")?.focus();
248
- };
249
- document.addEventListener("pointerdown", closeOnPointer);
250
- document.addEventListener("keydown", closeOnEscape);
251
- return () => {
252
- document.removeEventListener("pointerdown", closeOnPointer);
253
- document.removeEventListener("keydown", closeOnEscape);
254
- };
255
- }, [workflowOpen]);
256
166
  useEffect(() => {
257
167
  autoSize();
258
168
  }, [text]);
@@ -494,35 +404,9 @@ export function ChatInput({
494
404
  }, []);
495
405
 
496
406
  const hasDraft = text.trim().length > 0 || images.length > 0 || uploads.length > 0;
497
- const workflowName = activeWorkflowMode === "plan" ? t.workflowPlan : activeWorkflowMode === "goal" ? t.workflowGoal : t.workflowAgent;
498
- const workflowPlaceholder = activeWorkflowMode === "plan" ? t.workflowPlanPlaceholder : activeWorkflowMode === "goal" ? t.workflowGoalPlaceholder : t.inputPlaceholder;
499
- const composerExpanded = text.length > 56 || text.includes("\n") || images.length > 0 || uploads.length > 0 || Boolean(adopted);
500
407
 
501
408
  return (
502
- <div ref={wrapRef} className="pw-composer-shell relative w-full" data-expanded={composerExpanded || undefined} data-testid="composer">
503
- {activeWorkflowMode === "plan" && workflow?.mode === "plan" && workflow.planStatus === "ready" && onApprovePlan && (
504
- <section className="pw-plan-ready" aria-label={t.planReady}>
505
- <div className="pw-plan-ready-content">
506
- <span className="pw-plan-ready-icon" aria-hidden="true"><IconWorkflowPlan16 size={16} /></span>
507
- <div className="pw-plan-ready-copy">
508
- <strong>{t.planReady}</strong>
509
- <span>{t.planReadyHint}</span>
510
- </div>
511
- </div>
512
- <div className="pw-plan-ready-actions">
513
- <button type="button" className="pw-plan-ready-refine" disabled={disabled || approvalPending} onClick={() => taRef.current?.focus()}>{t.planRefine}</button>
514
- <button type="button" className="pw-plan-ready-approve" disabled={isStreaming || disabled || approvalPending} onClick={() => { void approvePlan(); }}>{approvalPending ? t.planApproving : t.planApprove}<IconChevronRight14 size={14} aria-hidden="true" /></button>
515
- </div>
516
- {approvalError && <p className="pw-plan-ready-error" role="alert">{approvalError}</p>}
517
- </section>
518
- )}
519
- {activeWorkflowMode === "goal" && workflow?.mode === "goal" && workflow.goal && (
520
- <div className="pw-goal-active" title={workflow.goal}>
521
- <IconWorkflowGoal16 size={14} aria-hidden="true" />
522
- <span className="pw-goal-active-label">{t.goalActive}</span>
523
- <span className="pw-goal-active-text">{workflow.goal}</span>
524
- </div>
525
- )}
409
+ <div ref={wrapRef} className="relative w-full" data-testid="composer">
526
410
  {/* 排队中的消息(Claude Code 同款:列在输入卡上方;↑ 取回编辑,或直接丢弃) */}
527
411
  {queuedCount > 0 && (
528
412
  <div className="pw-queue">
@@ -634,8 +518,16 @@ export function ChatInput({
634
518
  )}
635
519
 
636
520
  {/* 卡片(玻璃态)—— 拖放由 document 级监听统一接管 */}
637
- <div className="pw-composer relative w-full" data-mode={activeWorkflowMode}>
638
- <div className="pw-composer-body flex items-start gap-1.5">
521
+ <div
522
+ className="relative w-full"
523
+ style={{
524
+ borderRadius: 22,
525
+ background: "var(--dsw-input-major)",
526
+ boxShadow: "var(--dsw-elevation-soft)",
527
+ border: "0.5px solid var(--dsw-border-l1)",
528
+ }}
529
+ >
530
+ <div className="px-4 pt-3 flex items-start gap-1.5">
639
531
  {adopted && (
640
532
  <button
641
533
  type="button"
@@ -663,7 +555,7 @@ export function ChatInput({
663
555
  value={text}
664
556
  disabled={disabled || isBlocked || sendBusy}
665
557
  rows={1}
666
- placeholder={adopted ? (adopted.argumentHint ?? workflowPlaceholder) : !disabled && isBlocked ? t.blockedComposer : workflowPlaceholder}
558
+ placeholder={adopted ? (adopted.argumentHint ?? t.inputPlaceholder) : !disabled && isBlocked ? t.blockedComposer : t.inputPlaceholder}
667
559
  suppressHydrationWarning
668
560
  className="min-w-0 flex-1 resize-none"
669
561
  style={{ fontSize: "var(--piweb-chat-font-size, var(--dsh-content-font-size))", lineHeight: 1.55 }}
@@ -739,35 +631,19 @@ export function ChatInput({
739
631
  </div>
740
632
 
741
633
  {/* 按钮行:左侧只保留命令入口;图片通过拖放或粘贴添加。 */}
742
- <div className="pw-composer-toolbar flex items-center gap-2">
743
- {workflow && onWorkflowModeChange && (
744
- <div ref={workflowRef} className="relative flex shrink-0 items-center gap-2">
745
- <button type="button" className="pw-workflow-add" disabled={isStreaming || disabled} aria-label={`${t.workflowMenu}: ${workflowName}`} title={t.workflowMenu} aria-haspopup="menu" aria-expanded={workflowOpen} onClick={() => setWorkflowOpen((open) => !open)}>
746
- <span className="pw-workflow-plus" aria-hidden="true" />
747
- </button>
748
- {activeWorkflowMode !== "agent" && (
749
- <span className="pw-workflow-current" data-mode={activeWorkflowMode}>
750
- <span className="pw-workflow-current-icon" aria-hidden="true">{activeWorkflowMode === "plan" ? <IconWorkflowPlan16 size={14} /> : <IconWorkflowGoal16 size={14} />}</span>
751
- <span>{workflowName}</span>
752
- <button type="button" className="pw-workflow-current-dismiss" disabled={isStreaming || disabled} aria-label={`${t.workflowClear}: ${workflowName}`} title={t.workflowClear} onClick={() => { selectWorkflowMode("agent"); taRef.current?.focus(); }}><IconCloseOutline14 size={10} aria-hidden="true" /></button>
753
- </span>
754
- )}
755
- {workflowOpen && (
756
- <div className="popover pw-workflow-menu" role="menu">
757
- <div className="pw-workflow-menu-label">{t.workflowMenu}</div>
758
- {(["agent", "plan", "goal"] as const).map((mode) => (
759
- <button key={mode} type="button" className="pw-workflow-option" data-mode={mode} role="menuitemradio" aria-checked={activeWorkflowMode === mode} onClick={() => { setWorkflowOpen(false); selectWorkflowMode(mode); taRef.current?.focus(); }}>
760
- <span className="pw-workflow-option-icon" aria-hidden="true">{mode === "agent" ? <IconWorkflowAgent16 size={16} /> : mode === "plan" ? <IconWorkflowPlan16 size={16} /> : <IconWorkflowGoal16 size={16} />}</span>
761
- <strong className="pw-workflow-option-name">{mode === "agent" ? t.workflowAgent : mode === "plan" ? t.workflowPlan : t.workflowGoal}</strong>
762
- <span className="pw-workflow-option-description">{mode === "agent" ? t.workflowAgentHint : mode === "plan" ? t.workflowPlanHint : t.workflowGoalHint}</span>
763
- <IconCheckOutline14 className="pw-workflow-option-check" size={14} aria-hidden="true" />
764
- </button>
765
- ))}
766
- </div>
767
- )}
768
- </div>
769
- )}
770
- {!workflow && <div className="flex-1" />}
634
+ <div
635
+ className="flex items-center gap-2"
636
+ style={{
637
+ paddingLeft: 8,
638
+ paddingRight: 12,
639
+ paddingBottom: 8,
640
+ paddingTop: 4,
641
+ height: 40,
642
+ containerType: "inline-size",
643
+ }}
644
+ >
645
+ {/* 命令菜单通过输入 / 触发(dsh 同款),不再提供 + 启动按钮 */}
646
+ <div className="flex-1" />
771
647
 
772
648
  {/* 模型芯片(右组,dsh 分组菜单;/model 命令可受控打开) */}
773
649
  <ModelSelector
@@ -775,9 +651,6 @@ export function ChatInput({
775
651
  thinkingLevel={thinkingLevel}
776
652
  thinkingLevels={thinkingLevels}
777
653
  models={models}
778
- modelLoading={modelLoading}
779
- modelLoadError={modelLoadError}
780
- onRetryModels={onRetryModels}
781
654
  providerNames={providerNames}
782
655
  authByProvider={authByProvider}
783
656
  onSelectModel={onSelectModel}