@qlingzzy/qling 1.0.0 → 1.1.0

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 (254) hide show
  1. package/CHANGELOG.md +154 -0
  2. package/README.en.md +82 -17
  3. package/README.md +15 -7
  4. package/dist/agent/main-loop.d.ts +120 -0
  5. package/dist/agent/main-loop.d.ts.map +1 -0
  6. package/dist/agent/main-loop.js +279 -0
  7. package/dist/agent/subtask-parallel.d.ts +29 -0
  8. package/dist/agent/subtask-parallel.d.ts.map +1 -0
  9. package/dist/agent/subtask-parallel.js +107 -0
  10. package/dist/agent/subtask.d.ts +13 -0
  11. package/dist/agent/subtask.d.ts.map +1 -1
  12. package/dist/agent/subtask.js +79 -24
  13. package/dist/agent/system-prompt.d.ts +39 -0
  14. package/dist/agent/system-prompt.d.ts.map +1 -0
  15. package/dist/agent/system-prompt.js +89 -0
  16. package/dist/agent/tool-orchestrator.d.ts +66 -0
  17. package/dist/agent/tool-orchestrator.d.ts.map +1 -0
  18. package/dist/agent/tool-orchestrator.js +355 -0
  19. package/dist/agent-loop.d.ts +29 -16
  20. package/dist/agent-loop.d.ts.map +1 -1
  21. package/dist/agent-loop.js +262 -807
  22. package/dist/agents/roles.d.ts +57 -0
  23. package/dist/agents/roles.d.ts.map +1 -0
  24. package/dist/agents/roles.js +198 -0
  25. package/dist/commands/agents.d.ts.map +1 -1
  26. package/dist/commands/agents.js +17 -3
  27. package/dist/commands/claude-style.d.ts.map +1 -1
  28. package/dist/commands/claude-style.js +19 -10
  29. package/dist/commands/help.d.ts.map +1 -1
  30. package/dist/commands/help.js +3 -2
  31. package/dist/commands/index.d.ts.map +1 -1
  32. package/dist/commands/index.js +6 -0
  33. package/dist/commands/mode.d.ts +16 -0
  34. package/dist/commands/mode.d.ts.map +1 -0
  35. package/dist/commands/mode.js +67 -0
  36. package/dist/commands/recover.d.ts +3 -0
  37. package/dist/commands/recover.d.ts.map +1 -0
  38. package/dist/commands/recover.js +69 -0
  39. package/dist/commands/runtime.d.ts +2 -0
  40. package/dist/commands/runtime.d.ts.map +1 -1
  41. package/dist/commands/runtime.js +2 -0
  42. package/dist/commands/trace.d.ts +3 -0
  43. package/dist/commands/trace.d.ts.map +1 -0
  44. package/dist/commands/trace.js +45 -0
  45. package/dist/commands/verify.js +2 -2
  46. package/dist/config-report.d.ts +0 -1
  47. package/dist/config-report.d.ts.map +1 -1
  48. package/dist/config-report.js +1 -2
  49. package/dist/config.d.ts +0 -1
  50. package/dist/config.d.ts.map +1 -1
  51. package/dist/config.js +0 -1
  52. package/dist/context-report.d.ts +13 -7
  53. package/dist/context-report.d.ts.map +1 -1
  54. package/dist/context-report.js +64 -61
  55. package/dist/context-tool-hygiene.d.ts +36 -0
  56. package/dist/context-tool-hygiene.d.ts.map +1 -0
  57. package/dist/context-tool-hygiene.js +125 -0
  58. package/dist/dashboard/client.d.ts +2 -0
  59. package/dist/dashboard/client.d.ts.map +1 -0
  60. package/dist/dashboard/client.js +305 -0
  61. package/dist/dashboard/model.d.ts +13 -0
  62. package/dist/dashboard/model.d.ts.map +1 -0
  63. package/dist/dashboard/model.js +112 -0
  64. package/dist/dashboard/page.d.ts +3 -0
  65. package/dist/dashboard/page.d.ts.map +1 -0
  66. package/dist/dashboard/page.js +204 -0
  67. package/dist/dashboard/types.d.ts +63 -0
  68. package/dist/dashboard/types.d.ts.map +1 -0
  69. package/dist/dashboard/types.js +1 -0
  70. package/dist/dashboard-server.d.ts +24 -4
  71. package/dist/dashboard-server.d.ts.map +1 -1
  72. package/dist/dashboard-server.js +397 -302
  73. package/dist/discovery-registry.d.ts +17 -3
  74. package/dist/discovery-registry.d.ts.map +1 -1
  75. package/dist/discovery-registry.js +78 -3
  76. package/dist/doctor.d.ts +8 -0
  77. package/dist/doctor.d.ts.map +1 -1
  78. package/dist/doctor.js +116 -0
  79. package/dist/eval/llm-tasks.d.ts +5 -0
  80. package/dist/eval/llm-tasks.d.ts.map +1 -0
  81. package/dist/eval/llm-tasks.js +125 -0
  82. package/dist/eval/repo-tasks.d.ts +12 -0
  83. package/dist/eval/repo-tasks.d.ts.map +1 -0
  84. package/dist/eval/repo-tasks.js +220 -0
  85. package/dist/eval/runner.d.ts +3 -1
  86. package/dist/eval/runner.d.ts.map +1 -1
  87. package/dist/eval/runner.js +23 -4
  88. package/dist/eval/tasks.d.ts.map +1 -1
  89. package/dist/eval/tasks.js +186 -0
  90. package/dist/eval/types.d.ts +8 -5
  91. package/dist/eval/types.d.ts.map +1 -1
  92. package/dist/execution/event-bus.d.ts +44 -0
  93. package/dist/execution/event-bus.d.ts.map +1 -0
  94. package/dist/execution/event-bus.js +76 -0
  95. package/dist/execution/failure-classifier.d.ts +11 -0
  96. package/dist/execution/failure-classifier.d.ts.map +1 -0
  97. package/dist/execution/failure-classifier.js +66 -0
  98. package/dist/execution/progress-detector.d.ts +3 -0
  99. package/dist/execution/progress-detector.d.ts.map +1 -0
  100. package/dist/execution/progress-detector.js +23 -0
  101. package/dist/execution/recovery-controller.d.ts +24 -0
  102. package/dist/execution/recovery-controller.d.ts.map +1 -0
  103. package/dist/execution/recovery-controller.js +114 -0
  104. package/dist/execution/recovery-messages.d.ts +24 -0
  105. package/dist/execution/recovery-messages.d.ts.map +1 -0
  106. package/dist/execution/recovery-messages.js +48 -0
  107. package/dist/execution/recovery-metrics.d.ts +16 -0
  108. package/dist/execution/recovery-metrics.d.ts.map +1 -0
  109. package/dist/execution/recovery-metrics.js +73 -0
  110. package/dist/execution/recovery-strategy-planner.d.ts +6 -0
  111. package/dist/execution/recovery-strategy-planner.d.ts.map +1 -0
  112. package/dist/execution/recovery-strategy-planner.js +24 -0
  113. package/dist/execution/run-trace-store.d.ts +29 -0
  114. package/dist/execution/run-trace-store.d.ts.map +1 -0
  115. package/dist/execution/run-trace-store.js +140 -0
  116. package/dist/execution/staged-verifier.d.ts +33 -0
  117. package/dist/execution/staged-verifier.d.ts.map +1 -0
  118. package/dist/execution/staged-verifier.js +39 -0
  119. package/dist/execution/types.d.ts +58 -0
  120. package/dist/execution/types.d.ts.map +1 -0
  121. package/dist/execution/types.js +1 -0
  122. package/dist/execution/verification-loop.d.ts +58 -0
  123. package/dist/execution/verification-loop.d.ts.map +1 -0
  124. package/dist/execution/verification-loop.js +195 -0
  125. package/dist/execution/verification-stages.d.ts +17 -0
  126. package/dist/execution/verification-stages.d.ts.map +1 -0
  127. package/dist/execution/verification-stages.js +102 -0
  128. package/dist/help-topics.d.ts.map +1 -1
  129. package/dist/help-topics.js +11 -0
  130. package/dist/index.js +0 -8
  131. package/dist/lsp/ts-service.d.ts +36 -0
  132. package/dist/lsp/ts-service.d.ts.map +1 -0
  133. package/dist/lsp/ts-service.js +291 -0
  134. package/dist/memory/lifecycle.d.ts +19 -0
  135. package/dist/memory/lifecycle.d.ts.map +1 -0
  136. package/dist/memory/lifecycle.js +53 -0
  137. package/dist/memory.d.ts +0 -16
  138. package/dist/memory.d.ts.map +1 -1
  139. package/dist/memory.js +0 -36
  140. package/dist/metrics/collector.d.ts +7 -0
  141. package/dist/metrics/collector.d.ts.map +1 -1
  142. package/dist/metrics/collector.js +60 -0
  143. package/dist/mission/manager.d.ts +1 -0
  144. package/dist/mission/manager.d.ts.map +1 -1
  145. package/dist/mission/manager.js +9 -0
  146. package/dist/mission/progress-notify.d.ts +39 -0
  147. package/dist/mission/progress-notify.d.ts.map +1 -0
  148. package/dist/mission/progress-notify.js +386 -0
  149. package/dist/pipeline/hooks.d.ts +1 -1
  150. package/dist/pipeline/hooks.d.ts.map +1 -1
  151. package/dist/pipeline/hooks.js +1 -0
  152. package/dist/pipeline/sections.d.ts +8 -4
  153. package/dist/pipeline/sections.d.ts.map +1 -1
  154. package/dist/pipeline/sections.js +70 -27
  155. package/dist/pipeline/verification.d.ts +1 -0
  156. package/dist/pipeline/verification.d.ts.map +1 -1
  157. package/dist/pipeline/verification.js +10 -7
  158. package/dist/providers/llm-client.d.ts +38 -0
  159. package/dist/providers/llm-client.d.ts.map +1 -0
  160. package/dist/providers/llm-client.js +105 -0
  161. package/dist/sdk.d.ts +1 -0
  162. package/dist/sdk.d.ts.map +1 -1
  163. package/dist/sdk.js +1 -0
  164. package/dist/session/durable-session-supervisor.d.ts.map +1 -1
  165. package/dist/session/durable-session-supervisor.js +13 -6
  166. package/dist/session/session-persistence.d.ts +29 -0
  167. package/dist/session/session-persistence.d.ts.map +1 -0
  168. package/dist/session/session-persistence.js +45 -0
  169. package/dist/session/session-scheduler.d.ts +8 -1
  170. package/dist/session/session-scheduler.d.ts.map +1 -1
  171. package/dist/session/session-scheduler.js +33 -4
  172. package/dist/session-task-report.d.ts +1 -0
  173. package/dist/session-task-report.d.ts.map +1 -1
  174. package/dist/session-task-report.js +2 -1
  175. package/dist/shortcuts.d.ts.map +1 -1
  176. package/dist/shortcuts.js +1 -0
  177. package/dist/skills/registry.d.ts.map +1 -1
  178. package/dist/skills/registry.js +10 -0
  179. package/dist/skills/security-scan.d.ts +15 -0
  180. package/dist/skills/security-scan.d.ts.map +1 -0
  181. package/dist/skills/security-scan.js +95 -0
  182. package/dist/skills/types.d.ts +2 -0
  183. package/dist/skills/types.d.ts.map +1 -1
  184. package/dist/statusline.d.ts +3 -3
  185. package/dist/statusline.d.ts.map +1 -1
  186. package/dist/statusline.js +9 -17
  187. package/dist/token-usage.d.ts +27 -0
  188. package/dist/token-usage.d.ts.map +1 -0
  189. package/dist/token-usage.js +107 -0
  190. package/dist/tools/bash.d.ts.map +1 -1
  191. package/dist/tools/bash.js +5 -3
  192. package/dist/tools/browser-act-session.d.ts +48 -0
  193. package/dist/tools/browser-act-session.d.ts.map +1 -0
  194. package/dist/tools/browser-act-session.js +168 -0
  195. package/dist/tools/browser-act.d.ts +14 -0
  196. package/dist/tools/browser-act.d.ts.map +1 -0
  197. package/dist/tools/browser-act.js +297 -0
  198. package/dist/tools/code-symbols.d.ts +35 -0
  199. package/dist/tools/code-symbols.d.ts.map +1 -0
  200. package/dist/tools/code-symbols.js +257 -0
  201. package/dist/tools/index.d.ts +4 -1
  202. package/dist/tools/index.d.ts.map +1 -1
  203. package/dist/tools/index.js +22 -2
  204. package/dist/tools/lsp.d.ts +13 -0
  205. package/dist/tools/lsp.d.ts.map +1 -0
  206. package/dist/tools/lsp.js +136 -0
  207. package/dist/tools/patch.d.ts +5 -0
  208. package/dist/tools/patch.d.ts.map +1 -1
  209. package/dist/tools/patch.js +25 -4
  210. package/dist/tools/search.d.ts +7 -0
  211. package/dist/tools/search.d.ts.map +1 -1
  212. package/dist/tools/search.js +20 -3
  213. package/dist/tools/skill.d.ts +2 -0
  214. package/dist/tools/skill.d.ts.map +1 -1
  215. package/dist/tools/skill.js +47 -14
  216. package/dist/tools/subtask.d.ts +3 -1
  217. package/dist/tools/subtask.d.ts.map +1 -1
  218. package/dist/tools/subtask.js +151 -56
  219. package/dist/tui/shell.d.ts +12 -0
  220. package/dist/tui/shell.d.ts.map +1 -1
  221. package/dist/tui/shell.js +36 -3
  222. package/dist/tui/streaming-repl.d.ts +1 -0
  223. package/dist/tui/streaming-repl.d.ts.map +1 -1
  224. package/dist/tui/streaming-repl.js +27 -4
  225. package/dist/tui/streaming-tui.d.ts +10 -0
  226. package/dist/tui/streaming-tui.d.ts.map +1 -1
  227. package/dist/tui/streaming-tui.js +70 -12
  228. package/dist/types.d.ts +0 -8
  229. package/dist/types.d.ts.map +1 -1
  230. package/dist/workflow-runtime.d.ts.map +1 -1
  231. package/dist/workflow-runtime.js +10 -2
  232. package/dist/workflow-types.d.ts +2 -0
  233. package/dist/workflow-types.d.ts.map +1 -1
  234. package/docs/install.md +29 -8
  235. package/docs/skills.md +56 -7
  236. package/docs/web-routing.md +83 -0
  237. package/package.json +18 -4
  238. package/scripts/dep-layers.mjs +275 -0
  239. package/scripts/eval-llm.mjs +27 -0
  240. package/scripts/eval-recovery.mjs +101 -0
  241. package/scripts/eval-tasks.mjs +20 -0
  242. package/scripts/validate-packaging.mjs +51 -0
  243. package/skills/examples/README.md +23 -0
  244. package/skills/examples/add-function/SKILL.md +31 -0
  245. package/skills/examples/fix-failing-test/SKILL.md +32 -0
  246. package/skills/examples/pr-summary/SKILL.md +34 -0
  247. package/skills/lifecycle-build/SKILL.md +22 -0
  248. package/skills/lifecycle-plan/SKILL.md +32 -0
  249. package/skills/lifecycle-review/SKILL.md +25 -0
  250. package/skills/lifecycle-ship/SKILL.md +22 -0
  251. package/skills/lifecycle-spec/SKILL.md +24 -0
  252. package/skills/lifecycle-test/SKILL.md +21 -0
  253. package/skills/opencli/SKILL.md +222 -0
  254. package/skills/qling.md +14 -3
@@ -2,6 +2,8 @@ export interface SkillMeta {
2
2
  name: string;
3
3
  description: string;
4
4
  tags: string[];
5
+ /** 触发关键词/场景,仅进入索引,不进正文 */
6
+ triggers: string[];
5
7
  path: string;
6
8
  }
7
9
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/skills/types.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/skills/types.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,0BAA0B;IAC1B,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;CACd"}
@@ -9,8 +9,9 @@ export interface StatusLineSnapshot {
9
9
  goalStatus: string | null;
10
10
  activeTasks: number;
11
11
  tokens: number;
12
- tokenSource?: "provider" | "estimate" | "unknown";
13
- maxTokens?: number | null;
12
+ promptTokens?: number;
13
+ completionTokens?: number;
14
+ tokenSource?: "provider" | "unknown";
14
15
  costPer1kTokens?: number | null;
15
16
  inputQueue?: StatusLineInputQueueSnapshot;
16
17
  }
@@ -23,7 +24,6 @@ export interface LocalStatusLineSnapshotOptions {
23
24
  workspaceDir?: string | null;
24
25
  model?: string | null;
25
26
  permissionMode?: string | null;
26
- maxTokens?: number | null;
27
27
  costPer1kTokens?: number | null;
28
28
  }
29
29
  export declare function resolveGitBranch(workspaceDir?: string): string | null;
@@ -1 +1 @@
1
- {"version":3,"file":"statusline.d.ts","sourceRoot":"","sources":["../src/statusline.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAGjE,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,mBAAmB;IACnB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,UAAU,GAAG,UAAU,GAAG,SAAS,CAAC;IAClD,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,UAAU,CAAC,EAAE,4BAA4B,CAAC;CAC3C;AAED,MAAM,WAAW,4BAA4B;IAC3C,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,8BAA8B;IAC7C,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACjC;AA4BD,wBAAgB,gBAAgB,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAWrE;AAED,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAG/D;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAa5E;AAiBD,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAEpE;AAmCD,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,kBAAkB,GAAG,MAAM,CAyBrE;AAED,wBAAgB,8BAA8B,CAAC,OAAO,EAAE,8BAA8B,GAAG,kBAAkB,CAc1G;AAED,wBAAsB,yBAAyB,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAkDzG;AAED,wBAAsB,eAAe,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,MAAM,CAAC,CAEnF"}
1
+ {"version":3,"file":"statusline.d.ts","sourceRoot":"","sources":["../src/statusline.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAGjE,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,mBAAmB;IACnB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,WAAW,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;IACrC,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,UAAU,CAAC,EAAE,4BAA4B,CAAC;CAC3C;AAED,MAAM,WAAW,4BAA4B;IAC3C,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,8BAA8B;IAC7C,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACjC;AA4BD,wBAAgB,gBAAgB,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAWrE;AAED,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAG/D;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAa5E;AAiBD,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAEpE;AAqBD,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,kBAAkB,GAAG,MAAM,CA4BrE;AAED,wBAAgB,8BAA8B,CAAC,OAAO,EAAE,8BAA8B,GAAG,kBAAkB,CAe1G;AAED,wBAAsB,yBAAyB,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAmDzG;AAED,wBAAsB,eAAe,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,MAAM,CAAC,CAEnF"}
@@ -80,15 +80,6 @@ function normalizePositiveNumber(value) {
80
80
  export function parseStatusLineCostPer1k(raw) {
81
81
  return normalizePositiveNumber(raw);
82
82
  }
83
- function formatContextUsage(tokens, maxTokens) {
84
- const used = Math.max(0, Math.floor(Number(tokens ?? 0)));
85
- const max = normalizePositiveNumber(maxTokens);
86
- if (!max)
87
- return `${used.toLocaleString()}/-`;
88
- const roundedMax = Math.floor(max);
89
- const pct = Math.round((used / roundedMax) * 100);
90
- return `${used.toLocaleString()}/${roundedMax.toLocaleString()}(${pct}%)`;
91
- }
92
83
  function formatCostEstimate(tokens, costPer1kTokens) {
93
84
  const costPer1k = normalizePositiveNumber(costPer1kTokens);
94
85
  if (!costPer1k)
@@ -98,11 +89,7 @@ function formatCostEstimate(tokens, costPer1kTokens) {
98
89
  return `≈$${estimate.toFixed(4)}`;
99
90
  }
100
91
  function normalizeTokenSource(value) {
101
- return value === "provider" || value === "estimate" ? value : "unknown";
102
- }
103
- function resolveTokenBudgetMax(agentLoop) {
104
- const value = agentLoop.getTokenBudget?.()?.maxTokens ?? agentLoop.tokenBudget?.maxTokens;
105
- return normalizePositiveNumber(value);
92
+ return value === "provider" ? "provider" : "unknown";
106
93
  }
107
94
  function formatSessionMode(mode) {
108
95
  const m = String(mode ?? "").trim().toLowerCase();
@@ -119,6 +106,8 @@ export function formatStatusLine(snapshot) {
119
106
  const permission = formatPermissionMode(snapshot.permissionMode);
120
107
  const sessionMode = formatSessionMode(snapshot.sessionMode);
121
108
  const cost = formatCostEstimate(snapshot.tokens, snapshot.costPer1kTokens);
109
+ const prompt = Math.max(0, Math.floor(Number(snapshot.promptTokens ?? 0)));
110
+ const completion = Math.max(0, Math.floor(Number(snapshot.completionTokens ?? 0)));
122
111
  const parts = [
123
112
  `模型=${snapshot.model || "未知"}`,
124
113
  `模式=${sessionMode}`,
@@ -128,8 +117,9 @@ export function formatStatusLine(snapshot) {
128
117
  `目标=${goal}`,
129
118
  `任务=${snapshot.activeTasks}`,
130
119
  `令牌=${Number(snapshot.tokens ?? 0).toLocaleString()}`,
120
+ `in=${prompt.toLocaleString()}`,
121
+ `out=${completion.toLocaleString()}`,
131
122
  `来源=${normalizeTokenSource(snapshot.tokenSource)}`,
132
- `上下文=${formatContextUsage(snapshot.tokens, snapshot.maxTokens)}`,
133
123
  cost === "-" ? "成本=-" : `成本${cost}`,
134
124
  ];
135
125
  const queue = formatInputQueueStatus(snapshot.inputQueue);
@@ -148,8 +138,9 @@ export function collectLocalStatusLineSnapshot(options) {
148
138
  goalStatus: null,
149
139
  activeTasks: 0,
150
140
  tokens: 0,
141
+ promptTokens: 0,
142
+ completionTokens: 0,
151
143
  tokenSource: "unknown",
152
- maxTokens: normalizePositiveNumber(options.maxTokens),
153
144
  costPer1kTokens: parseStatusLineCostPer1k(options.costPer1kTokens),
154
145
  };
155
146
  }
@@ -196,8 +187,9 @@ export async function collectStatusLineSnapshot(context) {
196
187
  goalStatus: goal?.status ?? null,
197
188
  activeTasks,
198
189
  tokens: Number(stats.tokens ?? 0),
190
+ promptTokens: Number(stats.promptTokens ?? 0),
191
+ completionTokens: Number(stats.completionTokens ?? 0),
199
192
  tokenSource: normalizeTokenSource(stats.tokenSource),
200
- maxTokens: resolveTokenBudgetMax(agentLoop),
201
193
  costPer1kTokens: parseStatusLineCostPer1k(process.env.QLING_STATUSLINE_COST_PER_1K_TOKENS),
202
194
  inputQueue,
203
195
  };
@@ -0,0 +1,27 @@
1
+ export type TokenUsageSource = "provider" | "unknown";
2
+ export interface ChatUsage {
3
+ promptTokens?: number;
4
+ completionTokens?: number;
5
+ totalTokens: number;
6
+ raw?: Record<string, unknown>;
7
+ }
8
+ export interface ResolvedTokenUsage {
9
+ tokens: number;
10
+ promptTokens: number;
11
+ completionTokens: number;
12
+ source: TokenUsageSource;
13
+ }
14
+ /**
15
+ * 从 chat/completions 或 Ollama 等响应中提取官方 usage。
16
+ * 支持嵌套 `usage` 与顶层计数字段。
17
+ */
18
+ export declare function extractProviderUsage(raw: unknown): ChatUsage | undefined;
19
+ /** 将本轮官方 usage 解析为可累加的会话增量。 */
20
+ export declare function resolveRoundTokenUsage(usage: ChatUsage | undefined): ResolvedTokenUsage;
21
+ export declare function formatProviderTokenLine(options: {
22
+ tokens: number;
23
+ promptTokens?: number;
24
+ completionTokens?: number;
25
+ source?: TokenUsageSource;
26
+ }): string;
27
+ //# sourceMappingURL=token-usage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-usage.d.ts","sourceRoot":"","sources":["../src/token-usage.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,gBAAgB,GAAG,UAAU,GAAG,SAAS,CAAC;AAEtD,MAAM,WAAW,SAAS;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,MAAM,EAAE,gBAAgB,CAAC;CAC1B;AAoBD;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,OAAO,GAAG,SAAS,GAAG,SAAS,CAqDxE;AAED,+BAA+B;AAC/B,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,SAAS,GAAG,SAAS,GAAG,kBAAkB,CAevF;AAED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE;IAC/C,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,MAAM,CAAC,EAAE,gBAAgB,CAAC;CAC3B,GAAG,MAAM,CAaT"}
@@ -0,0 +1,107 @@
1
+ // ============================================================
2
+ // 轻灵 — 模型官方 Token Usage 解析
3
+ // 仅信任 provider 返回字段,不做字符启发式账单估算。
4
+ // ============================================================
5
+ function positiveInt(value) {
6
+ const n = typeof value === "number" ? value : Number(value);
7
+ if (!Number.isFinite(n) || n < 0)
8
+ return undefined;
9
+ const floored = Math.floor(n);
10
+ return floored >= 0 ? floored : undefined;
11
+ }
12
+ function firstPositive(obj, keys) {
13
+ for (const key of keys) {
14
+ if (!(key in obj))
15
+ continue;
16
+ const n = positiveInt(obj[key]);
17
+ if (n !== undefined && n > 0)
18
+ return n;
19
+ // 允许 0(空 completion 等)
20
+ if (n === 0)
21
+ return 0;
22
+ }
23
+ return undefined;
24
+ }
25
+ /**
26
+ * 从 chat/completions 或 Ollama 等响应中提取官方 usage。
27
+ * 支持嵌套 `usage` 与顶层计数字段。
28
+ */
29
+ export function extractProviderUsage(raw) {
30
+ if (!raw || typeof raw !== "object")
31
+ return undefined;
32
+ const root = raw;
33
+ const nested = root.usage && typeof root.usage === "object"
34
+ ? root.usage
35
+ : root;
36
+ const promptTokens = firstPositive(nested, [
37
+ "prompt_tokens",
38
+ "promptTokens",
39
+ "input_tokens",
40
+ "inputTokens",
41
+ "prompt_eval_count",
42
+ "promptEvalCount",
43
+ ]);
44
+ const completionTokens = firstPositive(nested, [
45
+ "completion_tokens",
46
+ "completionTokens",
47
+ "output_tokens",
48
+ "outputTokens",
49
+ "eval_count",
50
+ "evalCount",
51
+ ]);
52
+ let totalTokens = firstPositive(nested, [
53
+ "total_tokens",
54
+ "totalTokens",
55
+ "total",
56
+ ]);
57
+ if (totalTokens === undefined) {
58
+ if (promptTokens !== undefined || completionTokens !== undefined) {
59
+ totalTokens = (promptTokens ?? 0) + (completionTokens ?? 0);
60
+ }
61
+ }
62
+ if (totalTokens === undefined || totalTokens <= 0) {
63
+ // 若 total 为 0 但有明确 prompt/completion 0 之和,仍视为无有效用量
64
+ if (totalTokens === 0 && (promptTokens ?? 0) + (completionTokens ?? 0) === 0) {
65
+ return undefined;
66
+ }
67
+ if (totalTokens === undefined)
68
+ return undefined;
69
+ }
70
+ if (totalTokens <= 0)
71
+ return undefined;
72
+ return {
73
+ promptTokens,
74
+ completionTokens,
75
+ totalTokens,
76
+ raw: nested,
77
+ };
78
+ }
79
+ /** 将本轮官方 usage 解析为可累加的会话增量。 */
80
+ export function resolveRoundTokenUsage(usage) {
81
+ if (usage && Number.isFinite(usage.totalTokens) && usage.totalTokens > 0) {
82
+ return {
83
+ tokens: Math.floor(usage.totalTokens),
84
+ promptTokens: Math.max(0, Math.floor(usage.promptTokens ?? 0)),
85
+ completionTokens: Math.max(0, Math.floor(usage.completionTokens ?? 0)),
86
+ source: "provider",
87
+ };
88
+ }
89
+ return {
90
+ tokens: 0,
91
+ promptTokens: 0,
92
+ completionTokens: 0,
93
+ source: "unknown",
94
+ };
95
+ }
96
+ export function formatProviderTokenLine(options) {
97
+ const tokens = Math.max(0, Math.floor(options.tokens ?? 0));
98
+ const prompt = options.promptTokens;
99
+ const completion = options.completionTokens;
100
+ const source = options.source ?? "unknown";
101
+ if (typeof prompt === "number" &&
102
+ typeof completion === "number" &&
103
+ (prompt > 0 || completion > 0)) {
104
+ return `${tokens.toLocaleString()} (in ${prompt.toLocaleString()} + out ${completion.toLocaleString()}, ${source})`;
105
+ }
106
+ return `${tokens.toLocaleString()} (${source})`;
107
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"bash.d.ts","sourceRoot":"","sources":["../../src/tools/bash.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAOzD,eAAO,MAAM,QAAQ,EAAE,cA+FtB,CAAC;AAEF,wBAAsB,OAAO,CAAC,IAAI,EAAE;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACrC,GAAG,OAAO,CAAC,UAAU,CAAC,CAyJtB"}
1
+ {"version":3,"file":"bash.d.ts","sourceRoot":"","sources":["../../src/tools/bash.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAOzD,eAAO,MAAM,QAAQ,EAAE,cAiGtB,CAAC;AAEF,wBAAsB,OAAO,CAAC,IAAI,EAAE;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACrC,GAAG,OAAO,CAAC,UAAU,CAAC,CAyJtB"}
@@ -12,7 +12,7 @@ const MAX_COMMAND_LENGTH = 5000;
12
12
  const MAX_OUTPUT_BYTES = 1024 * 1024; // 1MB per stream
13
13
  export const bashTool = {
14
14
  name: "bash",
15
- description: "Execute shell commands on Linux/Windows (git, npm, file operations, CLI tools). Returns stdout/stderr. Hook intercepts dangerous operations (rm -rf, disk format, etc.).",
15
+ description: "Execute shell commands (git, npm, opencli, file ops). For Douyin/Xiaohongshu/Weibo/etc. run opencli after skill name=opencli; prefer opencli … -f json. Not for raw fetch of anti-bot pages.",
16
16
  longDescription: `执行 shell 命令的万能工具。**Linux**: 通过 /bin/sh 执行。**Windows**: 通过 cmd.exe 执行(而非 PowerShell)。
17
17
  **重要 - Windows 用户**:Windows 上请使用标准的 cmd.exe 命令(dir, type, copy, del 等),不要使用 PowerShell 独有语法(Invoke-WebRequest 等)。cmd.exe 不支持 PowerShell cmdlet。
18
18
  **Linux 用户**:通过 /bin/sh 执行标准 POSIX 命令。
@@ -20,15 +20,17 @@ export const bashTool = {
20
20
  **使用场景**:
21
21
  - git 操作(git add, git commit, git push)
22
22
  - npm/node 命令(npm install, node scripts)
23
+ - **opencli**(本机已安装时):opencli list / opencli douyin search … -f json(先 skill name="opencli")
23
24
  - 文件操作(ls, cp, mv, mkdir)
24
25
  - 进程管理(ps, kill, pgrep)
25
- - 网络工具(curl, wget, ping
26
+ - 网络工具(curl, wget, ping)— 强反爬社交站不要用 curl 硬抓
26
27
  - 编译构建(make, gcc, cargo)
27
28
 
28
29
  **注意事项**:
29
30
  - rm -rf 等危险操作会被 Hook 拦截并要求确认
30
31
  - Windows 下需要通过 cmd.exe /c 执行
31
- - 长时间运行的命令建议设置 timeout`,
32
+ - 长时间运行的命令建议设置 timeout
33
+ - opencli 写操作(delete/publish)须用户确认`,
32
34
  parameters: {
33
35
  type: "object",
34
36
  properties: {
@@ -0,0 +1,48 @@
1
+ import { type Browser, type BrowserContext, type Page } from "playwright";
2
+ export interface BrowserSessionHandle {
3
+ id: string;
4
+ browser: Browser;
5
+ context: BrowserContext;
6
+ page: Page;
7
+ lastUrl: string;
8
+ createdAt: number;
9
+ lastUsedAt: number;
10
+ requestGuardInstalled: boolean;
11
+ }
12
+ export type BrowserRequestGuard = (url: string) => Promise<boolean>;
13
+ export interface BrowserSessionPoolOptions {
14
+ /** 最大并发会话数 */
15
+ maxSessions?: number;
16
+ /** 空闲超时 ms,超过则自动关闭 */
17
+ idleTtlMs?: number;
18
+ /** 注入的 launch 工厂(测试用) */
19
+ launchBrowser?: () => Promise<Browser>;
20
+ }
21
+ export declare class BrowserSessionPool {
22
+ private sessions;
23
+ private maxSessions;
24
+ private idleTtlMs;
25
+ private launchBrowser;
26
+ constructor(options?: BrowserSessionPoolOptions);
27
+ list(): Array<{
28
+ id: string;
29
+ lastUrl: string;
30
+ ageMs: number;
31
+ idleMs: number;
32
+ }>;
33
+ has(id: string): boolean;
34
+ get(id: string): BrowserSessionHandle | undefined;
35
+ /** 关闭并移除空闲超时会话 */
36
+ sweepIdle(now?: number): Promise<string[]>;
37
+ open(id: string, requestGuard?: BrowserRequestGuard): Promise<BrowserSessionHandle>;
38
+ private installRequestGuard;
39
+ touch(id: string, lastUrl?: string): void;
40
+ close(id: string): Promise<boolean>;
41
+ closeAll(): Promise<void>;
42
+ size(): number;
43
+ }
44
+ export declare function getBrowserSessionPool(): BrowserSessionPool;
45
+ /** 测试用:替换 / 清空默认池 */
46
+ export declare function resetBrowserSessionPool(pool?: BrowserSessionPool | null): void;
47
+ export declare function normalizeSessionId(raw: unknown): string;
48
+ //# sourceMappingURL=browser-act-session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser-act-session.d.ts","sourceRoot":"","sources":["../../src/tools/browser-act-session.ts"],"names":[],"mappings":"AAIA,OAAO,EAAY,KAAK,OAAO,EAAE,KAAK,cAAc,EAAE,KAAK,IAAI,EAAE,MAAM,YAAY,CAAC;AAEpF,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,cAAc,CAAC;IACxB,IAAI,EAAE,IAAI,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,qBAAqB,EAAE,OAAO,CAAC;CAChC;AAED,MAAM,MAAM,mBAAmB,GAAG,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpE,MAAM,WAAW,yBAAyB;IACxC,cAAc;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,sBAAsB;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yBAAyB;IACzB,aAAa,CAAC,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;CACxC;AAiBD,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,QAAQ,CAA2C;IAC3D,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,aAAa,CAAyB;gBAElC,OAAO,GAAE,yBAA8B;IAWnD,IAAI,IAAI,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAU7E,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAIxB,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,oBAAoB,GAAG,SAAS;IAIjD,kBAAkB;IACZ,SAAS,CAAC,GAAG,SAAa,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAY9C,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,oBAAoB,CAAC;YAiD3E,mBAAmB;IAgBjC,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI;IAOnC,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAQnC,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAO/B,IAAI,IAAI,MAAM;CAGf;AAKD,wBAAgB,qBAAqB,IAAI,kBAAkB,CAG1D;AAED,qBAAqB;AACrB,wBAAgB,uBAAuB,CAAC,IAAI,CAAC,EAAE,kBAAkB,GAAG,IAAI,GAAG,IAAI,CAK9E;AAED,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAKvD"}
@@ -0,0 +1,168 @@
1
+ // ============================================================
2
+ // browser_act 跨步会话:进程内 Playwright page 保活
3
+ // ============================================================
4
+ import { chromium } from "playwright";
5
+ const DEFAULT_MAX = 3;
6
+ const DEFAULT_IDLE_TTL_MS = 10 * 60 * 1000;
7
+ function resolveMaxSessions(env = process.env) {
8
+ const n = Number(env.QLING_BROWSER_ACT_MAX_SESSIONS ?? DEFAULT_MAX);
9
+ if (!Number.isFinite(n) || n < 1)
10
+ return DEFAULT_MAX;
11
+ return Math.min(8, Math.floor(n));
12
+ }
13
+ function resolveIdleTtlMs(env = process.env) {
14
+ const n = Number(env.QLING_BROWSER_ACT_IDLE_TTL_MS ?? DEFAULT_IDLE_TTL_MS);
15
+ if (!Number.isFinite(n) || n < 0)
16
+ return DEFAULT_IDLE_TTL_MS;
17
+ return Math.floor(n);
18
+ }
19
+ export class BrowserSessionPool {
20
+ sessions = new Map();
21
+ maxSessions;
22
+ idleTtlMs;
23
+ launchBrowser;
24
+ constructor(options = {}) {
25
+ this.maxSessions = options.maxSessions ?? resolveMaxSessions();
26
+ this.idleTtlMs = options.idleTtlMs ?? resolveIdleTtlMs();
27
+ this.launchBrowser =
28
+ options.launchBrowser ??
29
+ (() => chromium.launch({
30
+ headless: true,
31
+ }));
32
+ }
33
+ list() {
34
+ const now = Date.now();
35
+ return Array.from(this.sessions.values()).map((s) => ({
36
+ id: s.id,
37
+ lastUrl: s.lastUrl,
38
+ ageMs: now - s.createdAt,
39
+ idleMs: now - s.lastUsedAt,
40
+ }));
41
+ }
42
+ has(id) {
43
+ return this.sessions.has(id);
44
+ }
45
+ get(id) {
46
+ return this.sessions.get(id);
47
+ }
48
+ /** 关闭并移除空闲超时会话 */
49
+ async sweepIdle(now = Date.now()) {
50
+ if (this.idleTtlMs <= 0)
51
+ return [];
52
+ const closed = [];
53
+ for (const [id, s] of this.sessions) {
54
+ if (now - s.lastUsedAt >= this.idleTtlMs) {
55
+ await this.close(id);
56
+ closed.push(id);
57
+ }
58
+ }
59
+ return closed;
60
+ }
61
+ async open(id, requestGuard) {
62
+ await this.sweepIdle();
63
+ const existing = this.sessions.get(id);
64
+ if (existing) {
65
+ if (requestGuard && !existing.requestGuardInstalled) {
66
+ await this.installRequestGuard(existing.context, requestGuard);
67
+ existing.requestGuardInstalled = true;
68
+ }
69
+ existing.lastUsedAt = Date.now();
70
+ return existing;
71
+ }
72
+ if (this.sessions.size >= this.maxSessions) {
73
+ // 驱逐最久未用
74
+ let oldestId = null;
75
+ let oldest = Infinity;
76
+ for (const [sid, s] of this.sessions) {
77
+ if (s.lastUsedAt < oldest) {
78
+ oldest = s.lastUsedAt;
79
+ oldestId = sid;
80
+ }
81
+ }
82
+ if (oldestId)
83
+ await this.close(oldestId);
84
+ }
85
+ const browser = await this.launchBrowser();
86
+ const context = await browser.newContext({
87
+ userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
88
+ });
89
+ if (requestGuard) {
90
+ await this.installRequestGuard(context, requestGuard);
91
+ }
92
+ const page = await context.newPage();
93
+ const now = Date.now();
94
+ const handle = {
95
+ id,
96
+ browser,
97
+ context,
98
+ page,
99
+ lastUrl: "",
100
+ createdAt: now,
101
+ lastUsedAt: now,
102
+ requestGuardInstalled: Boolean(requestGuard),
103
+ };
104
+ this.sessions.set(id, handle);
105
+ return handle;
106
+ }
107
+ async installRequestGuard(context, requestGuard) {
108
+ await context.route("**/*", async (route) => {
109
+ let allowed = false;
110
+ try {
111
+ allowed = await requestGuard(route.request().url());
112
+ }
113
+ catch {
114
+ allowed = false;
115
+ }
116
+ if (allowed)
117
+ await route.continue();
118
+ else
119
+ await route.abort("blockedbyclient");
120
+ });
121
+ }
122
+ touch(id, lastUrl) {
123
+ const s = this.sessions.get(id);
124
+ if (!s)
125
+ return;
126
+ s.lastUsedAt = Date.now();
127
+ if (lastUrl !== undefined)
128
+ s.lastUrl = lastUrl;
129
+ }
130
+ async close(id) {
131
+ const s = this.sessions.get(id);
132
+ if (!s)
133
+ return false;
134
+ this.sessions.delete(id);
135
+ await s.browser.close().catch(() => undefined);
136
+ return true;
137
+ }
138
+ async closeAll() {
139
+ const ids = Array.from(this.sessions.keys());
140
+ for (const id of ids) {
141
+ await this.close(id);
142
+ }
143
+ }
144
+ size() {
145
+ return this.sessions.size;
146
+ }
147
+ }
148
+ /** 进程内默认池(browser_act 共用) */
149
+ let defaultPool = null;
150
+ export function getBrowserSessionPool() {
151
+ if (!defaultPool)
152
+ defaultPool = new BrowserSessionPool();
153
+ return defaultPool;
154
+ }
155
+ /** 测试用:替换 / 清空默认池 */
156
+ export function resetBrowserSessionPool(pool) {
157
+ if (defaultPool) {
158
+ void defaultPool.closeAll();
159
+ }
160
+ defaultPool = pool === undefined ? null : pool;
161
+ }
162
+ export function normalizeSessionId(raw) {
163
+ const s = String(raw ?? "default").trim();
164
+ if (!s)
165
+ return "default";
166
+ // 防止路径穿越式 id
167
+ return s.replace(/[^\w.-]+/g, "_").slice(0, 64) || "default";
168
+ }
@@ -0,0 +1,14 @@
1
+ import type { ToolDefinition, ToolResult } from "../types.js";
2
+ export type BrowserActAction = "open" | "close" | "status" | "goto" | "click" | "type" | "wait_for" | "extract" | "press";
3
+ export declare function isBrowserActEnabled(env?: NodeJS.ProcessEnv | Record<string, string | undefined>): boolean;
4
+ export declare const browserActTool: ToolDefinition;
5
+ export declare function runBrowserAct(args: {
6
+ action?: string;
7
+ session?: string;
8
+ url?: string;
9
+ selector?: string;
10
+ text?: string;
11
+ key?: string;
12
+ timeout_ms?: number;
13
+ }): Promise<ToolResult>;
14
+ //# sourceMappingURL=browser-act.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser-act.d.ts","sourceRoot":"","sources":["../../src/tools/browser-act.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAS9D,MAAM,MAAM,gBAAgB,GACxB,MAAM,GACN,OAAO,GACP,QAAQ,GACR,MAAM,GACN,OAAO,GACP,MAAM,GACN,UAAU,GACV,SAAS,GACT,OAAO,CAAC;AAIZ,wBAAgB,mBAAmB,CACjC,GAAG,GAAE,MAAM,CAAC,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAe,GACxE,OAAO,CAGT;AAED,eAAO,MAAM,cAAc,EAAE,cA+C5B,CAAC;AAwDF,wBAAsB,aAAa,CAAC,IAAI,EAAE;IACxC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,GAAG,OAAO,CAAC,UAAU,CAAC,CAsNtB"}