@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,177 +1,131 @@
1
- import { createLogger } from "../utils/logger/index.js";
2
- import { init_logger } from "../utils/logger.js";
3
- import { init_sync_provider_auth, resolveProviderApiKeySync } from "../auth/sync-provider-auth.js";
4
- import { getApiKeySync, init_providers } from "../providers/index.js";
5
- import { createExtensionAwareStreamFn } from "../providers/extension-stream-bridge.js";
6
- import { extractTextContent } from "./context/workspace.js";
7
- import { resolveAgentTurnTimeoutMs, runAgentTurnWithTimeout } from "./orchestration/run-agent-turn-with-timeout.js";
1
+ import { evictEmbeddedSessionRunner } from "./embedded/session-runner.js";
2
+ import { InMemoryTranscriptRuntime } from "./embedded/transcript-runtime.js";
3
+ import { runXopcEmbeddedTurn } from "./embedded/run-turn.js";
4
+ import { createAgentTurnPolicy } from "./orchestration/agent-turn-policy.js";
8
5
  import { buildSubagentSystemPrompt } from "./prompt/subagent-context.js";
9
6
  import { resolveResponseLanguageForSession } from "./prompt/response-language.js";
10
- import { Agent } from "@earendil-works/pi-agent-core";
7
+ import { randomUUID } from "node:crypto";
11
8
  //#region src/agent/child-agent-factory.ts
12
- init_sync_provider_auth();
13
- init_providers();
14
- init_logger();
15
- const log = createLogger("delegate-child");
16
- /**
17
- * Build an isolated tool factory (no extensions, no session memory hooks) and a child {@link Agent}.
18
- */
9
+ /** Leaf workers use the same execution, transcript and verification harness as foreground turns. */
19
10
  function createDelegateChildHandle(options) {
20
- const allTools = options.buildChildTools({
21
- workspace: options.workspace,
22
- bus: options.bus,
23
- model: options.model,
24
- agentId: options.agentId,
25
- getConfig: options.getConfig,
26
- toolExecutorConfig: options.toolExecutorConfig
11
+ const controller = new AbortController();
12
+ const sessionKey = options.sessionKey ?? `agent:subagent:internal:${randomUUID()}`;
13
+ const runtime = options.transcriptRuntime ?? new InMemoryTranscriptRuntime({
14
+ runtimeId: sessionKey,
15
+ cwd: options.workspace
27
16
  });
28
- const allow = new Set(options.allowedToolNames);
29
- const filteredTools = allTools.filter((t) => allow.has(t.name));
30
- if (filteredTools.length === 0) return {
31
- async run() {
32
- return {
33
- summary: "No tools matched the allowlist after factory registration.",
34
- toolIterations: 0,
35
- messages: []
36
- };
37
- },
38
- abort() {}
39
- };
40
- let toolIterations = 0;
41
- let aborted = false;
42
- const progress = options.progressHooks;
43
- const agent = new Agent({
44
- initialState: {
45
- systemPrompt: buildSubagentSystemPrompt({
46
- goal: options.goal,
47
- context: options.context,
48
- workspace: options.workspace,
49
- toolNames: filteredTools.map((t) => t.name),
50
- responseLanguage: resolveResponseLanguageForSession(options.getConfig(), options.requesterSessionKey)
51
- }),
52
- model: options.model,
53
- thinkingLevel: "low",
54
- tools: filteredTools,
55
- messages: []
56
- },
57
- toolExecution: "parallel",
58
- streamFn: createExtensionAwareStreamFn(),
59
- getApiKey: (provider) => resolveProviderApiKeySync(provider) ?? getApiKeySync(provider) ?? "",
60
- beforeToolCall: async ({ toolCall, args }) => {
61
- if (aborted) return {
62
- block: true,
63
- reason: "Sub-agent aborted."
64
- };
65
- if (toolIterations >= options.maxIterations) return {
66
- block: true,
67
- reason: `Sub-agent reached max tool iterations (${options.maxIterations}).`
68
- };
69
- progress?.onProgress({
70
- type: "tool_start",
71
- toolCallId: toolCall.id,
72
- toolName: toolCall.name,
73
- args: args ?? {}
74
- });
75
- },
76
- afterToolCall: async ({ toolCall, isError }) => {
77
- toolIterations += 1;
78
- progress?.onProgress({
79
- type: "iteration",
80
- count: toolIterations,
81
- max: options.maxIterations
82
- });
83
- progress?.onProgress({
84
- type: "tool_end",
85
- toolCallId: toolCall.id,
86
- toolName: toolCall.name,
87
- isError: Boolean(isError)
88
- });
89
- }
90
- });
91
- const userText = options.context?.trim() ? `${options.goal}\n\nAdditional context:\n${options.context.trim()}` : options.goal;
17
+ let started = false;
92
18
  return {
19
+ abort: () => controller.abort(/* @__PURE__ */ new Error("Sub-agent cancelled")),
93
20
  async run() {
94
- toolIterations = 0;
95
- aborted = false;
96
- const unsub = agent.subscribe((ev) => {
97
- if (progress?.mode === "full" && ev.type === "message_update") {
98
- const delta = ev.assistantMessageEvent;
99
- if (delta?.type === "text_delta" && typeof delta.delta === "string" && delta.delta) progress.onProgress({
100
- type: "text_delta",
101
- delta: delta.delta
102
- });
103
- if (delta?.type === "thinking_delta" && typeof delta.delta === "string" && delta.delta) progress.onProgress({
104
- type: "thinking_delta",
105
- delta: delta.delta
106
- });
107
- }
108
- if (options.onTranscriptSnapshot && (ev.type === "message_end" || ev.type === "tool_execution_end")) try {
109
- Promise.resolve(options.onTranscriptSnapshot(agent.state.messages)).catch((err) => {
110
- const msg = err instanceof Error ? err.message : String(err);
111
- log.warn({
112
- err,
113
- errorMessage: msg
114
- }, `Failed to persist child transcript snapshot: ${msg}`);
115
- });
116
- } catch (err) {
117
- const msg = err instanceof Error ? err.message : String(err);
118
- log.warn({
119
- err,
120
- errorMessage: msg
121
- }, `Failed to persist child transcript snapshot: ${msg}`);
21
+ if (started) throw new Error("A child handle can only run once");
22
+ started = true;
23
+ controller.signal.throwIfAborted();
24
+ const allow = new Set(options.allowedToolNames);
25
+ const tools = options.buildChildTools({
26
+ workspace: options.workspace,
27
+ bus: options.bus,
28
+ model: options.model,
29
+ agentId: options.agentId,
30
+ getConfig: options.getConfig,
31
+ toolExecutorConfig: options.toolExecutorConfig
32
+ }).filter((tool) => allow.has(tool.name));
33
+ const limit = Math.min(60, Math.max(1, Math.floor(options.maxIterations)));
34
+ let toolIterations = 0, exhausted = false, tokens = 0;
35
+ const policy = createAgentTurnPolicy({
36
+ maxTurns: limit + 1,
37
+ maxToolFailures: 5,
38
+ authorizeToolCall: async () => {
39
+ if (toolIterations >= limit || tokens >= 1e5) {
40
+ exhausted = true;
41
+ return {
42
+ block: true,
43
+ terminate: true,
44
+ reason: "Sub-agent budget exhausted."
45
+ };
46
+ }
47
+ toolIterations++;
122
48
  }
123
49
  });
50
+ const baseStop = policy.shouldStopAfterTurn;
51
+ policy.shouldStopAfterTurn = (context) => {
52
+ const stop = baseStop(context) || tokens >= 1e5;
53
+ if (stop) exhausted = true;
54
+ return stop;
55
+ };
124
56
  try {
125
- await runAgentTurnWithTimeout(agent, async () => {
126
- await agent.prompt(userText);
127
- await agent.waitForIdle();
128
- }, resolveAgentTurnTimeoutMs(options.getConfig()));
129
- const messages = agent.state.messages;
130
- for (let i = messages.length - 1; i >= 0; i--) {
131
- const msg = messages[i];
132
- if (msg.role === "assistant") {
133
- const content = msg.content;
134
- if (typeof content === "string") return {
135
- summary: content.trim() || "(empty assistant message)",
136
- toolIterations,
137
- messages
138
- };
139
- if (Array.isArray(content)) return {
140
- summary: extractTextContent(content).trim() || "(empty assistant message)",
141
- toolIterations,
142
- messages
143
- };
57
+ const result = await runXopcEmbeddedTurn({
58
+ sessionKey,
59
+ runId: randomUUID(),
60
+ workspaceDir: options.workspace,
61
+ userMessage: {
62
+ role: "user",
63
+ content: options.goal,
64
+ timestamp: Date.now()
65
+ },
66
+ model: options.model,
67
+ modelRef: `${options.model.provider}/${options.model.id}`,
68
+ tools,
69
+ transcriptRuntime: runtime,
70
+ turnPolicy: policy,
71
+ abortSignal: controller.signal,
72
+ timeoutMs: Math.min(options.timeoutMs ?? 3e5, 3e5),
73
+ thinkingLevel: "medium",
74
+ verifyChanges: options.verifyChanges,
75
+ systemPrompt: buildSubagentSystemPrompt({
76
+ goal: options.goal,
77
+ context: options.context,
78
+ workspace: options.workspace,
79
+ toolNames: tools.map((tool) => tool.name),
80
+ responseLanguage: resolveResponseLanguageForSession(options.getConfig(), options.requesterSessionKey)
81
+ }),
82
+ onEvent: (event) => {
83
+ const progress = options.progressHooks;
84
+ if (event.type === "message_end" && event.message.role === "assistant") {
85
+ const usage = event.message.usage;
86
+ tokens += usage?.totalTokens ?? (usage?.input ?? 0) + (usage?.output ?? 0);
87
+ }
88
+ if (event.type === "tool_execution_start") progress?.onProgress({
89
+ type: "tool_start",
90
+ toolCallId: event.toolCallId,
91
+ toolName: event.toolName,
92
+ args: event.args
93
+ });
94
+ if (event.type === "tool_execution_end") {
95
+ progress?.onProgress({
96
+ type: "tool_end",
97
+ toolCallId: event.toolCallId,
98
+ toolName: event.toolName,
99
+ isError: event.isError
100
+ });
101
+ progress?.onProgress({
102
+ type: "iteration",
103
+ count: toolIterations,
104
+ max: limit
105
+ });
106
+ }
107
+ if (progress?.mode === "full" && event.type === "message_update") {
108
+ const delta = event.assistantMessageEvent;
109
+ if (delta?.type === "text_delta" || delta?.type === "thinking_delta") progress.onProgress({
110
+ type: delta.type,
111
+ delta: delta.delta
112
+ });
113
+ }
144
114
  }
145
- }
146
- return {
147
- summary: aborted ? "Sub-agent was aborted before producing a result." : "Sub-agent completed but produced no assistant text.",
148
- toolIterations,
149
- messages
150
- };
151
- } catch (e) {
152
- const msg = e instanceof Error ? e.message : String(e);
153
- const m = options.model;
154
- const modelId = m?.model ?? m?.id;
155
- log.warn({
156
- err: e,
157
- errorMessage: msg,
158
- goalPreview: options.goal.slice(0, 120),
159
- maxIterations: options.maxIterations,
160
- allowedToolCount: options.allowedToolNames.length,
161
- modelId
162
- }, `Delegate child run failed: ${msg}`);
115
+ });
116
+ const verification = runtime.openSessionManager(options.workspace).getBranch().findLast((entry) => entry.type === "custom" && entry.customType === "coding_verification");
117
+ const proof = verification?.type === "custom" ? verification.data : void 0;
118
+ const unverified = options.verifyChanges && proof?.changed && (!proof.evidence.some((item) => item.kind === "check" && item.status === "passed") || proof.evidence.some((item) => item.status !== "passed"));
163
119
  return {
164
- summary: `Sub-agent error: ${msg}`,
120
+ summary: result.lastAssistantText || result.errorMessage || (exhausted ? "Sub-agent budget exhausted." : "(no final response)"),
165
121
  toolIterations,
166
- messages: agent.state.messages
122
+ messages: await runtime.loadMessages(),
123
+ status: controller.signal.aborted ? "cancelled" : !result.ok ? "failed" : exhausted || unverified ? "partial" : "success",
124
+ ...verification?.type === "custom" ? { verification: verification.data } : {}
167
125
  };
168
126
  } finally {
169
- unsub?.();
127
+ evictEmbeddedSessionRunner(runtime.runtimeId, "leaf_worker_complete");
170
128
  }
171
- },
172
- abort() {
173
- aborted = true;
174
- agent.abort();
175
129
  }
176
130
  };
177
131
  }
@@ -1 +1 @@
1
- export { TurnDiffTracker, type TurnDiffState, type TurnFileChange, type TurnVerificationRecord, type WorkspaceMutationKind, } from './turn-diff-tracker.js';
1
+ export { RunVerification, type CodingVerificationEvidence } from './run-verification.js';
@@ -1,2 +1,2 @@
1
- import { TurnDiffTracker } from "./turn-diff-tracker.js";
2
- export { TurnDiffTracker };
1
+ import { RunVerification } from "./run-verification.js";
2
+ export { RunVerification };
@@ -0,0 +1,12 @@
1
+ /** Reload scoped instructions on content changes; never follow instruction links outside the repository. */
2
+ export declare class RepositoryInstructions {
3
+ private readonly root;
4
+ private readonly workspace;
5
+ private readonly seen;
6
+ private readonly pending;
7
+ acknowledge(): void;
8
+ private constructor();
9
+ static open(workspace: string): Promise<RepositoryInstructions>;
10
+ forTool(name: string, input: unknown): Promise<string>;
11
+ load(path: string, directory: boolean): Promise<string>;
12
+ }
@@ -0,0 +1,76 @@
1
+ import { dirname, isAbsolute, relative, resolve, sep } from "node:path";
2
+ import { execFile } from "node:child_process";
3
+ import { readFile, realpath, stat } from "node:fs/promises";
4
+ import { promisify } from "node:util";
5
+ //#region src/agent/coding/repository-instructions.ts
6
+ const exec$1 = promisify(execFile);
7
+ function inside(root, path) {
8
+ const rel = relative(root, path);
9
+ return rel !== ".." && !rel.startsWith(`..${sep}`) && !isAbsolute(rel);
10
+ }
11
+ /** Reload scoped instructions on content changes; never follow instruction links outside the repository. */
12
+ var RepositoryInstructions = class RepositoryInstructions {
13
+ seen = /* @__PURE__ */ new Map();
14
+ pending = /* @__PURE__ */ new Map();
15
+ acknowledge() {
16
+ for (const [path, content] of this.pending) this.seen.set(path, content);
17
+ this.pending.clear();
18
+ }
19
+ constructor(root, workspace) {
20
+ this.root = root;
21
+ this.workspace = workspace;
22
+ }
23
+ static async open(workspace) {
24
+ let root = resolve(workspace);
25
+ try {
26
+ root = await realpath(root);
27
+ } catch {}
28
+ const canonicalWorkspace = root;
29
+ try {
30
+ root = await realpath((await exec$1("git", ["rev-parse", "--show-toplevel"], {
31
+ cwd: root,
32
+ timeout: 5e3
33
+ })).stdout.trim());
34
+ } catch {}
35
+ return new RepositoryInstructions(root, canonicalWorkspace);
36
+ }
37
+ async forTool(name, input) {
38
+ const args = input && typeof input === "object" ? input : {};
39
+ if (name === "apply_patch") {
40
+ const paths = [...String(args.patch ?? "").matchAll(/^\*\*\* (?:Add File|Update File|Delete File|Move to): (.+)$/gm)].map((match) => match[1].trim());
41
+ return (await Promise.all(paths.map((path) => this.load(path, false)))).filter(Boolean).join("\n\n");
42
+ }
43
+ if (["read_file", "write_file"].includes(name) && typeof args.path === "string") return this.load(args.path, false);
44
+ if (name === "exec_command" || name === "managed_job" && args.action === "start") return this.load(typeof args.cwd === "string" ? args.cwd : ".", true);
45
+ return "";
46
+ }
47
+ async load(path, directory) {
48
+ const target = resolve(this.workspace, path);
49
+ if (!inside(this.root, target)) return "";
50
+ const leaf = directory ? target : dirname(target);
51
+ const directories = [];
52
+ for (let current = leaf; inside(this.root, current); current = dirname(current)) {
53
+ directories.unshift(current);
54
+ if (current === this.root) break;
55
+ }
56
+ const sections = [];
57
+ for (const dir of directories) {
58
+ const file = resolve(dir, "AGENTS.md");
59
+ try {
60
+ const canonical = await realpath(file);
61
+ if (!inside(this.root, canonical)) throw new Error(`Instruction file escapes repository: ${file}`);
62
+ if ((await stat(canonical)).size > 32768) throw new Error(`Instruction file is too large; read it explicitly: ${file}`);
63
+ const content = await readFile(canonical, "utf8");
64
+ if (this.seen.get(file) === content) continue;
65
+ this.pending.set(file, content);
66
+ if (content.trim()) sections.push(`Instructions for ${dir} and its descendants (${file}):\n${content}`);
67
+ } catch (error) {
68
+ if (["ENOENT", "ENOTDIR"].includes(String(error.code))) continue;
69
+ throw error;
70
+ }
71
+ }
72
+ return sections.length ? `Repository instructions (more specific directory rules take precedence within their scope):\n\n${sections.join("\n\n")}` : "";
73
+ }
74
+ };
75
+ //#endregion
76
+ export { RepositoryInstructions };
@@ -0,0 +1,34 @@
1
+ import type { AfterToolCallContext, AgentToolResult } from '@earendil-works/pi-agent-core';
2
+ export interface CodingVerificationEvidence {
3
+ command: string;
4
+ kind: 'check' | 'diff-review';
5
+ status: 'passed' | 'failed' | 'unverified';
6
+ revision?: string;
7
+ toolCallId: string;
8
+ durationMs?: number;
9
+ logPath?: string;
10
+ }
11
+ export declare function toolResultFailed(result: AgentToolResult<unknown>, isError?: boolean): boolean;
12
+ /** One run owns its evidence; transcript tool results are the durable record. */
13
+ export declare class RunVerification {
14
+ private readonly snapshot;
15
+ private revision?;
16
+ private changed;
17
+ private readonly before;
18
+ private readonly evidence;
19
+ constructor(snapshot: () => Promise<string | undefined>);
20
+ static open(workspace: string): Promise<RunVerification>;
21
+ restore(value: unknown, includeEvidence: boolean): void;
22
+ beforeTool(toolCallId: string, toolName?: string): Promise<void>;
23
+ afterTool(context: AfterToolCallContext): Promise<{
24
+ result: AgentToolResult<unknown>;
25
+ isError: boolean;
26
+ }>;
27
+ private observeRevision;
28
+ pendingContext(): Promise<string>;
29
+ summary(): Promise<{
30
+ changed: boolean;
31
+ revision?: string;
32
+ evidence: CodingVerificationEvidence[];
33
+ }>;
34
+ }
@@ -0,0 +1,134 @@
1
+ import { readWorkspaceRevision } from "./workspace-revision.js";
2
+ import { classifyVerificationCommand } from "./verification-command.js";
3
+ //#region src/agent/coding/run-verification.ts
4
+ const READ_ONLY_TOOLS = new Set([
5
+ "read_file",
6
+ "grep",
7
+ "find",
8
+ "list_dir",
9
+ "update_plan",
10
+ "session_status"
11
+ ]);
12
+ function record(value) {
13
+ return value && typeof value === "object" ? value : {};
14
+ }
15
+ function toolResultFailed(result, isError = false) {
16
+ const details = record(result.details);
17
+ return isError || [
18
+ "failed",
19
+ "blocked",
20
+ "timed_out",
21
+ "cancelled",
22
+ "interrupted"
23
+ ].includes(String(details.status)) || details.timedOut === true || typeof details.exitCode === "number" && details.exitCode !== 0;
24
+ }
25
+ /** One run owns its evidence; transcript tool results are the durable record. */
26
+ var RunVerification = class RunVerification {
27
+ revision;
28
+ changed = false;
29
+ before = /* @__PURE__ */ new Map();
30
+ evidence = /* @__PURE__ */ new Map();
31
+ constructor(snapshot) {
32
+ this.snapshot = snapshot;
33
+ }
34
+ static async open(workspace) {
35
+ const run = new RunVerification(() => readWorkspaceRevision(workspace));
36
+ run.revision = await run.snapshot();
37
+ return run;
38
+ }
39
+ restore(value, includeEvidence) {
40
+ const checkpoint = record(value);
41
+ this.changed ||= checkpoint.changed === true || typeof checkpoint.revision === "string" && checkpoint.revision !== this.revision;
42
+ if (!includeEvidence) return;
43
+ for (const raw of Array.isArray(checkpoint.evidence) ? checkpoint.evidence : []) {
44
+ const item = record(raw);
45
+ if (typeof item.command !== "string" || typeof item.toolCallId !== "string" || !["check", "diff-review"].includes(String(item.kind))) continue;
46
+ const revision = typeof item.revision === "string" ? item.revision : void 0;
47
+ this.evidence.set(item.command, {
48
+ command: item.command,
49
+ toolCallId: item.toolCallId,
50
+ kind: item.kind,
51
+ revision,
52
+ status: revision && revision === this.revision && ["passed", "failed"].includes(String(item.status)) ? item.status : "unverified"
53
+ });
54
+ }
55
+ }
56
+ async beforeTool(toolCallId, toolName) {
57
+ const revision = toolName && READ_ONLY_TOOLS.has(toolName) ? this.revision : await this.snapshot();
58
+ this.observeRevision(revision);
59
+ this.before.set(toolCallId, revision);
60
+ }
61
+ async afterTool(context) {
62
+ const { toolCall, args, result } = context;
63
+ const before = this.before.get(toolCall.id);
64
+ this.before.delete(toolCall.id);
65
+ const revision = READ_ONLY_TOOLS.has(toolCall.name) ? this.revision : await this.snapshot();
66
+ this.observeRevision(revision);
67
+ const details = record(result.details);
68
+ const isError = toolResultFailed(result, context.isError);
69
+ if ((toolCall.name === "apply_patch" || toolCall.name === "write_file") && !isError) this.changed = true;
70
+ const command = toolCall.name === "exec_command" || toolCall.name === "managed_job" || toolCall.name === "language_diagnostics" || toolCall.name === "review_workspace" ? String(details.command ?? record(args).cmd ?? "") : "";
71
+ const kind = toolCall.name === "review_workspace" && details.complete === true ? "diff-review" : toolCall.name === "language_diagnostics" && details.diagnosticEngine === "typescript" ? "check" : classifyVerificationCommand(command);
72
+ let verification;
73
+ if (kind && details.status !== "running") {
74
+ const observedBefore = typeof details.startRevision === "string" ? details.startRevision : before;
75
+ const observedAfter = typeof details.endRevision === "string" ? details.endRevision : revision;
76
+ const completedJob = toolCall.name !== "managed_job" || !!details.startRevision && !!details.endRevision;
77
+ verification = {
78
+ command,
79
+ kind,
80
+ toolCallId: toolCall.id,
81
+ ...typeof details.durationMs === "number" ? { durationMs: details.durationMs } : {},
82
+ ...typeof details.logPath === "string" ? { logPath: details.logPath } : {},
83
+ status: isError ? "failed" : details.exitCode === 0 && completedJob && revision && revision === observedBefore && revision === observedAfter ? "passed" : "unverified",
84
+ ...revision ? { revision } : {}
85
+ };
86
+ this.evidence.set(command, verification);
87
+ }
88
+ return {
89
+ isError,
90
+ result: {
91
+ ...result,
92
+ details: {
93
+ ...details,
94
+ workspaceRevision: revision ?? null,
95
+ workspaceChanged: this.changed,
96
+ ...verification ? { verification } : {}
97
+ }
98
+ }
99
+ };
100
+ }
101
+ observeRevision(revision) {
102
+ if (this.revision && revision !== this.revision) this.changed = true;
103
+ this.revision = revision;
104
+ }
105
+ async pendingContext() {
106
+ this.observeRevision(await this.snapshot());
107
+ if (!this.changed) return "";
108
+ const current = [...this.evidence.values()].filter((item) => item.revision && item.revision === this.revision);
109
+ const checked = current.some((item) => item.kind === "check" && item.status === "passed");
110
+ const reviewed = current.some((item) => item.kind === "diff-review" && item.status === "passed");
111
+ const failed = current.filter((item) => item.kind === "check" && item.status === "failed");
112
+ if (checked && reviewed && failed.length === 0) return "";
113
+ return [
114
+ "Workspace changes still need verification against the current files.",
115
+ ...!reviewed ? ["Inspect tracked and untracked changes using `review_workspace`."] : [],
116
+ ...!checked ? ["Run the smallest meaningful check as a direct command using exec_command."] : [],
117
+ ...failed.map((item) => `Resolve or explicitly report the failed check: ${item.command}`),
118
+ "If a check is unavailable or unrelated to the requested change, report what remains unverified and why. Do not claim verified completion."
119
+ ].join("\n");
120
+ }
121
+ async summary() {
122
+ this.observeRevision(await this.snapshot());
123
+ return {
124
+ changed: this.changed,
125
+ revision: this.revision,
126
+ evidence: [...this.evidence.values()].map((item) => ({
127
+ ...item,
128
+ status: !item.revision || item.revision !== this.revision ? "unverified" : item.status
129
+ }))
130
+ };
131
+ }
132
+ };
133
+ //#endregion
134
+ export { RunVerification, toolResultFailed };
@@ -0,0 +1,3 @@
1
+ export type VerificationCommandKind = 'check' | 'diff-review';
2
+ /** Recognize direct check invocations, never keywords inside arbitrary shell code. */
3
+ export declare function classifyVerificationCommand(command: string): VerificationCommandKind | undefined;
@@ -0,0 +1,50 @@
1
+ //#region src/agent/coding/verification-command.ts
2
+ /** Recognize direct check invocations, never keywords inside arbitrary shell code. */
3
+ function classifyVerificationCommand(command) {
4
+ if (/[\n\r;&|<>`$]/.test(command)) return void 0;
5
+ const tokens = command.match(/"[^"\\]*"|'[^'\\]*'|[^\s"']+/g) ?? [];
6
+ if (tokens.join(" ").replace(/\s/g, "") !== command.replace(/\s/g, "")) return void 0;
7
+ const args = tokens.map((token) => token.replace(/^(['"])(.*)\1$/, "$2"));
8
+ const executable = args.shift();
9
+ if (!executable) return void 0;
10
+ if ([
11
+ "pnpm",
12
+ "npm",
13
+ "yarn",
14
+ "bun"
15
+ ].includes(executable)) {
16
+ while (args[0] === "-C" || args[0] === "--dir" || args[0] === "--prefix") args.splice(0, 2);
17
+ if (args[0] === "exec") return classifyVerificationCommand(args.slice(1).join(" "));
18
+ if (args[0] === "run") args.shift();
19
+ const script = args.shift() ?? "";
20
+ return /^(test|typecheck|type-check|lint|build)(:[\w-]+)*$/.test(script) && !args.some((arg) => [
21
+ "--help",
22
+ "-h",
23
+ "--version",
24
+ "-v",
25
+ "--list",
26
+ "--listTests",
27
+ "--dry-run",
28
+ "--watch"
29
+ ].includes(arg)) ? "check" : void 0;
30
+ }
31
+ if (executable === "node" && args[0] === "--test") return args.some((arg) => /^(--help|--version|--test-only|--watch)(=|$)/.test(arg)) ? void 0 : "check";
32
+ if ([
33
+ "vitest",
34
+ "jest",
35
+ "pytest",
36
+ "tsc",
37
+ "mocha"
38
+ ].includes(executable)) {
39
+ if (args.some((arg) => /^(--help|-h|--version|-v|--list|--listTests|--collect-only|--watch|-w)$/.test(arg))) return void 0;
40
+ if (executable === "vitest" && args[0] !== "run") return void 0;
41
+ return "check";
42
+ }
43
+ if (executable === "go" && args[0] === "test" || executable === "cargo" && [
44
+ "test",
45
+ "check",
46
+ "clippy"
47
+ ].includes(args[0] ?? "") || executable === "python" && args[0] === "-m" && args[1] === "pytest") return args.some((arg) => /^(--help|--version|--collect-only|--no-run)$/.test(arg)) ? void 0 : "check";
48
+ }
49
+ //#endregion
50
+ export { classifyVerificationCommand };
@@ -0,0 +1,2 @@
1
+ /** A content fingerprint, including user changes and untracked files, without changing Git state. */
2
+ export declare function readWorkspaceRevision(workspace: string): Promise<string | undefined>;