@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.
- 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-DDH4HgP7.js → agent-avatar-dicebear-DRQnogaU.js} +1 -1
- package/dist/gateway/static/root/assets/{agent-defaults-settings-panel-BDCfJZhh.js → agent-defaults-settings-panel-CpOxGbMD.js} +1 -1
- package/dist/gateway/static/root/assets/{agents-B0ZWgf-U.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-Blfwszzn.js → app-management-settings-panel-CZl6n2xi.js} +1 -1
- package/dist/gateway/static/root/assets/{appearance-settings-C3V7Na75.js → appearance-settings-Bglp-pn6.js} +1 -1
- package/dist/gateway/static/root/assets/{apps-page-BiEks0-F.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-BS-S4LJ9.js → attachment-load-G0HenUmG.js} +1 -1
- package/dist/gateway/static/root/assets/{automations-page-C7Y3L30D.js → automations-page-B78bFjH2.js} +1 -1
- package/dist/gateway/static/root/assets/{automations-workspace-A3zPkPuo.js → automations-workspace-BMQGmn50.js} +1 -1
- package/dist/gateway/static/root/assets/{binary-plugins-BM9B5kcm.js → binary-plugins-BbSQmXqn.js} +1 -1
- package/dist/gateway/static/root/assets/{block-editor-BbnpkYP9.js → block-editor-DutTIH81.js} +1 -1
- package/dist/gateway/static/root/assets/{browser-settings-page-Dk4FQ7fY.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-B9qGL-it.js → browser-workflows-page-DE5HPrHZ.js} +1 -1
- package/dist/gateway/static/root/assets/{capabilities-settings-panel--tR_El9e.js → capabilities-settings-panel-Dts7XtP3.js} +1 -1
- package/dist/gateway/static/root/assets/{channels-settings-D347vl_J.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-DABPvwBT.js → chat-terminal-dock-Bp1fXQm1.js} +1 -1
- package/dist/gateway/static/root/assets/{connectors-page-B-tvJkRJ.js → connectors-page-CQ6wVNLm.js} +1 -1
- package/dist/gateway/static/root/assets/{cron-expression-D3bsKbNd.js → cron-expression-B8HA5IRb.js} +1 -1
- package/dist/gateway/static/root/assets/{date-picker-BsGM6Yty.js → date-picker-DD8b7oad.js} +1 -1
- package/dist/gateway/static/root/assets/{dependency-picker-Dj3g6YXZ.js → dependency-picker-BC9zwIyH.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-C1QT0Sur.js → desktop-pet-DsrsPZTW.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-settings-r6kAOnfY.js → desktop-pet-settings-D7gp_HNA.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-debug-page-DOkf7nh9.js → extension-debug-page-BoKbOX7x.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-Cq2IA4Ho.js → extension-page-BegL4FW8.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-DQn4qjDZ.js → extension-settings-page-CjPqq57s.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-config-api-DM3poL22.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-DPgH1hnh.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-Bk80-E3b.js → heartbeat-settings-BLZ48kSU.js} +1 -1
- package/dist/gateway/static/root/assets/{home-page-DKo5JiMR.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-B0WJL9N1.js → index-DG5CfYat.js} +10 -10
- package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-BEwvd8ZU.js → keyboard-shortcuts-settings-D2Has7-N.js} +1 -1
- package/dist/gateway/static/root/assets/{local-app-workbench-page--eJ5rmNj.js → local-app-workbench-page-BWidWY93.js} +1 -1
- package/dist/gateway/static/root/assets/{local-apps-page-CgkY9E-r.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-Z49Td0J9.js → logs-page-C5zSSgvA.js} +1 -1
- package/dist/gateway/static/root/assets/{management-settings-Dv8NSJKt.js → management-settings-B8c62vRS.js} +1 -1
- package/dist/gateway/static/root/assets/{markdown-split-Cm0RBB-t.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-Bcr5sU1f.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-kKDiXofY.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-CgsaRaGi.js → notes-page-DdybD0QM.js} +1 -1
- package/dist/gateway/static/root/assets/{notes-workbench-C1DEE09k.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-isRapnp5.js → project-detail-page-4wjw-b7h.js} +1 -1
- package/dist/gateway/static/root/assets/{projects-page-zvsjg0mi.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-C9TGZ9Hc.js → remote-access-hub-DsBJqWIk.js} +1 -1
- package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-2zm9edMA.js → runtime-tools-settings-panel-B4IDcqx0.js} +1 -1
- package/dist/gateway/static/root/assets/{schema-form-54A5gzkN.js → schema-form-DiGUUjO6.js} +1 -1
- package/dist/gateway/static/root/assets/{sessions-page-BP8RyiUn.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-DzDhoyxv.js → settings-page-CVQUsAhd.js} +1 -1
- package/dist/gateway/static/root/assets/{setup-status-panel-uDicHU1w.js → setup-status-panel-CQACRh1i.js} +1 -1
- package/dist/gateway/static/root/assets/{share-preview-page-lOmLCWFS.js → share-preview-page-DTP1dtuS.js} +1 -1
- package/dist/gateway/static/root/assets/{shares-settings-T4Yvouvv.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-CnyNH3To.js → skills-page-Czpn7Y28.js} +1 -1
- package/dist/gateway/static/root/assets/{skills-page.utils-CgDtf2qs.js → skills-page.utils-d39rm3hb.js} +1 -1
- package/dist/gateway/static/root/assets/{system-settings-panel-C8yWfwtR.js → system-settings-panel-CXXySCSp.js} +1 -1
- package/dist/gateway/static/root/assets/{task-detail-page-Tzfjlbf3.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-Bvg679no.js → tunnel-api-BiBGK7O2.js} +1 -1
- package/dist/gateway/static/root/assets/{use-autosave-D88VGoyG.js → use-autosave-DjpzpeIm.js} +1 -1
- package/dist/gateway/static/root/assets/{user-context-page-RijPtyfO.js → user-context-page-1XBRV5gX.js} +1 -1
- package/dist/gateway/static/root/assets/{voice-api-key-field-CBHLsMcc.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-GGe2TQ98.js → work-discovery-overlay-DVNxhb1x.js} +1 -1
- package/dist/gateway/static/root/assets/{workflow-run-setup-panel-C0layUE9.js → workflow-run-setup-panel-HxxFQFY7.js} +1 -1
- package/dist/gateway/static/root/assets/{workflows-page-DQXIzBAc.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 +24 -28
- package/dist/src/agent/background-review/coordinator.js +1 -1
- package/dist/src/agent/background-review/run-background-review.js +1 -1
- 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/run-for-session.js +2 -1
- 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/index.js +3 -3
- 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 +6 -23
- package/dist/src/agent/tasks/task-judge-service.d.ts +7 -0
- package/dist/src/agent/tasks/task-judge-service.js +24 -2
- 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/automations/draft/automation-draft-service.js +1 -1
- package/dist/src/cli/commands/extension-marketplace.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/update.js +1 -1
- package/dist/src/gateway/hono/lib/config-payload.d.ts +7 -0
- package/dist/src/gateway/hono/routes/auth-registry-extensions.js +1 -1
- package/dist/src/gateway/hono/routes/connectors.js +23 -23
- package/dist/src/gateway/hono/routes/sessions.js +1 -1
- package/dist/src/gateway/media-access.js +1 -1
- package/dist/src/gateway/service/config-coordinator.js +1 -1
- package/dist/src/gateway/service/run-gateway-agent.js +4 -1
- package/dist/src/gateway/service.js +1 -1
- 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/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/session/store.js +1 -1
- package/dist/src/session/turn-outcome-projector.js +26 -6
- 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/package.json +3 -3
- 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-D4EMxWAZ.js +0 -1
- package/dist/gateway/static/root/assets/skill-reload-api-DVb7nrXz.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,9 +1,14 @@
|
|
|
1
1
|
import type { AgentTool } from '@earendil-works/pi-agent-core';
|
|
2
2
|
import type { TurnOutcomeDeliverable } from '@xopcai/gateway-contract';
|
|
3
|
+
import type { CommandIsolation } from '../commands/command-isolation.js';
|
|
4
|
+
import { type CommandStatus } from '../commands/command-registry.js';
|
|
3
5
|
export interface ExecCommandDetails {
|
|
4
6
|
command: string;
|
|
5
7
|
cwd: string;
|
|
6
|
-
status:
|
|
8
|
+
status: CommandStatus | 'blocked';
|
|
9
|
+
id?: string;
|
|
10
|
+
logPath?: string;
|
|
11
|
+
logTruncated?: boolean;
|
|
7
12
|
exitCode: number | null;
|
|
8
13
|
durationMs: number;
|
|
9
14
|
timedOut: boolean;
|
|
@@ -27,6 +32,8 @@ export interface ExecCommandUpdateDetails {
|
|
|
27
32
|
}
|
|
28
33
|
export interface CreateExecCommandToolOptions {
|
|
29
34
|
/** Env var names allowed through prepareSafeToolEnv even if they match secret heuristics. */
|
|
35
|
+
getCommandIsolation?: () => CommandIsolation | undefined;
|
|
36
|
+
getSessionKey?: () => string | undefined;
|
|
30
37
|
getSkillPassthroughEnvVarNames?: () => string[];
|
|
31
38
|
prepareEnv?: (baseEnv: Record<string, string>, cwd: string) => Promise<Record<string, string>>;
|
|
32
39
|
}
|
|
@@ -1,76 +1,32 @@
|
|
|
1
|
+
import { commandRegistry, commandTimeout } from "../commands/command-registry.js";
|
|
1
2
|
import { formatSize, truncateTail } from "./truncate.js";
|
|
2
3
|
import { evaluateExecPolicy } from "../sandbox/exec-policy.js";
|
|
3
4
|
import { publishArtifactPaths } from "./publish-artifacts.js";
|
|
4
5
|
import { resolve } from "node:path";
|
|
5
|
-
import { spawn } from "node:child_process";
|
|
6
6
|
import { Type } from "@sinclair/typebox";
|
|
7
7
|
//#region src/agent/tools/exec-command.ts
|
|
8
|
-
const MAX_COMMAND_TIMEOUT_MS = 14400 * 1e3;
|
|
9
|
-
const DEFAULT_TIMEOUT_MS = 1800 * 1e3;
|
|
10
8
|
const DEFAULT_MAX_OUTPUT_CHARS = 5e4;
|
|
11
|
-
const STREAM_DELTA_MAX_CHARS = 16e3;
|
|
12
9
|
const ExecCommandSchema = Type.Object({
|
|
13
10
|
cmd: Type.String({ description: "Shell command to execute." }),
|
|
14
11
|
cwd: Type.Optional(Type.String({ description: "Working directory. Relative paths are resolved under the agent workspace." })),
|
|
15
12
|
timeoutMs: Type.Optional(Type.Number({ description: "Command timeout in milliseconds. Defaults to 1800000 (30m) and is capped at 14400000 (4h)." })),
|
|
16
13
|
maxOutputChars: Type.Optional(Type.Number({ description: "Maximum characters returned to the model. UI streaming still receives output deltas." })),
|
|
14
|
+
yieldTimeMs: Type.Optional(Type.Number({
|
|
15
|
+
minimum: 0,
|
|
16
|
+
maximum: 6e4,
|
|
17
|
+
description: "Return a running job after this wait; manage it with managed_job. Omit to wait for completion. Cannot be combined with outputs."
|
|
18
|
+
})),
|
|
17
19
|
outputs: Type.Optional(Type.Array(Type.String({ minLength: 1 }), {
|
|
18
20
|
maxItems: 50,
|
|
19
21
|
description: "Final user-facing files created by this command. Relative paths resolve under the effective cwd and are persisted as chat deliverables after a successful command."
|
|
20
22
|
}))
|
|
21
23
|
});
|
|
22
|
-
function clampTimeoutMs(raw) {
|
|
23
|
-
return Math.min(MAX_COMMAND_TIMEOUT_MS, Math.max(1e3, Math.floor(typeof raw === "number" && Number.isFinite(raw) ? raw : DEFAULT_TIMEOUT_MS)));
|
|
24
|
-
}
|
|
25
24
|
function clampMaxOutputChars(raw) {
|
|
26
25
|
return Math.max(1e3, Math.min(5e5, Math.floor(typeof raw === "number" && Number.isFinite(raw) ? raw : DEFAULT_MAX_OUTPUT_CHARS)));
|
|
27
26
|
}
|
|
28
|
-
function commandStatus(exitCode, timedOut) {
|
|
29
|
-
if (timedOut) return "timed_out";
|
|
30
|
-
if (exitCode === 0) return "success";
|
|
31
|
-
return "failed";
|
|
32
|
-
}
|
|
33
|
-
function appendBoundedTail(current, chunk, maxChars) {
|
|
34
|
-
const combined = current + chunk;
|
|
35
|
-
if (combined.length <= maxChars) return {
|
|
36
|
-
value: combined,
|
|
37
|
-
truncated: false
|
|
38
|
-
};
|
|
39
|
-
return {
|
|
40
|
-
value: combined.slice(-maxChars),
|
|
41
|
-
truncated: true
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
|
-
function terminateProcessTree(proc) {
|
|
45
|
-
if (!proc.pid) return;
|
|
46
|
-
if (process.platform === "win32") {
|
|
47
|
-
const killer = spawn("taskkill", [
|
|
48
|
-
"/pid",
|
|
49
|
-
String(proc.pid),
|
|
50
|
-
"/t",
|
|
51
|
-
"/f"
|
|
52
|
-
], {
|
|
53
|
-
stdio: "ignore",
|
|
54
|
-
windowsHide: true
|
|
55
|
-
});
|
|
56
|
-
killer.once("error", () => {
|
|
57
|
-
try {
|
|
58
|
-
proc.kill("SIGKILL");
|
|
59
|
-
} catch {}
|
|
60
|
-
});
|
|
61
|
-
killer.unref();
|
|
62
|
-
return;
|
|
63
|
-
}
|
|
64
|
-
try {
|
|
65
|
-
process.kill(-proc.pid, "SIGKILL");
|
|
66
|
-
return;
|
|
67
|
-
} catch {}
|
|
68
|
-
try {
|
|
69
|
-
proc.kill("SIGKILL");
|
|
70
|
-
} catch {}
|
|
71
|
-
}
|
|
72
27
|
function commandFailureHint(details) {
|
|
73
|
-
if (details.status === "success") return void 0;
|
|
28
|
+
if (details.status === "success" || details.status === "running") return void 0;
|
|
29
|
+
if (details.status === "cancelled") return "The command was cancelled. Inspect its partial output before deciding whether to restart.";
|
|
74
30
|
if (details.status === "timed_out") return "The command timed out. Re-run a narrower command, increase timeoutMs if the long run is expected, or inspect partial output before retrying.";
|
|
75
31
|
if (details.exitCode !== 0 && details.stderr.trim()) return "The command failed. Inspect stderr first, fix the underlying issue, then re-run the narrowest relevant verification command.";
|
|
76
32
|
if (details.exitCode !== 0 && details.stdout.trim()) return "The command failed. Inspect stdout for the failure location, then re-run the narrowest relevant verification command.";
|
|
@@ -80,7 +36,7 @@ function formatOutputForModel(details, maxOutputChars) {
|
|
|
80
36
|
let prefix = "";
|
|
81
37
|
if (details.timedOut) prefix += `Command timed out after ${Math.round(details.durationMs / 1e3)}s\n`;
|
|
82
38
|
if (details.exitCode !== 0 && details.exitCode != null) prefix += `Command exited with code ${details.exitCode}\n`;
|
|
83
|
-
if (details.captureTruncated) prefix += `Earlier command output was discarded after ${formatSize(details.totalOutputBytes)}; showing the latest captured output.\n`;
|
|
39
|
+
if (details.captureTruncated) prefix += `Earlier command output was discarded from model context after ${formatSize(details.totalOutputBytes)}; showing the latest captured output.\n`;
|
|
84
40
|
const truncation = truncateTail(details.aggregatedOutput, { maxBytes: Math.min(maxOutputChars, DEFAULT_MAX_OUTPUT_CHARS) });
|
|
85
41
|
let text = `${prefix}${truncation.content}`.trimEnd();
|
|
86
42
|
if (!text) text = "(no output)";
|
|
@@ -109,7 +65,8 @@ function createExecCommandTool(workspaceCwd, options) {
|
|
|
109
65
|
idempotent: false,
|
|
110
66
|
finalGuardRelevant: true,
|
|
111
67
|
async execute(toolCallId, params, signal, onUpdate) {
|
|
112
|
-
const command = (params.cmd ??
|
|
68
|
+
const command = (params.cmd ?? "").trim();
|
|
69
|
+
if (params.yieldTimeMs !== void 0 && params.outputs?.length) throw new Error("yieldTimeMs cannot be combined with outputs; publish files after the job completes.");
|
|
113
70
|
if (!command) return {
|
|
114
71
|
content: [{
|
|
115
72
|
type: "text",
|
|
@@ -163,127 +120,78 @@ function createExecCommandTool(workspaceCwd, options) {
|
|
|
163
120
|
}
|
|
164
121
|
};
|
|
165
122
|
}
|
|
166
|
-
const timeoutMs =
|
|
123
|
+
const timeoutMs = commandTimeout(params.timeoutMs, policy.timeoutMs);
|
|
167
124
|
const maxOutputChars = clampMaxOutputChars(params.maxOutputChars);
|
|
168
|
-
const startTime = Date.now();
|
|
169
125
|
const runtimeEnv = options?.prepareEnv ? await options.prepareEnv(policy.sanitizedEnv, policy.effectiveCwd) : policy.sanitizedEnv;
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
let
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
totalOutputBytes += Buffer.byteLength(text);
|
|
191
|
-
if (stream === "stdout") {
|
|
192
|
-
const next = appendBoundedTail(stdout, text, maxOutputChars);
|
|
193
|
-
stdout = next.value;
|
|
194
|
-
captureTruncated ||= next.truncated;
|
|
195
|
-
} else {
|
|
196
|
-
const next = appendBoundedTail(stderr, text, maxOutputChars);
|
|
197
|
-
stderr = next.value;
|
|
198
|
-
captureTruncated ||= next.truncated;
|
|
199
|
-
}
|
|
200
|
-
const nextAggregate = appendBoundedTail(aggregatedOutput, text, maxOutputChars);
|
|
201
|
-
aggregatedOutput = nextAggregate.value;
|
|
202
|
-
captureTruncated ||= nextAggregate.truncated;
|
|
203
|
-
const delta = text.length > STREAM_DELTA_MAX_CHARS ? `${text.slice(0, STREAM_DELTA_MAX_CHARS)}\n[stream delta truncated]` : text;
|
|
204
|
-
onUpdate?.({
|
|
205
|
-
content: [],
|
|
206
|
-
details: {
|
|
207
|
-
kind: "command_output_delta",
|
|
208
|
-
command,
|
|
209
|
-
cwd: policy.effectiveCwd,
|
|
210
|
-
stream,
|
|
211
|
-
delta
|
|
212
|
-
}
|
|
213
|
-
});
|
|
214
|
-
};
|
|
215
|
-
const finish = async (exitCode, errorText) => {
|
|
216
|
-
if (settled) return;
|
|
217
|
-
settled = true;
|
|
218
|
-
clearTimeout(timeout);
|
|
219
|
-
signal?.removeEventListener("abort", abort);
|
|
220
|
-
if (errorText) {
|
|
221
|
-
totalOutputBytes += Buffer.byteLength(errorText);
|
|
222
|
-
const nextStderr = appendBoundedTail(stderr, errorText, maxOutputChars);
|
|
223
|
-
stderr = nextStderr.value;
|
|
224
|
-
const nextAggregate = appendBoundedTail(aggregatedOutput, errorText, maxOutputChars);
|
|
225
|
-
aggregatedOutput = nextAggregate.value;
|
|
226
|
-
captureTruncated ||= nextStderr.truncated || nextAggregate.truncated;
|
|
227
|
-
}
|
|
228
|
-
const durationMs = Date.now() - startTime;
|
|
229
|
-
const baseDetails = {
|
|
126
|
+
const owner = options?.getSessionKey?.() ?? workspaceCwd;
|
|
127
|
+
const registry = commandRegistry();
|
|
128
|
+
let commandResult = await registry.start({
|
|
129
|
+
workspace: workspaceCwd,
|
|
130
|
+
isolation: options?.getCommandIsolation?.(),
|
|
131
|
+
owner,
|
|
132
|
+
command,
|
|
133
|
+
cwd: policy.effectiveCwd,
|
|
134
|
+
env: {
|
|
135
|
+
...runtimeEnv,
|
|
136
|
+
COLUMNS: "200"
|
|
137
|
+
},
|
|
138
|
+
timeoutMs,
|
|
139
|
+
maxOutputChars,
|
|
140
|
+
signal,
|
|
141
|
+
snapshot: true,
|
|
142
|
+
onOutput: (stream, delta) => onUpdate?.({
|
|
143
|
+
content: [],
|
|
144
|
+
details: {
|
|
145
|
+
kind: "command_output_delta",
|
|
230
146
|
command,
|
|
231
147
|
cwd: policy.effectiveCwd,
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
durationMs,
|
|
235
|
-
timedOut,
|
|
236
|
-
truncated: false,
|
|
237
|
-
outputBytes: Buffer.byteLength(aggregatedOutput),
|
|
238
|
-
totalOutputBytes,
|
|
239
|
-
captureTruncated,
|
|
240
|
-
stdout,
|
|
241
|
-
stderr,
|
|
242
|
-
aggregatedOutput
|
|
243
|
-
};
|
|
244
|
-
baseDetails.failureHint = commandFailureHint(baseDetails);
|
|
245
|
-
const formatted = formatOutputForModel(baseDetails, maxOutputChars);
|
|
246
|
-
const details = {
|
|
247
|
-
...baseDetails,
|
|
248
|
-
truncated: formatted.truncated,
|
|
249
|
-
truncatedBy: formatted.truncatedBy,
|
|
250
|
-
outputBytes: formatted.outputBytes
|
|
251
|
-
};
|
|
252
|
-
let resultText = formatted.text;
|
|
253
|
-
if (details.status === "success" && params.outputs?.length) {
|
|
254
|
-
details.artifacts = await publishArtifactPaths({
|
|
255
|
-
paths: params.outputs,
|
|
256
|
-
baseDir: policy.effectiveCwd,
|
|
257
|
-
workspaceRoot: workspaceCwd,
|
|
258
|
-
toolCallId
|
|
259
|
-
});
|
|
260
|
-
const published = details.artifacts.filter((item) => item.availability === "available").length;
|
|
261
|
-
const failed = details.artifacts.length - published;
|
|
262
|
-
resultText += `\n\nArtifacts: ${published} published${failed > 0 ? `, ${failed} failed` : ""}.`;
|
|
148
|
+
stream,
|
|
149
|
+
delta
|
|
263
150
|
}
|
|
264
|
-
|
|
265
|
-
content: [{
|
|
266
|
-
type: "text",
|
|
267
|
-
text: resultText
|
|
268
|
-
}],
|
|
269
|
-
details
|
|
270
|
-
});
|
|
271
|
-
};
|
|
272
|
-
const abort = () => {
|
|
273
|
-
timedOut = true;
|
|
274
|
-
terminateProcessTree(proc);
|
|
275
|
-
};
|
|
276
|
-
const timeout = setTimeout(() => {
|
|
277
|
-
timedOut = true;
|
|
278
|
-
terminateProcessTree(proc);
|
|
279
|
-
}, timeoutMs);
|
|
280
|
-
if (signal?.aborted) abort();
|
|
281
|
-
else signal?.addEventListener("abort", abort, { once: true });
|
|
282
|
-
proc.stdout?.on("data", (data) => publishDelta("stdout", data));
|
|
283
|
-
proc.stderr?.on("data", (data) => publishDelta("stderr", data));
|
|
284
|
-
proc.on("error", (err) => void finish(null, `Error: ${err.message}`));
|
|
285
|
-
proc.on("close", (code) => void finish(code));
|
|
151
|
+
})
|
|
286
152
|
});
|
|
153
|
+
try {
|
|
154
|
+
do
|
|
155
|
+
commandResult = await registry.wait(owner, commandResult.id, params.yieldTimeMs ?? 6e4, signal);
|
|
156
|
+
while (params.yieldTimeMs === void 0 && commandResult.status === "running");
|
|
157
|
+
} catch (error) {
|
|
158
|
+
if (!signal?.aborted) throw error;
|
|
159
|
+
commandResult = await registry.cancel(owner, commandResult.id);
|
|
160
|
+
}
|
|
161
|
+
const baseDetails = {
|
|
162
|
+
...commandResult,
|
|
163
|
+
truncated: false,
|
|
164
|
+
outputBytes: Buffer.byteLength(commandResult.aggregatedOutput)
|
|
165
|
+
};
|
|
166
|
+
baseDetails.failureHint = commandFailureHint(baseDetails);
|
|
167
|
+
const formatted = formatOutputForModel(baseDetails, maxOutputChars);
|
|
168
|
+
const details = {
|
|
169
|
+
...baseDetails,
|
|
170
|
+
truncated: formatted.truncated,
|
|
171
|
+
truncatedBy: formatted.truncatedBy,
|
|
172
|
+
outputBytes: formatted.outputBytes
|
|
173
|
+
};
|
|
174
|
+
let resultText = formatted.text;
|
|
175
|
+
if (details.status === "running") resultText += `\n\nCommand is running (jobId: ${details.id}). Use managed_job wait/status/stdin/cancel.`;
|
|
176
|
+
if (details.logPath) resultText += `\n\nLog: ${details.logPath}${details.logTruncated ? " (truncated)" : ""}`;
|
|
177
|
+
if (details.status === "success" && params.outputs?.length) {
|
|
178
|
+
details.artifacts = await publishArtifactPaths({
|
|
179
|
+
paths: params.outputs,
|
|
180
|
+
baseDir: policy.effectiveCwd,
|
|
181
|
+
workspaceRoot: workspaceCwd,
|
|
182
|
+
toolCallId
|
|
183
|
+
});
|
|
184
|
+
const published = details.artifacts.filter((item) => item.availability === "available").length;
|
|
185
|
+
const failed = details.artifacts.length - published;
|
|
186
|
+
resultText += `\n\nArtifacts: ${published} published${failed > 0 ? `, ${failed} failed` : ""}.`;
|
|
187
|
+
}
|
|
188
|
+
return {
|
|
189
|
+
content: [{
|
|
190
|
+
type: "text",
|
|
191
|
+
text: resultText
|
|
192
|
+
}],
|
|
193
|
+
details
|
|
194
|
+
};
|
|
287
195
|
}
|
|
288
196
|
};
|
|
289
197
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { createLogger } from "../../utils/logger/index.js";
|
|
2
2
|
import { init_logger } from "../../utils/logger.js";
|
|
3
|
+
import { commandTimeout } from "../commands/command-registry.js";
|
|
3
4
|
import { DEFAULT_TOOL_EXECUTION_TIMEOUT_MS, TimeoutError, executeWithTimeout } from "../lifecycle/timeout-wrapper.js";
|
|
4
5
|
import { withRetry } from "../../infra/retry.js";
|
|
5
6
|
import { ToolConcurrencyController, resolveToolLockMode } from "./concurrency.js";
|
|
@@ -41,8 +42,14 @@ async function executeToolWithProtection(tool, toolCallId, params, signal, onUpd
|
|
|
41
42
|
const onParentAbort = () => controller.abort(signal?.reason);
|
|
42
43
|
if (signal?.aborted) onParentAbort();
|
|
43
44
|
else signal?.addEventListener("abort", onParentAbort, { once: true });
|
|
44
|
-
const
|
|
45
|
-
|
|
45
|
+
const policyDeadline = fullConfig.resolveTimeoutMs?.(toolName);
|
|
46
|
+
const commandDeadlineField = toolName === "exec_command" ? "timeoutMs" : toolName === "managed_job" && params.action === "start" ? "maxRuntimeMs" : void 0;
|
|
47
|
+
const executionParams = commandDeadlineField && policyDeadline ? {
|
|
48
|
+
...params,
|
|
49
|
+
[commandDeadlineField]: Math.min(commandTimeout(params[commandDeadlineField]), policyDeadline)
|
|
50
|
+
} : params;
|
|
51
|
+
const execute = () => tool.execute(toolCallId, executionParams, controller.signal, onUpdate);
|
|
52
|
+
return (fullConfig.enableTimeout && toolName !== "exec_command" ? executeWithTimeout(execute, {
|
|
46
53
|
toolName,
|
|
47
54
|
timeoutMs: resolveTimeoutMs(tool, fullConfig),
|
|
48
55
|
description: `Executing ${toolName}`,
|
|
@@ -5,7 +5,9 @@ import { isXopcDatabaseOpen } from "../../storage/sqlite/connection.js";
|
|
|
5
5
|
import { getSessionTaskPlan, setSessionTaskPlan } from "../../storage/sqlite/session-task-plan-repository.js";
|
|
6
6
|
import "../../storage/sqlite/index.js";
|
|
7
7
|
import { init_agent_scope, resolveDefaultAgentId } from "../agent-scope.js";
|
|
8
|
+
import { resolveEffectiveAgentConfigForSession } from "../../config/agent-profile.js";
|
|
8
9
|
import { wrapToolsWithProtection } from "./executor.js";
|
|
10
|
+
import { EXTERNAL_TOOL_NAMES } from "../external-tools/gateway-tools.js";
|
|
9
11
|
import { buildRuntimeEnvironment } from "../../runtime-tools/environment.js";
|
|
10
12
|
import { createDefaultExternalToolGatewayTools } from "../external-tools/index.js";
|
|
11
13
|
import { createReadFileTool } from "./read.js";
|
|
@@ -36,9 +38,8 @@ import { resolveBrowserBackendFromConfig } from "../../browser/backend-from-conf
|
|
|
36
38
|
import { checkBrowserReadiness } from "../../browser/readiness.js";
|
|
37
39
|
import { CdpSupervisor } from "../../browser/cdp-supervisor.js";
|
|
38
40
|
import "../../browser/index.js";
|
|
39
|
-
import "./delegate-tool.js";
|
|
41
|
+
import { createDelegateTool } from "./delegate-tool.js";
|
|
40
42
|
import { createWorkflowTool } from "./workflow-tool.js";
|
|
41
|
-
import "./execute-code-tool.js";
|
|
42
43
|
import { createAutomationTool } from "./automation-tool.js";
|
|
43
44
|
import { createBrowserRecipeTool } from "./browser-recipe-tool.js";
|
|
44
45
|
import { createXopcUseTool } from "./xopc-use-tool.js";
|
|
@@ -53,6 +54,8 @@ import { createImageTool } from "./image-tool.js";
|
|
|
53
54
|
import { createImageGenerateTool } from "./image-generate-tool.js";
|
|
54
55
|
import "./index.js";
|
|
55
56
|
import { createBrowserUseTool } from "./browser/tool/browser-use-tool.js";
|
|
57
|
+
import { createReviewWorkspaceTool } from "./review-workspace.js";
|
|
58
|
+
import { createLanguageDiagnosticsTool } from "./language-diagnostics.js";
|
|
56
59
|
import { createWorkflowCatalog } from "../workflow/catalog.js";
|
|
57
60
|
import { mergeTtsConfigFromAppConfig } from "../../voice/tts/merge-config.js";
|
|
58
61
|
import { createTextToSpeechTool } from "./tts-tool.js";
|
|
@@ -70,7 +73,7 @@ const CLARIFY_SUPPORTED_CHANNELS = new Set([
|
|
|
70
73
|
"telegram",
|
|
71
74
|
"cli"
|
|
72
75
|
]);
|
|
73
|
-
var AgentToolsFactory = class {
|
|
76
|
+
var AgentToolsFactory = class AgentToolsFactory {
|
|
74
77
|
browserManager = null;
|
|
75
78
|
/** One dialog/console supervisor per chat session (browser tab). */
|
|
76
79
|
browserTaskSupervisors = /* @__PURE__ */ new Map();
|
|
@@ -193,6 +196,10 @@ var AgentToolsFactory = class {
|
|
|
193
196
|
agentId: options?.agentId ?? (cfg ? resolveDefaultAgentId(cfg) : "main")
|
|
194
197
|
});
|
|
195
198
|
const agentId = options?.agentId;
|
|
199
|
+
const getCommandIsolation = () => {
|
|
200
|
+
const config = this.deps.getConfig?.();
|
|
201
|
+
return config ? resolveEffectiveAgentConfigForSession(config, this.deps.getCurrentContext()?.sessionKey ?? `agent:${agentId ?? "main"}:internal`).config.runtime.commandIsolation : void 0;
|
|
202
|
+
};
|
|
196
203
|
const externalTools = createDefaultExternalToolGatewayTools({
|
|
197
204
|
workspace,
|
|
198
205
|
getConfig: () => this.deps.getConfig?.(),
|
|
@@ -271,10 +278,18 @@ var AgentToolsFactory = class {
|
|
|
271
278
|
grep,
|
|
272
279
|
find,
|
|
273
280
|
createExecCommandTool(workspace, {
|
|
281
|
+
getCommandIsolation,
|
|
282
|
+
getSessionKey: () => this.deps.getCurrentContext()?.sessionKey,
|
|
274
283
|
getSkillPassthroughEnvVarNames: this.deps.getSkillPassthroughEnvVarNames,
|
|
275
284
|
prepareEnv: this.prepareRuntimeEnv
|
|
276
285
|
}),
|
|
277
|
-
|
|
286
|
+
createReviewWorkspaceTool(workspace),
|
|
287
|
+
createLanguageDiagnosticsTool(workspace, {
|
|
288
|
+
getCommandIsolation,
|
|
289
|
+
getSessionKey: () => this.deps.getCurrentContext()?.sessionKey,
|
|
290
|
+
prepareEnv: this.prepareRuntimeEnv
|
|
291
|
+
}),
|
|
292
|
+
createManagedJobTool(workspace, () => this.deps.getCurrentContext()?.sessionKey, this.deps.getSkillPassthroughEnvVarNames, this.prepareRuntimeEnv, getCommandIsolation),
|
|
278
293
|
createWebSearchTool(() => this.deps.getConfig?.()),
|
|
279
294
|
createWebFetchTool(() => this.deps.getConfig?.()),
|
|
280
295
|
createWebExtractTool({ getConfig: () => this.deps.getConfig?.() }),
|
|
@@ -345,7 +360,37 @@ var AgentToolsFactory = class {
|
|
|
345
360
|
getConfig: () => this.deps.getConfig?.(),
|
|
346
361
|
startWorkflowRun: this.deps.getWorkflowRunService ? (params) => this.deps.getWorkflowRunService().startWorkflowRun(params) : void 0
|
|
347
362
|
})] : [],
|
|
348
|
-
...[
|
|
363
|
+
...primary ? [createDelegateTool({
|
|
364
|
+
workspace,
|
|
365
|
+
getSubagentModel: () => {
|
|
366
|
+
const m = (options?.getPrimaryModel ?? this.deps.getPrimaryModel)?.();
|
|
367
|
+
if (!m) throw new Error("No primary model configured for delegate_task");
|
|
368
|
+
return m;
|
|
369
|
+
},
|
|
370
|
+
bus: this.deps.bus,
|
|
371
|
+
getConfig: () => this.deps.getConfig?.(),
|
|
372
|
+
getCurrentContext: () => this.deps.getCurrentContext?.() ?? null,
|
|
373
|
+
toolExecutorConfig: this.deps.toolExecutorConfig,
|
|
374
|
+
buildChildTools: (childOpts) => {
|
|
375
|
+
return new AgentToolsFactory({
|
|
376
|
+
workspace: childOpts.workspace,
|
|
377
|
+
bus: childOpts.bus,
|
|
378
|
+
getCurrentContext: () => null,
|
|
379
|
+
getConfig: childOpts.getConfig,
|
|
380
|
+
getPrimaryModel: () => childOpts.model,
|
|
381
|
+
toolExecutorConfig: childOpts.toolExecutorConfig
|
|
382
|
+
}).createAllTools({
|
|
383
|
+
workspace: childOpts.workspace,
|
|
384
|
+
getPrimaryModel: () => childOpts.model,
|
|
385
|
+
agentId: options?.agentId ?? childOpts.agentId,
|
|
386
|
+
disabledTools: new Set([
|
|
387
|
+
EXTERNAL_TOOL_NAMES.search,
|
|
388
|
+
EXTERNAL_TOOL_NAMES.describe,
|
|
389
|
+
EXTERNAL_TOOL_NAMES.execute
|
|
390
|
+
])
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
})] : [],
|
|
349
394
|
...optionalTools
|
|
350
395
|
], disabled);
|
|
351
396
|
}
|
|
@@ -1,17 +1,14 @@
|
|
|
1
|
+
import { type Static } from '@sinclair/typebox';
|
|
1
2
|
import type { AgentTool } from '@earendil-works/pi-agent-core';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
};
|
|
3
|
+
declare const findSchema: import("@sinclair/typebox").TObject<{
|
|
4
|
+
pattern: import("@sinclair/typebox").TString;
|
|
5
|
+
path: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
6
|
+
limit: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TInteger>;
|
|
7
|
+
}>;
|
|
8
8
|
export interface FindToolDetails {
|
|
9
|
-
|
|
10
|
-
resultLimitReached?: number;
|
|
9
|
+
truncated: boolean;
|
|
11
10
|
}
|
|
12
|
-
|
|
13
|
-
* Find tool - Search for files by glob pattern
|
|
14
|
-
*/
|
|
11
|
+
export type FindToolInput = Static<typeof findSchema>;
|
|
15
12
|
export declare function createFindTool(cwd: string): AgentTool;
|
|
16
|
-
|
|
17
|
-
export
|
|
13
|
+
export declare const findTool: AgentTool<import("typebox").TSchema, any>;
|
|
14
|
+
export {};
|
|
@@ -1,97 +1,50 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { evaluateFilePolicy } from "../sandbox/exec-policy.js";
|
|
2
2
|
import { resolveToCwd } from "../../utils/helpers.js";
|
|
3
|
-
import
|
|
4
|
-
import { existsSync } from "fs";
|
|
3
|
+
import { repositorySearch } from "./repository-search.js";
|
|
5
4
|
import { Type } from "@sinclair/typebox";
|
|
6
|
-
import { globSync } from "glob";
|
|
7
5
|
//#region src/agent/tools/find.ts
|
|
8
6
|
const findSchema = Type.Object({
|
|
9
|
-
pattern: Type.String({ description: "Glob pattern
|
|
10
|
-
path: Type.Optional(Type.String(
|
|
11
|
-
limit: Type.Optional(Type.
|
|
7
|
+
pattern: Type.String({ description: "Glob pattern, e.g. *.ts or src/**/*.json" }),
|
|
8
|
+
path: Type.Optional(Type.String()),
|
|
9
|
+
limit: Type.Optional(Type.Integer({
|
|
10
|
+
minimum: 1,
|
|
11
|
+
maximum: 1e4
|
|
12
|
+
}))
|
|
12
13
|
});
|
|
13
|
-
const DEFAULT_LIMIT = 1e3;
|
|
14
|
-
/**
|
|
15
|
-
* Find tool - Search for files by glob pattern
|
|
16
|
-
*/
|
|
17
14
|
function createFindTool(cwd) {
|
|
18
15
|
return {
|
|
19
16
|
name: "find",
|
|
20
|
-
label: "
|
|
21
|
-
description: "Find files by glob pattern (e.g., *.ts, **/*.json).",
|
|
17
|
+
label: "Find files",
|
|
22
18
|
parameters: findSchema,
|
|
19
|
+
description: "Find files by glob with ripgrep; respects .gitignore and skips .git and node_modules. Results are relative to the search directory.",
|
|
23
20
|
supportsParallel: true,
|
|
24
21
|
idempotent: true,
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
});
|
|
49
|
-
if (filePaths.length === 0) return {
|
|
50
|
-
content: [{
|
|
51
|
-
type: "text",
|
|
52
|
-
text: "No files found matching pattern"
|
|
53
|
-
}],
|
|
54
|
-
details: {}
|
|
55
|
-
};
|
|
56
|
-
const relativized = filePaths.map((p) => {
|
|
57
|
-
if (p.startsWith(searchPath)) return p.slice(searchPath.length + 1);
|
|
58
|
-
return path.relative(searchPath, p);
|
|
59
|
-
});
|
|
60
|
-
relativized.sort();
|
|
61
|
-
const resultLimitReached = relativized.length >= effectiveLimit;
|
|
62
|
-
const truncation = truncateHead((resultLimitReached ? relativized.slice(0, effectiveLimit) : relativized).join("\n"), { maxLines: Number.MAX_SAFE_INTEGER });
|
|
63
|
-
let resultOutput = truncation.content;
|
|
64
|
-
const details = {};
|
|
65
|
-
const notices = [];
|
|
66
|
-
if (resultLimitReached) {
|
|
67
|
-
notices.push(`${effectiveLimit} results limit reached`);
|
|
68
|
-
details.resultLimitReached = effectiveLimit;
|
|
69
|
-
}
|
|
70
|
-
if (truncation.truncated) {
|
|
71
|
-
notices.push(`${formatSize(DEFAULT_MAX_BYTES)} limit reached`);
|
|
72
|
-
details.truncation = truncation;
|
|
73
|
-
}
|
|
74
|
-
if (notices.length > 0) resultOutput += `\n\n[${notices.join(". ")}]`;
|
|
75
|
-
return {
|
|
76
|
-
content: [{
|
|
77
|
-
type: "text",
|
|
78
|
-
text: resultOutput
|
|
79
|
-
}],
|
|
80
|
-
details: Object.keys(details).length > 0 ? details : void 0
|
|
81
|
-
};
|
|
82
|
-
} catch (error) {
|
|
83
|
-
return {
|
|
84
|
-
content: [{
|
|
85
|
-
type: "text",
|
|
86
|
-
text: `Error during find: ${error instanceof Error ? error.message : String(error)}`
|
|
87
|
-
}],
|
|
88
|
-
details: {}
|
|
89
|
-
};
|
|
90
|
-
}
|
|
22
|
+
async execute(_id, params, signal) {
|
|
23
|
+
const path = resolveToCwd(params.path || ".", cwd);
|
|
24
|
+
const policy = evaluateFilePolicy({
|
|
25
|
+
operation: "read",
|
|
26
|
+
path,
|
|
27
|
+
workspaceRoot: cwd
|
|
28
|
+
});
|
|
29
|
+
if (!policy.allowed) throw new Error(policy.reason);
|
|
30
|
+
const result = await repositorySearch(path, [
|
|
31
|
+
"--files",
|
|
32
|
+
"--glob",
|
|
33
|
+
params.pattern
|
|
34
|
+
], signal);
|
|
35
|
+
const limit = Math.min(1e4, Math.max(1, params.limit ?? 1e3));
|
|
36
|
+
const lines = result.output.trimEnd().split("\n").filter(Boolean).sort();
|
|
37
|
+
const truncated = result.truncated || lines.length > limit;
|
|
38
|
+
return {
|
|
39
|
+
content: [{
|
|
40
|
+
type: "text",
|
|
41
|
+
text: (lines.slice(0, limit).join("\n") || "No files found matching pattern") + (truncated ? "\n[Results truncated; narrow the glob.]" : "")
|
|
42
|
+
}],
|
|
43
|
+
details: { truncated }
|
|
44
|
+
};
|
|
91
45
|
}
|
|
92
46
|
};
|
|
93
47
|
}
|
|
94
|
-
/** Default find tool using process.cwd() */
|
|
95
48
|
const findTool = createFindTool(process.cwd());
|
|
96
49
|
//#endregion
|
|
97
50
|
export { createFindTool, findTool };
|
|
@@ -1,22 +1,18 @@
|
|
|
1
|
+
import { type Static } from '@sinclair/typebox';
|
|
1
2
|
import type { AgentTool } from '@earendil-works/pi-agent-core';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
};
|
|
3
|
+
declare const grepSchema: import("@sinclair/typebox").TObject<{
|
|
4
|
+
pattern: import("@sinclair/typebox").TString;
|
|
5
|
+
path: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
6
|
+
glob: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
7
|
+
ignoreCase: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TBoolean>;
|
|
8
|
+
literal: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TBoolean>;
|
|
9
|
+
context: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TInteger>;
|
|
10
|
+
limit: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TInteger>;
|
|
11
|
+
}>;
|
|
12
12
|
export interface GrepToolDetails {
|
|
13
|
-
|
|
14
|
-
matchLimitReached?: number;
|
|
15
|
-
linesTruncated?: boolean;
|
|
13
|
+
truncated: boolean;
|
|
16
14
|
}
|
|
17
|
-
|
|
18
|
-
* Grep tool - Search file contents for a pattern
|
|
19
|
-
*/
|
|
15
|
+
export type GrepToolInput = Static<typeof grepSchema>;
|
|
20
16
|
export declare function createGrepTool(cwd: string): AgentTool;
|
|
21
|
-
|
|
22
|
-
export
|
|
17
|
+
export declare const grepTool: AgentTool<import("typebox").TSchema, any>;
|
|
18
|
+
export {};
|