wave-agent-sdk 1.2.0 → 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 +58 -4
- package/dist/agent.js +91 -19
- package/dist/builtin/index.js +2 -0
- package/dist/builtin/skills/settings.js +1 -12
- 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 +53 -13
- package/dist/core/plugin.js +134 -26
- 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 +5 -0
- package/dist/index.js +6 -0
- package/dist/managers/MemoryRuleManager.d.ts +6 -0
- package/dist/managers/MemoryRuleManager.js +12 -0
- package/dist/managers/aiManager.d.ts +35 -1
- package/dist/managers/aiManager.js +190 -21
- package/dist/managers/backgroundTaskManager.js +14 -0
- package/dist/managers/hookManager.d.ts +13 -0
- package/dist/managers/hookManager.js +31 -4
- package/dist/managers/liveConfigManager.d.ts +33 -0
- package/dist/managers/liveConfigManager.js +103 -8
- package/dist/managers/lspManager.d.ts +9 -0
- package/dist/managers/lspManager.js +47 -18
- package/dist/managers/mcpManager.d.ts +45 -10
- package/dist/managers/mcpManager.js +103 -1
- package/dist/managers/messageManager.d.ts +48 -5
- package/dist/managers/messageManager.js +107 -21
- package/dist/managers/permissionManager.d.ts +40 -0
- package/dist/managers/permissionManager.js +63 -8
- 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 +19 -0
- package/dist/managers/skillManager.js +44 -0
- package/dist/managers/slashCommandManager.d.ts +10 -0
- package/dist/managers/slashCommandManager.js +35 -3
- package/dist/managers/subagentManager.d.ts +8 -0
- package/dist/managers/subagentManager.js +20 -0
- package/dist/managers/toolManager.d.ts +29 -3
- package/dist/managers/toolManager.js +87 -13
- 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/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 +318 -119
- 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 +60 -9
- package/dist/services/configurationService.js +129 -54
- 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 +19 -15
- package/dist/services/interactionService.d.ts +9 -1
- package/dist/services/interactionService.js +28 -8
- package/dist/services/jsonlHandler.d.ts +84 -0
- package/dist/services/jsonlHandler.js +209 -14
- package/dist/services/memory.d.ts +3 -1
- package/dist/services/memory.js +13 -9
- package/dist/services/officialMarketplaceMirror.js +3 -2
- package/dist/services/pluginLoader.d.ts +12 -4
- package/dist/services/pluginLoader.js +38 -7
- package/dist/services/remoteSettingsService.js +16 -2
- package/dist/services/session.d.ts +74 -0
- package/dist/services/session.js +144 -3
- package/dist/services/sessionEntries.d.ts +2 -0
- package/dist/services/sessionEntries.js +20 -0
- package/dist/stdio/index.d.ts +3 -1
- package/dist/stdio/index.js +3 -1
- package/dist/stdio/notificationRouter.js +1 -0
- package/dist/stdio/stdioAgent.d.ts +14 -7
- package/dist/stdio/stdioAgent.js +19 -0
- package/dist/tools/artifactTool.js +406 -273
- package/dist/tools/bashTool.js +8 -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/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 +20 -5
- package/dist/types/configuration.d.ts +39 -1
- package/dist/types/marketplace.d.ts +40 -2
- package/dist/types/mcp.d.ts +39 -0
- 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 +15 -0
- package/dist/utils/constants.d.ts +10 -0
- package/dist/utils/constants.js +10 -0
- package/dist/utils/containerSetup.js +43 -0
- 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 +33 -0
- package/dist/utils/fileUtils.js +81 -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 -2
- package/dist/utils/messageOperations.js +40 -29
- 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 +39 -43
- package/dist/utils/userSettings.d.ts +90 -0
- package/dist/utils/userSettings.js +291 -0
- package/package.json +10 -7
|
@@ -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,15 +29,24 @@ 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;
|
|
34
38
|
/**
|
|
35
|
-
* Per-session override for auto-memory extraction (
|
|
36
|
-
*
|
|
37
|
-
*
|
|
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「设置实时重载」)。
|
|
38
44
|
*/
|
|
39
45
|
autoMemoryEnabled?: boolean;
|
|
40
|
-
/**
|
|
46
|
+
/**
|
|
47
|
+
* Per-session override for auto-memory extraction frequency (turns). 同
|
|
48
|
+
* `autoMemoryEnabled`:设置页的值不在这一层。
|
|
49
|
+
*/
|
|
41
50
|
autoMemoryFrequency?: number;
|
|
42
51
|
callbacks?: AgentCallbacks;
|
|
43
52
|
restoreSessionId?: string;
|
|
@@ -119,4 +128,10 @@ export interface AgentCallbacks extends MessageManagerCallbacks, BackgroundTaskM
|
|
|
119
128
|
onCompactionContentUpdate?: (content: string) => void;
|
|
120
129
|
/** Streaming reasoning from the compaction fork (accumulated). */
|
|
121
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;
|
|
122
137
|
}
|
|
@@ -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
|
|
@@ -62,6 +61,8 @@ export interface WaveConfiguration {
|
|
|
62
61
|
};
|
|
63
62
|
/** Whether the Artifact tool is enabled. Unset follows the code default constant (ARTIFACT_DEFAULT_ENABLED). */
|
|
64
63
|
enableArtifact?: boolean;
|
|
64
|
+
/** Whether the Exec tool is enabled. Unset follows the code default constant (EXEC_DEFAULT_ENABLED). */
|
|
65
|
+
enableExec?: boolean;
|
|
65
66
|
/**
|
|
66
67
|
* Session transcript retention in days (aligned with Claude Code's
|
|
67
68
|
* cleanupPeriodDays). Session jsonl files in ~/.wave/projects older than
|
|
@@ -70,6 +71,43 @@ export interface WaveConfiguration {
|
|
|
70
71
|
*/
|
|
71
72
|
cleanupPeriodDays?: number;
|
|
72
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
|
+
}
|
|
73
111
|
/**
|
|
74
112
|
* Legacy alias for backward compatibility - will be deprecated
|
|
75
113
|
*/
|
|
@@ -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,6 +19,34 @@ 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;
|
|
@@ -32,6 +60,17 @@ export interface McpServerStatus {
|
|
|
32
60
|
tools?: McpTool[];
|
|
33
61
|
toolCount?: number;
|
|
34
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;
|
|
35
74
|
lastConnected?: number;
|
|
36
75
|
error?: string;
|
|
37
76
|
}
|
|
@@ -15,6 +15,8 @@ export interface PermissionDecision {
|
|
|
15
15
|
newPermissionMode?: PermissionMode;
|
|
16
16
|
/** Signal to persist a new allowed rule */
|
|
17
17
|
newPermissionRule?: string;
|
|
18
|
+
/** Signal to add a directory to this session's Safe Zone (not persisted) */
|
|
19
|
+
newAdditionalDirectory?: string;
|
|
18
20
|
}
|
|
19
21
|
/** Callback function for custom permission logic */
|
|
20
22
|
export type PermissionCallback = (context: ToolPermissionContext) => Promise<PermissionDecision>;
|
|
@@ -32,6 +34,12 @@ export interface ToolPermissionContext {
|
|
|
32
34
|
suggestedPrefix?: string;
|
|
33
35
|
/** Whether to hide the persistent permission option (e.g., "Don't ask again") in the UI */
|
|
34
36
|
hidePersistentOption?: boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Absolute path of the directory holding an out-of-Safe-Zone target, set for
|
|
39
|
+
* Edit/Write when the target lies outside the Safe Zone. Lets the confirmation
|
|
40
|
+
* UI offer adding that directory to the session Safe Zone.
|
|
41
|
+
*/
|
|
42
|
+
outsideSafeZoneDirectory?: string;
|
|
35
43
|
/** The ID of the tool call that triggered this permission request */
|
|
36
44
|
toolCallId?: string;
|
|
37
45
|
/** The content of the plan being exited from */
|
|
@@ -41,6 +49,20 @@ export interface ToolPermissionContext {
|
|
|
41
49
|
}
|
|
42
50
|
/** List of tools that require permission checks in default mode */
|
|
43
51
|
export declare const RESTRICTED_TOOLS: readonly ["Edit", "Bash", "Write", "EnterPlanMode", "ExitPlanMode", "AskUserQuestion", "Artifact"];
|
|
52
|
+
/**
|
|
53
|
+
* Tools that must still reach the user when permission checks are bypassed
|
|
54
|
+
* (`bypassPermissions` mode, or `plan` mode in a session holding the bypass
|
|
55
|
+
* authorization) — aligned with Claude Code's `requiresUserInteraction`:
|
|
56
|
+
* its permission pipeline returns the tool's own ask result before the
|
|
57
|
+
* bypass step can allow it.
|
|
58
|
+
*
|
|
59
|
+
* - `AskUserQuestion`: the tool *is* the question; bypassing it would strand
|
|
60
|
+
* the agent without an answer.
|
|
61
|
+
* - `ExitPlanMode`: leaving plan mode is the user's approval of the plan, so
|
|
62
|
+
* it stays a user decision even in a "don't ask me" session. This is the
|
|
63
|
+
* one remaining gate on plan mode for such sessions (see plan-mode.md).
|
|
64
|
+
*/
|
|
65
|
+
export declare const USER_INTERACTION_REQUIRED_TOOLS: readonly ["AskUserQuestion", "ExitPlanMode"];
|
|
44
66
|
/** Type for restricted tool names */
|
|
45
67
|
export type RestrictedTool = (typeof RESTRICTED_TOOLS)[number];
|
|
46
68
|
export declare const OPERATION_CANCELLED_BY_USER = "Operation cancelled by user";
|
|
@@ -13,4 +13,21 @@ export const RESTRICTED_TOOLS = [
|
|
|
13
13
|
ASK_USER_QUESTION_TOOL_NAME,
|
|
14
14
|
ARTIFACT_TOOL_NAME,
|
|
15
15
|
];
|
|
16
|
+
/**
|
|
17
|
+
* Tools that must still reach the user when permission checks are bypassed
|
|
18
|
+
* (`bypassPermissions` mode, or `plan` mode in a session holding the bypass
|
|
19
|
+
* authorization) — aligned with Claude Code's `requiresUserInteraction`:
|
|
20
|
+
* its permission pipeline returns the tool's own ask result before the
|
|
21
|
+
* bypass step can allow it.
|
|
22
|
+
*
|
|
23
|
+
* - `AskUserQuestion`: the tool *is* the question; bypassing it would strand
|
|
24
|
+
* the agent without an answer.
|
|
25
|
+
* - `ExitPlanMode`: leaving plan mode is the user's approval of the plan, so
|
|
26
|
+
* it stays a user decision even in a "don't ask me" session. This is the
|
|
27
|
+
* one remaining gate on plan mode for such sessions (see plan-mode.md).
|
|
28
|
+
*/
|
|
29
|
+
export const USER_INTERACTION_REQUIRED_TOOLS = [
|
|
30
|
+
ASK_USER_QUESTION_TOOL_NAME,
|
|
31
|
+
EXIT_PLAN_MODE_TOOL_NAME,
|
|
32
|
+
];
|
|
16
33
|
export const OPERATION_CANCELLED_BY_USER = "Operation cancelled by user";
|
package/dist/types/plugins.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { CustomSlashCommand } from "./commands.js";
|
|
2
2
|
import { Skill } from "./skills.js";
|
|
3
3
|
import { LspConfig } from "./lsp.js";
|
|
4
|
-
import { McpConfig } from "./mcp.js";
|
|
4
|
+
import { McpConfig, McpServerConfig } from "./mcp.js";
|
|
5
5
|
import { PartialHookConfiguration } from "./configuration.js";
|
|
6
6
|
import { SubagentConfiguration } from "../utils/subagentParser.js";
|
|
7
7
|
/**
|
|
@@ -10,10 +10,20 @@ import { SubagentConfiguration } from "../utils/subagentParser.js";
|
|
|
10
10
|
export interface PluginManifest {
|
|
11
11
|
name: string;
|
|
12
12
|
description: string;
|
|
13
|
-
|
|
13
|
+
/**
|
|
14
|
+
* Optional: plugins in the Claude Code ecosystem often omit it (spec plugin
|
|
15
|
+
* A-022). Install and load both fall back to `1.0.0`.
|
|
16
|
+
*/
|
|
17
|
+
version?: string;
|
|
14
18
|
author?: {
|
|
15
19
|
name: string;
|
|
16
20
|
};
|
|
21
|
+
/**
|
|
22
|
+
* Inline MCP server declarations, equivalent to a sibling `.mcp.json`
|
|
23
|
+
* (spec plugin A-023). Claude Code also allows a path string or array of
|
|
24
|
+
* paths here; only the object form is supported.
|
|
25
|
+
*/
|
|
26
|
+
mcpServers?: Record<string, McpServerConfig>;
|
|
17
27
|
}
|
|
18
28
|
/**
|
|
19
29
|
* Plugin configuration in AgentOptions or wave.settings.json
|
|
@@ -22,10 +32,24 @@ export interface PluginConfig {
|
|
|
22
32
|
type: "local";
|
|
23
33
|
path: string;
|
|
24
34
|
}
|
|
35
|
+
/** A plugin root that failed to load during the most recent load/reload. */
|
|
36
|
+
export interface PluginLoadFailure {
|
|
37
|
+
path: string;
|
|
38
|
+
error: string;
|
|
39
|
+
}
|
|
40
|
+
/** Result of `Agent.reloadPlugins()` / `PluginManager.reloadAllPlugins()`. */
|
|
41
|
+
export interface PluginReloadResult {
|
|
42
|
+
/** Plugin names loaded after the reload. */
|
|
43
|
+
plugins: string[];
|
|
44
|
+
/** Plugins that could not be loaded; the reload does not roll back. */
|
|
45
|
+
failures: PluginLoadFailure[];
|
|
46
|
+
}
|
|
25
47
|
/**
|
|
26
48
|
* Represents a loaded plugin in the system
|
|
27
49
|
*/
|
|
28
50
|
export interface Plugin extends PluginManifest {
|
|
51
|
+
/** Always resolved on load: a missing manifest version becomes `1.0.0` (A-022). */
|
|
52
|
+
version: string;
|
|
29
53
|
path: string;
|
|
30
54
|
commands: CustomSlashCommand[];
|
|
31
55
|
skills: Skill[];
|
package/dist/types/skills.d.ts
CHANGED
|
@@ -91,6 +91,21 @@ export interface SkillParseOptions {
|
|
|
91
91
|
validateMetadata?: boolean;
|
|
92
92
|
basePath?: string;
|
|
93
93
|
}
|
|
94
|
+
/**
|
|
95
|
+
* A skill invocation recorded for context restoration (post-compaction
|
|
96
|
+
* re-injection, spec core/message-compact 场景 4).
|
|
97
|
+
*/
|
|
98
|
+
export interface InvokedSkillRecord {
|
|
99
|
+
skillName: string;
|
|
100
|
+
timestamp: number;
|
|
101
|
+
/**
|
|
102
|
+
* The content the model actually saw when the skill was invoked — directory
|
|
103
|
+
* placeholders already substituted, prefixed with
|
|
104
|
+
* `Base directory for this skill: <path>`. Re-injecting the raw SKILL.md
|
|
105
|
+
* instead would hand the model a literal `${WAVE_SKILL_DIR}`.
|
|
106
|
+
*/
|
|
107
|
+
content?: string;
|
|
108
|
+
}
|
|
94
109
|
export declare const SKILL_DEFAULTS: {
|
|
95
110
|
readonly PERSONAL_SKILLS_DIR: ".wave/skills";
|
|
96
111
|
readonly PROJECT_SKILLS_DIR: ".wave/skills";
|
|
@@ -23,6 +23,16 @@ export declare const USER_MEMORY_FILE: string;
|
|
|
23
23
|
*/
|
|
24
24
|
export declare const DEFAULT_WAVE_MAX_INPUT_TOKENS = 200000;
|
|
25
25
|
export declare const DEFAULT_WAVE_MAX_OUTPUT_TOKENS = 32000;
|
|
26
|
+
/**
|
|
27
|
+
* AI 回复语言的默认值(未设置 `language` 时生效)。
|
|
28
|
+
*
|
|
29
|
+
* 取值必须与设置页「AI 回复语言」下拉的默认项是同一个串(webview
|
|
30
|
+
* `SettingsPage.tsx` 的 `zh-CN` / `en-US`),否则未设置时会出现「设置页显示中文、
|
|
31
|
+
* 实际生效却不是中文」的分叉(spec core/agent-config.md 边界说明「语言默认值」:
|
|
32
|
+
* 未设置时 **显示 ≡ 生效**)。该值原样注入系统提示的
|
|
33
|
+
* `# Language\nAlways respond in <值>` 指令。
|
|
34
|
+
*/
|
|
35
|
+
export declare const DEFAULT_LANGUAGE = "zh-CN";
|
|
26
36
|
/**
|
|
27
37
|
* Default server URL for SSO authentication.
|
|
28
38
|
* Overridden by WAVE_SERVER_URL env var or programmatic AgentOptions.serverUrl.
|
package/dist/utils/constants.js
CHANGED
|
@@ -25,6 +25,16 @@ export const USER_MEMORY_FILE = path.join(DATA_DIRECTORY, "AGENTS.md");
|
|
|
25
25
|
*/
|
|
26
26
|
export const DEFAULT_WAVE_MAX_INPUT_TOKENS = 200000; // Default token limit
|
|
27
27
|
export const DEFAULT_WAVE_MAX_OUTPUT_TOKENS = 32000; // Default output token limit (aligned with Claude Code)
|
|
28
|
+
/**
|
|
29
|
+
* AI 回复语言的默认值(未设置 `language` 时生效)。
|
|
30
|
+
*
|
|
31
|
+
* 取值必须与设置页「AI 回复语言」下拉的默认项是同一个串(webview
|
|
32
|
+
* `SettingsPage.tsx` 的 `zh-CN` / `en-US`),否则未设置时会出现「设置页显示中文、
|
|
33
|
+
* 实际生效却不是中文」的分叉(spec core/agent-config.md 边界说明「语言默认值」:
|
|
34
|
+
* 未设置时 **显示 ≡ 生效**)。该值原样注入系统提示的
|
|
35
|
+
* `# Language\nAlways respond in <值>` 指令。
|
|
36
|
+
*/
|
|
37
|
+
export const DEFAULT_LANGUAGE = "zh-CN";
|
|
28
38
|
/**
|
|
29
39
|
* Default server URL for SSO authentication.
|
|
30
40
|
* Overridden by WAVE_SERVER_URL env var or programmatic AgentOptions.serverUrl.
|
|
@@ -28,6 +28,8 @@ import { MemoryService } from "../services/memory.js";
|
|
|
28
28
|
import { AutoMemoryService } from "../services/autoMemoryService.js";
|
|
29
29
|
import { USER_MEMORY_FILE } from "./constants.js";
|
|
30
30
|
import { getGitMainRepoRoot } from "./gitUtils.js";
|
|
31
|
+
import { toPosixPath } from "./path.js";
|
|
32
|
+
import { EDIT_TOOL_NAME, WRITE_TOOL_NAME } from "../constants/tools.js";
|
|
31
33
|
import { AsyncWorkRegistry } from "./asyncWorkRegistry.js";
|
|
32
34
|
import { logger } from "./globalLogger.js";
|
|
33
35
|
import { authService } from "../services/authService.js";
|
|
@@ -211,6 +213,19 @@ export function setupAgentContainer(setupOptions) {
|
|
|
211
213
|
if (decision.newPermissionRule) {
|
|
212
214
|
await addPermissionRule(decision.newPermissionRule);
|
|
213
215
|
}
|
|
216
|
+
if (decision.newAdditionalDirectory) {
|
|
217
|
+
// Session-level only: the user approved this directory from the
|
|
218
|
+
// confirmation dialog (never persisted to settings).
|
|
219
|
+
permissionManager.addInstanceAdditionalDirectory(decision.newAdditionalDirectory);
|
|
220
|
+
// The dialog option is "允许本会话编辑 <目录名>/" — it has to cover
|
|
221
|
+
// later edits too, otherwise `default` mode would keep prompting for
|
|
222
|
+
// every Write/Edit in that directory. Forward slashes: minimatch
|
|
223
|
+
// treats the pattern `\` as an escape, while it normalises the input
|
|
224
|
+
// path's separators on Windows.
|
|
225
|
+
const pattern = `${toPosixPath(decision.newAdditionalDirectory)}/**`;
|
|
226
|
+
permissionManager.addInstanceAllowedRule(`${EDIT_TOOL_NAME}(${pattern})`);
|
|
227
|
+
permissionManager.addInstanceAllowedRule(`${WRITE_TOOL_NAME}(${pattern})`);
|
|
228
|
+
}
|
|
214
229
|
return decision;
|
|
215
230
|
}
|
|
216
231
|
: undefined;
|
|
@@ -248,13 +263,41 @@ export function setupAgentContainer(setupOptions) {
|
|
|
248
263
|
},
|
|
249
264
|
});
|
|
250
265
|
container.register("LiveConfigManager", liveConfigManager);
|
|
266
|
+
// The turn-scoped configuration snapshot is held by LiveConfigManager (it owns
|
|
267
|
+
// the turn boundaries and the live reload) and read by ConfigurationService's
|
|
268
|
+
// resolve chain, so a mid-turn settings.json change applies from the next turn
|
|
269
|
+
// instead of shifting values under the running one.
|
|
270
|
+
configurationService.setTurnSnapshotSource(() => liveConfigManager.getTurnSnapshot());
|
|
251
271
|
// Wire up remote settings hot-update: when polling detects changed settings,
|
|
252
272
|
// reload configuration so admin changes propagate to the running agent.
|
|
253
273
|
// The callback strongly captures the per-agent LiveConfigManager, so it MUST
|
|
254
274
|
// be unsubscribed in destroy() via teardown — otherwise the module-level
|
|
255
275
|
// callback array pins the whole agent object graph.
|
|
276
|
+
// Managed plugin config (enabledPlugins / marketplaces) last applied to the
|
|
277
|
+
// plugin subsystem, keyed by a JSON signature: a synced change that touches
|
|
278
|
+
// neither field must not bounce every plugin's MCP servers.
|
|
279
|
+
const remoteAtSetup = remoteSettingsService.getRemoteSettingsSync();
|
|
280
|
+
let managedPluginSignature = JSON.stringify([
|
|
281
|
+
remoteAtSetup?.enabledPlugins ?? null,
|
|
282
|
+
remoteAtSetup?.marketplaces ?? null,
|
|
283
|
+
]);
|
|
256
284
|
teardowns.push(remoteSettingsService.onSettingsUpdate(async () => {
|
|
257
285
|
await liveConfigManager.reload();
|
|
286
|
+
// Managed settings also drive plugin installation and loading: a synced
|
|
287
|
+
// change to `enabledPlugins` / `marketplaces` must re-read the plugins in
|
|
288
|
+
// place, otherwise an admin push would only take effect after a restart
|
|
289
|
+
// (spec enterprise server-managed-config「托管配置下发插件市场与启用列表」
|
|
290
|
+
// 场景 1 与 3).
|
|
291
|
+
const remote = remoteSettingsService.getRemoteSettingsSync();
|
|
292
|
+
const signature = JSON.stringify([
|
|
293
|
+
remote?.enabledPlugins ?? null,
|
|
294
|
+
remote?.marketplaces ?? null,
|
|
295
|
+
]);
|
|
296
|
+
if (signature === managedPluginSignature) {
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
managedPluginSignature = signature;
|
|
300
|
+
await container.get("PluginManager")?.reloadAllPlugins();
|
|
258
301
|
}));
|
|
259
302
|
const subagentManager = new SubagentManager(container, {
|
|
260
303
|
workdir,
|
|
@@ -10,8 +10,14 @@ export interface ConvertMessagesOptions {
|
|
|
10
10
|
/**
|
|
11
11
|
* Convert message format to API call format, stopping when a compacted message is encountered.
|
|
12
12
|
* Messages with no meaningful content or tool calls are filtered out.
|
|
13
|
+
*
|
|
14
|
+
* Async because every outbound image is routed through `planOutboundImage`,
|
|
15
|
+
* which may have to re-encode an oversized image with the optional `sharp`
|
|
16
|
+
* codec (`utils/imageRewrite.ts`). Images that are already inside the budget —
|
|
17
|
+
* the common case — take a synchronous fast path and come out byte-identical.
|
|
18
|
+
*
|
|
13
19
|
* @param messages Message list
|
|
14
20
|
* @param options Optional conversion options (e.g. supportsVision)
|
|
15
21
|
* @returns Converted API message format list
|
|
16
22
|
*/
|
|
17
|
-
export declare function convertMessagesForAPI(messages: Message[], options?: ConvertMessagesOptions): ChatCompletionMessageParam[]
|
|
23
|
+
export declare function convertMessagesForAPI(messages: Message[], options?: ConvertMessagesOptions): Promise<ChatCompletionMessageParam[]>;
|