march-cli 0.1.9 → 0.1.11
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/package.json +1 -1
- package/src/agent/editing/lsp-report.mjs +69 -0
- package/src/agent/file-edit-tool.mjs +10 -24
- package/src/agent/model-payload-dumper.mjs +11 -4
- package/src/agent/runner/runner-utils.mjs +18 -0
- package/src/agent/runner.mjs +26 -27
- package/src/agent/runtime/runner-runtime-host.mjs +2 -0
- package/src/agent/turn/turn-logging.mjs +30 -0
- package/src/agent/turn/turn-runner.mjs +40 -0
- package/src/cli/commands/status-command.mjs +4 -16
- package/src/cli/permissions.mjs +1 -1
- package/src/cli/shell/shell-drawer.mjs +1 -1
- package/src/cli/startup/runtime-close.mjs +23 -0
- package/src/cli/tui/output/visible-lines.mjs +8 -0
- package/src/cli/tui/output-buffer.mjs +30 -21
- package/src/cli/tui/render/stream-delta-buffer.mjs +46 -0
- package/src/cli/tui/selection-screen.mjs +12 -4
- package/src/cli/tui/tool-rendering.mjs +1 -1
- package/src/cli/ui.mjs +16 -17
- package/src/config/loader.mjs +28 -1
- package/src/context/system-core/base.md +1 -1
- package/src/debug/logger.mjs +141 -0
- package/src/lsp/client.mjs +2 -2
- package/src/lsp/diagnostic-store.mjs +5 -2
- package/src/lsp/diagnostics-format.mjs +3 -1
- package/src/lsp/managed-node-server.mjs +94 -0
- package/src/lsp/path-match.mjs +10 -0
- package/src/lsp/servers.mjs +56 -13
- package/src/lsp/service.mjs +6 -6
- package/src/lsp/status-message.mjs +1 -0
- package/src/lsp/typescript-project-resolver.mjs +186 -0
- package/src/main.mjs +17 -24
- package/src/platform/spawn-command.mjs +27 -0
- package/src/provider/hosted-tools.mjs +111 -0
- package/src/shell/runtime.mjs +9 -1
- package/src/web/tools.mjs +2 -2
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
const OPENAI_PROVIDERS = new Set(["openai"]);
|
|
2
|
+
const OPENAI_CODEX_PROVIDERS = new Set(["openai-codex"]);
|
|
3
|
+
const AZURE_OPENAI_PROVIDERS = new Set(["azure-openai-responses"]);
|
|
4
|
+
const ANTHROPIC_PROVIDERS = new Set(["anthropic"]);
|
|
5
|
+
const GOOGLE_PROVIDERS = new Set(["google", "google-vertex"]);
|
|
6
|
+
const XAI_PROVIDERS = new Set(["xai", "supergrok-oauth", "xai-oauth"]);
|
|
7
|
+
|
|
8
|
+
export function injectHostedTools(payload, model, config = {}) {
|
|
9
|
+
const capabilities = resolveHostedToolCapabilities(model).filter((tool) => isToolEnabled(tool, config));
|
|
10
|
+
if (capabilities.length === 0) return payload;
|
|
11
|
+
return injectPayloadHostedTools(payload, capabilities);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function resolveHostedTools(model, config = {}) {
|
|
15
|
+
return resolveHostedToolCapabilities(model).filter((tool) => isToolEnabled(tool, config)).map(createHostedTool);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function resolveHostedToolCapabilities(model) {
|
|
19
|
+
if (!model || typeof model !== "object") return [];
|
|
20
|
+
if (OPENAI_PROVIDERS.has(model.provider) && isOpenAiResponsesApi(model.api)) return ["openai.webSearch"];
|
|
21
|
+
if (OPENAI_CODEX_PROVIDERS.has(model.provider) && model.api === "openai-codex-responses") {
|
|
22
|
+
return ["openaiCodex.webSearch"];
|
|
23
|
+
}
|
|
24
|
+
if (AZURE_OPENAI_PROVIDERS.has(model.provider) && model.api === "azure-openai-responses") {
|
|
25
|
+
return ["azureOpenai.webSearch"];
|
|
26
|
+
}
|
|
27
|
+
if (ANTHROPIC_PROVIDERS.has(model.provider) && model.api === "anthropic-messages") return ["anthropic.webSearch"];
|
|
28
|
+
if (GOOGLE_PROVIDERS.has(model.provider) && isGoogleApi(model.api)) return ["google.webSearch"];
|
|
29
|
+
if (XAI_PROVIDERS.has(model.provider) && model.api === "openai-responses") return ["xai.webSearch", "xai.xSearch"];
|
|
30
|
+
return [];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function isToolEnabled(tool, config) {
|
|
34
|
+
const [provider, name] = tool.split(".");
|
|
35
|
+
const value = config?.[provider]?.[name] ?? "auto";
|
|
36
|
+
return value !== false;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function createHostedTool(tool) {
|
|
40
|
+
if (tool === "openai.webSearch" || tool === "azureOpenai.webSearch") return { type: "web_search_preview" };
|
|
41
|
+
if (tool === "openaiCodex.webSearch") return { type: "web_search" };
|
|
42
|
+
if (tool === "anthropic.webSearch") return { type: "web_search_20250305", name: "web_search" };
|
|
43
|
+
if (tool === "google.webSearch") return { googleSearch: {} };
|
|
44
|
+
if (tool === "xai.webSearch") return { type: "web_search", enable_image_understanding: true };
|
|
45
|
+
if (tool === "xai.xSearch") {
|
|
46
|
+
return { type: "x_search", enable_image_understanding: true, enable_video_understanding: true };
|
|
47
|
+
}
|
|
48
|
+
throw new Error(`Unsupported hosted tool capability: ${tool}`);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function isOpenAiResponsesApi(api) {
|
|
52
|
+
return api === "openai-responses";
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function isGoogleApi(api) {
|
|
56
|
+
return api === "google-generative-ai" || api === "google-vertex";
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function injectPayloadHostedTools(payload, capabilities) {
|
|
60
|
+
if (!payload || typeof payload !== "object") return payload;
|
|
61
|
+
if (payload.body && typeof payload.body === "object") {
|
|
62
|
+
return { ...payload, body: injectPayloadHostedTools(payload.body, capabilities) };
|
|
63
|
+
}
|
|
64
|
+
if (typeof payload.body === "string") return injectStringBodyHostedTools(payload, capabilities);
|
|
65
|
+
return capabilities.reduce((next, capability) => injectPayloadHostedTool(next, capability), payload);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function injectPayloadHostedTool(payload, capability) {
|
|
69
|
+
if (capability.startsWith("google.")) return appendGoogleTool(payload, createHostedTool(capability));
|
|
70
|
+
return appendTopLevelTool(payload, createHostedTool(capability));
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function injectStringBodyHostedTools(payload, capabilities) {
|
|
74
|
+
try {
|
|
75
|
+
const body = JSON.parse(payload.body);
|
|
76
|
+
return { ...payload, body: JSON.stringify(injectPayloadHostedTools(body, capabilities)) };
|
|
77
|
+
} catch {
|
|
78
|
+
return payload;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function appendTopLevelTool(payload, tool) {
|
|
83
|
+
if (!Array.isArray(payload.tools)) return { ...payload, tools: [tool] };
|
|
84
|
+
return { ...payload, tools: mergeTools(payload.tools, [tool], getToolKey) };
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function appendGoogleTool(payload, tool) {
|
|
88
|
+
const config = payload.config && typeof payload.config === "object" ? payload.config : {};
|
|
89
|
+
const tools = Array.isArray(config.tools) ? config.tools : [];
|
|
90
|
+
return {
|
|
91
|
+
...payload,
|
|
92
|
+
config: {
|
|
93
|
+
...config,
|
|
94
|
+
tools: mergeTools(tools, [tool], getGoogleToolKey),
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function mergeTools(existing, added, keyForTool) {
|
|
100
|
+
const keys = new Set(existing.map(keyForTool).filter(Boolean));
|
|
101
|
+
return [...existing, ...added.filter((tool) => !keys.has(keyForTool(tool)))];
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function getToolKey(tool) {
|
|
105
|
+
return tool?.type ?? tool?.name;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function getGoogleToolKey(tool) {
|
|
109
|
+
if (tool?.googleSearch) return "googleSearch";
|
|
110
|
+
return tool?.functionDeclarations ? "functionDeclarations" : getToolKey(tool);
|
|
111
|
+
}
|
package/src/shell/runtime.mjs
CHANGED
|
@@ -10,7 +10,6 @@ import {
|
|
|
10
10
|
normalizeSize,
|
|
11
11
|
publicShell,
|
|
12
12
|
requireShell,
|
|
13
|
-
stripAnsi,
|
|
14
13
|
touch,
|
|
15
14
|
uniqueName,
|
|
16
15
|
} from "./runtime-state.mjs";
|
|
@@ -194,6 +193,14 @@ export function createShellRuntime({
|
|
|
194
193
|
};
|
|
195
194
|
}
|
|
196
195
|
|
|
196
|
+
function snapshotShellScreen(id) {
|
|
197
|
+
const shell = requireShell(shells, id);
|
|
198
|
+
return {
|
|
199
|
+
shell: publicShell(shell),
|
|
200
|
+
screen: shell.screen?.snapshot?.() ?? null,
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
|
|
197
204
|
function clearShell(id) {
|
|
198
205
|
const shell = requireShell(shells, id);
|
|
199
206
|
shell.rawChunks = [];
|
|
@@ -238,6 +245,7 @@ export function createShellRuntime({
|
|
|
238
245
|
getShell,
|
|
239
246
|
searchShell,
|
|
240
247
|
snapshotShell,
|
|
248
|
+
snapshotShellScreen,
|
|
241
249
|
clearShell,
|
|
242
250
|
dispose,
|
|
243
251
|
};
|
package/src/web/tools.mjs
CHANGED
|
@@ -6,8 +6,8 @@ import { fetchWebPage } from "./fetch.mjs";
|
|
|
6
6
|
|
|
7
7
|
export function createWebTools({ tavilyKey, braveKey } = {}) {
|
|
8
8
|
const webSearchTool = defineTool({
|
|
9
|
-
name: "
|
|
10
|
-
label: "Web Search",
|
|
9
|
+
name: "external_web_search",
|
|
10
|
+
label: "External Web Search",
|
|
11
11
|
description:
|
|
12
12
|
"Search the web for current information on any topic. " +
|
|
13
13
|
"Requires TAVILY_API_KEY or BRAVE_API_KEY; if neither is configured, use web_fetch when you already know the URL. " +
|