march-cli 0.1.24 → 0.1.26
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/bin/march.mjs +13 -13
- package/package.json +49 -49
- package/src/agent/command-exec-tool.mjs +172 -172
- package/src/agent/context-stats-tool.mjs +57 -57
- package/src/agent/editing/diff-apply.mjs +28 -28
- package/src/agent/editing/diff-format.mjs +57 -57
- package/src/agent/editing/lsp-report.mjs +69 -69
- package/src/agent/file-edit-tool.mjs +250 -250
- package/src/agent/file-tools/read-file-tool.mjs +112 -112
- package/src/agent/file-tools/read-image-tool.mjs +76 -76
- package/src/agent/model-payload-dumper.mjs +208 -208
- package/src/agent/pi-session/pi-session-sidecar-failure.mjs +10 -10
- package/src/agent/provider/payload-messages.mjs +138 -138
- package/src/agent/runner/codex-large-context-guard.mjs +87 -87
- package/src/agent/runner/codex-transport-compression.mjs +180 -180
- package/src/agent/runner/codex-transport-debug.mjs +113 -113
- package/src/agent/runner/codex-websocket-event-debug.mjs +130 -130
- package/src/agent/runner/fast-model.mjs +36 -36
- package/src/agent/runner/runner-cleanup.mjs +12 -12
- package/src/agent/runner/runner-init.mjs +15 -15
- package/src/agent/runner/runner-session-state.mjs +40 -40
- package/src/agent/runner/runner-utils.mjs +24 -24
- package/src/agent/runner.mjs +299 -299
- package/src/agent/runtime/ipc/ipc-peer.mjs +99 -99
- package/src/agent/runtime/ipc/process-ipc-transport.mjs +16 -16
- package/src/agent/runtime/remote-runner-client.mjs +73 -73
- package/src/agent/runtime/remote-ui-client.mjs +20 -20
- package/src/agent/runtime/runner-ipc-target.mjs +125 -125
- package/src/agent/runtime/runner-process-client.mjs +47 -47
- package/src/agent/runtime/runner-process-entry.mjs +11 -11
- package/src/agent/runtime/runner-process-factory.mjs +111 -108
- package/src/agent/runtime/runner-runtime-host.mjs +79 -79
- package/src/agent/runtime/runtime-factory.mjs +42 -42
- package/src/agent/runtime/runtime-host.mjs +34 -34
- package/src/agent/runtime/ui-event-bridge.mjs +95 -95
- package/src/agent/screen-tools/list-windows-tool.mjs +39 -39
- package/src/agent/screen-tools/screen-tool.mjs +49 -49
- package/src/agent/screen-tools/windows-screen.mjs +133 -133
- package/src/agent/session/session-auto-name.mjs +41 -41
- package/src/agent/session/session-binding.mjs +12 -12
- package/src/agent/session/session-options.mjs +47 -47
- package/src/agent/tool-names.mjs +1 -1
- package/src/agent/tool-result.mjs +3 -3
- package/src/agent/tool-summary.mjs +112 -112
- package/src/agent/tools.mjs +58 -58
- package/src/agent/turn/turn-events.mjs +111 -111
- package/src/agent/turn/turn-logging.mjs +30 -30
- package/src/agent/turn/turn-runner.mjs +196 -196
- package/src/agent/vision-capability.mjs +14 -14
- package/src/auth/login-command.mjs +90 -90
- package/src/auth/storage.mjs +34 -34
- package/src/cli/args.mjs +96 -79
- package/src/cli/commands/copy-command.mjs +87 -87
- package/src/cli/commands/export-command.mjs +206 -206
- package/src/cli/commands/extensions-command.mjs +53 -53
- package/src/cli/commands/help-command.mjs +7 -7
- package/src/cli/commands/model-command.mjs +141 -141
- package/src/cli/commands/paste-image-command.mjs +43 -43
- package/src/cli/commands/provider-command.mjs +59 -59
- package/src/cli/commands/status-command.mjs +196 -194
- package/src/cli/commands/thinking-command.mjs +87 -87
- package/src/cli/fallback-ui.mjs +156 -156
- package/src/cli/input/attachment-tokens.mjs +20 -20
- package/src/cli/input/autocomplete.mjs +74 -74
- package/src/cli/input/external-editor.mjs +39 -39
- package/src/cli/input/file-search/index.mjs +160 -160
- package/src/cli/input/history-store.mjs +35 -35
- package/src/cli/input/image-clipboard.mjs +55 -55
- package/src/cli/input/keybinding-dispatch.mjs +76 -76
- package/src/cli/input/keybindings.mjs +96 -96
- package/src/cli/input/mode-state.mjs +43 -43
- package/src/cli/input/prompt-templates.mjs +84 -84
- package/src/cli/input/select-with-keyboard.mjs +86 -86
- package/src/cli/permissions.mjs +103 -103
- package/src/cli/repl-commands.mjs +86 -86
- package/src/cli/repl-loop.mjs +183 -183
- package/src/cli/selector-list.mjs +21 -21
- package/src/cli/session/pi-session-switch-command.mjs +41 -41
- package/src/cli/session/session-command.mjs +23 -23
- package/src/cli/session/session-list-command.mjs +68 -68
- package/src/cli/session/session-name-command.mjs +26 -26
- package/src/cli/session/session-source-command.mjs +89 -89
- package/src/cli/session/session-switch-command.mjs +1 -1
- package/src/cli/shell/shell-command.mjs +55 -55
- package/src/cli/shell/shell-drawer-controls.mjs +33 -33
- package/src/cli/shell/shell-drawer.mjs +192 -192
- package/src/cli/shell/shell-split-layout.mjs +70 -70
- package/src/cli/slash-commands.mjs +192 -192
- package/src/cli/startup/create-runtime-runner.mjs +61 -61
- package/src/cli/startup/runtime-close.mjs +23 -23
- package/src/cli/startup/startup-banner.mjs +71 -71
- package/src/cli/startup/startup-session.mjs +51 -51
- package/src/cli/status-line-updater.mjs +75 -75
- package/src/cli/tool-output.mjs +9 -9
- package/src/cli/tui/editor/external-editor-runner.mjs +24 -24
- package/src/cli/tui/input/mouse-selection-controller.mjs +91 -91
- package/src/cli/tui/input/mouse-tracking.mjs +20 -20
- package/src/cli/tui/layout/main-pane-layout.mjs +47 -47
- package/src/cli/tui/layout/safe-render-boundary.mjs +46 -46
- package/src/cli/tui/markdown-renderer.mjs +285 -285
- package/src/cli/tui/output/scroll-state.mjs +79 -79
- package/src/cli/tui/output/text-line-renderer.mjs +50 -50
- package/src/cli/tui/output/tool-card-renderer.mjs +59 -59
- package/src/cli/tui/output/visible-lines.mjs +8 -8
- package/src/cli/tui/output-buffer.mjs +293 -293
- package/src/cli/tui/permission-request-ui.mjs +18 -18
- package/src/cli/tui/recall-rendering.mjs +28 -25
- package/src/cli/tui/render/render-scheduler.mjs +26 -26
- package/src/cli/tui/render/stream-delta-buffer.mjs +46 -46
- package/src/cli/tui/select/editor-select-list.mjs +111 -111
- package/src/cli/tui/selection-screen.mjs +269 -269
- package/src/cli/tui/status/retry-status.mjs +72 -72
- package/src/cli/tui/status/spinner-status.mjs +42 -42
- package/src/cli/tui/status/status-bar.mjs +225 -225
- package/src/cli/tui/syntax/highlighting.mjs +260 -260
- package/src/cli/tui/syntax/languages.mjs +91 -91
- package/src/cli/tui/syntax/tree-sitter/bash.highlights.scm +261 -261
- package/src/cli/tui/syntax/tree-sitter/c.highlights.scm +341 -341
- package/src/cli/tui/syntax/tree-sitter/cpp.highlights.scm +268 -268
- package/src/cli/tui/syntax/tree-sitter/csharp.highlights.scm +577 -577
- package/src/cli/tui/syntax/tree-sitter/css.highlights.scm +109 -109
- package/src/cli/tui/syntax/tree-sitter/diff.highlights.scm +49 -49
- package/src/cli/tui/syntax/tree-sitter/go.highlights.scm +254 -254
- package/src/cli/tui/syntax/tree-sitter/html.highlights.scm +13 -13
- package/src/cli/tui/syntax/tree-sitter/java.highlights.scm +330 -330
- package/src/cli/tui/syntax/tree-sitter/json.highlights.scm +38 -38
- package/src/cli/tui/syntax/tree-sitter/php.highlights.scm +203 -203
- package/src/cli/tui/syntax/tree-sitter/python.highlights.scm +137 -137
- package/src/cli/tui/syntax/tree-sitter/ruby.highlights.scm +309 -309
- package/src/cli/tui/syntax/tree-sitter/rust.highlights.scm +531 -531
- package/src/cli/tui/syntax/tree-sitter/toml.highlights.scm +39 -39
- package/src/cli/tui/syntax/tree-sitter/tsx.highlights.scm +35 -35
- package/src/cli/tui/syntax/tree-sitter/typescript.highlights.scm +35 -35
- package/src/cli/tui/syntax/tree-sitter/yaml.highlights.scm +99 -99
- package/src/cli/tui/tool-rendering.mjs +87 -87
- package/src/cli/tui/tui-diff-rendering.mjs +157 -157
- package/src/cli/tui/tui-handlers.mjs +111 -111
- package/src/cli/tui/tui-input-controller.mjs +61 -61
- package/src/cli/tui/ui-theme.mjs +157 -157
- package/src/cli/ui.mjs +297 -297
- package/src/config/config-json.mjs +108 -84
- package/src/config/dotenv.mjs +20 -20
- package/src/config/features.mjs +75 -75
- package/src/config/loader.mjs +156 -143
- package/src/config/settings-command.mjs +97 -97
- package/src/context/engine.mjs +199 -198
- package/src/context/injections.mjs +26 -26
- package/src/context/profiles.mjs +39 -39
- package/src/context/project-context.mjs +20 -20
- package/src/context/session-status.mjs +25 -17
- package/src/context/shell-layers.mjs +23 -23
- package/src/context/system-core/base.md +51 -50
- package/src/context/system-core/prompts/deepseek-v4-pro.md +3 -3
- package/src/context/system-core/prompts/default.md +3 -3
- package/src/context/system-core.mjs +35 -35
- package/src/debug/logger.mjs +141 -141
- package/src/debug/model-context-dumper.mjs +52 -52
- package/src/extensions/discovery.mjs +40 -40
- package/src/extensions/lifecycle-adapter.mjs +210 -210
- package/src/extensions/lifecycle-manifest.mjs +69 -69
- package/src/image-gen/index.mjs +7 -7
- package/src/image-gen/provider.mjs +231 -231
- package/src/image-gen/tool.mjs +84 -84
- package/src/lsp/client.mjs +257 -257
- package/src/lsp/diagnostic-store.mjs +42 -42
- package/src/lsp/diagnostics-format.mjs +72 -72
- package/src/lsp/managed-node-server.mjs +99 -99
- package/src/lsp/path-match.mjs +10 -10
- package/src/lsp/server-definitions.mjs +188 -188
- package/src/lsp/servers.mjs +165 -165
- package/src/lsp/service.mjs +110 -110
- package/src/lsp/status-message.mjs +9 -9
- package/src/lsp/typescript-project-resolver.mjs +186 -186
- package/src/main.mjs +294 -299
- package/src/mcp/client.mjs +195 -195
- package/src/mcp/config.mjs +130 -130
- package/src/mcp/index.mjs +48 -48
- package/src/mcp/tools.mjs +98 -98
- package/src/memory/command.mjs +120 -0
- package/src/memory/markdown/markdown-delete.mjs +23 -23
- package/src/memory/markdown/markdown-format.mjs +128 -128
- package/src/memory/markdown/markdown-recall.mjs +28 -28
- package/src/memory/markdown/ripgrep.mjs +16 -16
- package/src/memory/markdown/sqlite-index.mjs +87 -87
- package/src/memory/markdown-store.mjs +272 -286
- package/src/memory/markdown-tools.mjs +174 -103
- package/src/memory/remote/client.mjs +68 -0
- package/src/memory/remote/config.mjs +52 -0
- package/src/memory/remote/server.mjs +99 -0
- package/src/memory/search.mjs +183 -0
- package/src/network/environment.mjs +131 -131
- package/src/notification/desktop-notifier.mjs +262 -262
- package/src/platform/open-file.mjs +28 -28
- package/src/platform/spawn-command.mjs +27 -27
- package/src/provider/accept-command.mjs +89 -89
- package/src/provider/command.mjs +21 -21
- package/src/provider/config-command.mjs +129 -129
- package/src/provider/custom-provider.mjs +113 -113
- package/src/provider/hosted-tools.mjs +111 -111
- package/src/provider/presets.mjs +72 -72
- package/src/provider/share-command.mjs +79 -79
- package/src/provider/share-payload.mjs +52 -52
- package/src/session/attachment-display.mjs +16 -16
- package/src/session/attachment-references.mjs +65 -65
- package/src/session/attachments.mjs +140 -140
- package/src/session/persist.mjs +1 -1
- package/src/session/pi-manager.mjs +34 -34
- package/src/session/session-utils.mjs +16 -16
- package/src/session/sidecar-sync.mjs +19 -19
- package/src/session/sidecar.mjs +69 -69
- package/src/session/transcript.mjs +83 -83
- package/src/session/tree.mjs +42 -42
- package/src/shell/cli-runtime.mjs +11 -11
- package/src/shell/hints.mjs +12 -12
- package/src/shell/node-pty-adapter.mjs +81 -81
- package/src/shell/runtime-state.mjs +126 -126
- package/src/shell/runtime.mjs +252 -252
- package/src/shell/screen-buffer.mjs +136 -136
- package/src/shell/tool-read.mjs +74 -74
- package/src/shell/tools.mjs +299 -299
- package/src/supergrok/actions/image-generate.mjs +60 -60
- package/src/supergrok/actions/search.mjs +78 -78
- package/src/supergrok/auth.mjs +36 -36
- package/src/supergrok/constants.mjs +18 -18
- package/src/supergrok/oauth-provider.mjs +278 -278
- package/src/supergrok/provider.mjs +35 -35
- package/src/supergrok/response.mjs +76 -76
- package/src/supergrok/tool.mjs +61 -61
- package/src/text/ansi.mjs +3 -3
- package/src/web/config-command.mjs +43 -43
- package/src/web/fetch.mjs +78 -78
- package/src/web/presets.mjs +16 -16
- package/src/web/search.mjs +83 -83
- package/src/web/tools.mjs +107 -107
|
@@ -1,49 +1,49 @@
|
|
|
1
|
-
import { defineTool } from "@earendil-works/pi-coding-agent";
|
|
2
|
-
import { Type } from "typebox";
|
|
3
|
-
import { currentModelImageInputError } from "../vision-capability.mjs";
|
|
4
|
-
import { captureScreenWindows } from "./windows-screen.mjs";
|
|
5
|
-
|
|
6
|
-
export function createScreenTool({ getCurrentModel = null, captureScreenImpl = captureScreenWindows } = {}) {
|
|
7
|
-
return defineTool({
|
|
8
|
-
name: "screen",
|
|
9
|
-
label: "Screen Capture",
|
|
10
|
-
description: "Capture the current desktop or a visible window and send it to the model as an image attachment.",
|
|
11
|
-
parameters: Type.Object({
|
|
12
|
-
target: Type.Optional(Type.String({ description: "desktop (default) or window" })),
|
|
13
|
-
windowId: Type.Optional(Type.String({ description: "Window id from list_windows when target is window" })),
|
|
14
|
-
}),
|
|
15
|
-
execute: async (_toolCallId, params = {}) => captureScreenTool({ getCurrentModel, captureScreenImpl, ...params }),
|
|
16
|
-
});
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export function captureScreenTool({ getCurrentModel = null, captureScreenImpl = captureScreenWindows, target = "desktop", windowId = null } = {}) {
|
|
20
|
-
const capabilityError = currentModelImageInputError(getCurrentModel);
|
|
21
|
-
if (capabilityError) return screenError(capabilityError, { unsupportedModel: true });
|
|
22
|
-
const normalizedTarget = target === "window" ? "window" : "desktop";
|
|
23
|
-
const result = captureScreenImpl({ target: normalizedTarget, windowId });
|
|
24
|
-
if (!result?.ok) return screenError(`Error capturing screen: ${result?.message || "unknown error"}`, { target: normalizedTarget, windowId });
|
|
25
|
-
|
|
26
|
-
const bounds = result.bounds ?? {};
|
|
27
|
-
const label = normalizedTarget === "window" ? `window ${result.windowId || windowId}` : "desktop";
|
|
28
|
-
return {
|
|
29
|
-
content: [
|
|
30
|
-
{ type: "text", text: `Captured ${label} screenshot\nMIME: ${result.mimeType || "image/png"}\nBounds: ${formatBounds(bounds)}` },
|
|
31
|
-
{ type: "image", data: result.data, mimeType: result.mimeType || "image/png" },
|
|
32
|
-
],
|
|
33
|
-
details: {
|
|
34
|
-
target: normalizedTarget,
|
|
35
|
-
windowId: result.windowId ?? windowId ?? undefined,
|
|
36
|
-
bounds,
|
|
37
|
-
mimeType: result.mimeType || "image/png",
|
|
38
|
-
},
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
function screenError(text, details = {}) {
|
|
43
|
-
return { content: [{ type: "text", text }], details: { ...details, error: true } };
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
function formatBounds(bounds) {
|
|
47
|
-
const { x = 0, y = 0, width = 0, height = 0 } = bounds ?? {};
|
|
48
|
-
return `${width}x${height} at ${x},${y}`;
|
|
49
|
-
}
|
|
1
|
+
import { defineTool } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
import { Type } from "typebox";
|
|
3
|
+
import { currentModelImageInputError } from "../vision-capability.mjs";
|
|
4
|
+
import { captureScreenWindows } from "./windows-screen.mjs";
|
|
5
|
+
|
|
6
|
+
export function createScreenTool({ getCurrentModel = null, captureScreenImpl = captureScreenWindows } = {}) {
|
|
7
|
+
return defineTool({
|
|
8
|
+
name: "screen",
|
|
9
|
+
label: "Screen Capture",
|
|
10
|
+
description: "Capture the current desktop or a visible window and send it to the model as an image attachment.",
|
|
11
|
+
parameters: Type.Object({
|
|
12
|
+
target: Type.Optional(Type.String({ description: "desktop (default) or window" })),
|
|
13
|
+
windowId: Type.Optional(Type.String({ description: "Window id from list_windows when target is window" })),
|
|
14
|
+
}),
|
|
15
|
+
execute: async (_toolCallId, params = {}) => captureScreenTool({ getCurrentModel, captureScreenImpl, ...params }),
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function captureScreenTool({ getCurrentModel = null, captureScreenImpl = captureScreenWindows, target = "desktop", windowId = null } = {}) {
|
|
20
|
+
const capabilityError = currentModelImageInputError(getCurrentModel);
|
|
21
|
+
if (capabilityError) return screenError(capabilityError, { unsupportedModel: true });
|
|
22
|
+
const normalizedTarget = target === "window" ? "window" : "desktop";
|
|
23
|
+
const result = captureScreenImpl({ target: normalizedTarget, windowId });
|
|
24
|
+
if (!result?.ok) return screenError(`Error capturing screen: ${result?.message || "unknown error"}`, { target: normalizedTarget, windowId });
|
|
25
|
+
|
|
26
|
+
const bounds = result.bounds ?? {};
|
|
27
|
+
const label = normalizedTarget === "window" ? `window ${result.windowId || windowId}` : "desktop";
|
|
28
|
+
return {
|
|
29
|
+
content: [
|
|
30
|
+
{ type: "text", text: `Captured ${label} screenshot\nMIME: ${result.mimeType || "image/png"}\nBounds: ${formatBounds(bounds)}` },
|
|
31
|
+
{ type: "image", data: result.data, mimeType: result.mimeType || "image/png" },
|
|
32
|
+
],
|
|
33
|
+
details: {
|
|
34
|
+
target: normalizedTarget,
|
|
35
|
+
windowId: result.windowId ?? windowId ?? undefined,
|
|
36
|
+
bounds,
|
|
37
|
+
mimeType: result.mimeType || "image/png",
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function screenError(text, details = {}) {
|
|
43
|
+
return { content: [{ type: "text", text }], details: { ...details, error: true } };
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function formatBounds(bounds) {
|
|
47
|
+
const { x = 0, y = 0, width = 0, height = 0 } = bounds ?? {};
|
|
48
|
+
return `${width}x${height} at ${x},${y}`;
|
|
49
|
+
}
|
|
@@ -1,133 +1,133 @@
|
|
|
1
|
-
import { execFileSync } from "node:child_process";
|
|
2
|
-
|
|
3
|
-
const POWERSHELL = process.env.SystemRoot ? `${process.env.SystemRoot}\\System32\\WindowsPowerShell\\v1.0\\powershell.exe` : "powershell.exe";
|
|
4
|
-
const MAX_BUFFER = 80 * 1024 * 1024;
|
|
5
|
-
|
|
6
|
-
export function listWindowsWindows() {
|
|
7
|
-
return runJson(LIST_WINDOWS_SCRIPT);
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export function captureScreenWindows({ target = "desktop", windowId = null } = {}) {
|
|
11
|
-
if (target === "window") {
|
|
12
|
-
if (!windowId) return { ok: false, message: "windowId is required when target is window" };
|
|
13
|
-
return runJson(CAPTURE_WINDOW_SCRIPT.replace("__WINDOW_ID__", escapePowershellString(windowId)));
|
|
14
|
-
}
|
|
15
|
-
return runJson(CAPTURE_DESKTOP_SCRIPT);
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
function runJson(script) {
|
|
19
|
-
if (process.platform !== "win32") return { ok: false, message: `screen tools are not supported on ${process.platform}` };
|
|
20
|
-
try {
|
|
21
|
-
const output = execFileSync(POWERSHELL, ["-NoProfile", "-NonInteractive", "-ExecutionPolicy", "Bypass", "-Command", script], {
|
|
22
|
-
encoding: "utf8",
|
|
23
|
-
maxBuffer: MAX_BUFFER,
|
|
24
|
-
windowsHide: true,
|
|
25
|
-
}).trim();
|
|
26
|
-
return JSON.parse(output);
|
|
27
|
-
} catch (err) {
|
|
28
|
-
return { ok: false, message: `failed to run Windows screen capture: ${err.stderr || err.message}` };
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
function escapePowershellString(value) {
|
|
33
|
-
return String(value).replaceAll("'", "''");
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const WIN32_TYPE = String.raw`
|
|
37
|
-
using System;
|
|
38
|
-
using System.Text;
|
|
39
|
-
using System.Runtime.InteropServices;
|
|
40
|
-
public static class MarchWin32 {
|
|
41
|
-
public delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
|
|
42
|
-
[StructLayout(LayoutKind.Sequential)] public struct RECT { public int Left; public int Top; public int Right; public int Bottom; }
|
|
43
|
-
[DllImport("user32.dll")] public static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam);
|
|
44
|
-
[DllImport("user32.dll")] public static extern bool IsWindowVisible(IntPtr hWnd);
|
|
45
|
-
[DllImport("user32.dll")] public static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count);
|
|
46
|
-
[DllImport("user32.dll")] public static extern int GetWindowTextLength(IntPtr hWnd);
|
|
47
|
-
[DllImport("user32.dll")] public static extern bool GetWindowRect(IntPtr hWnd, out RECT rect);
|
|
48
|
-
[DllImport("user32.dll")] public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint processId);
|
|
49
|
-
[DllImport("user32.dll")] public static extern bool IsIconic(IntPtr hWnd);
|
|
50
|
-
}
|
|
51
|
-
`;
|
|
52
|
-
|
|
53
|
-
const LIST_WINDOWS_SCRIPT = String.raw`
|
|
54
|
-
Add-Type -TypeDefinition @'
|
|
55
|
-
${WIN32_TYPE}
|
|
56
|
-
'@
|
|
57
|
-
$items = New-Object System.Collections.Generic.List[object]
|
|
58
|
-
[MarchWin32]::EnumWindows({ param($hwnd, $lparam)
|
|
59
|
-
if (-not [MarchWin32]::IsWindowVisible($hwnd)) { return $true }
|
|
60
|
-
$length = [MarchWin32]::GetWindowTextLength($hwnd)
|
|
61
|
-
if ($length -le 0) { return $true }
|
|
62
|
-
$builder = New-Object System.Text.StringBuilder ($length + 1)
|
|
63
|
-
[void][MarchWin32]::GetWindowText($hwnd, $builder, $builder.Capacity)
|
|
64
|
-
$rect = New-Object MarchWin32+RECT
|
|
65
|
-
if (-not [MarchWin32]::GetWindowRect($hwnd, [ref]$rect)) { return $true }
|
|
66
|
-
$width = $rect.Right - $rect.Left
|
|
67
|
-
$height = $rect.Bottom - $rect.Top
|
|
68
|
-
if ($width -le 0 -or $height -le 0) { return $true }
|
|
69
|
-
$pidValue = 0
|
|
70
|
-
[void][MarchWin32]::GetWindowThreadProcessId($hwnd, [ref]$pidValue)
|
|
71
|
-
$processName = $null
|
|
72
|
-
try { $processName = (Get-Process -Id $pidValue -ErrorAction Stop).ProcessName } catch {}
|
|
73
|
-
$items.Add([ordered]@{
|
|
74
|
-
id = ("0x{0:x}" -f $hwnd.ToInt64())
|
|
75
|
-
title = $builder.ToString()
|
|
76
|
-
process = $processName
|
|
77
|
-
pid = $pidValue
|
|
78
|
-
bounds = [ordered]@{ x = $rect.Left; y = $rect.Top; width = $width; height = $height }
|
|
79
|
-
minimized = [MarchWin32]::IsIconic($hwnd)
|
|
80
|
-
}) | Out-Null
|
|
81
|
-
return $true
|
|
82
|
-
}, [IntPtr]::Zero) | Out-Null
|
|
83
|
-
[ordered]@{ ok = $true; windows = $items } | ConvertTo-Json -Compress -Depth 5
|
|
84
|
-
`;
|
|
85
|
-
|
|
86
|
-
const CAPTURE_DESKTOP_SCRIPT = String.raw`
|
|
87
|
-
Add-Type -AssemblyName System.Windows.Forms
|
|
88
|
-
Add-Type -AssemblyName System.Drawing
|
|
89
|
-
$bounds = [System.Windows.Forms.SystemInformation]::VirtualScreen
|
|
90
|
-
$bitmap = New-Object System.Drawing.Bitmap $bounds.Width, $bounds.Height
|
|
91
|
-
$graphics = [System.Drawing.Graphics]::FromImage($bitmap)
|
|
92
|
-
$graphics.CopyFromScreen($bounds.Left, $bounds.Top, 0, 0, $bounds.Size)
|
|
93
|
-
$stream = New-Object System.IO.MemoryStream
|
|
94
|
-
$bitmap.Save($stream, [System.Drawing.Imaging.ImageFormat]::Png)
|
|
95
|
-
$graphics.Dispose(); $bitmap.Dispose()
|
|
96
|
-
[ordered]@{
|
|
97
|
-
ok = $true; data = [Convert]::ToBase64String($stream.ToArray()); mimeType = "image/png";
|
|
98
|
-
target = "desktop"; bounds = [ordered]@{ x = $bounds.Left; y = $bounds.Top; width = $bounds.Width; height = $bounds.Height }
|
|
99
|
-
} | ConvertTo-Json -Compress -Depth 5
|
|
100
|
-
`;
|
|
101
|
-
|
|
102
|
-
const CAPTURE_WINDOW_SCRIPT = String.raw`
|
|
103
|
-
Add-Type -AssemblyName System.Drawing
|
|
104
|
-
Add-Type -TypeDefinition @'
|
|
105
|
-
${WIN32_TYPE}
|
|
106
|
-
'@
|
|
107
|
-
$rawId = '__WINDOW_ID__'
|
|
108
|
-
$hex = $rawId -replace '^0x',''
|
|
109
|
-
try { $hwnd = [IntPtr]::new([Convert]::ToInt64($hex, 16)) } catch {
|
|
110
|
-
[ordered]@{ ok = $false; message = "invalid windowId: $rawId" } | ConvertTo-Json -Compress; exit 0
|
|
111
|
-
}
|
|
112
|
-
if ([MarchWin32]::IsIconic($hwnd)) {
|
|
113
|
-
[ordered]@{ ok = $false; message = "window is minimized and cannot be captured" } | ConvertTo-Json -Compress; exit 0
|
|
114
|
-
}
|
|
115
|
-
$rect = New-Object MarchWin32+RECT
|
|
116
|
-
if (-not [MarchWin32]::GetWindowRect($hwnd, [ref]$rect)) {
|
|
117
|
-
[ordered]@{ ok = $false; message = "window not found: $rawId" } | ConvertTo-Json -Compress; exit 0
|
|
118
|
-
}
|
|
119
|
-
$width = $rect.Right - $rect.Left; $height = $rect.Bottom - $rect.Top
|
|
120
|
-
if ($width -le 0 -or $height -le 0) {
|
|
121
|
-
[ordered]@{ ok = $false; message = "window has empty bounds: $rawId" } | ConvertTo-Json -Compress; exit 0
|
|
122
|
-
}
|
|
123
|
-
$bitmap = New-Object System.Drawing.Bitmap $width, $height
|
|
124
|
-
$graphics = [System.Drawing.Graphics]::FromImage($bitmap)
|
|
125
|
-
$graphics.CopyFromScreen($rect.Left, $rect.Top, 0, 0, (New-Object System.Drawing.Size $width, $height))
|
|
126
|
-
$stream = New-Object System.IO.MemoryStream
|
|
127
|
-
$bitmap.Save($stream, [System.Drawing.Imaging.ImageFormat]::Png)
|
|
128
|
-
$graphics.Dispose(); $bitmap.Dispose()
|
|
129
|
-
[ordered]@{
|
|
130
|
-
ok = $true; data = [Convert]::ToBase64String($stream.ToArray()); mimeType = "image/png";
|
|
131
|
-
target = "window"; windowId = $rawId; bounds = [ordered]@{ x = $rect.Left; y = $rect.Top; width = $width; height = $height }
|
|
132
|
-
} | ConvertTo-Json -Compress -Depth 5
|
|
133
|
-
`;
|
|
1
|
+
import { execFileSync } from "node:child_process";
|
|
2
|
+
|
|
3
|
+
const POWERSHELL = process.env.SystemRoot ? `${process.env.SystemRoot}\\System32\\WindowsPowerShell\\v1.0\\powershell.exe` : "powershell.exe";
|
|
4
|
+
const MAX_BUFFER = 80 * 1024 * 1024;
|
|
5
|
+
|
|
6
|
+
export function listWindowsWindows() {
|
|
7
|
+
return runJson(LIST_WINDOWS_SCRIPT);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function captureScreenWindows({ target = "desktop", windowId = null } = {}) {
|
|
11
|
+
if (target === "window") {
|
|
12
|
+
if (!windowId) return { ok: false, message: "windowId is required when target is window" };
|
|
13
|
+
return runJson(CAPTURE_WINDOW_SCRIPT.replace("__WINDOW_ID__", escapePowershellString(windowId)));
|
|
14
|
+
}
|
|
15
|
+
return runJson(CAPTURE_DESKTOP_SCRIPT);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function runJson(script) {
|
|
19
|
+
if (process.platform !== "win32") return { ok: false, message: `screen tools are not supported on ${process.platform}` };
|
|
20
|
+
try {
|
|
21
|
+
const output = execFileSync(POWERSHELL, ["-NoProfile", "-NonInteractive", "-ExecutionPolicy", "Bypass", "-Command", script], {
|
|
22
|
+
encoding: "utf8",
|
|
23
|
+
maxBuffer: MAX_BUFFER,
|
|
24
|
+
windowsHide: true,
|
|
25
|
+
}).trim();
|
|
26
|
+
return JSON.parse(output);
|
|
27
|
+
} catch (err) {
|
|
28
|
+
return { ok: false, message: `failed to run Windows screen capture: ${err.stderr || err.message}` };
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function escapePowershellString(value) {
|
|
33
|
+
return String(value).replaceAll("'", "''");
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const WIN32_TYPE = String.raw`
|
|
37
|
+
using System;
|
|
38
|
+
using System.Text;
|
|
39
|
+
using System.Runtime.InteropServices;
|
|
40
|
+
public static class MarchWin32 {
|
|
41
|
+
public delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
|
|
42
|
+
[StructLayout(LayoutKind.Sequential)] public struct RECT { public int Left; public int Top; public int Right; public int Bottom; }
|
|
43
|
+
[DllImport("user32.dll")] public static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam);
|
|
44
|
+
[DllImport("user32.dll")] public static extern bool IsWindowVisible(IntPtr hWnd);
|
|
45
|
+
[DllImport("user32.dll")] public static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count);
|
|
46
|
+
[DllImport("user32.dll")] public static extern int GetWindowTextLength(IntPtr hWnd);
|
|
47
|
+
[DllImport("user32.dll")] public static extern bool GetWindowRect(IntPtr hWnd, out RECT rect);
|
|
48
|
+
[DllImport("user32.dll")] public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint processId);
|
|
49
|
+
[DllImport("user32.dll")] public static extern bool IsIconic(IntPtr hWnd);
|
|
50
|
+
}
|
|
51
|
+
`;
|
|
52
|
+
|
|
53
|
+
const LIST_WINDOWS_SCRIPT = String.raw`
|
|
54
|
+
Add-Type -TypeDefinition @'
|
|
55
|
+
${WIN32_TYPE}
|
|
56
|
+
'@
|
|
57
|
+
$items = New-Object System.Collections.Generic.List[object]
|
|
58
|
+
[MarchWin32]::EnumWindows({ param($hwnd, $lparam)
|
|
59
|
+
if (-not [MarchWin32]::IsWindowVisible($hwnd)) { return $true }
|
|
60
|
+
$length = [MarchWin32]::GetWindowTextLength($hwnd)
|
|
61
|
+
if ($length -le 0) { return $true }
|
|
62
|
+
$builder = New-Object System.Text.StringBuilder ($length + 1)
|
|
63
|
+
[void][MarchWin32]::GetWindowText($hwnd, $builder, $builder.Capacity)
|
|
64
|
+
$rect = New-Object MarchWin32+RECT
|
|
65
|
+
if (-not [MarchWin32]::GetWindowRect($hwnd, [ref]$rect)) { return $true }
|
|
66
|
+
$width = $rect.Right - $rect.Left
|
|
67
|
+
$height = $rect.Bottom - $rect.Top
|
|
68
|
+
if ($width -le 0 -or $height -le 0) { return $true }
|
|
69
|
+
$pidValue = 0
|
|
70
|
+
[void][MarchWin32]::GetWindowThreadProcessId($hwnd, [ref]$pidValue)
|
|
71
|
+
$processName = $null
|
|
72
|
+
try { $processName = (Get-Process -Id $pidValue -ErrorAction Stop).ProcessName } catch {}
|
|
73
|
+
$items.Add([ordered]@{
|
|
74
|
+
id = ("0x{0:x}" -f $hwnd.ToInt64())
|
|
75
|
+
title = $builder.ToString()
|
|
76
|
+
process = $processName
|
|
77
|
+
pid = $pidValue
|
|
78
|
+
bounds = [ordered]@{ x = $rect.Left; y = $rect.Top; width = $width; height = $height }
|
|
79
|
+
minimized = [MarchWin32]::IsIconic($hwnd)
|
|
80
|
+
}) | Out-Null
|
|
81
|
+
return $true
|
|
82
|
+
}, [IntPtr]::Zero) | Out-Null
|
|
83
|
+
[ordered]@{ ok = $true; windows = $items } | ConvertTo-Json -Compress -Depth 5
|
|
84
|
+
`;
|
|
85
|
+
|
|
86
|
+
const CAPTURE_DESKTOP_SCRIPT = String.raw`
|
|
87
|
+
Add-Type -AssemblyName System.Windows.Forms
|
|
88
|
+
Add-Type -AssemblyName System.Drawing
|
|
89
|
+
$bounds = [System.Windows.Forms.SystemInformation]::VirtualScreen
|
|
90
|
+
$bitmap = New-Object System.Drawing.Bitmap $bounds.Width, $bounds.Height
|
|
91
|
+
$graphics = [System.Drawing.Graphics]::FromImage($bitmap)
|
|
92
|
+
$graphics.CopyFromScreen($bounds.Left, $bounds.Top, 0, 0, $bounds.Size)
|
|
93
|
+
$stream = New-Object System.IO.MemoryStream
|
|
94
|
+
$bitmap.Save($stream, [System.Drawing.Imaging.ImageFormat]::Png)
|
|
95
|
+
$graphics.Dispose(); $bitmap.Dispose()
|
|
96
|
+
[ordered]@{
|
|
97
|
+
ok = $true; data = [Convert]::ToBase64String($stream.ToArray()); mimeType = "image/png";
|
|
98
|
+
target = "desktop"; bounds = [ordered]@{ x = $bounds.Left; y = $bounds.Top; width = $bounds.Width; height = $bounds.Height }
|
|
99
|
+
} | ConvertTo-Json -Compress -Depth 5
|
|
100
|
+
`;
|
|
101
|
+
|
|
102
|
+
const CAPTURE_WINDOW_SCRIPT = String.raw`
|
|
103
|
+
Add-Type -AssemblyName System.Drawing
|
|
104
|
+
Add-Type -TypeDefinition @'
|
|
105
|
+
${WIN32_TYPE}
|
|
106
|
+
'@
|
|
107
|
+
$rawId = '__WINDOW_ID__'
|
|
108
|
+
$hex = $rawId -replace '^0x',''
|
|
109
|
+
try { $hwnd = [IntPtr]::new([Convert]::ToInt64($hex, 16)) } catch {
|
|
110
|
+
[ordered]@{ ok = $false; message = "invalid windowId: $rawId" } | ConvertTo-Json -Compress; exit 0
|
|
111
|
+
}
|
|
112
|
+
if ([MarchWin32]::IsIconic($hwnd)) {
|
|
113
|
+
[ordered]@{ ok = $false; message = "window is minimized and cannot be captured" } | ConvertTo-Json -Compress; exit 0
|
|
114
|
+
}
|
|
115
|
+
$rect = New-Object MarchWin32+RECT
|
|
116
|
+
if (-not [MarchWin32]::GetWindowRect($hwnd, [ref]$rect)) {
|
|
117
|
+
[ordered]@{ ok = $false; message = "window not found: $rawId" } | ConvertTo-Json -Compress; exit 0
|
|
118
|
+
}
|
|
119
|
+
$width = $rect.Right - $rect.Left; $height = $rect.Bottom - $rect.Top
|
|
120
|
+
if ($width -le 0 -or $height -le 0) {
|
|
121
|
+
[ordered]@{ ok = $false; message = "window has empty bounds: $rawId" } | ConvertTo-Json -Compress; exit 0
|
|
122
|
+
}
|
|
123
|
+
$bitmap = New-Object System.Drawing.Bitmap $width, $height
|
|
124
|
+
$graphics = [System.Drawing.Graphics]::FromImage($bitmap)
|
|
125
|
+
$graphics.CopyFromScreen($rect.Left, $rect.Top, 0, 0, (New-Object System.Drawing.Size $width, $height))
|
|
126
|
+
$stream = New-Object System.IO.MemoryStream
|
|
127
|
+
$bitmap.Save($stream, [System.Drawing.Imaging.ImageFormat]::Png)
|
|
128
|
+
$graphics.Dispose(); $bitmap.Dispose()
|
|
129
|
+
[ordered]@{
|
|
130
|
+
ok = $true; data = [Convert]::ToBase64String($stream.ToArray()); mimeType = "image/png";
|
|
131
|
+
target = "window"; windowId = $rawId; bounds = [ordered]@{ x = $rect.Left; y = $rect.Top; width = $width; height = $height }
|
|
132
|
+
} | ConvertTo-Json -Compress -Depth 5
|
|
133
|
+
`;
|
|
@@ -1,41 +1,41 @@
|
|
|
1
|
-
const MAX_SESSION_NAME_LENGTH = 60;
|
|
2
|
-
|
|
3
|
-
export function maybeAutoNameSession({ engine, session, setSessionName }) {
|
|
4
|
-
if (engine?.sessionName || session?.sessionName) return null;
|
|
5
|
-
if (!Array.isArray(engine?.turns) || engine.turns.length !== 1) return null;
|
|
6
|
-
if (typeof setSessionName !== "function") return null;
|
|
7
|
-
|
|
8
|
-
const title = generateSessionName(engine.turns[0]);
|
|
9
|
-
if (!title) return null;
|
|
10
|
-
return setSessionName(title);
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export function generateSessionName(turn) {
|
|
14
|
-
const text = normalizeTitleSource(turn?.userMessage) || normalizeTitleSource(turn?.assistantMessage);
|
|
15
|
-
if (!text) return "New session";
|
|
16
|
-
return truncateTitle(stripPromptNoise(text), MAX_SESSION_NAME_LENGTH) || "New session";
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
function normalizeTitleSource(value) {
|
|
20
|
-
return String(value ?? "")
|
|
21
|
-
.replace(/```[\s\S]*?```/g, " ")
|
|
22
|
-
.replace(/`([^`]+)`/g, "$1")
|
|
23
|
-
.replace(/\s+/g, " ")
|
|
24
|
-
.trim();
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function stripPromptNoise(text) {
|
|
28
|
-
return text
|
|
29
|
-
.replace(/^[@#>\-\s]+/, "")
|
|
30
|
-
.replace(/^(please|pls|can you|could you|help me|帮我|请)\s+/i, "")
|
|
31
|
-
.replace(/[.。!?!?,:;,:;]+$/g, "")
|
|
32
|
-
.trim();
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
function truncateTitle(text, maxLength) {
|
|
36
|
-
if (text.length <= maxLength) return text;
|
|
37
|
-
const sliced = text.slice(0, maxLength).trimEnd();
|
|
38
|
-
const lastSpace = sliced.lastIndexOf(" ");
|
|
39
|
-
if (lastSpace >= Math.floor(maxLength * 0.6)) return sliced.slice(0, lastSpace);
|
|
40
|
-
return sliced;
|
|
41
|
-
}
|
|
1
|
+
const MAX_SESSION_NAME_LENGTH = 60;
|
|
2
|
+
|
|
3
|
+
export function maybeAutoNameSession({ engine, session, setSessionName }) {
|
|
4
|
+
if (engine?.sessionName || session?.sessionName) return null;
|
|
5
|
+
if (!Array.isArray(engine?.turns) || engine.turns.length !== 1) return null;
|
|
6
|
+
if (typeof setSessionName !== "function") return null;
|
|
7
|
+
|
|
8
|
+
const title = generateSessionName(engine.turns[0]);
|
|
9
|
+
if (!title) return null;
|
|
10
|
+
return setSessionName(title);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function generateSessionName(turn) {
|
|
14
|
+
const text = normalizeTitleSource(turn?.userMessage) || normalizeTitleSource(turn?.assistantMessage);
|
|
15
|
+
if (!text) return "New session";
|
|
16
|
+
return truncateTitle(stripPromptNoise(text), MAX_SESSION_NAME_LENGTH) || "New session";
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function normalizeTitleSource(value) {
|
|
20
|
+
return String(value ?? "")
|
|
21
|
+
.replace(/```[\s\S]*?```/g, " ")
|
|
22
|
+
.replace(/`([^`]+)`/g, "$1")
|
|
23
|
+
.replace(/\s+/g, " ")
|
|
24
|
+
.trim();
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function stripPromptNoise(text) {
|
|
28
|
+
return text
|
|
29
|
+
.replace(/^[@#>\-\s]+/, "")
|
|
30
|
+
.replace(/^(please|pls|can you|could you|help me|帮我|请)\s+/i, "")
|
|
31
|
+
.replace(/[.。!?!?,:;,:;]+$/g, "")
|
|
32
|
+
.trim();
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function truncateTitle(text, maxLength) {
|
|
36
|
+
if (text.length <= maxLength) return text;
|
|
37
|
+
const sliced = text.slice(0, maxLength).trimEnd();
|
|
38
|
+
const lastSpace = sliced.lastIndexOf(" ");
|
|
39
|
+
if (lastSpace >= Math.floor(maxLength * 0.6)) return sliced.slice(0, lastSpace);
|
|
40
|
+
return sliced;
|
|
41
|
+
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
export function createSessionBinding(initialSession) {
|
|
2
|
-
let current = initialSession;
|
|
3
|
-
return {
|
|
4
|
-
get() {
|
|
5
|
-
return current;
|
|
6
|
-
},
|
|
7
|
-
set(nextSession) {
|
|
8
|
-
current = nextSession;
|
|
9
|
-
return current;
|
|
10
|
-
},
|
|
11
|
-
};
|
|
12
|
-
}
|
|
1
|
+
export function createSessionBinding(initialSession) {
|
|
2
|
+
let current = initialSession;
|
|
3
|
+
return {
|
|
4
|
+
get() {
|
|
5
|
+
return current;
|
|
6
|
+
},
|
|
7
|
+
set(nextSession) {
|
|
8
|
+
current = nextSession;
|
|
9
|
+
return current;
|
|
10
|
+
},
|
|
11
|
+
};
|
|
12
|
+
}
|
|
@@ -1,47 +1,47 @@
|
|
|
1
|
-
import { getModel } from "@earendil-works/pi-ai";
|
|
2
|
-
import { MARCH_BASE_TOOL_NAMES } from "../tool-names.mjs";
|
|
3
|
-
import { createMarchCustomTools } from "../tools.mjs";
|
|
4
|
-
|
|
5
|
-
export function resolveRunnerSessionOptions({
|
|
6
|
-
cwd,
|
|
7
|
-
provider,
|
|
8
|
-
modelId,
|
|
9
|
-
modelRegistry,
|
|
10
|
-
engine,
|
|
11
|
-
ui,
|
|
12
|
-
memoryTools = [],
|
|
13
|
-
shellRuntime = null,
|
|
14
|
-
lspService = null,
|
|
15
|
-
mcpTools = [],
|
|
16
|
-
webTools = [],
|
|
17
|
-
permissionController = null,
|
|
18
|
-
authStorage = null,
|
|
19
|
-
projectMarchDir = null,
|
|
20
|
-
getCurrentModel = null,
|
|
21
|
-
}) {
|
|
22
|
-
if (engine.cwd !== cwd) {
|
|
23
|
-
throw new Error(`Runtime session cwd mismatch: engine=${engine.cwd}, session=${cwd}`);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
const availableModels = modelRegistry.getAvailable?.() ?? [];
|
|
27
|
-
const model = (provider && modelId ? modelRegistry.find(provider, modelId) : null)
|
|
28
|
-
?? availableModels[0]
|
|
29
|
-
?? (provider && modelId ? getModel(provider, modelId) : null);
|
|
30
|
-
if (!model) throw new Error(`Model not found: ${provider}/${modelId}`);
|
|
31
|
-
|
|
32
|
-
const customTools = createMarchCustomTools({ cwd, engine, ui, memoryTools, shellRuntime, lspService, mcpTools, webTools, permissionController, authStorage, projectMarchDir, getCurrentModel: () => getCurrentModel?.() ?? model });
|
|
33
|
-
const customToolNames = customTools.map((tool) => tool.name);
|
|
34
|
-
const tools = [
|
|
35
|
-
...customToolNames.filter((name) => name === "read"),
|
|
36
|
-
...MARCH_BASE_TOOL_NAMES,
|
|
37
|
-
...customToolNames.filter((name) => name !== "read"),
|
|
38
|
-
];
|
|
39
|
-
|
|
40
|
-
return {
|
|
41
|
-
model,
|
|
42
|
-
thinkingLevel: "medium",
|
|
43
|
-
customTools,
|
|
44
|
-
tools,
|
|
45
|
-
scopedModels: availableModels.map((model) => ({ model })),
|
|
46
|
-
};
|
|
47
|
-
}
|
|
1
|
+
import { getModel } from "@earendil-works/pi-ai";
|
|
2
|
+
import { MARCH_BASE_TOOL_NAMES } from "../tool-names.mjs";
|
|
3
|
+
import { createMarchCustomTools } from "../tools.mjs";
|
|
4
|
+
|
|
5
|
+
export function resolveRunnerSessionOptions({
|
|
6
|
+
cwd,
|
|
7
|
+
provider,
|
|
8
|
+
modelId,
|
|
9
|
+
modelRegistry,
|
|
10
|
+
engine,
|
|
11
|
+
ui,
|
|
12
|
+
memoryTools = [],
|
|
13
|
+
shellRuntime = null,
|
|
14
|
+
lspService = null,
|
|
15
|
+
mcpTools = [],
|
|
16
|
+
webTools = [],
|
|
17
|
+
permissionController = null,
|
|
18
|
+
authStorage = null,
|
|
19
|
+
projectMarchDir = null,
|
|
20
|
+
getCurrentModel = null,
|
|
21
|
+
}) {
|
|
22
|
+
if (engine.cwd !== cwd) {
|
|
23
|
+
throw new Error(`Runtime session cwd mismatch: engine=${engine.cwd}, session=${cwd}`);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const availableModels = modelRegistry.getAvailable?.() ?? [];
|
|
27
|
+
const model = (provider && modelId ? modelRegistry.find(provider, modelId) : null)
|
|
28
|
+
?? availableModels[0]
|
|
29
|
+
?? (provider && modelId ? getModel(provider, modelId) : null);
|
|
30
|
+
if (!model) throw new Error(`Model not found: ${provider}/${modelId}`);
|
|
31
|
+
|
|
32
|
+
const customTools = createMarchCustomTools({ cwd, engine, ui, memoryTools, shellRuntime, lspService, mcpTools, webTools, permissionController, authStorage, projectMarchDir, getCurrentModel: () => getCurrentModel?.() ?? model });
|
|
33
|
+
const customToolNames = customTools.map((tool) => tool.name);
|
|
34
|
+
const tools = [
|
|
35
|
+
...customToolNames.filter((name) => name === "read"),
|
|
36
|
+
...MARCH_BASE_TOOL_NAMES,
|
|
37
|
+
...customToolNames.filter((name) => name !== "read"),
|
|
38
|
+
];
|
|
39
|
+
|
|
40
|
+
return {
|
|
41
|
+
model,
|
|
42
|
+
thinkingLevel: "medium",
|
|
43
|
+
customTools,
|
|
44
|
+
tools,
|
|
45
|
+
scopedModels: availableModels.map((model) => ({ model })),
|
|
46
|
+
};
|
|
47
|
+
}
|
package/src/agent/tool-names.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const MARCH_BASE_TOOL_NAMES = ["grep", "find", "ls"];
|
|
1
|
+
export const MARCH_BASE_TOOL_NAMES = ["grep", "find", "ls"];
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export function toolText(text, details = {}) {
|
|
2
|
-
return { content: [{ type: "text", text }], details };
|
|
3
|
-
}
|
|
1
|
+
export function toolText(text, details = {}) {
|
|
2
|
+
return { content: [{ type: "text", text }], details };
|
|
3
|
+
}
|