wave-agent-sdk 1.1.5 → 1.3.0
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/agent.d.ts +128 -28
- package/dist/agent.js +201 -49
- package/dist/builtin/index.js +2 -0
- package/dist/builtin/plugins.js +11 -20
- package/dist/builtin/skills/settings.js +7 -20
- package/dist/builtin/skills/wave-daemon.d.ts +1 -0
- package/dist/builtin/skills/wave-daemon.js +194 -0
- package/dist/constants/images.d.ts +26 -0
- package/dist/constants/images.js +26 -0
- package/dist/constants/index.d.ts +16 -0
- package/dist/constants/index.js +16 -0
- package/dist/constants/memory.d.ts +26 -0
- package/dist/constants/memory.js +34 -0
- package/dist/constants/messages.d.ts +11 -0
- package/dist/constants/messages.js +11 -0
- package/dist/constants/plugins.d.ts +8 -0
- package/dist/constants/plugins.js +8 -0
- package/dist/constants/tools.d.ts +1 -0
- package/dist/constants/tools.js +1 -0
- package/dist/core/plugin.d.ts +54 -10
- package/dist/core/plugin.js +137 -23
- package/dist/core/session.d.ts +1 -1
- package/dist/core/session.js +1 -1
- package/dist/exec/catalog.d.ts +140 -0
- package/dist/exec/catalog.js +470 -0
- package/dist/exec/catalogAnnouncement.d.ts +89 -0
- package/dist/exec/catalogAnnouncement.js +293 -0
- package/dist/exec/constants.d.ts +51 -0
- package/dist/exec/constants.js +51 -0
- package/dist/exec/execRuntime.d.ts +55 -0
- package/dist/exec/execRuntime.js +217 -0
- package/dist/exec/workerSource.d.ts +28 -0
- package/dist/exec/workerSource.js +299 -0
- package/dist/host/index.d.ts +23 -0
- package/dist/host/index.js +23 -0
- package/dist/index.d.ts +7 -1
- package/dist/index.js +8 -1
- package/dist/managers/MemoryRuleManager.d.ts +6 -0
- package/dist/managers/MemoryRuleManager.js +12 -0
- package/dist/managers/aiManager.d.ts +35 -25
- package/dist/managers/aiManager.js +204 -202
- package/dist/managers/backgroundTaskManager.js +14 -0
- package/dist/managers/bashModeManager.d.ts +33 -0
- package/dist/managers/bashModeManager.js +110 -0
- package/dist/managers/hookManager.d.ts +18 -0
- package/dist/managers/hookManager.js +37 -3
- package/dist/managers/liveConfigManager.d.ts +33 -0
- package/dist/managers/liveConfigManager.js +106 -11
- package/dist/managers/lspManager.d.ts +9 -0
- package/dist/managers/lspManager.js +47 -18
- package/dist/managers/mcpManager.d.ts +68 -10
- package/dist/managers/mcpManager.js +265 -15
- package/dist/managers/messageManager.d.ts +60 -18
- package/dist/managers/messageManager.js +170 -81
- package/dist/managers/permissionManager.d.ts +69 -0
- package/dist/managers/permissionManager.js +221 -78
- package/dist/managers/planManager.d.ts +9 -0
- package/dist/managers/planManager.js +19 -1
- package/dist/managers/pluginManager.d.ts +46 -2
- package/dist/managers/pluginManager.js +117 -11
- package/dist/managers/pluginScopeManager.d.ts +15 -2
- package/dist/managers/pluginScopeManager.js +20 -1
- package/dist/managers/skillManager.d.ts +50 -0
- package/dist/managers/skillManager.js +166 -12
- package/dist/managers/slashCommandManager.d.ts +10 -0
- package/dist/managers/slashCommandManager.js +44 -31
- package/dist/managers/subagentManager.d.ts +15 -0
- package/dist/managers/subagentManager.js +81 -9
- package/dist/managers/toolManager.d.ts +29 -3
- package/dist/managers/toolManager.js +87 -13
- package/dist/managers/workflowManager.js +6 -0
- package/dist/prompts/autoMemory.d.ts +9 -0
- package/dist/prompts/autoMemory.js +30 -31
- package/dist/prompts/autoMemoryExtraction.d.ts +4 -0
- package/dist/prompts/autoMemoryExtraction.js +8 -111
- package/dist/prompts/index.d.ts +0 -1
- package/dist/prompts/index.js +0 -4
- package/dist/prompts/memoryTypes.d.ts +63 -0
- package/dist/prompts/memoryTypes.js +191 -0
- package/dist/services/GitService.d.ts +7 -0
- package/dist/services/GitService.js +23 -0
- package/dist/services/MarketplaceService.d.ts +101 -17
- package/dist/services/MarketplaceService.js +323 -102
- package/dist/services/artifactContent.d.ts +84 -0
- package/dist/services/artifactContent.js +204 -0
- package/dist/services/artifactSession.d.ts +6 -0
- package/dist/services/artifactSession.js +17 -0
- package/dist/services/autoMemoryService.js +5 -13
- package/dist/services/configurationService.d.ts +92 -9
- package/dist/services/configurationService.js +246 -64
- package/dist/services/contentSummarizer.d.ts +15 -0
- package/dist/services/contentSummarizer.js +45 -0
- package/dist/services/execAvailability.d.ts +9 -0
- package/dist/services/execAvailability.js +32 -0
- package/dist/services/fileWatcher.js +61 -6
- package/dist/services/initializationService.js +21 -17
- package/dist/services/interactionService.d.ts +9 -1
- package/dist/services/interactionService.js +28 -8
- package/dist/services/jsonlHandler.d.ts +98 -0
- package/dist/services/jsonlHandler.js +250 -12
- package/dist/services/memory.d.ts +17 -1
- package/dist/services/memory.js +44 -7
- package/dist/services/officialMarketplaceMirror.d.ts +85 -0
- package/dist/services/officialMarketplaceMirror.js +290 -0
- package/dist/services/pluginLoader.d.ts +12 -4
- package/dist/services/pluginLoader.js +38 -7
- package/dist/services/remoteSettingsService.js +20 -6
- package/dist/services/session.d.ts +74 -0
- package/dist/services/session.js +174 -16
- package/dist/services/sessionEntries.d.ts +2 -0
- package/dist/services/sessionEntries.js +20 -0
- package/dist/services/worktreeHooks.js +6 -1
- package/dist/stdio/index.d.ts +12 -0
- package/dist/stdio/index.js +12 -0
- package/dist/stdio/notificationRouter.d.ts +38 -0
- package/dist/stdio/notificationRouter.js +97 -0
- package/dist/stdio/rpcClient.d.ts +18 -0
- package/dist/stdio/rpcClient.js +10 -0
- package/dist/stdio/stdioAgent.d.ts +229 -0
- package/dist/stdio/stdioAgent.js +360 -0
- package/dist/tools/artifactTool.js +406 -273
- package/dist/tools/bashTool.js +10 -6
- package/dist/tools/editTool.js +6 -3
- package/dist/tools/execTool.d.ts +2 -0
- package/dist/tools/execTool.js +165 -0
- package/dist/tools/exitPlanMode.js +10 -2
- package/dist/tools/grepTool.js +7 -1
- package/dist/tools/readTool.js +30 -2
- package/dist/tools/types.d.ts +34 -8
- package/dist/tools/webFetchTool.js +15 -166
- package/dist/tools/workflowTool.js +40 -8
- package/dist/tools/writeTool.js +6 -3
- package/dist/types/agent.d.ts +24 -1
- package/dist/types/commands.d.ts +7 -0
- package/dist/types/configuration.d.ts +45 -2
- package/dist/types/hooks.d.ts +1 -0
- package/dist/types/hooks.js +19 -0
- package/dist/types/marketplace.d.ts +40 -2
- package/dist/types/mcp.d.ts +42 -0
- package/dist/types/messaging.d.ts +1 -8
- package/dist/types/permissions.d.ts +22 -0
- package/dist/types/permissions.js +17 -0
- package/dist/types/plugins.d.ts +26 -2
- package/dist/types/skills.d.ts +26 -0
- package/dist/utils/bashParser.d.ts +17 -0
- package/dist/utils/bashParser.js +72 -0
- package/dist/utils/bashStructure/bashLexer.d.ts +96 -0
- package/dist/utils/bashStructure/bashLexer.js +676 -0
- package/dist/utils/bashStructure/bashParser.d.ts +144 -0
- package/dist/utils/bashStructure/bashParser.js +606 -0
- package/dist/utils/bashStructure/bashSemantics.d.ts +70 -0
- package/dist/utils/bashStructure/bashSemantics.js +477 -0
- package/dist/utils/bashStructure/index.d.ts +26 -0
- package/dist/utils/bashStructure/index.js +27 -0
- package/dist/utils/bashStructure/types.d.ts +62 -0
- package/dist/utils/bashStructure/types.js +47 -0
- package/dist/utils/constants.d.ts +10 -0
- package/dist/utils/constants.js +10 -0
- package/dist/utils/containerSetup.js +48 -6
- package/dist/utils/convertMessagesForAPI.d.ts +7 -1
- package/dist/utils/convertMessagesForAPI.js +64 -14
- package/dist/utils/fileChangeReminder.d.ts +20 -0
- package/dist/utils/fileChangeReminder.js +153 -0
- package/dist/utils/fileSearch.js +4 -3
- package/dist/utils/fileUtils.d.ts +44 -0
- package/dist/utils/fileUtils.js +118 -0
- package/dist/utils/frontmatterYaml.d.ts +33 -0
- package/dist/utils/frontmatterYaml.js +192 -0
- package/dist/utils/imageBudget.d.ts +85 -0
- package/dist/utils/imageBudget.js +109 -0
- package/dist/utils/imageDimensions.d.ts +83 -0
- package/dist/utils/imageDimensions.js +232 -0
- package/dist/utils/imageProcessor.d.ts +66 -0
- package/dist/utils/imageProcessor.js +84 -0
- package/dist/utils/imageRewrite.d.ts +29 -0
- package/dist/utils/imageRewrite.js +251 -0
- package/dist/utils/markdownParser.d.ts +5 -1
- package/dist/utils/markdownParser.js +9 -51
- package/dist/utils/mcpInstructions.d.ts +61 -0
- package/dist/utils/mcpInstructions.js +126 -0
- package/dist/utils/mcpUtils.d.ts +7 -0
- package/dist/utils/mcpUtils.js +11 -2
- package/dist/utils/memoryAge.d.ts +32 -0
- package/dist/utils/memoryAge.js +47 -0
- package/dist/utils/memoryEntrypoint.d.ts +20 -0
- package/dist/utils/memoryEntrypoint.js +49 -0
- package/dist/utils/memoryIndex.d.ts +30 -0
- package/dist/utils/memoryIndex.js +76 -0
- package/dist/utils/messageOperations.d.ts +6 -20
- package/dist/utils/messageOperations.js +40 -91
- package/dist/utils/nestedMemory.d.ts +22 -0
- package/dist/utils/nestedMemory.js +61 -0
- package/dist/utils/npmTarball.d.ts +19 -0
- package/dist/utils/npmTarball.js +92 -0
- package/dist/utils/pluginSource.d.ts +37 -0
- package/dist/utils/pluginSource.js +73 -0
- package/dist/utils/ripgrep.d.ts +18 -4
- package/dist/utils/ripgrep.js +56 -4
- package/dist/utils/runtimeDeps.d.ts +35 -0
- package/dist/utils/runtimeDeps.js +426 -0
- package/dist/utils/skillParser.js +22 -52
- package/dist/utils/subagentParser.js +48 -45
- package/dist/utils/tokenCalculation.js +0 -8
- package/dist/utils/userSettings.d.ts +90 -0
- package/dist/utils/userSettings.js +291 -0
- package/dist/utils/worktreeUtils.d.ts +2 -1
- package/dist/utils/worktreeUtils.js +64 -34
- package/package.json +12 -4
- package/dist/managers/bangManager.d.ts +0 -26
- package/dist/managers/bangManager.js +0 -78
|
@@ -1,19 +1,16 @@
|
|
|
1
|
-
import TurndownService from "turndown";
|
|
2
1
|
import { LRUCache } from "lru-cache";
|
|
3
2
|
import { WEB_FETCH_TOOL_NAME } from "../constants/tools.js";
|
|
4
3
|
import { logger } from "../utils/globalLogger.js";
|
|
5
4
|
import { isArtifactEnabled } from "../services/artifactAvailability.js";
|
|
6
|
-
import { authService, createAuthAwareFetch } from "../services/authService.js";
|
|
7
5
|
import { recordVersion } from "../services/artifactSession.js";
|
|
8
|
-
import {
|
|
6
|
+
import { extractArtifactSlug, htmlToMarkdown, readArtifactContent, summarizeArtifactAsReader, } from "../services/artifactContent.js";
|
|
7
|
+
import { formatSize, processContentWithAI, } from "../services/contentSummarizer.js";
|
|
9
8
|
// --- Security Limits ---
|
|
10
9
|
const MAX_HTTP_CONTENT_LENGTH = 10 * 1024 * 1024; // 10MB
|
|
11
10
|
const FETCH_TIMEOUT_MS = 60000; // 60s
|
|
12
11
|
const MAX_REDIRECTS = 10;
|
|
13
12
|
const MAX_MARKDOWN_LENGTH = 100000;
|
|
14
13
|
const USER_AGENT = "Wave-User (+https://github.com/netease-lcap/wave-agent)";
|
|
15
|
-
/** Artifact HTML beyond this size is persisted to a temp file (path + head preview). */
|
|
16
|
-
const ARTIFACT_PREVIEW_BYTES = 2 * 1024; // ~2KB
|
|
17
14
|
// --- Cache (LRU with 15min TTL, 50MB max) ---
|
|
18
15
|
const CACHE_TTL = 15 * 60 * 1000; // 15 minutes
|
|
19
16
|
const CACHE_MAX_BYTES = 50 * 1024 * 1024; // 50MB
|
|
@@ -22,14 +19,6 @@ const cache = new LRUCache({
|
|
|
22
19
|
maxSize: CACHE_MAX_BYTES,
|
|
23
20
|
sizeCalculation: (entry) => entry.bytes,
|
|
24
21
|
});
|
|
25
|
-
// --- Helpers ---
|
|
26
|
-
function formatSize(bytes) {
|
|
27
|
-
if (bytes < 1024)
|
|
28
|
-
return `${bytes}B`;
|
|
29
|
-
if (bytes < 1024 * 1024)
|
|
30
|
-
return `${(bytes / 1024).toFixed(1)}KB`;
|
|
31
|
-
return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
|
|
32
|
-
}
|
|
33
22
|
function validateURL(url) {
|
|
34
23
|
if (url.length > 2000) {
|
|
35
24
|
return {
|
|
@@ -79,124 +68,6 @@ function isPermittedRedirect(originalUrl, redirectUrl) {
|
|
|
79
68
|
return false;
|
|
80
69
|
}
|
|
81
70
|
}
|
|
82
|
-
// --- Artifact read channel ---
|
|
83
|
-
/** Extract the artifact slug from a `{host}/code/artifact/{slug}` URL. */
|
|
84
|
-
function extractArtifactSlug(url) {
|
|
85
|
-
try {
|
|
86
|
-
const parsed = new URL(url);
|
|
87
|
-
const match = parsed.pathname.match(/^\/code\/artifact\/([^/]+)\/?$/);
|
|
88
|
-
return match ? decodeURIComponent(match[1]) : null;
|
|
89
|
-
}
|
|
90
|
-
catch {
|
|
91
|
-
return null;
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
/**
|
|
95
|
-
* Fetch artifact metadata (`via=model_read`) then the HTML content (Bearer).
|
|
96
|
-
* Returns markdown (HTML converted via turndown) on success.
|
|
97
|
-
*/
|
|
98
|
-
async function readArtifact(url, slug, abortSignal) {
|
|
99
|
-
const serverUrl = authService.getServerUrl();
|
|
100
|
-
const authFetch = createAuthAwareFetch(globalThis.fetch);
|
|
101
|
-
const signal = abortSignal
|
|
102
|
-
? AbortSignal.any([abortSignal, AbortSignal.timeout(FETCH_TIMEOUT_MS)])
|
|
103
|
-
: AbortSignal.timeout(FETCH_TIMEOUT_MS);
|
|
104
|
-
let meta;
|
|
105
|
-
try {
|
|
106
|
-
const metaRes = await authFetch(`${serverUrl}/api/frame/${encodeURIComponent(slug)}?via=model_read`, { method: "GET", signal });
|
|
107
|
-
if (metaRes.status === 404) {
|
|
108
|
-
return {
|
|
109
|
-
kind: "error",
|
|
110
|
-
error: `Artifact not found: ${url} (it may have been deleted)`,
|
|
111
|
-
};
|
|
112
|
-
}
|
|
113
|
-
if (!metaRes.ok) {
|
|
114
|
-
return {
|
|
115
|
-
kind: "error",
|
|
116
|
-
error: `Failed to fetch artifact metadata: ${metaRes.status} ${metaRes.statusText}`,
|
|
117
|
-
};
|
|
118
|
-
}
|
|
119
|
-
meta = (await metaRes.json());
|
|
120
|
-
}
|
|
121
|
-
catch (error) {
|
|
122
|
-
logger?.warn("Artifact read metadata failed", {
|
|
123
|
-
slug,
|
|
124
|
-
error: String(error),
|
|
125
|
-
});
|
|
126
|
-
return {
|
|
127
|
-
kind: "error",
|
|
128
|
-
error: `Failed to fetch artifact metadata: ${error instanceof Error ? error.message : String(error)}`,
|
|
129
|
-
};
|
|
130
|
-
}
|
|
131
|
-
const contentUrl = typeof meta.contentUrl === "string" ? meta.contentUrl : "";
|
|
132
|
-
const version = typeof meta.version === "string" ? meta.version : "";
|
|
133
|
-
if (!contentUrl) {
|
|
134
|
-
return {
|
|
135
|
-
kind: "error",
|
|
136
|
-
error: "Artifact metadata did not include a contentUrl",
|
|
137
|
-
};
|
|
138
|
-
}
|
|
139
|
-
let html;
|
|
140
|
-
try {
|
|
141
|
-
const contentRes = await authFetch(new URL(contentUrl, serverUrl).toString(), { method: "GET", signal });
|
|
142
|
-
if (!contentRes.ok) {
|
|
143
|
-
return {
|
|
144
|
-
kind: "error",
|
|
145
|
-
error: `Failed to fetch artifact content: ${contentRes.status} ${contentRes.statusText}`,
|
|
146
|
-
};
|
|
147
|
-
}
|
|
148
|
-
html = await contentRes.text();
|
|
149
|
-
}
|
|
150
|
-
catch (error) {
|
|
151
|
-
logger?.warn("Artifact read content failed", {
|
|
152
|
-
slug,
|
|
153
|
-
error: String(error),
|
|
154
|
-
});
|
|
155
|
-
return {
|
|
156
|
-
kind: "error",
|
|
157
|
-
error: `Failed to fetch artifact content: ${error instanceof Error ? error.message : String(error)}`,
|
|
158
|
-
};
|
|
159
|
-
}
|
|
160
|
-
const turndownService = new TurndownService();
|
|
161
|
-
const markdown = turndownService.turndown(html);
|
|
162
|
-
return {
|
|
163
|
-
kind: "ok",
|
|
164
|
-
slug,
|
|
165
|
-
version,
|
|
166
|
-
markdown,
|
|
167
|
-
bytes: new TextEncoder().encode(markdown).length,
|
|
168
|
-
};
|
|
169
|
-
}
|
|
170
|
-
/**
|
|
171
|
-
* Process an artifact read result: persist content >~2KB to a temp file
|
|
172
|
-
* (return file path + head preview), run the prompt, attach artifactRead metadata.
|
|
173
|
-
*/
|
|
174
|
-
async function processArtifactRead(url, prompt, markdown, slug, version, context) {
|
|
175
|
-
const bytes = new TextEncoder().encode(markdown).length;
|
|
176
|
-
let aiInput = markdown;
|
|
177
|
-
let persistedMessage = "";
|
|
178
|
-
if (bytes > ARTIFACT_PREVIEW_BYTES) {
|
|
179
|
-
const filePath = persistToolResult(markdown, "artifact");
|
|
180
|
-
if (filePath) {
|
|
181
|
-
persistedMessage = buildPersistedOutputMessage(markdown.length, filePath, generatePreview(markdown));
|
|
182
|
-
aiInput = persistedMessage;
|
|
183
|
-
}
|
|
184
|
-
else {
|
|
185
|
-
aiInput =
|
|
186
|
-
markdown.substring(0, MAX_MARKDOWN_LENGTH) +
|
|
187
|
-
"\n\n... (content truncated, failed to persist full output)";
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
const result = await processWithAI(url, prompt, aiInput, 200, "OK", context, bytes);
|
|
191
|
-
result.metadata = { artifactRead: { slug, ver: version } };
|
|
192
|
-
if (persistedMessage) {
|
|
193
|
-
// Append the persisted-output message so the model can Read the full content.
|
|
194
|
-
result.content = result.content
|
|
195
|
-
? result.content + "\n\n" + persistedMessage
|
|
196
|
-
: persistedMessage;
|
|
197
|
-
}
|
|
198
|
-
return result;
|
|
199
|
-
}
|
|
200
71
|
// --- Tool ---
|
|
201
72
|
export const webFetchTool = {
|
|
202
73
|
name: WEB_FETCH_TOOL_NAME,
|
|
@@ -271,22 +142,28 @@ Usage notes:
|
|
|
271
142
|
if (isArtifactEnabled(context.workdir)) {
|
|
272
143
|
const artifactSlug = extractArtifactSlug(url);
|
|
273
144
|
if (artifactSlug) {
|
|
274
|
-
const readResult = await
|
|
145
|
+
const readResult = await readArtifactContent(artifactSlug, {
|
|
146
|
+
url,
|
|
147
|
+
abortSignal: context.abortSignal,
|
|
148
|
+
});
|
|
275
149
|
if (readResult.kind === "error") {
|
|
276
150
|
return { success: false, content: "", error: readResult.error };
|
|
277
151
|
}
|
|
278
|
-
|
|
152
|
+
const { slug, version, html } = readResult.artifact;
|
|
153
|
+
if (context.sessionId && version) {
|
|
279
154
|
// Keep the stale-version guard in sync with what the model has seen.
|
|
280
|
-
recordVersion(context.sessionId,
|
|
155
|
+
recordVersion(context.sessionId, slug, version);
|
|
281
156
|
}
|
|
282
|
-
|
|
157
|
+
const result = await summarizeArtifactAsReader(url, prompt, html, context);
|
|
158
|
+
result.metadata = { artifactRead: { slug, ver: version } };
|
|
159
|
+
return result;
|
|
283
160
|
}
|
|
284
161
|
}
|
|
285
162
|
try {
|
|
286
163
|
const cached = cache.get(url);
|
|
287
164
|
if (cached) {
|
|
288
165
|
const markdown = cached.content;
|
|
289
|
-
return
|
|
166
|
+
return processContentWithAI(url, prompt, markdown, cached.code, cached.codeText, context);
|
|
290
167
|
}
|
|
291
168
|
// Fetch with redirect following
|
|
292
169
|
const result = await fetchWithRedirects(url, context.abortSignal);
|
|
@@ -323,8 +200,7 @@ Usage notes:
|
|
|
323
200
|
};
|
|
324
201
|
}
|
|
325
202
|
const html = await response.text();
|
|
326
|
-
|
|
327
|
-
let markdown = turndownService.turndown(html);
|
|
203
|
+
let markdown = htmlToMarkdown(html);
|
|
328
204
|
const markdownBytes = new TextEncoder().encode(markdown).length;
|
|
329
205
|
// Truncate if too large
|
|
330
206
|
if (markdown.length > MAX_MARKDOWN_LENGTH) {
|
|
@@ -340,7 +216,7 @@ Usage notes:
|
|
|
340
216
|
content: markdown,
|
|
341
217
|
contentType: response.headers.get("content-type") || "",
|
|
342
218
|
});
|
|
343
|
-
return
|
|
219
|
+
return processContentWithAI(finalUrl, prompt, markdown, response.status, response.statusText, context, markdownBytes);
|
|
344
220
|
}
|
|
345
221
|
catch (error) {
|
|
346
222
|
logger.error(`WebFetch failed for ${url}:`, error);
|
|
@@ -398,30 +274,3 @@ async function fetchWithRedirects(initialUrl, abortSignal, redirectCount = 0) {
|
|
|
398
274
|
}
|
|
399
275
|
return { kind: "response", response, finalUrl: initialUrl };
|
|
400
276
|
}
|
|
401
|
-
// --- AI Processing ---
|
|
402
|
-
async function processWithAI(url, prompt, markdown, statusCode, statusText, context, contentSize) {
|
|
403
|
-
if (!context.aiManager || !context.aiService) {
|
|
404
|
-
return {
|
|
405
|
-
success: false,
|
|
406
|
-
content: markdown,
|
|
407
|
-
error: "AI Manager or AI Service not available for processing content",
|
|
408
|
-
};
|
|
409
|
-
}
|
|
410
|
-
const modelConfig = context.aiManager.getModelConfig();
|
|
411
|
-
const fastModel = modelConfig.fastModel;
|
|
412
|
-
const aiResponse = await context.aiService.processWebContent({
|
|
413
|
-
gatewayConfig: context.aiManager.getGatewayConfig(),
|
|
414
|
-
modelConfig: modelConfig,
|
|
415
|
-
content: markdown,
|
|
416
|
-
prompt: prompt,
|
|
417
|
-
model: fastModel,
|
|
418
|
-
abortSignal: context.abortSignal,
|
|
419
|
-
});
|
|
420
|
-
const sizeStr = contentSize !== undefined ? formatSize(contentSize) : "unknown size";
|
|
421
|
-
const statusStr = `${statusCode} ${statusText}`.trim();
|
|
422
|
-
return {
|
|
423
|
-
success: true,
|
|
424
|
-
content: aiResponse.content || "",
|
|
425
|
-
shortResult: `Received ${sizeStr} (${statusStr}) from ${url}`,
|
|
426
|
-
};
|
|
427
|
-
}
|
|
@@ -1,5 +1,33 @@
|
|
|
1
|
+
import * as path from "node:path";
|
|
1
2
|
import { WORKFLOW_TOOL_NAME } from "../constants/tools.js";
|
|
3
|
+
import { parseScript } from "../workflow/scriptRuntime.js";
|
|
2
4
|
import { logger } from "../utils/globalLogger.js";
|
|
5
|
+
/** Characters that would corrupt a single-line summary (ANSI-adjacent controls, separators, invisibles). */
|
|
6
|
+
const SUMMARY_UNSAFE_CHARS = /[\p{Cc}\p{Cf}\p{Cs}\p{Default_Ignorable_Code_Point}\u2028\u2029]/gu;
|
|
7
|
+
/** Max characters of the script head shown when `meta` cannot be parsed. */
|
|
8
|
+
const FALLBACK_SUMMARY_MAX_CHARS = 80;
|
|
9
|
+
function sanitizeForSummary(text) {
|
|
10
|
+
return text.replace(SUMMARY_UNSAFE_CHARS, "");
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Summary for a script whose `meta` could not be parsed: its first non-empty
|
|
14
|
+
* line, truncated if needed, plus a hint that more lines follow.
|
|
15
|
+
*/
|
|
16
|
+
function summarizeUnparsedScript(script) {
|
|
17
|
+
const lines = script.split("\n");
|
|
18
|
+
const head = sanitizeForSummary(lines.find((line) => line.trim()) ?? "");
|
|
19
|
+
if (!head) {
|
|
20
|
+
return "";
|
|
21
|
+
}
|
|
22
|
+
const preview = head.length > FALLBACK_SUMMARY_MAX_CHARS
|
|
23
|
+
? `${head.slice(0, FALLBACK_SUMMARY_MAX_CHARS - 1)}…`
|
|
24
|
+
: head;
|
|
25
|
+
const extraLines = lines.length - 1;
|
|
26
|
+
if (extraLines <= 0) {
|
|
27
|
+
return preview;
|
|
28
|
+
}
|
|
29
|
+
return `${preview} … +${extraLines} line${extraLines === 1 ? "" : "s"}`;
|
|
30
|
+
}
|
|
3
31
|
/**
|
|
4
32
|
* Workflow tool plugin for executing deterministic multi-subagent orchestration scripts.
|
|
5
33
|
*
|
|
@@ -176,15 +204,19 @@ Use this tool for multi-step orchestration where control flow should be determin
|
|
|
176
204
|
}
|
|
177
205
|
},
|
|
178
206
|
formatCompactParams: (params) => {
|
|
179
|
-
if (params.scriptPath) {
|
|
180
|
-
return `scriptPath: ${params.scriptPath}`;
|
|
181
|
-
}
|
|
182
207
|
const script = params.script;
|
|
183
|
-
if (script) {
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
208
|
+
if (typeof script === "string" && script) {
|
|
209
|
+
try {
|
|
210
|
+
return sanitizeForSummary(parseScript(script).meta.description);
|
|
211
|
+
}
|
|
212
|
+
catch {
|
|
213
|
+
return summarizeUnparsedScript(script);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
const scriptPath = params.scriptPath;
|
|
217
|
+
if (typeof scriptPath === "string" && scriptPath) {
|
|
218
|
+
return sanitizeForSummary(path.basename(scriptPath));
|
|
187
219
|
}
|
|
188
|
-
return "
|
|
220
|
+
return "";
|
|
189
221
|
},
|
|
190
222
|
};
|
package/dist/tools/writeTool.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { readFile,
|
|
1
|
+
import { readFile, mkdir, stat } from "fs/promises";
|
|
2
2
|
import { createHash } from "crypto";
|
|
3
3
|
import { dirname } from "path";
|
|
4
4
|
import { logger } from "../utils/globalLogger.js";
|
|
5
|
+
import { atomicWriteFile } from "../utils/atomicWrite.js";
|
|
5
6
|
import { resolvePath, getDisplayPath } from "../utils/path.js";
|
|
6
7
|
import { READ_TOOL_NAME } from "../constants/tools.js";
|
|
7
8
|
/**
|
|
@@ -157,9 +158,10 @@ Usage:
|
|
|
157
158
|
if (context.reversionManager && context.messageId) {
|
|
158
159
|
snapshotId = await context.reversionManager.recordSnapshot(context.messageId, resolvedPath, isExistingFile ? "modify" : "create");
|
|
159
160
|
}
|
|
160
|
-
// Write file
|
|
161
|
+
// Write file (atomic: temp file + rename, so concurrent readers never
|
|
162
|
+
// observe a truncated file). Staleness/OCC was checked above.
|
|
161
163
|
try {
|
|
162
|
-
await
|
|
164
|
+
await atomicWriteFile(resolvedPath, content);
|
|
163
165
|
// Commit snapshot on success
|
|
164
166
|
if (context.reversionManager && snapshotId) {
|
|
165
167
|
await context.reversionManager.commitSnapshot(snapshotId);
|
|
@@ -180,6 +182,7 @@ Usage:
|
|
|
180
182
|
mtime: newStats.mtime.getTime(),
|
|
181
183
|
hash,
|
|
182
184
|
source: "write",
|
|
185
|
+
content,
|
|
183
186
|
offset: undefined,
|
|
184
187
|
limit: undefined,
|
|
185
188
|
});
|
package/dist/types/agent.d.ts
CHANGED
|
@@ -29,8 +29,25 @@ export interface AgentOptions {
|
|
|
29
29
|
visionModel?: string;
|
|
30
30
|
maxInputTokens?: number;
|
|
31
31
|
maxTokens?: number;
|
|
32
|
-
/**
|
|
32
|
+
/**
|
|
33
|
+
* Preferred language for agent communication, injected verbatim into the
|
|
34
|
+
* system prompt (`# Language\nAlways respond in <value>`). When unset, the
|
|
35
|
+
* resolve chain falls back to `DEFAULT_LANGUAGE` (`zh-CN`).
|
|
36
|
+
*/
|
|
33
37
|
language?: string;
|
|
38
|
+
/**
|
|
39
|
+
* Per-session override for auto-memory extraction (程序化会话级覆盖).
|
|
40
|
+
* Takes precedence over settings.json merged config and
|
|
41
|
+
* WAVE_DISABLE_AUTO_MEMORY env; undefined defers to them. 三端设置页的开关
|
|
42
|
+
* **不**经这一层下发——它落用户级 `~/.wave/settings.json`,由实时重载在下一轮
|
|
43
|
+
* 生效(spec core/agent-config.md「设置实时重载」)。
|
|
44
|
+
*/
|
|
45
|
+
autoMemoryEnabled?: boolean;
|
|
46
|
+
/**
|
|
47
|
+
* Per-session override for auto-memory extraction frequency (turns). 同
|
|
48
|
+
* `autoMemoryEnabled`:设置页的值不在这一层。
|
|
49
|
+
*/
|
|
50
|
+
autoMemoryFrequency?: number;
|
|
34
51
|
callbacks?: AgentCallbacks;
|
|
35
52
|
restoreSessionId?: string;
|
|
36
53
|
continueLastSession?: boolean;
|
|
@@ -111,4 +128,10 @@ export interface AgentCallbacks extends MessageManagerCallbacks, BackgroundTaskM
|
|
|
111
128
|
onCompactionContentUpdate?: (content: string) => void;
|
|
112
129
|
/** Streaming reasoning from the compaction fork (accumulated). */
|
|
113
130
|
onCompactionReasoningUpdate?: (content: string) => void;
|
|
131
|
+
/**
|
|
132
|
+
* Full content of the plan file right after a successful `Write`/`Edit` of
|
|
133
|
+
* that file (spec: 计划文件更新后刷新计划面板). Hosts use it to refresh an
|
|
134
|
+
* already-open plan panel; it is not emitted for other files.
|
|
135
|
+
*/
|
|
136
|
+
onPlanFileUpdated?: (content: string) => void;
|
|
114
137
|
}
|
package/dist/types/commands.d.ts
CHANGED
|
@@ -2,10 +2,17 @@
|
|
|
2
2
|
* Slash command and custom command types
|
|
3
3
|
* Dependencies: None
|
|
4
4
|
*/
|
|
5
|
+
/** UI-facing source of a skill-derived slash command. "user" covers personal
|
|
6
|
+
* (~/.wave、~/.claude、~/.agents) skills; plugin skills carry pluginName. */
|
|
7
|
+
export type SkillSource = "builtin" | "user" | "project" | "plugin";
|
|
5
8
|
export interface SlashCommand {
|
|
6
9
|
id: string;
|
|
7
10
|
name: string;
|
|
8
11
|
description: string;
|
|
12
|
+
/** Set only on commands registered from skills — GUI slash-command popup
|
|
13
|
+
* renders a source tag (内置/用户/项目/插件) from it. Plain/custom/plugin
|
|
14
|
+
* commands leave it undefined. */
|
|
15
|
+
skillSource?: SkillSource;
|
|
9
16
|
handler: (args?: string, signal?: AbortSignal) => Promise<void> | void;
|
|
10
17
|
/** Whether this command should bypass the message queue when AI is busy.
|
|
11
18
|
* - `true`: always immediate
|
|
@@ -13,7 +13,6 @@ import type { TelemetryConfig } from "./telemetry.js";
|
|
|
13
13
|
export type Scope = "user" | "project" | "local";
|
|
14
14
|
export interface MarketplaceConfig {
|
|
15
15
|
source: MarketplaceSource;
|
|
16
|
-
autoUpdate?: boolean;
|
|
17
16
|
}
|
|
18
17
|
/**
|
|
19
18
|
* Root configuration structure for all Wave Agent settings including hooks and environment variables
|
|
@@ -25,7 +24,12 @@ export interface WaveConfiguration {
|
|
|
25
24
|
permissions?: {
|
|
26
25
|
allow?: string[];
|
|
27
26
|
deny?: string[];
|
|
28
|
-
|
|
27
|
+
/**
|
|
28
|
+
* Default permission mode for restricted tools. Settings key aligns with
|
|
29
|
+
* Claude Code's `permissions.defaultMode`; the runtime permission context
|
|
30
|
+
* and CLI `--permission-mode` keep the "permission mode" naming.
|
|
31
|
+
*/
|
|
32
|
+
defaultMode?: PermissionMode;
|
|
29
33
|
/**
|
|
30
34
|
* List of directories that are considered part of the Safe Zone.
|
|
31
35
|
* File operations within these directories can be auto-accepted.
|
|
@@ -57,6 +61,8 @@ export interface WaveConfiguration {
|
|
|
57
61
|
};
|
|
58
62
|
/** Whether the Artifact tool is enabled. Unset follows the code default constant (ARTIFACT_DEFAULT_ENABLED). */
|
|
59
63
|
enableArtifact?: boolean;
|
|
64
|
+
/** Whether the Exec tool is enabled. Unset follows the code default constant (EXEC_DEFAULT_ENABLED). */
|
|
65
|
+
enableExec?: boolean;
|
|
60
66
|
/**
|
|
61
67
|
* Session transcript retention in days (aligned with Claude Code's
|
|
62
68
|
* cleanupPeriodDays). Session jsonl files in ~/.wave/projects older than
|
|
@@ -65,6 +71,43 @@ export interface WaveConfiguration {
|
|
|
65
71
|
*/
|
|
66
72
|
cleanupPeriodDays?: number;
|
|
67
73
|
}
|
|
74
|
+
/**
|
|
75
|
+
* 设置页读写的用户偏好子集(落点 = 用户级 `~/.wave/settings.json`;读写实现见
|
|
76
|
+
* `utils/userSettings.ts`)。三端(VSCE / JetBrains / desktop)设置页与 CLI 的
|
|
77
|
+
* `getUserSettings` / `updateUserSettings` RPC 共用这一形状;`contextLength` 单位
|
|
78
|
+
* 为 K(落盘换算为 `env.WAVE_MAX_INPUT_TOKENS`)。
|
|
79
|
+
*/
|
|
80
|
+
export interface UserPreferenceSettings {
|
|
81
|
+
/** AI 回复语言(settings.json 顶层 `language`,如 zh-CN / en-US)。 */
|
|
82
|
+
language?: string;
|
|
83
|
+
/** 上下文长度,单位 K(如 200 = 200K)。 */
|
|
84
|
+
contextLength?: number;
|
|
85
|
+
/** 是否开启自动记忆提取。 */
|
|
86
|
+
autoMemoryEnabled?: boolean;
|
|
87
|
+
/** 自动记忆提取的轮次频率(1–100)。 */
|
|
88
|
+
autoMemoryFrequency?: number;
|
|
89
|
+
/** Wave 服务端地址(settings.json 的 `env.WAVE_SERVER_URL`,如 https://…)。 */
|
|
90
|
+
serverUrl?: string;
|
|
91
|
+
}
|
|
92
|
+
/** 用户偏好键(设置页控件)。 */
|
|
93
|
+
export type UserPreferenceKey = keyof UserPreferenceSettings;
|
|
94
|
+
/**
|
|
95
|
+
* 生效值的来源层。只归因**进程级可达**的层(Remote 组织下发 / 用户级文件 /
|
|
96
|
+
* 机器环境变量 / SDK 默认):`project` / `local` 需要 workdir,而
|
|
97
|
+
* `getUserSettings` 是刻意的无会话全局 RPC;`override` / `options` 是会话级
|
|
98
|
+
* 语义,不在这条链路上(见 spec core/agent-config.md 边界说明「用户偏好的层与来源」)。
|
|
99
|
+
*/
|
|
100
|
+
export type UserPreferenceSource = "remote" | "user" | "env" | "default";
|
|
101
|
+
/**
|
|
102
|
+
* `getUserSettings` / `updateUserSettings` 的回包:**生效**用户偏好——键缺失
|
|
103
|
+
* 表示该偏好没有任何提供者(设置页据此显示「未设置」态)——外加每个键的来源层
|
|
104
|
+
* (`preferenceSources`,设置页对来源为 `remote` 的键显示生效值 + 置灰 +
|
|
105
|
+
* 「由组织配置管理」)。
|
|
106
|
+
*/
|
|
107
|
+
export interface UserPreferenceSettingsView extends UserPreferenceSettings {
|
|
108
|
+
/** 每个键恒有来源(缺省即 `default`)。 */
|
|
109
|
+
preferenceSources?: Partial<Record<UserPreferenceKey, UserPreferenceSource>>;
|
|
110
|
+
}
|
|
68
111
|
/**
|
|
69
112
|
* Legacy alias for backward compatibility - will be deprecated
|
|
70
113
|
*/
|
package/dist/types/hooks.d.ts
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
export type { WaveConfiguration, HookConfiguration, PartialHookConfiguration, HookConfigurationRecord, } from "./configuration.js";
|
|
8
8
|
export type HookEvent = "PreToolUse" | "PostToolUse" | "UserPromptSubmit" | "Stop" | "SubagentStop" | "PermissionRequest" | "WorktreeCreate" | "WorktreeRemove" | "CwdChanged" | "SessionStart" | "SessionEnd" | "PreCompact" | "PostCompact";
|
|
9
|
+
export declare const HOOK_EVENT_SUMMARIES: Record<HookEvent, string>;
|
|
9
10
|
export interface HookCommand {
|
|
10
11
|
type: "command";
|
|
11
12
|
command: string;
|
package/dist/types/hooks.js
CHANGED
|
@@ -4,6 +4,25 @@
|
|
|
4
4
|
* Provides comprehensive TypeScript types for the Wave Code hooks system,
|
|
5
5
|
* enabling automated actions at specific workflow points.
|
|
6
6
|
*/
|
|
7
|
+
// One-line summary per hook event, aligned with Claude Code's
|
|
8
|
+
// HookEventMetadata.summary (hooksConfigManager.ts). Shared by the CLI
|
|
9
|
+
// /hooks detail view and the webview settings hooks page; unknown/plugin
|
|
10
|
+
// events fall back to displaying the event name itself.
|
|
11
|
+
export const HOOK_EVENT_SUMMARIES = {
|
|
12
|
+
PreToolUse: "Before tool execution",
|
|
13
|
+
PostToolUse: "After tool execution",
|
|
14
|
+
UserPromptSubmit: "When the user submits a prompt",
|
|
15
|
+
Stop: "Right before Claude concludes its response",
|
|
16
|
+
SubagentStop: "Right before a subagent (Agent tool call) concludes its response",
|
|
17
|
+
PermissionRequest: "When a permission dialog is displayed",
|
|
18
|
+
WorktreeCreate: "Create an isolated worktree for VCS-agnostic isolation",
|
|
19
|
+
WorktreeRemove: "Remove a previously created worktree",
|
|
20
|
+
CwdChanged: "After the working directory changes",
|
|
21
|
+
SessionStart: "When a new session is started",
|
|
22
|
+
SessionEnd: "When a session is ending",
|
|
23
|
+
PreCompact: "Before conversation compaction",
|
|
24
|
+
PostCompact: "After conversation compaction",
|
|
25
|
+
};
|
|
7
26
|
// Hook execution errors (non-blocking)
|
|
8
27
|
export class HookExecutionError extends Error {
|
|
9
28
|
constructor(hookCommand, originalError, context) {
|
|
@@ -3,18 +3,47 @@ export interface MarketplaceOwner {
|
|
|
3
3
|
name: string;
|
|
4
4
|
email?: string;
|
|
5
5
|
}
|
|
6
|
+
/**
|
|
7
|
+
* Object form of a plugin entry's `source` (spec plugin A-021): `url` is a whole
|
|
8
|
+
* repository, `git-subdir` is a subdirectory of one. Both are outside the
|
|
9
|
+
* marketplace checkout, so they carry no readable local copy for「最新版本」(A-010).
|
|
10
|
+
*/
|
|
11
|
+
export interface MarketplacePluginObjectSource {
|
|
12
|
+
source: "url" | "git-subdir";
|
|
13
|
+
url: string;
|
|
14
|
+
/** Only for `git-subdir`: path of the plugin inside the repository. */
|
|
15
|
+
path?: string;
|
|
16
|
+
/** Branch or tag. */
|
|
17
|
+
ref?: string;
|
|
18
|
+
/** Pinned commit; checked out after cloning. */
|
|
19
|
+
sha?: string;
|
|
20
|
+
}
|
|
6
21
|
export interface MarketplacePluginEntry {
|
|
7
22
|
name: string;
|
|
8
|
-
source: string;
|
|
23
|
+
source: string | MarketplacePluginObjectSource;
|
|
9
24
|
description: string;
|
|
10
25
|
}
|
|
11
26
|
export interface MarketplacePluginStatus extends MarketplacePluginEntry {
|
|
12
27
|
marketplace: string;
|
|
13
28
|
installed: boolean;
|
|
29
|
+
/** 已安装版本(未安装时 undefined) */
|
|
14
30
|
version?: string;
|
|
31
|
+
/**
|
|
32
|
+
* 市场内该插件当前可安装的最新版本,取自市场检出目录内插件的
|
|
33
|
+
* `.wave-plugin/plugin.json`(兼容 `.claude-plugin/plugin.json`)。
|
|
34
|
+
* 插件来源是独立 Git 仓库等无法就地读取清单的情况为 undefined
|
|
35
|
+
* (spec plugin A-010:此时不展示最新版本)。
|
|
36
|
+
*/
|
|
37
|
+
latestVersion?: string;
|
|
15
38
|
cachePath?: string;
|
|
16
39
|
projectPath?: string;
|
|
17
40
|
scope?: Scope;
|
|
41
|
+
/**
|
|
42
|
+
* 该插件由组织的托管配置(远端托管设置)声明启用:成员不能卸载或禁用它,
|
|
43
|
+
* 界面据此把卸载入口判为不可用并给出由组织管理的说明(spec plugin A-024)。
|
|
44
|
+
* 判据只看下发值,本机不落任何标记。
|
|
45
|
+
*/
|
|
46
|
+
managed?: boolean;
|
|
18
47
|
}
|
|
19
48
|
export interface MarketplaceManifest {
|
|
20
49
|
name: string;
|
|
@@ -37,7 +66,6 @@ export interface KnownMarketplace {
|
|
|
37
66
|
name: string;
|
|
38
67
|
source: MarketplaceSource;
|
|
39
68
|
isBuiltin?: boolean;
|
|
40
|
-
autoUpdate?: boolean;
|
|
41
69
|
lastUpdated?: string;
|
|
42
70
|
/** The scope where this marketplace was declared (user, project, local, or builtin) */
|
|
43
71
|
declaredScope?: "user" | "project" | "local" | "builtin";
|
|
@@ -46,12 +74,22 @@ export interface KnownMarketplacesRegistry {
|
|
|
46
74
|
builtinSeeded?: boolean;
|
|
47
75
|
marketplaces: KnownMarketplace[];
|
|
48
76
|
}
|
|
77
|
+
/**
|
|
78
|
+
* 安装产物的记账位置(spec plugin A-015):用户作用域是本机全局的,不带
|
|
79
|
+
* projectPath;项目作用域与本地作用域归属某个仓库,以该仓库路径为 projectPath。
|
|
80
|
+
*/
|
|
81
|
+
export interface PluginInstallLocation {
|
|
82
|
+
scope: Scope;
|
|
83
|
+
projectPath?: string;
|
|
84
|
+
}
|
|
49
85
|
export interface InstalledPlugin {
|
|
50
86
|
name: string;
|
|
51
87
|
marketplace: string;
|
|
52
88
|
version: string;
|
|
53
89
|
cachePath: string;
|
|
90
|
+
/** 该条安装记录所属的作用域;引入作用域维度之前写入的历史记录不带此字段(spec plugin A-015)。 */
|
|
54
91
|
scope?: Scope;
|
|
92
|
+
/** 项目作用域与本地作用域所属仓库的路径;用户作用域不带。 */
|
|
55
93
|
projectPath?: string;
|
|
56
94
|
}
|
|
57
95
|
export interface InstalledPluginsRegistry {
|
package/dist/types/mcp.d.ts
CHANGED
|
@@ -19,16 +19,58 @@ export interface McpTool {
|
|
|
19
19
|
name: string;
|
|
20
20
|
description?: string;
|
|
21
21
|
inputSchema: Record<string, unknown>;
|
|
22
|
+
/**
|
|
23
|
+
* The schema the server declared for its *output*, raw as listed. Not passed
|
|
24
|
+
* through `cleanSchema` like `inputSchema`: that cleaning exists because the
|
|
25
|
+
* input schema travels inside a request, and this one is only ever rendered as
|
|
26
|
+
* a return type. Absent for most servers today, and degenerate
|
|
27
|
+
* (`{ type: "object" }`) when present.
|
|
28
|
+
*/
|
|
29
|
+
outputSchema?: Record<string, unknown>;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* What one MCP tool call produced. Two audiences, two fields:
|
|
33
|
+
*
|
|
34
|
+
* - `content` is the display text the flat path hands the model — a placeholder
|
|
35
|
+
* when the tool said nothing (`No content`) or returned only images.
|
|
36
|
+
* - `output` is what a sandbox `await` resolves to: the server's
|
|
37
|
+
* `structuredContent` when it returned one, otherwise its text, otherwise
|
|
38
|
+
* `null`. The catalog renders its return types from this same rule, so a
|
|
39
|
+
* signature can never promise a shape the sandbox does not deliver.
|
|
40
|
+
*/
|
|
41
|
+
export interface McpToolCallResult {
|
|
42
|
+
success: boolean;
|
|
43
|
+
content: string;
|
|
44
|
+
output: unknown;
|
|
45
|
+
serverName?: string;
|
|
46
|
+
images?: Array<{
|
|
47
|
+
data: string;
|
|
48
|
+
mediaType?: string;
|
|
49
|
+
}>;
|
|
22
50
|
}
|
|
23
51
|
export interface McpServerStatus {
|
|
24
52
|
name: string;
|
|
25
53
|
config: McpServerConfig;
|
|
26
54
|
/** Pre-resolution URL with template variables preserved for safe display */
|
|
27
55
|
originalUrl?: string;
|
|
56
|
+
/** Config source: user (~/.wave/mcp.json), project (<workdir>/.mcp.json),
|
|
57
|
+
* or plugin (registered from a plugin manifest) */
|
|
58
|
+
scope?: "user" | "project" | "plugin";
|
|
28
59
|
status: "disconnected" | "connected" | "connecting" | "reconnecting" | "error";
|
|
29
60
|
tools?: McpTool[];
|
|
30
61
|
toolCount?: number;
|
|
31
62
|
capabilities?: string[];
|
|
63
|
+
/**
|
|
64
|
+
* Usage notes the server described about itself during `initialize`
|
|
65
|
+
* (`instructions`): rate limits, preconditions, how the server is meant to be
|
|
66
|
+
* used. Server-level prose, announced once in the conversation instead of the
|
|
67
|
+
* system prompt — see `utils/mcpInstructions.ts` for why, and for the per-server
|
|
68
|
+
* cap — and already truncated by the time it lands here, unlike a tool
|
|
69
|
+
* description, which the catalog compresses.
|
|
70
|
+
* Retained across a reconnecting server (like `tools`) and cleared once the
|
|
71
|
+
* server is gone, so a dropped server cannot keep talking to the model.
|
|
72
|
+
*/
|
|
73
|
+
instructions?: string;
|
|
32
74
|
lastConnected?: number;
|
|
33
75
|
error?: string;
|
|
34
76
|
}
|
|
@@ -16,7 +16,7 @@ export interface Message {
|
|
|
16
16
|
additionalFields?: Record<string, unknown>;
|
|
17
17
|
isMeta?: boolean;
|
|
18
18
|
}
|
|
19
|
-
export type MessageBlock = TextBlock | ErrorBlock | ToolBlock | ImageBlock |
|
|
19
|
+
export type MessageBlock = TextBlock | ErrorBlock | ToolBlock | ImageBlock | CompactBlock | ReasoningBlock | FileHistoryBlock | TaskNotificationBlock;
|
|
20
20
|
export interface TextBlock {
|
|
21
21
|
type: "text";
|
|
22
22
|
content: string;
|
|
@@ -62,13 +62,6 @@ export interface ImageBlock {
|
|
|
62
62
|
type: "image";
|
|
63
63
|
imageUrls?: string[];
|
|
64
64
|
}
|
|
65
|
-
export interface BangBlock {
|
|
66
|
-
type: "bang";
|
|
67
|
-
command: string;
|
|
68
|
-
output: string;
|
|
69
|
-
stage: "running" | "end";
|
|
70
|
-
exitCode: number | null;
|
|
71
|
-
}
|
|
72
65
|
export interface CompactBlock {
|
|
73
66
|
type: "compact";
|
|
74
67
|
content: string;
|