@xopcai/xopc 0.0.244 → 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.
- package/dist/browser-ext/manifest.json +1 -1
- package/dist/extensions/telegram/xopc.extension.json +1 -1
- package/dist/gateway/static/root/assets/{activity-store-CAah-_8h.js → activity-store-BlxqErph.js} +1 -1
- package/dist/gateway/static/root/assets/{agent-avatar-dicebear-BhXGsupm.js → agent-avatar-dicebear-DRQnogaU.js} +1 -1
- package/dist/gateway/static/root/assets/{agent-defaults-settings-panel-Blzn2H6t.js → agent-defaults-settings-panel-CpOxGbMD.js} +1 -1
- package/dist/gateway/static/root/assets/{agents-Cmp-z8Y_.js → agents-flnXZLaT.js} +1 -1
- package/dist/gateway/static/root/assets/{api-B2tKxbcz.js → api-BbXzyQMj.js} +1 -1
- package/dist/gateway/static/root/assets/{app-management-settings-panel-CezjAP1K.js → app-management-settings-panel-CZl6n2xi.js} +1 -1
- package/dist/gateway/static/root/assets/{appearance-settings-C-CfS05x.js → appearance-settings-Bglp-pn6.js} +1 -1
- package/dist/gateway/static/root/assets/{apps-page-7Y13_bqZ.js → apps-page-CmsWarVB.js} +1 -1
- package/dist/gateway/static/root/assets/{archive-plugin-BmSx7wzY.js → archive-plugin-DD2SweEH.js} +1 -1
- package/dist/gateway/static/root/assets/{attachment-load-DI4CoIga.js → attachment-load-G0HenUmG.js} +1 -1
- package/dist/gateway/static/root/assets/{automations-page-D04Xceck.js → automations-page-B78bFjH2.js} +1 -1
- package/dist/gateway/static/root/assets/{automations-workspace-wEO1OWk0.js → automations-workspace-BMQGmn50.js} +1 -1
- package/dist/gateway/static/root/assets/{binary-plugins-BJQe8TRu.js → binary-plugins-BbSQmXqn.js} +1 -1
- package/dist/gateway/static/root/assets/{block-editor-BSzGjJC6.js → block-editor-DutTIH81.js} +1 -1
- package/dist/gateway/static/root/assets/{browser-settings-page-DjAZ_LF2.js → browser-settings-page-CALiFKm4.js} +1 -1
- package/dist/gateway/static/root/assets/{browser-workflow-inputs-CRnkgZHI.js → browser-workflow-inputs-BAAc151l.js} +1 -1
- package/dist/gateway/static/root/assets/{browser-workflows-page-CwbxA3B7.js → browser-workflows-page-DE5HPrHZ.js} +1 -1
- package/dist/gateway/static/root/assets/{capabilities-settings-panel-jt9bqUMK.js → capabilities-settings-panel-Dts7XtP3.js} +1 -1
- package/dist/gateway/static/root/assets/{channels-settings-Cz_TWY3a.js → channels-settings-CWEd3wzh.js} +1 -1
- package/dist/gateway/static/root/assets/{channels-status-swr-DuY4MGxe.js → channels-status-swr-CCBCtLDg.js} +1 -1
- package/dist/gateway/static/root/assets/{chat-terminal-dock-D3gj2D3U.js → chat-terminal-dock-Bp1fXQm1.js} +1 -1
- package/dist/gateway/static/root/assets/{connectors-page-Shs5vbzx.js → connectors-page-CQ6wVNLm.js} +1 -1
- package/dist/gateway/static/root/assets/{cron-expression-DgWHw0jX.js → cron-expression-B8HA5IRb.js} +1 -1
- package/dist/gateway/static/root/assets/{date-picker-CKg-RPbs.js → date-picker-DD8b7oad.js} +1 -1
- package/dist/gateway/static/root/assets/{dependency-picker-CVYkw-NN.js → dependency-picker-BC9zwIyH.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-Bf46oXTY.js → desktop-pet-DsrsPZTW.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-settings-BJO_klc7.js → desktop-pet-settings-D7gp_HNA.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-debug-page-T2PmFFOW.js → extension-debug-page-BoKbOX7x.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-2wAE2RCe.js → extension-page-BegL4FW8.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-Y9ZiCJ21.js → extension-settings-page-CjPqq57s.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-config-api-DaYY1Gkn.js → gateway-config-api-DaG57o4X.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-config-swr-BC3pgb_P.js → gateway-config-swr-826dipyU.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-settings-eO3IzW_J.js → gateway-settings-DkJGpgm6.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-startup-retry-uMcSfLru.js → gateway-startup-retry-DyvcAIMm.js} +1 -1
- package/dist/gateway/static/root/assets/{heartbeat-settings-BAgrkyHc.js → heartbeat-settings-BLZ48kSU.js} +1 -1
- package/dist/gateway/static/root/assets/{home-page-GTjKH7LK.js → home-page-Dtw7Ipt1.js} +1 -1
- package/dist/gateway/static/root/assets/{image-generation-api-D1qlQA-A.js → image-generation-api-D7cyfks6.js} +1 -1
- package/dist/gateway/static/root/assets/{index-DUz0O54y.js → index-DG5CfYat.js} +10 -10
- package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-CWGqL6o5.js → keyboard-shortcuts-settings-D2Has7-N.js} +1 -1
- package/dist/gateway/static/root/assets/{local-app-workbench-page-DKJ-rks0.js → local-app-workbench-page-BWidWY93.js} +1 -1
- package/dist/gateway/static/root/assets/{local-apps-page-Bfidv29d.js → local-apps-page-Bkekjoxf.js} +1 -1
- package/dist/gateway/static/root/assets/{locale-store-CMZljTJx.js → locale-store-CBoCuIMx.js} +1 -1
- package/dist/gateway/static/root/assets/{logs-page-DwAHrPbF.js → logs-page-C5zSSgvA.js} +1 -1
- package/dist/gateway/static/root/assets/{management-settings-BG7j1I9f.js → management-settings-B8c62vRS.js} +1 -1
- package/dist/gateway/static/root/assets/{markdown-split-AnmmpLs6.js → markdown-split-3kxTTGO7.js} +1 -1
- package/dist/gateway/static/root/assets/{markdown-view-PPCLt7fu.js → markdown-view-BXsHghJd.js} +1 -1
- package/dist/gateway/static/root/assets/{media-plugins-CGS-05cE.js → media-plugins-BW8J1nCG.js} +1 -1
- package/dist/gateway/static/root/assets/messages-BbdwoxVo.js +3 -0
- package/dist/gateway/static/root/assets/{mobile-pairing-wizard-DoKK5GfV.js → mobile-pairing-wizard-nwQ8iUcd.js} +1 -1
- package/dist/gateway/static/root/assets/models-hub-cache-88f4fzYS.js +1 -0
- package/dist/gateway/static/root/assets/{notes-page-Lr8rsFAR.js → notes-page-DdybD0QM.js} +1 -1
- package/dist/gateway/static/root/assets/{notes-workbench-ISWnKLxO.js → notes-workbench-IYfpy2Jx.js} +2 -2
- package/dist/gateway/static/root/assets/{oauth-api-4VeMbkTJ.js → oauth-api-BjSUDIgq.js} +1 -1
- package/dist/gateway/static/root/assets/{product-open-page-BU0HiZtv.js → product-open-page-CAJeUXeU.js} +1 -1
- package/dist/gateway/static/root/assets/{project-detail-page-BZqr4yam.js → project-detail-page-4wjw-b7h.js} +1 -1
- package/dist/gateway/static/root/assets/{projects-page-Dau8733A.js → projects-page-CCMj9PeL.js} +1 -1
- package/dist/gateway/static/root/assets/{registry-api-CWOtPFrE.js → registry-api-BhGKnvLP.js} +1 -1
- package/dist/gateway/static/root/assets/{remote-access-hub-DdChlvGP.js → remote-access-hub-DsBJqWIk.js} +1 -1
- package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-CmZTNv1W.js → runtime-tools-settings-panel-B4IDcqx0.js} +1 -1
- package/dist/gateway/static/root/assets/{schema-form-XlVPyiVQ.js → schema-form-DiGUUjO6.js} +1 -1
- package/dist/gateway/static/root/assets/{sessions-page-C3kADsd4.js → sessions-page-BwGj0t-2.js} +1 -1
- package/dist/gateway/static/root/assets/settings-advanced-gate-BJCfUghk.js +1 -0
- package/dist/gateway/static/root/assets/{settings-page-DblUeM3V.js → settings-page-CVQUsAhd.js} +1 -1
- package/dist/gateway/static/root/assets/{setup-status-panel-bDfRfSnq.js → setup-status-panel-CQACRh1i.js} +1 -1
- package/dist/gateway/static/root/assets/{share-preview-page-DBMWFMN-.js → share-preview-page-DTP1dtuS.js} +1 -1
- package/dist/gateway/static/root/assets/{shares-settings-Bu6lIStj.js → shares-settings-D_YPh6Rw.js} +1 -1
- package/dist/gateway/static/root/assets/skill-reload-api-B43xlJlX.js +1 -0
- package/dist/gateway/static/root/assets/{skills-page-CSOseeQe.js → skills-page-Czpn7Y28.js} +1 -1
- package/dist/gateway/static/root/assets/{skills-page.utils-CniRGhkJ.js → skills-page.utils-d39rm3hb.js} +1 -1
- package/dist/gateway/static/root/assets/{system-settings-panel-D0GqNpKy.js → system-settings-panel-CXXySCSp.js} +1 -1
- package/dist/gateway/static/root/assets/{task-detail-page-BRCq-nR7.js → task-detail-page-DHiOqQMx.js} +1 -1
- package/dist/gateway/static/root/assets/{theme-store-uxUwr10D.js → theme-store-hybK3oC9.js} +1 -1
- package/dist/gateway/static/root/assets/{tunnel-api-BtjS2nrM.js → tunnel-api-BiBGK7O2.js} +1 -1
- package/dist/gateway/static/root/assets/{use-autosave-TwuAycG8.js → use-autosave-DjpzpeIm.js} +1 -1
- package/dist/gateway/static/root/assets/{user-context-page-CbqPu8xZ.js → user-context-page-1XBRV5gX.js} +1 -1
- package/dist/gateway/static/root/assets/{voice-api-key-field-CzwG5plu.js → voice-api-key-field-CUIPNmOc.js} +1 -1
- package/dist/gateway/static/root/assets/{voice-config-api-MqyI6cgq.js → voice-config-api-CBbiF1T3.js} +1 -1
- package/dist/gateway/static/root/assets/{work-discovery-overlay-DS15FzQA.js → work-discovery-overlay-DVNxhb1x.js} +1 -1
- package/dist/gateway/static/root/assets/{workflow-run-setup-panel-C_boCemi.js → workflow-run-setup-panel-HxxFQFY7.js} +1 -1
- package/dist/gateway/static/root/assets/{workflows-page-CaI2ruyy.js → workflows-page-BCgL7PRm.js} +1 -1
- package/dist/gateway/static/root/index.html +11 -11
- package/dist/package.js +1 -1
- package/dist/packages/gateway-contract/src/turn-outcome.js +3 -1
- package/dist/src/agent/agent-instance-gateway.d.ts +3 -1
- package/dist/src/agent/agent-manager.d.ts +2 -4
- package/dist/src/agent/agent-manager.js +28 -32
- package/dist/src/agent/background-review/coordinator.js +1 -1
- package/dist/src/agent/background-review/run-background-review.js +2 -2
- package/dist/src/agent/child-agent-factory.d.ts +10 -7
- package/dist/src/agent/child-agent-factory.js +112 -158
- package/dist/src/agent/coding/index.d.ts +1 -1
- package/dist/src/agent/coding/index.js +2 -2
- package/dist/src/agent/coding/repository-instructions.d.ts +12 -0
- package/dist/src/agent/coding/repository-instructions.js +76 -0
- package/dist/src/agent/coding/run-verification.d.ts +34 -0
- package/dist/src/agent/coding/run-verification.js +134 -0
- package/dist/src/agent/coding/verification-command.d.ts +3 -0
- package/dist/src/agent/coding/verification-command.js +50 -0
- package/dist/src/agent/coding/workspace-revision.d.ts +2 -0
- package/dist/src/agent/coding/workspace-revision.js +77 -0
- package/dist/src/agent/commands/command-isolation.d.ts +21 -0
- package/dist/src/agent/commands/command-isolation.js +71 -0
- package/dist/src/agent/commands/command-registry.d.ts +56 -0
- package/dist/src/agent/commands/command-registry.js +259 -0
- package/dist/src/agent/embedded/index.js +1 -1
- package/dist/src/agent/embedded/model-runtime.js +1 -1
- package/dist/src/agent/embedded/run-for-session.js +3 -2
- package/dist/src/agent/embedded/run-turn.js +88 -25
- package/dist/src/agent/embedded/session-tool-result-guard.js +2 -2
- package/dist/src/agent/embedded/subscribe-session.d.ts +2 -1
- package/dist/src/agent/embedded/subscribe-session.js +2 -1
- package/dist/src/agent/embedded/types.d.ts +3 -1
- package/dist/src/agent/embedded/xopc-tools-bridge.js +4 -1
- package/dist/src/agent/image/index.js +1 -1
- package/dist/src/agent/image/tool-model-config.js +1 -1
- package/dist/src/agent/index.js +3 -3
- package/dist/src/agent/ipc/inbox.js +1 -1
- package/dist/src/agent/mcp/oauth/mcp-oauth-store.js +1 -1
- package/dist/src/agent/memory/user-context-coordinator.js +1 -1
- package/dist/src/agent/middleware/index.d.ts +0 -5
- package/dist/src/agent/middleware/index.js +1 -2
- package/dist/src/agent/orchestration/agent-event-handler.d.ts +0 -5
- package/dist/src/agent/orchestration/agent-event-handler.js +1 -96
- package/dist/src/agent/orchestration/agent-orchestrator.js +1 -1
- package/dist/src/agent/orchestration/agent-turn-policy.js +5 -5
- package/dist/src/agent/orchestration/index.d.ts +1 -1
- package/dist/src/agent/orchestration/index.js +2 -2
- package/dist/src/agent/orchestration/loop-guard.d.ts +4 -31
- package/dist/src/agent/orchestration/loop-guard.js +14 -99
- package/dist/src/agent/prompt/sections/tooling.js +2 -4
- package/dist/src/agent/sandbox/types.d.ts +2 -2
- package/dist/src/agent/sandbox/types.js +1 -1
- package/dist/src/agent/service/direct-turn-helpers.js +1 -1
- package/dist/src/agent/service/process-direct-streaming.js +1 -1
- package/dist/src/agent/service.d.ts +0 -2
- package/dist/src/agent/service.js +8 -25
- package/dist/src/agent/session/session-inspector.js +1 -1
- package/dist/src/agent/skills/hub-lock.js +1 -1
- package/dist/src/agent/tasks/task-judge-service.d.ts +7 -0
- package/dist/src/agent/tasks/task-judge-service.js +27 -5
- package/dist/src/agent/tools/delegate-tool.d.ts +2 -1
- package/dist/src/agent/tools/delegate-tool.js +102 -124
- package/dist/src/agent/tools/exec-command.d.ts +8 -1
- package/dist/src/agent/tools/exec-command.js +77 -169
- package/dist/src/agent/tools/executor.js +9 -2
- package/dist/src/agent/tools/factory.js +50 -5
- package/dist/src/agent/tools/find.d.ts +10 -13
- package/dist/src/agent/tools/find.js +33 -80
- package/dist/src/agent/tools/grep.d.ts +14 -18
- package/dist/src/agent/tools/grep.js +56 -144
- package/dist/src/agent/tools/index.d.ts +0 -1
- package/dist/src/agent/tools/index.js +2 -3
- package/dist/src/agent/tools/language-diagnostics.d.ts +11 -0
- package/dist/src/agent/tools/language-diagnostics.js +62 -0
- package/dist/src/agent/tools/managed-job-tool.d.ts +2 -1
- package/dist/src/agent/tools/managed-job-tool.js +58 -118
- package/dist/src/agent/tools/read.js +24 -7
- package/dist/src/agent/tools/repository-search.d.ts +5 -0
- package/dist/src/agent/tools/repository-search.js +56 -0
- package/dist/src/agent/tools/review-workspace.d.ts +2 -0
- package/dist/src/agent/tools/review-workspace.js +103 -0
- package/dist/src/agent/tools/write.js +4 -4
- package/dist/src/agent/transcript/index.js +2 -2
- package/dist/src/agent/transcript/transcript-hygiene.js +2 -2
- package/dist/src/agent/workflow/subagent-runner.d.ts +0 -2
- package/dist/src/agent/workflow/subagent-runner.js +12 -31
- package/dist/src/agent-config/schema.d.ts +42 -0
- package/dist/src/agent-config/schema.js +5 -0
- package/dist/src/ai-assist/text-assist.js +1 -1
- package/dist/src/auth/credentials.js +2 -2
- package/dist/src/auth/profiles/store.js +1 -1
- package/dist/src/auth/sync-provider-auth.js +2 -2
- package/dist/src/browser/providers/browser-ext-install.js +1 -1
- package/dist/src/cli/commands/agent.js +2 -2
- package/dist/src/cli/commands/doctor/checks/provider-auth.js +1 -1
- package/dist/src/cli/commands/extension-marketplace.js +1 -1
- package/dist/src/cli/commands/gateway/lifecycle.js +1 -1
- package/dist/src/cli/commands/models.js +2 -2
- package/dist/src/cli/commands/onboard.js +1 -1
- package/dist/src/cli/commands/profile.js +1 -1
- package/dist/src/cli/commands/tunnel.js +1 -1
- package/dist/src/cli/commands/update.js +1 -1
- package/dist/src/cli/extension-cli-register.js +1 -1
- package/dist/src/config/index.js +5 -5
- package/dist/src/config/loader.js +1 -1
- package/dist/src/config/models-json.js +1 -1
- package/dist/src/config/schema.d.ts +28 -0
- package/dist/src/execution-environments/local-worktree-manager.d.ts +3 -1
- package/dist/src/execution-environments/local-worktree-manager.js +8 -3
- package/dist/src/execution-environments/session-environment-service.js +5 -3
- package/dist/src/extensions/lockfile.js +1 -1
- package/dist/src/extensions/update.js +1 -1
- package/dist/src/gateway/agents-admin.js +1 -1
- package/dist/src/gateway/file-path-classifier.js +1 -1
- package/dist/src/gateway/heartbeat/service.js +1 -1
- package/dist/src/gateway/hono/lib/config-payload.d.ts +7 -0
- package/dist/src/gateway/hono/lib/config-payload.js +1 -1
- package/dist/src/gateway/hono/routes/auth-registry-extensions.js +1 -1
- package/dist/src/gateway/hono/routes/models.js +1 -1
- package/dist/src/gateway/hono/routes/sessions.js +1 -1
- package/dist/src/gateway/media-access.js +1 -1
- package/dist/src/gateway/run-loop.js +1 -1
- package/dist/src/gateway/service/config-coordinator.js +2 -2
- package/dist/src/gateway/service/run-gateway-agent.js +4 -1
- package/dist/src/gateway/service.js +7 -7
- package/dist/src/gateway/session-reset-service.js +1 -1
- package/dist/src/gateway/workspace-ripgrep.d.ts +0 -6
- package/dist/src/gateway/workspace-ripgrep.js +2 -40
- package/dist/src/heartbeat/index.js +1 -1
- package/dist/src/infra/ripgrep.d.ts +13 -0
- package/dist/src/infra/ripgrep.js +46 -0
- package/dist/src/infra/update-runner.js +1 -1
- package/dist/src/proactive/execution/agent-executor.js +1 -1
- package/dist/src/providers/auth-runtime/resolve-auth.js +1 -1
- package/dist/src/providers/index.js +2 -2
- package/dist/src/providers/model-registry.js +1 -1
- package/dist/src/providers/register-runtime-providers.js +1 -1
- package/dist/src/session/store.js +1 -1
- package/dist/src/session/turn-outcome-projector.js +26 -6
- package/dist/src/share/hosted-session-share.js +1 -1
- package/dist/src/tasks/task-run-coordinator.d.ts +2 -2
- package/dist/src/tasks/task-run-coordinator.js +14 -12
- package/dist/src/tui/backends/embedded-backend.js +1 -1
- package/dist/src/tui/tui-startup-resources.js +1 -1
- package/dist/src/tui/tui.js +1 -1
- package/dist/src/workflows/service/workflow-run-service.js +1 -1
- package/package.json +1 -1
- package/dist/gateway/static/root/assets/messages-CTSgFlE4.js +0 -3
- package/dist/gateway/static/root/assets/models-hub-cache-ZrbGRiGY.js +0 -1
- package/dist/gateway/static/root/assets/settings-advanced-gate-CSYy6SUa.js +0 -1
- package/dist/gateway/static/root/assets/skill-reload-api-BNMc4l04.js +0 -1
- package/dist/src/agent/coding/turn-diff-tracker.d.ts +0 -67
- package/dist/src/agent/coding/turn-diff-tracker.js +0 -231
- package/dist/src/agent/middleware/self-verify.d.ts +0 -136
- package/dist/src/agent/middleware/self-verify.js +0 -380
- package/dist/src/agent/tools/execute-code-tool.d.ts +0 -11
- package/dist/src/agent/tools/execute-code-tool.js +0 -208
|
@@ -1,177 +1,131 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
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 {
|
|
7
|
+
import { randomUUID } from "node:crypto";
|
|
11
8
|
//#region src/agent/child-agent-factory.ts
|
|
12
|
-
|
|
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
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
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
|
-
|
|
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
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
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
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
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
|
-
|
|
147
|
-
|
|
148
|
-
|
|
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:
|
|
120
|
+
summary: result.lastAssistantText || result.errorMessage || (exhausted ? "Sub-agent budget exhausted." : "(no final response)"),
|
|
165
121
|
toolIterations,
|
|
166
|
-
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
|
-
|
|
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 {
|
|
1
|
+
export { RunVerification, type CodingVerificationEvidence } from './run-verification.js';
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export {
|
|
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,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 };
|