@xopcai/xopc 0.0.243 → 0.0.245

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 (202) hide show
  1. package/dist/browser-ext/manifest.json +1 -1
  2. package/dist/extensions/telegram/xopc.extension.json +1 -1
  3. package/dist/gateway/static/root/assets/{activity-store-CAah-_8h.js → activity-store-BlxqErph.js} +1 -1
  4. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-DDH4HgP7.js → agent-avatar-dicebear-DRQnogaU.js} +1 -1
  5. package/dist/gateway/static/root/assets/{agent-defaults-settings-panel-BDCfJZhh.js → agent-defaults-settings-panel-CpOxGbMD.js} +1 -1
  6. package/dist/gateway/static/root/assets/{agents-B0ZWgf-U.js → agents-flnXZLaT.js} +1 -1
  7. package/dist/gateway/static/root/assets/{api-B2tKxbcz.js → api-BbXzyQMj.js} +1 -1
  8. package/dist/gateway/static/root/assets/{app-management-settings-panel-Blfwszzn.js → app-management-settings-panel-CZl6n2xi.js} +1 -1
  9. package/dist/gateway/static/root/assets/{appearance-settings-C3V7Na75.js → appearance-settings-Bglp-pn6.js} +1 -1
  10. package/dist/gateway/static/root/assets/{apps-page-BiEks0-F.js → apps-page-CmsWarVB.js} +1 -1
  11. package/dist/gateway/static/root/assets/{archive-plugin-BmSx7wzY.js → archive-plugin-DD2SweEH.js} +1 -1
  12. package/dist/gateway/static/root/assets/{attachment-load-BS-S4LJ9.js → attachment-load-G0HenUmG.js} +1 -1
  13. package/dist/gateway/static/root/assets/{automations-page-C7Y3L30D.js → automations-page-B78bFjH2.js} +1 -1
  14. package/dist/gateway/static/root/assets/{automations-workspace-A3zPkPuo.js → automations-workspace-BMQGmn50.js} +1 -1
  15. package/dist/gateway/static/root/assets/{binary-plugins-BM9B5kcm.js → binary-plugins-BbSQmXqn.js} +1 -1
  16. package/dist/gateway/static/root/assets/{block-editor-BbnpkYP9.js → block-editor-DutTIH81.js} +1 -1
  17. package/dist/gateway/static/root/assets/{browser-settings-page-Dk4FQ7fY.js → browser-settings-page-CALiFKm4.js} +1 -1
  18. package/dist/gateway/static/root/assets/{browser-workflow-inputs-CRnkgZHI.js → browser-workflow-inputs-BAAc151l.js} +1 -1
  19. package/dist/gateway/static/root/assets/{browser-workflows-page-B9qGL-it.js → browser-workflows-page-DE5HPrHZ.js} +1 -1
  20. package/dist/gateway/static/root/assets/{capabilities-settings-panel--tR_El9e.js → capabilities-settings-panel-Dts7XtP3.js} +1 -1
  21. package/dist/gateway/static/root/assets/{channels-settings-D347vl_J.js → channels-settings-CWEd3wzh.js} +1 -1
  22. package/dist/gateway/static/root/assets/{channels-status-swr-DuY4MGxe.js → channels-status-swr-CCBCtLDg.js} +1 -1
  23. package/dist/gateway/static/root/assets/{chat-terminal-dock-DABPvwBT.js → chat-terminal-dock-Bp1fXQm1.js} +1 -1
  24. package/dist/gateway/static/root/assets/{connectors-page-B-tvJkRJ.js → connectors-page-CQ6wVNLm.js} +1 -1
  25. package/dist/gateway/static/root/assets/{cron-expression-D3bsKbNd.js → cron-expression-B8HA5IRb.js} +1 -1
  26. package/dist/gateway/static/root/assets/{date-picker-BsGM6Yty.js → date-picker-DD8b7oad.js} +1 -1
  27. package/dist/gateway/static/root/assets/{dependency-picker-Dj3g6YXZ.js → dependency-picker-BC9zwIyH.js} +1 -1
  28. package/dist/gateway/static/root/assets/{desktop-pet-C1QT0Sur.js → desktop-pet-DsrsPZTW.js} +1 -1
  29. package/dist/gateway/static/root/assets/{desktop-pet-settings-r6kAOnfY.js → desktop-pet-settings-D7gp_HNA.js} +1 -1
  30. package/dist/gateway/static/root/assets/{extension-debug-page-DOkf7nh9.js → extension-debug-page-BoKbOX7x.js} +1 -1
  31. package/dist/gateway/static/root/assets/{extension-page-Cq2IA4Ho.js → extension-page-BegL4FW8.js} +1 -1
  32. package/dist/gateway/static/root/assets/{extension-settings-page-DQn4qjDZ.js → extension-settings-page-CjPqq57s.js} +1 -1
  33. package/dist/gateway/static/root/assets/{gateway-config-api-DM3poL22.js → gateway-config-api-DaG57o4X.js} +1 -1
  34. package/dist/gateway/static/root/assets/{gateway-config-swr-BC3pgb_P.js → gateway-config-swr-826dipyU.js} +1 -1
  35. package/dist/gateway/static/root/assets/{gateway-settings-DPgH1hnh.js → gateway-settings-DkJGpgm6.js} +1 -1
  36. package/dist/gateway/static/root/assets/{gateway-startup-retry-uMcSfLru.js → gateway-startup-retry-DyvcAIMm.js} +1 -1
  37. package/dist/gateway/static/root/assets/{heartbeat-settings-Bk80-E3b.js → heartbeat-settings-BLZ48kSU.js} +1 -1
  38. package/dist/gateway/static/root/assets/{home-page-DKo5JiMR.js → home-page-Dtw7Ipt1.js} +1 -1
  39. package/dist/gateway/static/root/assets/{image-generation-api-D1qlQA-A.js → image-generation-api-D7cyfks6.js} +1 -1
  40. package/dist/gateway/static/root/assets/{index-B0WJL9N1.js → index-DG5CfYat.js} +10 -10
  41. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-BEwvd8ZU.js → keyboard-shortcuts-settings-D2Has7-N.js} +1 -1
  42. package/dist/gateway/static/root/assets/{local-app-workbench-page--eJ5rmNj.js → local-app-workbench-page-BWidWY93.js} +1 -1
  43. package/dist/gateway/static/root/assets/{local-apps-page-CgkY9E-r.js → local-apps-page-Bkekjoxf.js} +1 -1
  44. package/dist/gateway/static/root/assets/{locale-store-CMZljTJx.js → locale-store-CBoCuIMx.js} +1 -1
  45. package/dist/gateway/static/root/assets/{logs-page-Z49Td0J9.js → logs-page-C5zSSgvA.js} +1 -1
  46. package/dist/gateway/static/root/assets/{management-settings-Dv8NSJKt.js → management-settings-B8c62vRS.js} +1 -1
  47. package/dist/gateway/static/root/assets/{markdown-split-Cm0RBB-t.js → markdown-split-3kxTTGO7.js} +1 -1
  48. package/dist/gateway/static/root/assets/{markdown-view-PPCLt7fu.js → markdown-view-BXsHghJd.js} +1 -1
  49. package/dist/gateway/static/root/assets/{media-plugins-Bcr5sU1f.js → media-plugins-BW8J1nCG.js} +1 -1
  50. package/dist/gateway/static/root/assets/messages-BbdwoxVo.js +3 -0
  51. package/dist/gateway/static/root/assets/{mobile-pairing-wizard-kKDiXofY.js → mobile-pairing-wizard-nwQ8iUcd.js} +1 -1
  52. package/dist/gateway/static/root/assets/models-hub-cache-88f4fzYS.js +1 -0
  53. package/dist/gateway/static/root/assets/{notes-page-CgsaRaGi.js → notes-page-DdybD0QM.js} +1 -1
  54. package/dist/gateway/static/root/assets/{notes-workbench-C1DEE09k.js → notes-workbench-IYfpy2Jx.js} +2 -2
  55. package/dist/gateway/static/root/assets/{oauth-api-4VeMbkTJ.js → oauth-api-BjSUDIgq.js} +1 -1
  56. package/dist/gateway/static/root/assets/{product-open-page-BU0HiZtv.js → product-open-page-CAJeUXeU.js} +1 -1
  57. package/dist/gateway/static/root/assets/{project-detail-page-isRapnp5.js → project-detail-page-4wjw-b7h.js} +1 -1
  58. package/dist/gateway/static/root/assets/{projects-page-zvsjg0mi.js → projects-page-CCMj9PeL.js} +1 -1
  59. package/dist/gateway/static/root/assets/{registry-api-CWOtPFrE.js → registry-api-BhGKnvLP.js} +1 -1
  60. package/dist/gateway/static/root/assets/{remote-access-hub-C9TGZ9Hc.js → remote-access-hub-DsBJqWIk.js} +1 -1
  61. package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-2zm9edMA.js → runtime-tools-settings-panel-B4IDcqx0.js} +1 -1
  62. package/dist/gateway/static/root/assets/{schema-form-54A5gzkN.js → schema-form-DiGUUjO6.js} +1 -1
  63. package/dist/gateway/static/root/assets/{sessions-page-BP8RyiUn.js → sessions-page-BwGj0t-2.js} +1 -1
  64. package/dist/gateway/static/root/assets/settings-advanced-gate-BJCfUghk.js +1 -0
  65. package/dist/gateway/static/root/assets/{settings-page-DzDhoyxv.js → settings-page-CVQUsAhd.js} +1 -1
  66. package/dist/gateway/static/root/assets/{setup-status-panel-uDicHU1w.js → setup-status-panel-CQACRh1i.js} +1 -1
  67. package/dist/gateway/static/root/assets/{share-preview-page-lOmLCWFS.js → share-preview-page-DTP1dtuS.js} +1 -1
  68. package/dist/gateway/static/root/assets/{shares-settings-T4Yvouvv.js → shares-settings-D_YPh6Rw.js} +1 -1
  69. package/dist/gateway/static/root/assets/skill-reload-api-B43xlJlX.js +1 -0
  70. package/dist/gateway/static/root/assets/{skills-page-CnyNH3To.js → skills-page-Czpn7Y28.js} +1 -1
  71. package/dist/gateway/static/root/assets/{skills-page.utils-CgDtf2qs.js → skills-page.utils-d39rm3hb.js} +1 -1
  72. package/dist/gateway/static/root/assets/{system-settings-panel-C8yWfwtR.js → system-settings-panel-CXXySCSp.js} +1 -1
  73. package/dist/gateway/static/root/assets/{task-detail-page-Tzfjlbf3.js → task-detail-page-DHiOqQMx.js} +1 -1
  74. package/dist/gateway/static/root/assets/{theme-store-uxUwr10D.js → theme-store-hybK3oC9.js} +1 -1
  75. package/dist/gateway/static/root/assets/{tunnel-api-Bvg679no.js → tunnel-api-BiBGK7O2.js} +1 -1
  76. package/dist/gateway/static/root/assets/{use-autosave-D88VGoyG.js → use-autosave-DjpzpeIm.js} +1 -1
  77. package/dist/gateway/static/root/assets/{user-context-page-RijPtyfO.js → user-context-page-1XBRV5gX.js} +1 -1
  78. package/dist/gateway/static/root/assets/{voice-api-key-field-CBHLsMcc.js → voice-api-key-field-CUIPNmOc.js} +1 -1
  79. package/dist/gateway/static/root/assets/{voice-config-api-MqyI6cgq.js → voice-config-api-CBbiF1T3.js} +1 -1
  80. package/dist/gateway/static/root/assets/{work-discovery-overlay-GGe2TQ98.js → work-discovery-overlay-DVNxhb1x.js} +1 -1
  81. package/dist/gateway/static/root/assets/{workflow-run-setup-panel-C0layUE9.js → workflow-run-setup-panel-HxxFQFY7.js} +1 -1
  82. package/dist/gateway/static/root/assets/{workflows-page-DQXIzBAc.js → workflows-page-BCgL7PRm.js} +1 -1
  83. package/dist/gateway/static/root/index.html +11 -11
  84. package/dist/package.js +1 -1
  85. package/dist/packages/gateway-contract/src/turn-outcome.js +3 -1
  86. package/dist/src/agent/agent-instance-gateway.d.ts +3 -1
  87. package/dist/src/agent/agent-manager.d.ts +2 -4
  88. package/dist/src/agent/agent-manager.js +24 -28
  89. package/dist/src/agent/background-review/coordinator.js +1 -1
  90. package/dist/src/agent/background-review/run-background-review.js +1 -1
  91. package/dist/src/agent/child-agent-factory.d.ts +10 -7
  92. package/dist/src/agent/child-agent-factory.js +112 -158
  93. package/dist/src/agent/coding/index.d.ts +1 -1
  94. package/dist/src/agent/coding/index.js +2 -2
  95. package/dist/src/agent/coding/repository-instructions.d.ts +12 -0
  96. package/dist/src/agent/coding/repository-instructions.js +76 -0
  97. package/dist/src/agent/coding/run-verification.d.ts +34 -0
  98. package/dist/src/agent/coding/run-verification.js +134 -0
  99. package/dist/src/agent/coding/verification-command.d.ts +3 -0
  100. package/dist/src/agent/coding/verification-command.js +50 -0
  101. package/dist/src/agent/coding/workspace-revision.d.ts +2 -0
  102. package/dist/src/agent/coding/workspace-revision.js +77 -0
  103. package/dist/src/agent/commands/command-isolation.d.ts +21 -0
  104. package/dist/src/agent/commands/command-isolation.js +71 -0
  105. package/dist/src/agent/commands/command-registry.d.ts +56 -0
  106. package/dist/src/agent/commands/command-registry.js +259 -0
  107. package/dist/src/agent/embedded/index.js +1 -1
  108. package/dist/src/agent/embedded/run-for-session.js +2 -1
  109. package/dist/src/agent/embedded/run-turn.js +88 -25
  110. package/dist/src/agent/embedded/session-tool-result-guard.js +2 -2
  111. package/dist/src/agent/embedded/subscribe-session.d.ts +2 -1
  112. package/dist/src/agent/embedded/subscribe-session.js +2 -1
  113. package/dist/src/agent/embedded/types.d.ts +3 -1
  114. package/dist/src/agent/embedded/xopc-tools-bridge.js +4 -1
  115. package/dist/src/agent/image/index.js +1 -1
  116. package/dist/src/agent/index.js +3 -3
  117. package/dist/src/agent/memory/user-context-coordinator.js +1 -1
  118. package/dist/src/agent/middleware/index.d.ts +0 -5
  119. package/dist/src/agent/middleware/index.js +1 -2
  120. package/dist/src/agent/orchestration/agent-event-handler.d.ts +0 -5
  121. package/dist/src/agent/orchestration/agent-event-handler.js +1 -96
  122. package/dist/src/agent/orchestration/agent-orchestrator.js +1 -1
  123. package/dist/src/agent/orchestration/agent-turn-policy.js +5 -5
  124. package/dist/src/agent/orchestration/index.d.ts +1 -1
  125. package/dist/src/agent/orchestration/index.js +2 -2
  126. package/dist/src/agent/orchestration/loop-guard.d.ts +4 -31
  127. package/dist/src/agent/orchestration/loop-guard.js +14 -99
  128. package/dist/src/agent/prompt/sections/tooling.js +2 -4
  129. package/dist/src/agent/sandbox/types.d.ts +2 -2
  130. package/dist/src/agent/sandbox/types.js +1 -1
  131. package/dist/src/agent/service/direct-turn-helpers.js +1 -1
  132. package/dist/src/agent/service/process-direct-streaming.js +1 -1
  133. package/dist/src/agent/service.d.ts +0 -2
  134. package/dist/src/agent/service.js +6 -23
  135. package/dist/src/agent/tasks/task-judge-service.d.ts +7 -0
  136. package/dist/src/agent/tasks/task-judge-service.js +24 -2
  137. package/dist/src/agent/tools/delegate-tool.d.ts +2 -1
  138. package/dist/src/agent/tools/delegate-tool.js +102 -124
  139. package/dist/src/agent/tools/exec-command.d.ts +8 -1
  140. package/dist/src/agent/tools/exec-command.js +77 -169
  141. package/dist/src/agent/tools/executor.js +9 -2
  142. package/dist/src/agent/tools/factory.js +50 -5
  143. package/dist/src/agent/tools/find.d.ts +10 -13
  144. package/dist/src/agent/tools/find.js +33 -80
  145. package/dist/src/agent/tools/grep.d.ts +14 -18
  146. package/dist/src/agent/tools/grep.js +56 -144
  147. package/dist/src/agent/tools/index.d.ts +0 -1
  148. package/dist/src/agent/tools/index.js +2 -3
  149. package/dist/src/agent/tools/language-diagnostics.d.ts +11 -0
  150. package/dist/src/agent/tools/language-diagnostics.js +62 -0
  151. package/dist/src/agent/tools/managed-job-tool.d.ts +2 -1
  152. package/dist/src/agent/tools/managed-job-tool.js +58 -118
  153. package/dist/src/agent/tools/read.js +24 -7
  154. package/dist/src/agent/tools/repository-search.d.ts +5 -0
  155. package/dist/src/agent/tools/repository-search.js +56 -0
  156. package/dist/src/agent/tools/review-workspace.d.ts +2 -0
  157. package/dist/src/agent/tools/review-workspace.js +103 -0
  158. package/dist/src/agent/tools/write.js +4 -4
  159. package/dist/src/agent/transcript/index.js +2 -2
  160. package/dist/src/agent/transcript/transcript-hygiene.js +2 -2
  161. package/dist/src/agent/workflow/subagent-runner.d.ts +0 -2
  162. package/dist/src/agent/workflow/subagent-runner.js +12 -31
  163. package/dist/src/agent-config/schema.d.ts +42 -0
  164. package/dist/src/agent-config/schema.js +5 -0
  165. package/dist/src/automations/draft/automation-draft-service.js +1 -1
  166. package/dist/src/cli/commands/extension-marketplace.js +1 -1
  167. package/dist/src/config/schema.d.ts +28 -0
  168. package/dist/src/execution-environments/local-worktree-manager.d.ts +3 -1
  169. package/dist/src/execution-environments/local-worktree-manager.js +8 -3
  170. package/dist/src/execution-environments/session-environment-service.js +5 -3
  171. package/dist/src/extensions/update.js +1 -1
  172. package/dist/src/gateway/hono/lib/config-payload.d.ts +7 -0
  173. package/dist/src/gateway/hono/routes/auth-registry-extensions.js +1 -1
  174. package/dist/src/gateway/hono/routes/connectors.js +23 -23
  175. package/dist/src/gateway/hono/routes/sessions.js +1 -1
  176. package/dist/src/gateway/media-access.js +1 -1
  177. package/dist/src/gateway/service/config-coordinator.js +1 -1
  178. package/dist/src/gateway/service/run-gateway-agent.js +4 -1
  179. package/dist/src/gateway/service.js +1 -1
  180. package/dist/src/gateway/session-reset-service.js +1 -1
  181. package/dist/src/gateway/workspace-ripgrep.d.ts +0 -6
  182. package/dist/src/gateway/workspace-ripgrep.js +2 -40
  183. package/dist/src/infra/ripgrep.d.ts +13 -0
  184. package/dist/src/infra/ripgrep.js +46 -0
  185. package/dist/src/infra/update-runner.js +1 -1
  186. package/dist/src/proactive/execution/agent-executor.js +1 -1
  187. package/dist/src/session/store.js +1 -1
  188. package/dist/src/session/turn-outcome-projector.js +26 -6
  189. package/dist/src/tasks/task-run-coordinator.d.ts +2 -2
  190. package/dist/src/tasks/task-run-coordinator.js +14 -12
  191. package/dist/src/tui/backends/embedded-backend.js +1 -1
  192. package/package.json +3 -3
  193. package/dist/gateway/static/root/assets/messages-CTSgFlE4.js +0 -3
  194. package/dist/gateway/static/root/assets/models-hub-cache-ZrbGRiGY.js +0 -1
  195. package/dist/gateway/static/root/assets/settings-advanced-gate-D4EMxWAZ.js +0 -1
  196. package/dist/gateway/static/root/assets/skill-reload-api-DVb7nrXz.js +0 -1
  197. package/dist/src/agent/coding/turn-diff-tracker.d.ts +0 -67
  198. package/dist/src/agent/coding/turn-diff-tracker.js +0 -231
  199. package/dist/src/agent/middleware/self-verify.d.ts +0 -136
  200. package/dist/src/agent/middleware/self-verify.js +0 -380
  201. package/dist/src/agent/tools/execute-code-tool.d.ts +0 -11
  202. package/dist/src/agent/tools/execute-code-tool.js +0 -208
@@ -1,20 +1,22 @@
1
1
  import { createLogger } from "../../utils/logger/index.js";
2
2
  import { init_logger } from "../../utils/logger.js";
3
+ import { EmbeddedRunConflictError, abortEmbeddedRun, acquireEmbeddedRunLease, queueEmbeddedSteer } from "./runs.js";
4
+ import { lastAssistantPlainText, subscribeEmbeddedSessionEvents } from "./subscribe-session.js";
5
+ import { isContextOverflowError } from "../orchestration/context-overflow.js";
6
+ import { getAssistantTurnErrorMessage, isAssistantTurnAborted, isAssistantTurnFailed, maybeRetryTurnAfterTransientLlmFailure, stripTrailingErrorAssistantMessages } from "../orchestration/llm-turn-retry.js";
3
7
  import { isAgentTurnUnsettledError, resolveAgentTurnTimeoutMs, runAgentTurnWithTimeout } from "../orchestration/run-agent-turn-with-timeout.js";
8
+ import { detectToolLoops } from "../orchestration/loop-guard.js";
9
+ import { tryApplySessionTranscriptHygiene } from "../transcript/transcript-hygiene.js";
4
10
  import { resolvePromptCachePolicy } from "../../providers/prompt-cache-plan.js";
5
11
  import { wrapStreamFnForXopcExtensions } from "./xopc-stream-bridge.js";
6
12
  import { acquireEmbeddedSessionRunner, evictEmbeddedSessionRunner } from "./session-runner.js";
7
- import { markTurnToolResult } from "../memory/turn-provenance.js";
8
- import { isContextOverflowError } from "../orchestration/context-overflow.js";
9
- import { getAssistantTurnErrorMessage, isAssistantTurnAborted, isAssistantTurnFailed, maybeRetryTurnAfterTransientLlmFailure, stripTrailingErrorAssistantMessages } from "../orchestration/llm-turn-retry.js";
10
13
  import { projectContextForModel } from "../memory/context-budget.js";
11
- import { EmbeddedRunConflictError, abortEmbeddedRun, acquireEmbeddedRunLease, queueEmbeddedSteer } from "./runs.js";
12
- import { lastAssistantPlainText, subscribeEmbeddedSessionEvents } from "./subscribe-session.js";
13
- import { detectToolLoops } from "../orchestration/loop-guard.js";
14
- import { tryApplySessionTranscriptHygiene } from "../transcript/transcript-hygiene.js";
15
14
  import { createSqliteTranscriptRuntime } from "./transcript-runtime.js";
16
15
  import { buildPromptCacheSnapshot, observePromptCacheSnapshot } from "../../providers/prompt-cache-observability.js";
17
16
  import { isPromptCacheExpired, recordPromptCacheTouch } from "../../providers/prompt-cache-lifecycle.js";
17
+ import { markTurnToolResult } from "../memory/turn-provenance.js";
18
+ import { RepositoryInstructions } from "../coding/repository-instructions.js";
19
+ import { RunVerification } from "../coding/run-verification.js";
18
20
  //#region src/agent/embedded/run-turn.ts
19
21
  init_logger();
20
22
  const log = createLogger("EmbeddedRun");
@@ -30,12 +32,17 @@ function extractTextFromContent(content) {
30
32
  }).map((block) => block.text).join("");
31
33
  }
32
34
  function extractRecentToolCalls(messages) {
35
+ const lastUser = messages.findLastIndex((message) => message.role === "user");
36
+ messages = messages.slice(Math.max(0, lastUser));
33
37
  const resultByToolCallId = /* @__PURE__ */ new Map();
38
+ const revisionByToolCallId = /* @__PURE__ */ new Map();
34
39
  for (const message of messages) {
35
40
  if (message.role !== "toolResult") continue;
36
41
  const toolCallId = message.toolCallId;
37
42
  if (typeof toolCallId !== "string" || !toolCallId) continue;
38
- resultByToolCallId.set(toolCallId, truncateForLog(extractTextFromContent(message.content)));
43
+ resultByToolCallId.set(toolCallId, extractTextFromContent(message.content));
44
+ const revision = message.details?.workspaceRevision;
45
+ if (typeof revision === "string") revisionByToolCallId.set(toolCallId, revision);
39
46
  }
40
47
  const calls = [];
41
48
  for (const message of messages) {
@@ -45,11 +52,12 @@ function extractRecentToolCalls(messages) {
45
52
  calls.push({
46
53
  name: toolCall.name,
47
54
  params: toolCall.arguments,
55
+ ...toolCall.id && revisionByToolCallId.has(toolCall.id) ? { revision: revisionByToolCallId.get(toolCall.id) } : {},
48
56
  ...toolCall.id && resultByToolCallId.has(toolCall.id) ? { resultPreview: resultByToolCallId.get(toolCall.id) } : {}
49
57
  });
50
58
  }
51
59
  }
52
- return calls;
60
+ return calls.slice(-12);
53
61
  }
54
62
  function getLastUserMessagePreview(messages) {
55
63
  for (let messageIndex = messages.length - 1; messageIndex >= 0; messageIndex--) {
@@ -119,6 +127,8 @@ async function runXopcEmbeddedTurn(params) {
119
127
  sessionId: transcriptRuntime.sessionId,
120
128
  runId
121
129
  });
130
+ const instructions = await RepositoryInstructions.open(workspaceDir);
131
+ const rootInstructions = await instructions.load(".", true);
122
132
  runner = await acquireEmbeddedSessionRunner({
123
133
  runtimeId: transcriptRuntime.runtimeId,
124
134
  sessionId: transcriptRuntime.sessionId,
@@ -126,7 +136,7 @@ async function runXopcEmbeddedTurn(params) {
126
136
  model: resolvedModel,
127
137
  modelRef: params.modelRef,
128
138
  tools,
129
- systemPrompt,
139
+ systemPrompt: [systemPrompt, rootInstructions].filter(Boolean).join("\n\n"),
130
140
  thinkingLevel: thinkingLevel ?? "medium",
131
141
  transcriptRuntime
132
142
  });
@@ -143,6 +153,7 @@ async function runXopcEmbeddedTurn(params) {
143
153
  runner.piSm.setActiveTurnId?.(runId);
144
154
  const streamFnWithXopcExtensions = wrapStreamFnForXopcExtensions(session.agent.streamFunction, params.promptCachePolicy);
145
155
  const loggingStreamFn = (streamModel, context, options) => {
156
+ instructions.acknowledge();
146
157
  const sourceMessages = [...context.messages];
147
158
  const hygienicMessages = tryApplySessionTranscriptHygiene(sourceMessages, streamModel);
148
159
  const loopGuard = detectToolLoops(extractRecentToolCalls(hygienicMessages));
@@ -150,19 +161,14 @@ async function runXopcEmbeddedTurn(params) {
150
161
  ...context,
151
162
  messages: hygienicMessages
152
163
  };
153
- if (loopGuard.injection || loopGuard.hiddenTools.size > 0) {
154
- const messages = loopGuard.injection ? [...hygienicMessages, {
164
+ if (loopGuard.injection) effectiveContext = {
165
+ ...effectiveContext,
166
+ messages: [...hygienicMessages, {
155
167
  role: "user",
156
168
  content: loopGuard.injection,
157
169
  timestamp: Date.now()
158
- }] : hygienicMessages;
159
- const contextTools = loopGuard.hiddenTools.size > 0 && context.tools ? context.tools.filter((t) => !loopGuard.hiddenTools.has(t.name)) : context.tools;
160
- effectiveContext = {
161
- ...context,
162
- messages,
163
- tools: contextTools
164
- };
165
- }
170
+ }]
171
+ };
166
172
  const projection = projectContextForModel({
167
173
  messages: effectiveContext.messages,
168
174
  contextWindow: streamModel.contextWindow ?? 128e3,
@@ -203,7 +209,6 @@ async function runXopcEmbeddedTurn(params) {
203
209
  toolCount: effectiveContext.tools?.length ?? 0,
204
210
  lastUserMessagePreview: getLastUserMessagePreview(effectiveContext.messages),
205
211
  loopWarningInjected: !!loopGuard.injection,
206
- hiddenToolCount: loopGuard.hiddenTools.size,
207
212
  promptCache: promptCacheSnapshot,
208
213
  promptCacheChanges,
209
214
  ...process.env.XOPC_LOG_LLM_PAYLOAD === "true" ? { effectiveContext: {
@@ -215,10 +220,53 @@ async function runXopcEmbeddedTurn(params) {
215
220
  return streamFnWithXopcExtensions(streamModel, effectiveContext, { ...options });
216
221
  };
217
222
  session.agent.streamFunction = loggingStreamFn;
223
+ const verification = await RunVerification.open(workspaceDir);
224
+ const checkpoints = runner.piSm.getBranch?.() ?? [];
225
+ const lastStart = checkpoints.findLastIndex((entry) => entry.type === "custom" && entry.customType === "coding_run_started");
226
+ const lastSummary = checkpoints.findLastIndex((entry) => entry.type === "custom" && entry.customType === "coding_verification");
227
+ const checkpoint = checkpoints[params.resumeLastUserMessage && lastSummary >= lastStart ? lastSummary : lastStart];
228
+ if (checkpoint?.type === "custom" && (params.resumeLastUserMessage || lastStart > lastSummary)) verification.restore(checkpoint.data, params.resumeLastUserMessage === true && lastSummary >= lastStart);
229
+ runner.piSm.appendCustomEntry("coding_run_started", {
230
+ runId,
231
+ workspace: workspaceDir,
232
+ required: params.verifyChanges ?? sessionKey.startsWith("agent:coder:"),
233
+ ...await verification.summary()
234
+ });
235
+ let policyStopped = false;
218
236
  params.turnPolicy?.reset();
219
- session.agent.beforeToolCall = params.turnPolicy?.beforeToolCall;
220
- session.agent.afterToolCall = params.turnPolicy?.afterToolCall;
221
- session.agent.shouldStopAfterTurn = params.turnPolicy?.shouldStopAfterTurn;
237
+ session.agent.beforeToolCall = async (context, signal) => {
238
+ const decision = await params.turnPolicy?.beforeToolCall(context, signal);
239
+ if (decision?.block) {
240
+ policyStopped ||= decision.terminate === true;
241
+ return decision;
242
+ }
243
+ if (context.toolCall.name !== "read_file") {
244
+ const scoped = await instructions.forTool(context.toolCall.name, context.args);
245
+ if (scoped) return {
246
+ block: true,
247
+ reason: `${scoped}\n\nApply these instructions, then retry the operation.`
248
+ };
249
+ }
250
+ await verification.beforeTool(context.toolCall.id, context.toolCall.name);
251
+ return decision;
252
+ };
253
+ session.agent.afterToolCall = async (context) => {
254
+ const scoped = context.toolCall.name === "read_file" ? await instructions.forTool(context.toolCall.name, context.args) : "";
255
+ const checked = await verification.afterTool(context);
256
+ if (scoped) checked.result.content.unshift({
257
+ type: "text",
258
+ text: scoped
259
+ });
260
+ await params.turnPolicy?.afterToolCall({
261
+ ...context,
262
+ ...checked
263
+ });
264
+ return checked;
265
+ };
266
+ session.agent.shouldStopAfterTurn = (context) => {
267
+ policyStopped ||= params.turnPolicy?.shouldStopAfterTurn(context) ?? false;
268
+ return policyStopped;
269
+ };
222
270
  unsubscribe = subscribeEmbeddedSessionEvents(session, (event) => {
223
271
  if (event.type === "message_end" && event.message.role === "assistant") recordPromptCacheTouch(sessionKey, resolvedModel, event.message.usage);
224
272
  if (event.type === "tool_execution_end") markTurnToolResult(sessionKey, runId, event.toolName);
@@ -226,7 +274,7 @@ async function runXopcEmbeddedTurn(params) {
226
274
  ...event,
227
275
  runId
228
276
  });
229
- });
277
+ }, params.onAgentEvent);
230
278
  const abortListener = () => {
231
279
  session.abort();
232
280
  };
@@ -253,7 +301,22 @@ async function runXopcEmbeddedTurn(params) {
253
301
  abortSignal: runAbortSignal,
254
302
  onEvent
255
303
  });
304
+ const pending = await verification.pendingContext();
305
+ if ((params.verifyChanges ?? sessionKey.startsWith("agent:coder:")) && pending && !policyStopped && !runAbortSignal.aborted && !isAssistantTurnFailed(session.agent) && !isAssistantTurnAborted(session.agent)) {
306
+ await session.sendCustomMessage({
307
+ customType: "coding_verification",
308
+ content: pending,
309
+ display: false
310
+ }, { triggerTurn: true });
311
+ await session.agent.waitForIdle();
312
+ }
256
313
  }, timeoutMs);
314
+ runner.piSm.appendCustomEntry("coding_verification", {
315
+ runId,
316
+ workspace: workspaceDir,
317
+ required: params.verifyChanges ?? sessionKey.startsWith("agent:coder:"),
318
+ ...await verification.summary()
319
+ });
257
320
  if (runAbortSignal.aborted) return {
258
321
  ok: false,
259
322
  errorMessage: "aborted"
@@ -1,10 +1,10 @@
1
1
  import { init_string_coerce, normalizeOptionalString } from "../../utils/string-coerce.js";
2
+ import { extractToolCallsFromAssistant, extractToolResultId } from "../transcript/tool-call-id.js";
3
+ import { makeMissingToolResult, sanitizeToolCallInputs } from "../transcript/session-transcript-repair.js";
2
4
  import { boundedJsonUtf8Bytes, firstEnumerableOwnKeys, jsonUtf8BytesOrInfinity } from "../../infra/json-utf8-bytes.js";
3
5
  import { emitSessionTranscriptUpdate } from "../../session/transcript-events.js";
4
6
  import { formatContextLimitTruncationNotice } from "./tool-result-context-guard.js";
5
7
  import { resolveLiveToolResultMaxChars, truncateToolResultMessage } from "./tool-result-truncation.js";
6
- import { extractToolCallsFromAssistant, extractToolResultId } from "../transcript/tool-call-id.js";
7
- import { makeMissingToolResult, sanitizeToolCallInputs } from "../transcript/session-transcript-repair.js";
8
8
  //#region src/agent/embedded/session-tool-result-guard.ts
9
9
  init_string_coerce();
10
10
  /**
@@ -1,4 +1,5 @@
1
1
  import type { AgentSession } from '@earendil-works/pi-coding-agent';
2
+ import type { AgentEvent } from '@earendil-works/pi-agent-core';
2
3
  import type { EmbeddedStreamEvent } from './types.js';
3
- export declare function subscribeEmbeddedSessionEvents(session: AgentSession, onEvent: (event: EmbeddedStreamEvent) => void): () => void;
4
+ export declare function subscribeEmbeddedSessionEvents(session: AgentSession, onEvent: (event: EmbeddedStreamEvent) => void, onAgentEvent?: (event: AgentEvent) => void): () => void;
4
5
  export declare function lastAssistantPlainText(session: AgentSession): string | undefined;
@@ -1,8 +1,9 @@
1
1
  import { extractTextContent } from "../context/workspace.js";
2
2
  //#region src/agent/embedded/subscribe-session.ts
3
- function subscribeEmbeddedSessionEvents(session, onEvent) {
3
+ function subscribeEmbeddedSessionEvents(session, onEvent, onAgentEvent) {
4
4
  return session.subscribe((event) => {
5
5
  const base = event;
6
+ onAgentEvent?.(base);
6
7
  switch (base.type) {
7
8
  case "agent_start":
8
9
  onEvent({ type: "agent_start" });
@@ -1,4 +1,4 @@
1
- import type { AgentMessage, AgentToolResult, ThinkingLevel } from '@earendil-works/pi-agent-core';
1
+ import type { AgentEvent, AgentMessage, AgentToolResult, ThinkingLevel } from '@earendil-works/pi-agent-core';
2
2
  import type { AssistantMessageEvent, Model, Api, ImageContent } from '@earendil-works/pi-ai';
3
3
  import type { TurnOutcome } from '@xopcai/gateway-contract';
4
4
  import type { SessionStore } from '../../session/store.js';
@@ -106,9 +106,11 @@ export type RunXopcEmbeddedTurnParams = {
106
106
  turnPolicy?: AgentTurnPolicy;
107
107
  abortSignal?: AbortSignal;
108
108
  onEvent?: (event: EmbeddedStreamEvent) => void;
109
+ onAgentEvent?: (event: AgentEvent) => void;
109
110
  images?: ImageContent[];
110
111
  /** Continue from the persisted trailing user row instead of appending it again. */
111
112
  resumeLastUserMessage?: boolean;
113
+ verifyChanges?: boolean;
112
114
  };
113
115
  export type RunXopcEmbeddedTurnResult = {
114
116
  ok: boolean;
@@ -84,7 +84,10 @@ function invalidApplyPatchEnvelopeResult(error) {
84
84
  type: "text",
85
85
  text: `apply_patch input rejected (${error.issue}). Expected: ${error.expected}.${received} ${error.retryHint} Use this exact envelope:\n${APPLY_PATCH_BEGIN_MARKER}\n*** Update File: path\n@@\n-old\n+new\n${APPLY_PATCH_END_MARKER}`
86
86
  }],
87
- details: error
87
+ details: {
88
+ ...error,
89
+ status: "failed"
90
+ }
88
91
  };
89
92
  }
90
93
  /** Map xopc {@link AgentTool} instances to pi-coding-agent {@link ToolDefinition}s for `createAgentSession`. */
@@ -1,9 +1,9 @@
1
1
  import { getImageUnderstandingProvider, listImageUnderstandingProviders, registerImageUnderstandingProvider } from "./understanding/provider-registry.js";
2
2
  import { resolveImageModelConfigForTool } from "./tool-model-config.js";
3
3
  import { describeImages, describeImagesWithFallback } from "./understanding/runtime.js";
4
+ import { modelSupportsVision, resolveImageHandlingStrategy } from "./vision-detection.js";
4
5
  import { runWithImageModelFallback } from "./image-model-fallback.js";
5
6
  import { loadImageForToolInput } from "./load-image-media.js";
6
7
  import { getImageGenerationProvider, listImageGenerationProviders } from "./generation/provider-registry.js";
7
8
  import { generateImage, listImageGenerationProvidersSummary } from "./generation/runtime.js";
8
- import { modelSupportsVision, resolveImageHandlingStrategy } from "./vision-detection.js";
9
9
  export { describeImages, describeImagesWithFallback, generateImage, getImageGenerationProvider, getImageUnderstandingProvider, listImageGenerationProviders, listImageGenerationProvidersSummary, listImageUnderstandingProviders, loadImageForToolInput, modelSupportsVision, registerImageUnderstandingProvider, resolveImageHandlingStrategy, resolveImageModelConfigForTool, runWithImageModelFallback };
@@ -1,13 +1,13 @@
1
+ import { resolveTranscriptPolicy } from "./transcript/transcript-policy.js";
2
+ import { dropThinkingBlocks } from "./transcript/thinking.js";
1
3
  import { extractToolCallsFromAssistant, extractToolResultId, sanitizeToolCallId, sanitizeToolCallIdsForCloudCodeAssist } from "./transcript/tool-call-id.js";
2
4
  import { makeMissingToolResult, repairToolUseResultPairing, sanitizeToolCallInputs, sanitizeToolUseResultPairing, stripToolResultDetails } from "./transcript/session-transcript-repair.js";
5
+ import { applySessionTranscriptHygiene, applySessionTranscriptHygieneForPersistence, applySessionTranscriptHygieneWithPolicy, resolvePolicyForModel, tryApplySessionTranscriptHygiene, tryApplySessionTranscriptHygieneForPersistence } from "./transcript/transcript-hygiene.js";
3
6
  import { createResponseMessage, createSignalMessage, createTaskMessage, isValidIPCMessage } from "./ipc/types.js";
4
7
  import { AgentInbox } from "./ipc/inbox.js";
5
8
  import { AgentBus } from "./ipc/bus.js";
6
9
  import { AgentSocketClient, AgentSocketServer, isSocketAvailable } from "./ipc/socket.js";
7
10
  import "./ipc/index.js";
8
- import { resolveTranscriptPolicy } from "./transcript/transcript-policy.js";
9
- import { dropThinkingBlocks } from "./transcript/thinking.js";
10
- import { applySessionTranscriptHygiene, applySessionTranscriptHygieneForPersistence, applySessionTranscriptHygieneWithPolicy, resolvePolicyForModel, tryApplySessionTranscriptHygiene, tryApplySessionTranscriptHygieneForPersistence } from "./transcript/transcript-hygiene.js";
11
11
  import { AgentService } from "./service.js";
12
12
  import { stripToolMessages } from "./transcript/strip-tool-messages.js";
13
13
  import "./transcript/index.js";
@@ -1,9 +1,9 @@
1
1
  import { init_session_key, parseSessionKey } from "../../routing/session-key.js";
2
+ import { consumeTurnMemoryProvenance, markTurnRecalledContext } from "./turn-provenance.js";
2
3
  import { assembleTaskContext } from "../../tasks/task-context-assembler.js";
3
4
  import { shouldPlanUserContextThisTurn } from "./memory-config.js";
4
5
  import { UserContextPlanner, prependAgentContext } from "../../user-context/planner.js";
5
6
  import { extractAgentUserPlainText } from "./user-message-text.js";
6
- import { consumeTurnMemoryProvenance, markTurnRecalledContext } from "./turn-provenance.js";
7
7
  import { planTrustedRecall } from "./trusted-recall.js";
8
8
  //#region src/agent/memory/user-context-coordinator.ts
9
9
  init_session_key();
@@ -1,6 +1 @@
1
- /**
2
- * Agent middleware — request-scoped log context (`ContextMiddleware`) and
3
- * harness-style self-verify tracking (`SelfVerifyMiddleware`).
4
- */
5
- export { SelfVerifyMiddleware, type FileEditRecord, type SelfVerifyConfig, type SelfVerifyAgentKind, type SelfVerifyState, type VerificationTask, type VerificationRecord, } from './self-verify.js';
6
1
  export { ContextMiddleware, type RequestContext } from './context.js';
@@ -1,3 +1,2 @@
1
- import { SelfVerifyMiddleware } from "./self-verify.js";
2
1
  import { ContextMiddleware } from "./context.js";
3
- export { ContextMiddleware, SelfVerifyMiddleware };
2
+ export { ContextMiddleware };
@@ -18,11 +18,9 @@ import type { ToolErrorTracker } from '../tools/error-tracker.js';
18
18
  import type { RequestLimiter } from '../models/request-limiter.js';
19
19
  import type { LifecycleManager } from '../lifecycle/index.js';
20
20
  import type { ToolChainTracker } from '../tools/chain-tracker.js';
21
- import type { SelfVerifyMiddleware } from '../middleware/index.js';
22
21
  import type { SystemReminder } from '../prompt/system-reminder.js';
23
22
  import type { ToolUsageAnalyzer } from '../tools/usage-analyzer.js';
24
23
  import type { ErrorPatternMatcher } from '../tools/error-pattern-matcher.js';
25
- import type { TurnDiffTracker } from '../coding/index.js';
26
24
  export type SessionEventListener = (event: AgentEvent, context: SessionContext) => void;
27
25
  export type SessionEventTypeFilter = AgentEvent['type'] | 'all';
28
26
  /**
@@ -35,17 +33,14 @@ export declare class SessionEventBus {
35
33
  on(type: SessionEventTypeFilter, listener: SessionEventListener): () => void;
36
34
  dispatch(event: AgentEvent, context: SessionContext | null): void;
37
35
  }
38
- export declare function readChangedPathsFromToolEnd(toolName: string, args: unknown, result: unknown): string[];
39
36
  export interface AgentEventHandlerConfig {
40
37
  errorTracker: ToolErrorTracker;
41
38
  requestLimiter: RequestLimiter;
42
39
  lifecycleManager: LifecycleManager;
43
40
  toolChainTracker: ToolChainTracker;
44
- selfVerifyMiddleware: SelfVerifyMiddleware;
45
41
  systemReminder: SystemReminder;
46
42
  toolUsageAnalyzer: ToolUsageAnalyzer;
47
43
  errorPatternMatcher: ErrorPatternMatcher;
48
- turnDiffTracker?: TurnDiffTracker;
49
44
  }
50
45
  /**
51
46
  * Thin façade over {@link SessionEventBus} that pre-registers all built-in
@@ -122,58 +122,6 @@ function installSystemReminderListener(bus, systemReminder) {
122
122
  e.result = systemReminder.appendToResult(e.result, e.toolName);
123
123
  });
124
124
  }
125
- function appendTextToToolResult(result, text) {
126
- if (!text.trim()) return result;
127
- if (result && typeof result === "object") {
128
- const res = result;
129
- if (Array.isArray(res.content)) {
130
- res.content = [...res.content, {
131
- type: "text",
132
- text: `\n${text}`
133
- }];
134
- return res;
135
- }
136
- if (typeof res.content === "string") {
137
- res.content = `${res.content}\n${text}`;
138
- return res;
139
- }
140
- }
141
- return result;
142
- }
143
- function readRecord(value) {
144
- return value && typeof value === "object" ? value : null;
145
- }
146
- function readToolResultDetails(result) {
147
- const rec = readRecord(result);
148
- if (!rec) return null;
149
- return readRecord(rec.details);
150
- }
151
- function readStringArray(value) {
152
- return Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
153
- }
154
- function readChangedPathsFromToolEnd(toolName, args, result) {
155
- const name = toolName.toLowerCase();
156
- const details = readToolResultDetails(result);
157
- if (name === "apply_patch") {
158
- const files = readStringArray(details?.files);
159
- if (files.length > 0) return files;
160
- return (Array.isArray(details?.changes) ? details.changes : []).flatMap((change) => {
161
- const rec = readRecord(change);
162
- if (!rec) return [];
163
- return readStringArray([rec.moveTo, rec.path]);
164
- });
165
- }
166
- if (name === "write_file") {
167
- if (typeof details?.size !== "number") return [];
168
- const rec = readRecord(args);
169
- return typeof rec?.path === "string" ? [rec.path] : [];
170
- }
171
- if (name.includes("write") || name.includes("edit")) {
172
- const rec = readRecord(args);
173
- return typeof rec?.path === "string" ? [rec.path] : [];
174
- }
175
- return [];
176
- }
177
125
  function installToolChainListener(bus, toolChainTracker) {
178
126
  bus.on("turn_start", (_event, context) => {
179
127
  toolChainTracker.startChain(context.sessionKey);
@@ -231,47 +179,6 @@ function installErrorTrackingListener(bus, deps) {
231
179
  deps.errorTracker.reset();
232
180
  });
233
181
  }
234
- function installSelfVerifyListener(bus, selfVerifyMiddleware) {
235
- bus.on("tool_execution_end", (event, context) => {
236
- const e = event;
237
- const name = e.toolName?.toLowerCase() ?? "";
238
- const args = e.args;
239
- if (name === "exec_command") {
240
- selfVerifyMiddleware.recordVerification(e.toolName, args, {
241
- isError: e.isError,
242
- result: e.result
243
- }, context.sessionKey);
244
- return;
245
- }
246
- if (!e.isError) {
247
- const changedPaths = readChangedPathsFromToolEnd(e.toolName, args, e.result);
248
- for (const path of changedPaths) selfVerifyMiddleware.recordEdit(path, name.includes("write") ? "write" : "edit", context.sessionKey);
249
- if (changedPaths.length > 0) {
250
- e.result = appendTextToToolResult(e.result, selfVerifyMiddleware.consumePostEditReminder(context.sessionKey));
251
- return;
252
- }
253
- selfVerifyMiddleware.recordVerification(e.toolName, args, {
254
- isError: e.isError,
255
- result: e.result
256
- }, context.sessionKey);
257
- }
258
- });
259
- bus.on("turn_start", (_event, context) => {
260
- selfVerifyMiddleware.onTurnStart(context.sessionKey);
261
- });
262
- }
263
- function installTurnDiffTrackerListener(bus, turnDiffTracker) {
264
- bus.on("tool_execution_end", (event, context) => {
265
- const e = event;
266
- turnDiffTracker.recordToolResult({
267
- sessionKey: context.sessionKey,
268
- toolName: e.toolName,
269
- args: e.args,
270
- result: e.result,
271
- isError: e.isError
272
- });
273
- });
274
- }
275
182
  /**
276
183
  * Thin façade over {@link SessionEventBus} that pre-registers all built-in
277
184
  * listeners in their required order. `handle(event, ctx)` is the entry point
@@ -288,8 +195,6 @@ var AgentEventHandler = class {
288
195
  });
289
196
  installLifecycleHookListener(this.bus, config.lifecycleManager);
290
197
  installSystemReminderListener(this.bus, config.systemReminder);
291
- if (config.turnDiffTracker) installTurnDiffTrackerListener(this.bus, config.turnDiffTracker);
292
- installSelfVerifyListener(this.bus, config.selfVerifyMiddleware);
293
198
  installToolUsageListener(this.bus, config.toolUsageAnalyzer);
294
199
  installToolChainListener(this.bus, config.toolChainTracker);
295
200
  installErrorTrackingListener(this.bus, {
@@ -312,4 +217,4 @@ var AgentEventHandler = class {
312
217
  }
313
218
  };
314
219
  //#endregion
315
- export { AgentEventHandler, SessionEventBus, readChangedPathsFromToolEnd };
220
+ export { AgentEventHandler, SessionEventBus };
@@ -1,11 +1,11 @@
1
1
  import { createLogger } from "../../utils/logger/index.js";
2
2
  import { init_logger } from "../../utils/logger.js";
3
3
  import { runContextConsolidation } from "../../user-context/consolidation.js";
4
+ import { abortEmbeddedRun } from "../embedded/runs.js";
4
5
  import { persistInboundAttachments } from "../../channels/attachments/inbound-persist.js";
5
6
  import { buildTranscriptUserMessage, clearPendingTranscriptUserMessage, hydrateUserTurnForLlm, setPendingTranscriptUserMessage } from "../inbound/attachment-pipeline.js";
6
7
  import { extractAgentUserPlainText } from "../memory/user-message-text.js";
7
8
  import { resolveEffectiveThinkingLevel } from "../../session/thinking-resolve.js";
8
- import { abortEmbeddedRun } from "../embedded/runs.js";
9
9
  import { runEmbeddedTurnForSession } from "../embedded/run-for-session.js";
10
10
  import { randomUUID } from "node:crypto";
11
11
  //#region src/agent/orchestration/agent-orchestrator.ts
@@ -1,15 +1,14 @@
1
1
  //#region src/agent/orchestration/agent-turn-policy.ts
2
- function assistantMessageCount(messages) {
3
- return messages.filter((message) => message.role === "assistant").length;
4
- }
5
2
  /** One user-visible run policy. A fresh instance is created for every embedded run. */
6
3
  function createAgentTurnPolicy(options) {
7
4
  const toolCalls = /* @__PURE__ */ new Map();
8
5
  let toolFailures = 0;
6
+ let assistantTurns = 0;
9
7
  return {
10
8
  reset() {
11
9
  toolCalls.clear();
12
10
  toolFailures = 0;
11
+ assistantTurns = 0;
13
12
  },
14
13
  async beforeToolCall(context, signal) {
15
14
  const limit = options.resolveToolLimit?.(context.toolCall.name, context.args);
@@ -27,8 +26,9 @@ function createAgentTurnPolicy(options) {
27
26
  async afterToolCall(context) {
28
27
  if (context.isError) toolFailures += 1;
29
28
  },
30
- shouldStopAfterTurn(context) {
31
- return Boolean(options.maxTurns && assistantMessageCount(context.newMessages) >= options.maxTurns || options.maxToolFailures && toolFailures >= options.maxToolFailures);
29
+ shouldStopAfterTurn(_context) {
30
+ assistantTurns += 1;
31
+ return Boolean(options.maxTurns && assistantTurns >= options.maxTurns || options.maxToolFailures && toolFailures >= options.maxToolFailures);
32
32
  }
33
33
  };
34
34
  }
@@ -2,4 +2,4 @@
2
2
  * Orchestration Layer - Exports all orchestration-related modules
3
3
  */
4
4
  export { AgentOrchestrator, type AgentOrchestratorConfig } from './agent-orchestrator.js';
5
- export { AgentEventHandler, SessionEventBus, readChangedPathsFromToolEnd, type AgentEventHandlerConfig, type SessionEventListener, type SessionEventTypeFilter, } from './agent-event-handler.js';
5
+ export { AgentEventHandler, SessionEventBus, type AgentEventHandlerConfig, type SessionEventListener, type SessionEventTypeFilter, } from './agent-event-handler.js';
@@ -1,3 +1,3 @@
1
1
  import { AgentOrchestrator } from "./agent-orchestrator.js";
2
- import { AgentEventHandler, SessionEventBus, readChangedPathsFromToolEnd } from "./agent-event-handler.js";
3
- export { AgentEventHandler, AgentOrchestrator, SessionEventBus, readChangedPathsFromToolEnd };
2
+ import { AgentEventHandler, SessionEventBus } from "./agent-event-handler.js";
3
+ export { AgentEventHandler, AgentOrchestrator, SessionEventBus };
@@ -1,37 +1,10 @@
1
- /**
2
- * Loop Guard — Detects repetitive tool call patterns within an agent turn
3
- * and produces context injections for the LLM.
4
- *
5
- * Design: pure function that analyzes recent tool call history (already in
6
- * the transcript) and returns:
7
- * - A developer-role message to inject into the next LLM request
8
- * - A set of tool names to temporarily hide from the model
9
- *
10
- * This operates at the orchestration layer (before LLM sees tools/messages)
11
- * rather than the execution layer, so the model naturally stops calling
12
- * blocked tools without receiving confusing "fake" tool outputs.
13
- */
14
1
  export interface RecentToolCall {
15
2
  name: string;
16
3
  params: unknown;
17
- /** Optional: tool result text (for same-result detection). */
18
4
  resultPreview?: string;
5
+ revision?: string;
19
6
  }
20
- export interface LoopGuardConfig {
21
- /** Consecutive identical calls before injecting a soft warning (default: 2). */
22
- softThreshold: number;
23
- /** Consecutive identical calls before hiding the tool (default: 3). */
24
- hideThreshold: number;
25
- }
26
- export interface LoopGuardResult {
27
- /** Developer message to inject into LLM context (null = no loop). */
7
+ /** Warn on a stalled tail, without removing tools needed to recover or verify a repair. */
8
+ export declare function detectToolLoops(recentCalls: readonly RecentToolCall[]): {
28
9
  injection: string | null;
29
- /** Tool names to remove from the available tools list. */
30
- hiddenTools: Set<string>;
31
- }
32
- /**
33
- * Analyze recent tool calls and produce loop guard result.
34
- *
35
- * Pure function — no side effects, no shared state.
36
- */
37
- export declare function detectToolLoops(recentCalls: readonly RecentToolCall[], config?: Partial<LoopGuardConfig>): LoopGuardResult;
10
+ };