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
package/dist/core/plugin.d.ts
CHANGED
|
@@ -14,13 +14,24 @@ export declare class PluginCore {
|
|
|
14
14
|
private workdir;
|
|
15
15
|
constructor(workdir?: string);
|
|
16
16
|
/**
|
|
17
|
-
* Installs a plugin from a marketplace
|
|
17
|
+
* Installs a plugin from a marketplace and, when a scope is given, enables it
|
|
18
|
+
* there — the install record is filed under that same scope (spec plugin A-015).
|
|
18
19
|
*/
|
|
19
20
|
installPlugin(pluginId: string, scope?: Scope): Promise<InstalledPlugin>;
|
|
20
21
|
/**
|
|
21
|
-
*
|
|
22
|
+
* Managed plugins are the ones the organization pushed through remote managed
|
|
23
|
+
* settings: a member cannot uninstall or disable them (spec plugin A-024).
|
|
24
|
+
* The check reads the managed layer only — a plugin the admin never mentioned
|
|
25
|
+
* stays the user's to manage, and dropping the entry restores that at once.
|
|
22
26
|
*/
|
|
23
|
-
|
|
27
|
+
private assertNotManaged;
|
|
28
|
+
/**
|
|
29
|
+
* Uninstalls a plugin from a single scope (spec plugin A-015):只清除该作用域的
|
|
30
|
+
* 启用记录与该作用域的安装记录,其它作用域(含其它项目的项目/本地作用域)不受
|
|
31
|
+
* 影响;本机产物仅在该插件再无安装记录时删除。未指定作用域时按
|
|
32
|
+
* `local` > `project` > `user` 探测当前生效作用域(与 enable/disable 一致)。
|
|
33
|
+
*/
|
|
34
|
+
uninstallPlugin(pluginId: string, scope?: Scope): Promise<Scope>;
|
|
24
35
|
/**
|
|
25
36
|
* Enables a plugin in the specified scope. If no scope is provided, it tries to find
|
|
26
37
|
* the scope where the plugin is already configured, or defaults to "user".
|
|
@@ -32,20 +43,32 @@ export declare class PluginCore {
|
|
|
32
43
|
*/
|
|
33
44
|
disablePlugin(pluginId: string, scope?: Scope): Promise<Scope>;
|
|
34
45
|
/**
|
|
35
|
-
*
|
|
46
|
+
* Moves an installed plugin to another installation scope: clears its
|
|
47
|
+
* enabledPlugins record from every scope, then enables it in the target one
|
|
48
|
+
* (spec plugin「设置页插件市场」场景 11:更换作用域后旧作用域不再保留该插件)。
|
|
49
|
+
* The install record follows the plugin, otherwise uninstalling it at the new
|
|
50
|
+
* scope would find no record there (spec plugin A-015)。
|
|
36
51
|
*/
|
|
37
|
-
|
|
52
|
+
setPluginScope(pluginId: string, scope: Scope): Promise<Scope>;
|
|
38
53
|
/**
|
|
39
|
-
*
|
|
54
|
+
* Updates an installed plugin to the latest version from its marketplace
|
|
40
55
|
*/
|
|
41
|
-
|
|
56
|
+
updatePlugin(pluginId: string): Promise<InstalledPlugin>;
|
|
42
57
|
/**
|
|
43
|
-
* Lists all plugins from all registered marketplaces with their installation and enabled status
|
|
58
|
+
* Lists all plugins from all registered marketplaces with their installation and enabled status.
|
|
44
59
|
*/
|
|
45
60
|
listPlugins(): Promise<{
|
|
46
61
|
plugins: MarketplacePluginStatus[];
|
|
47
62
|
mergedEnabled: Record<string, boolean>;
|
|
48
63
|
}>;
|
|
64
|
+
/**
|
|
65
|
+
* Reads the version declared by a marketplace plugin's own manifest inside the
|
|
66
|
+
* marketplace checkout — the version a fresh install would get. Sources that
|
|
67
|
+
* live outside the checkout (Git URLs and both object shapes, which always point
|
|
68
|
+
* at an external repository) have no local copy until install, so they yield
|
|
69
|
+
* undefined (spec plugin A-010 / A-021).
|
|
70
|
+
*/
|
|
71
|
+
private readLatestVersion;
|
|
49
72
|
/**
|
|
50
73
|
* Adds a new marketplace
|
|
51
74
|
*/
|
|
@@ -55,9 +78,30 @@ export declare class PluginCore {
|
|
|
55
78
|
*/
|
|
56
79
|
removeMarketplace(name: string, scope?: Scope): Promise<void>;
|
|
57
80
|
/**
|
|
58
|
-
* Updates a specific marketplace or all marketplaces
|
|
81
|
+
* Updates a specific marketplace or all marketplaces: refreshes the checkout
|
|
82
|
+
* from its upstream and reinstalls any plugins that are already installed from
|
|
83
|
+
* it (mirrors Claude Code's refresh-and-bump).
|
|
84
|
+
*
|
|
85
|
+
* 无界面可依赖的入口(非交互命令 `wave plugin marketplace update`)走这里;
|
|
86
|
+
* 交互界面的「批量更新插件」走 [updateMarketplacePlugins](不拉检出)。
|
|
87
|
+
*
|
|
88
|
+
* @returns 实际发生版本变化的插件数量(0 = 全部已是最新),供 GUI 宿主区分提示。
|
|
89
|
+
*/
|
|
90
|
+
updateMarketplace(name?: string): Promise<number>;
|
|
91
|
+
/**
|
|
92
|
+
* 批量升级某市场内已安装的插件,且不拉取检出——交互界面的「批量更新插件」
|
|
93
|
+
* (GUI 三端按钮与 CLI 插件管理器的同名项)。清单的新鲜度由打开这些界面时的
|
|
94
|
+
* 后台刷新保证(spec 插件市场 A-013、场景 14)。
|
|
95
|
+
*
|
|
96
|
+
* @returns 实际发生版本变化的插件数量(0 = 该市场已是最新),供宿主区分提示。
|
|
97
|
+
*/
|
|
98
|
+
updateMarketplacePlugins(name?: string): Promise<number>;
|
|
99
|
+
/**
|
|
100
|
+
* Refreshes the checkout of every registered marketplace, without touching
|
|
101
|
+
* installed plugins. Called by hosts when the user opens a plugin
|
|
102
|
+
* marketplace surface (spec 插件市场 A-013 场景 5/13).
|
|
59
103
|
*/
|
|
60
|
-
|
|
104
|
+
refreshMarketplaces(): Promise<void>;
|
|
61
105
|
/**
|
|
62
106
|
* Lists all registered marketplaces
|
|
63
107
|
*/
|
package/dist/core/plugin.js
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
import { Container } from "../utils/container.js";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import fs from "node:fs/promises";
|
|
2
4
|
import { PluginManager } from "../managers/pluginManager.js";
|
|
3
5
|
import { PluginScopeManager } from "../managers/pluginScopeManager.js";
|
|
4
6
|
import { MarketplaceService } from "../services/MarketplaceService.js";
|
|
5
7
|
import { ConfigurationService } from "../services/configurationService.js";
|
|
8
|
+
import { remoteSettingsService } from "../services/remoteSettingsService.js";
|
|
9
|
+
import { parsePluginSource } from "../utils/pluginSource.js";
|
|
10
|
+
import { logger } from "../utils/globalLogger.js";
|
|
6
11
|
/**
|
|
7
12
|
* PluginCore
|
|
8
13
|
*
|
|
@@ -12,6 +17,11 @@ import { ConfigurationService } from "../services/configurationService.js";
|
|
|
12
17
|
export class PluginCore {
|
|
13
18
|
constructor(workdir = process.cwd()) {
|
|
14
19
|
this.workdir = workdir;
|
|
20
|
+
// 托管层(spec plugin A-024)读的是远端设置的磁盘缓存,而 `wave plugin
|
|
21
|
+
// uninstall` 这类独立命令不经过 Agent 初始化,没人调过 initialize() ⇒
|
|
22
|
+
// 缓存为空、托管限制在这些入口上形同虚设。这里补上:initialize() 只是
|
|
23
|
+
// 同步读一次 `~/.wave/remote-settings.json`(幂等),已加载过的进程不受影响。
|
|
24
|
+
remoteSettingsService.initialize();
|
|
15
25
|
this.container = new Container();
|
|
16
26
|
this.configurationService = new ConfigurationService();
|
|
17
27
|
this.marketplaceService = new MarketplaceService(this.workdir, this.configurationService);
|
|
@@ -27,21 +37,45 @@ export class PluginCore {
|
|
|
27
37
|
});
|
|
28
38
|
}
|
|
29
39
|
/**
|
|
30
|
-
* Installs a plugin from a marketplace
|
|
40
|
+
* Installs a plugin from a marketplace and, when a scope is given, enables it
|
|
41
|
+
* there — the install record is filed under that same scope (spec plugin A-015).
|
|
31
42
|
*/
|
|
32
43
|
async installPlugin(pluginId, scope) {
|
|
33
|
-
const installedPlugin = await this.marketplaceService.installPlugin(pluginId);
|
|
44
|
+
const installedPlugin = await this.marketplaceService.installPlugin(pluginId, scope ? this.pluginScopeManager.getInstallLocation(scope) : undefined);
|
|
34
45
|
if (scope) {
|
|
35
46
|
await this.enablePlugin(pluginId, scope);
|
|
36
47
|
}
|
|
37
48
|
return installedPlugin;
|
|
38
49
|
}
|
|
39
50
|
/**
|
|
40
|
-
*
|
|
51
|
+
* Managed plugins are the ones the organization pushed through remote managed
|
|
52
|
+
* settings: a member cannot uninstall or disable them (spec plugin A-024).
|
|
53
|
+
* The check reads the managed layer only — a plugin the admin never mentioned
|
|
54
|
+
* stays the user's to manage, and dropping the entry restores that at once.
|
|
41
55
|
*/
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
56
|
+
assertNotManaged(pluginId, action) {
|
|
57
|
+
const managed = this.configurationService.getManagedEnabledPlugins();
|
|
58
|
+
if (!managed || !Object.prototype.hasOwnProperty.call(managed, pluginId)) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
const verb = action === "uninstall" ? "uninstalled" : "disabled";
|
|
62
|
+
throw new Error(`Plugin ${pluginId} is managed by your organization and cannot be ${verb}. Contact your admin to change the managed plugin configuration.`);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Uninstalls a plugin from a single scope (spec plugin A-015):只清除该作用域的
|
|
66
|
+
* 启用记录与该作用域的安装记录,其它作用域(含其它项目的项目/本地作用域)不受
|
|
67
|
+
* 影响;本机产物仅在该插件再无安装记录时删除。未指定作用域时按
|
|
68
|
+
* `local` > `project` > `user` 探测当前生效作用域(与 enable/disable 一致)。
|
|
69
|
+
*/
|
|
70
|
+
async uninstallPlugin(pluginId, scope) {
|
|
71
|
+
this.assertNotManaged(pluginId, "uninstall");
|
|
72
|
+
const targetScope = scope ?? this.findPluginScope(pluginId);
|
|
73
|
+
if (!targetScope) {
|
|
74
|
+
throw new Error(`Plugin ${pluginId} is not enabled in any scope for ${this.workdir}. Use --scope to pick the scope to uninstall from.`);
|
|
75
|
+
}
|
|
76
|
+
await this.marketplaceService.uninstallPlugin(pluginId, this.pluginScopeManager.getInstallLocation(targetScope));
|
|
77
|
+
await this.pluginScopeManager.removePluginFromScope(targetScope, pluginId);
|
|
78
|
+
return targetScope;
|
|
45
79
|
}
|
|
46
80
|
/**
|
|
47
81
|
* Enables a plugin in the specified scope. If no scope is provided, it tries to find
|
|
@@ -57,49 +91,77 @@ export class PluginCore {
|
|
|
57
91
|
* the scope where the plugin is already configured, or defaults to "user".
|
|
58
92
|
*/
|
|
59
93
|
async disablePlugin(pluginId, scope) {
|
|
94
|
+
this.assertNotManaged(pluginId, "disable");
|
|
60
95
|
const targetScope = scope || this.findPluginScope(pluginId) || "user";
|
|
61
96
|
await this.pluginScopeManager.disablePlugin(targetScope, pluginId);
|
|
62
97
|
return targetScope;
|
|
63
98
|
}
|
|
64
99
|
/**
|
|
65
|
-
*
|
|
100
|
+
* Moves an installed plugin to another installation scope: clears its
|
|
101
|
+
* enabledPlugins record from every scope, then enables it in the target one
|
|
102
|
+
* (spec plugin「设置页插件市场」场景 11:更换作用域后旧作用域不再保留该插件)。
|
|
103
|
+
* The install record follows the plugin, otherwise uninstalling it at the new
|
|
104
|
+
* scope would find no record there (spec plugin A-015)。
|
|
66
105
|
*/
|
|
67
|
-
async
|
|
68
|
-
|
|
106
|
+
async setPluginScope(pluginId, scope) {
|
|
107
|
+
const previousScope = this.findPluginScope(pluginId);
|
|
108
|
+
await this.pluginScopeManager.removePluginFromAllScopes(pluginId);
|
|
109
|
+
await this.pluginScopeManager.enablePlugin(scope, pluginId);
|
|
110
|
+
await this.marketplaceService.relocatePlugin(pluginId, previousScope
|
|
111
|
+
? this.pluginScopeManager.getInstallLocation(previousScope)
|
|
112
|
+
: undefined, this.pluginScopeManager.getInstallLocation(scope));
|
|
113
|
+
return scope;
|
|
69
114
|
}
|
|
70
115
|
/**
|
|
71
|
-
*
|
|
116
|
+
* Updates an installed plugin to the latest version from its marketplace
|
|
72
117
|
*/
|
|
73
|
-
async
|
|
74
|
-
await this.marketplaceService.
|
|
118
|
+
async updatePlugin(pluginId) {
|
|
119
|
+
return await this.marketplaceService.updatePlugin(pluginId);
|
|
75
120
|
}
|
|
76
121
|
/**
|
|
77
|
-
* Lists all plugins from all registered marketplaces with their installation and enabled status
|
|
122
|
+
* Lists all plugins from all registered marketplaces with their installation and enabled status.
|
|
78
123
|
*/
|
|
79
124
|
async listPlugins() {
|
|
80
125
|
const installedPlugins = await this.marketplaceService.getInstalledPlugins();
|
|
81
126
|
const marketplaces = await this.marketplaceService.listMarketplaces();
|
|
82
127
|
const mergedEnabled = this.configurationService.getMergedEnabledPlugins(this.workdir);
|
|
128
|
+
const managedEnabled = this.configurationService.getManagedEnabledPlugins() ?? {};
|
|
83
129
|
const allMarketplacePlugins = [];
|
|
84
130
|
for (const m of marketplaces) {
|
|
85
131
|
try {
|
|
86
|
-
const
|
|
87
|
-
manifest.
|
|
132
|
+
const marketplacePath = this.marketplaceService.getMarketplacePath(m.source);
|
|
133
|
+
const manifest = await this.marketplaceService.loadMarketplaceManifest(marketplacePath);
|
|
134
|
+
for (const p of manifest.plugins) {
|
|
88
135
|
const pluginId = `${p.name}@${m.name}`;
|
|
89
|
-
const
|
|
136
|
+
const scope = this.pluginScopeManager.findPluginScope(pluginId) ?? undefined;
|
|
137
|
+
const installedEntry = installedPlugins.plugins.find((ip) => ip.name === p.name && ip.marketplace === m.name);
|
|
138
|
+
// 安装状态以当前工作目录为准(spec plugin A-012):配置链里有启用记录、
|
|
139
|
+
// 且本机已有安装产物,才视为「已安装」。安装产物单独存在只说明该插件曾被
|
|
140
|
+
// 下载过(例如以项目/本地作用域装在别的项目里),若据此判为已安装,会在
|
|
141
|
+
// 当前目录渲染出「已安装 + 作用域未知」。作用域标签与安装态同源,未安装时
|
|
142
|
+
// 不回传作用域。
|
|
143
|
+
// 托管插件由组织下发(spec plugin A-024):它在任何工程都算已安装,
|
|
144
|
+
// 成员本机没有可卸载的记录,界面据此把卸载入口判为不可用。
|
|
145
|
+
const managed = Object.prototype.hasOwnProperty.call(managedEnabled, pluginId);
|
|
146
|
+
const installed = managed || scope ? installedEntry : undefined;
|
|
90
147
|
allMarketplacePlugins.push({
|
|
91
148
|
...p,
|
|
92
149
|
marketplace: m.name,
|
|
93
|
-
installed: !!installed,
|
|
150
|
+
installed: managed || !!installed,
|
|
94
151
|
version: installed?.version,
|
|
152
|
+
latestVersion: await this.readLatestVersion(marketplacePath, p.source),
|
|
95
153
|
cachePath: installed?.cachePath,
|
|
96
154
|
projectPath: installed?.projectPath,
|
|
97
|
-
scope:
|
|
155
|
+
scope: installed ? scope : undefined,
|
|
156
|
+
managed: managed || undefined,
|
|
98
157
|
});
|
|
99
|
-
}
|
|
158
|
+
}
|
|
100
159
|
}
|
|
101
|
-
catch {
|
|
102
|
-
//
|
|
160
|
+
catch (error) {
|
|
161
|
+
// A marketplace that fails to load must be diagnosable: swallowing this
|
|
162
|
+
// silently is what made an unparsable entry look like an empty market
|
|
163
|
+
// (spec plugin「兼容 Claude Code 生态的市场清单与插件」场景 5).
|
|
164
|
+
logger.warn(`Failed to load marketplace ${m.name}: ${error instanceof Error ? error.message : String(error)}`);
|
|
103
165
|
}
|
|
104
166
|
}
|
|
105
167
|
return {
|
|
@@ -107,6 +169,31 @@ export class PluginCore {
|
|
|
107
169
|
mergedEnabled,
|
|
108
170
|
};
|
|
109
171
|
}
|
|
172
|
+
/**
|
|
173
|
+
* Reads the version declared by a marketplace plugin's own manifest inside the
|
|
174
|
+
* marketplace checkout — the version a fresh install would get. Sources that
|
|
175
|
+
* live outside the checkout (Git URLs and both object shapes, which always point
|
|
176
|
+
* at an external repository) have no local copy until install, so they yield
|
|
177
|
+
* undefined (spec plugin A-010 / A-021).
|
|
178
|
+
*/
|
|
179
|
+
async readLatestVersion(marketplacePath, source) {
|
|
180
|
+
const parsed = parsePluginSource(source);
|
|
181
|
+
if (!parsed || parsed.kind !== "local")
|
|
182
|
+
return undefined;
|
|
183
|
+
const pluginPath = path.resolve(marketplacePath, parsed.path);
|
|
184
|
+
for (const dir of [".wave-plugin", ".claude-plugin"]) {
|
|
185
|
+
try {
|
|
186
|
+
const raw = await fs.readFile(path.join(pluginPath, dir, "plugin.json"), "utf-8");
|
|
187
|
+
const version = JSON.parse(raw).version;
|
|
188
|
+
if (version)
|
|
189
|
+
return version;
|
|
190
|
+
}
|
|
191
|
+
catch {
|
|
192
|
+
// Try the next manifest location
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
return undefined;
|
|
196
|
+
}
|
|
110
197
|
/**
|
|
111
198
|
* Adds a new marketplace
|
|
112
199
|
*/
|
|
@@ -120,10 +207,37 @@ export class PluginCore {
|
|
|
120
207
|
await this.marketplaceService.removeMarketplace(name, scope);
|
|
121
208
|
}
|
|
122
209
|
/**
|
|
123
|
-
* Updates a specific marketplace or all marketplaces
|
|
210
|
+
* Updates a specific marketplace or all marketplaces: refreshes the checkout
|
|
211
|
+
* from its upstream and reinstalls any plugins that are already installed from
|
|
212
|
+
* it (mirrors Claude Code's refresh-and-bump).
|
|
213
|
+
*
|
|
214
|
+
* 无界面可依赖的入口(非交互命令 `wave plugin marketplace update`)走这里;
|
|
215
|
+
* 交互界面的「批量更新插件」走 [updateMarketplacePlugins](不拉检出)。
|
|
216
|
+
*
|
|
217
|
+
* @returns 实际发生版本变化的插件数量(0 = 全部已是最新),供 GUI 宿主区分提示。
|
|
124
218
|
*/
|
|
125
219
|
async updateMarketplace(name) {
|
|
126
|
-
await this.marketplaceService.updateMarketplace(name
|
|
220
|
+
return await this.marketplaceService.updateMarketplace(name, {
|
|
221
|
+
updatePlugins: true,
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* 批量升级某市场内已安装的插件,且不拉取检出——交互界面的「批量更新插件」
|
|
226
|
+
* (GUI 三端按钮与 CLI 插件管理器的同名项)。清单的新鲜度由打开这些界面时的
|
|
227
|
+
* 后台刷新保证(spec 插件市场 A-013、场景 14)。
|
|
228
|
+
*
|
|
229
|
+
* @returns 实际发生版本变化的插件数量(0 = 该市场已是最新),供宿主区分提示。
|
|
230
|
+
*/
|
|
231
|
+
async updateMarketplacePlugins(name) {
|
|
232
|
+
return await this.marketplaceService.updateMarketplacePlugins(name);
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Refreshes the checkout of every registered marketplace, without touching
|
|
236
|
+
* installed plugins. Called by hosts when the user opens a plugin
|
|
237
|
+
* marketplace surface (spec 插件市场 A-013 场景 5/13).
|
|
238
|
+
*/
|
|
239
|
+
async refreshMarketplaces() {
|
|
240
|
+
await this.marketplaceService.refreshMarketplaces();
|
|
127
241
|
}
|
|
128
242
|
/**
|
|
129
243
|
* Lists all registered marketplaces
|
package/dist/core/session.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { listSessions, listAllSessions, truncateContent, loadSessionFromJsonl, loadFullMessageThread, deleteSession, } from "../services/session.js";
|
|
1
|
+
export { listSessions, listAllSessions, setSessionCustomTitle, truncateContent, loadSessionFromJsonl, loadFullMessageThread, deleteSession, } from "../services/session.js";
|
|
2
2
|
export type { SessionMetadata, SessionData } from "../services/session.js";
|
package/dist/core/session.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { listSessions, listAllSessions, truncateContent, loadSessionFromJsonl, loadFullMessageThread, deleteSession, } from "../services/session.js";
|
|
1
|
+
export { listSessions, listAllSessions, setSessionCustomTitle, truncateContent, loadSessionFromJsonl, loadFullMessageThread, deleteSession, } from "../services/session.js";
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Exec catalog: which MCP tools exist, how they are rendered, how that
|
|
3
|
+
* rendering is budgeted, and the shape of the sandbox's `search` entry point.
|
|
4
|
+
*
|
|
5
|
+
* "Rendered" means into the catalog announcement (`exec/catalogAnnouncement.ts`),
|
|
6
|
+
* not into `Exec`'s tool description: the description has to stay a
|
|
7
|
+
* pool-independent constant, or every server that connects rewrites the cached
|
|
8
|
+
* prefix. This module produces the entries; the announcement wraps them.
|
|
9
|
+
*
|
|
10
|
+
* This module is the single source of truth for "what the sandbox may reach".
|
|
11
|
+
* The hard constraint is that the pool must equal the tools the agent could
|
|
12
|
+
* already call directly — if a tool were reachable from the sandbox but hidden
|
|
13
|
+
* from the agent, Exec would be a permission-escalation channel.
|
|
14
|
+
*
|
|
15
|
+
* The same reasoning applies to `search`: its call form is written once, as a
|
|
16
|
+
* schema, and both the model-visible prose and the host-side validation derive
|
|
17
|
+
* from that one object. Teaching a form in prose while accepting a different one
|
|
18
|
+
* in code is a bug with no diff to review.
|
|
19
|
+
*/
|
|
20
|
+
import type { McpManager } from "../managers/mcpManager.js";
|
|
21
|
+
import type { PermissionManager } from "../managers/permissionManager.js";
|
|
22
|
+
export interface ExecPoolEntry {
|
|
23
|
+
/** Flattened `mcp__<server>__<tool>` name — the key on the sandbox `tools` object. */
|
|
24
|
+
name: string;
|
|
25
|
+
description?: string;
|
|
26
|
+
/** Raw MCP input schema (JSON Schema), used only to render a compact signature. */
|
|
27
|
+
inputSchema?: Record<string, unknown>;
|
|
28
|
+
/**
|
|
29
|
+
* The schema the server declared for this tool's output, rendered as the
|
|
30
|
+
* signature's return type. Absent for most servers today; a tool without one
|
|
31
|
+
* still gets a return type (`Promise<unknown>`), because leaving it out would
|
|
32
|
+
* read as "this call returns nothing".
|
|
33
|
+
*/
|
|
34
|
+
outputSchema?: Record<string, unknown>;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Every MCP tool the current agent may call, in catalog form.
|
|
38
|
+
*
|
|
39
|
+
* Derived from `getMcpToolsConfig()` — the exact source that produces the flat
|
|
40
|
+
* `tools[]` declarations when the pool is not collapsed, and the one whose
|
|
41
|
+
* connected/reconnecting filtering already keeps a transient disconnect from
|
|
42
|
+
* churning the tool list. So "the catalog equals what would have been declared"
|
|
43
|
+
* holds structurally, not by parallel construction.
|
|
44
|
+
*/
|
|
45
|
+
export declare function buildExecPool(mcpManager: McpManager, permissionManager?: PermissionManager): ExecPoolEntry[];
|
|
46
|
+
/**
|
|
47
|
+
* The callable signature for one tool: parameters and return type. The catalog and
|
|
48
|
+
* search results share it, so the model can copy either one verbatim.
|
|
49
|
+
*
|
|
50
|
+
* The return type comes from the schema the server declared for its output, and a
|
|
51
|
+
* tool that declared none still gets `Promise<unknown>` rather than no return type
|
|
52
|
+
* at all: the sandbox resolves every call to the tool's output (its structured
|
|
53
|
+
* content, else its text, else `null`), and a signature ending at the parameters
|
|
54
|
+
* would read as "calls this, get nothing". Rendering it from the same rule the
|
|
55
|
+
* runtime applies is what keeps the catalog from teaching a shape the host will
|
|
56
|
+
* not deliver.
|
|
57
|
+
*/
|
|
58
|
+
export declare function renderToolSignature(entry: ExecPoolEntry): string;
|
|
59
|
+
/**
|
|
60
|
+
* The callable signature of search, rendered by the very function that renders
|
|
61
|
+
* every catalog entry, so its shape cannot drift from what the host accepts or
|
|
62
|
+
* returns. Multi-line, for the sandbox API blurb where there is room to show the
|
|
63
|
+
* field docs.
|
|
64
|
+
*/
|
|
65
|
+
export declare function renderSearchSignature(): string;
|
|
66
|
+
/**
|
|
67
|
+
* The one-line call form of search: the path plus a placeholder per field, all
|
|
68
|
+
* derived from `SEARCH_INPUT_SCHEMA`. For prose that cannot afford the multi-line
|
|
69
|
+
* block — the catalog's `PARTIAL` notice and error messages, which must still name
|
|
70
|
+
* a shape the host accepts.
|
|
71
|
+
*/
|
|
72
|
+
export declare function renderSearchCallForm(): string;
|
|
73
|
+
/**
|
|
74
|
+
* Validate a search call's arguments against `SEARCH_INPUT_SCHEMA` and return the
|
|
75
|
+
* query to match on.
|
|
76
|
+
*
|
|
77
|
+
* The sandbox only guarantees a plain object (see `callHost`); it knows nothing
|
|
78
|
+
* about this schema, so a call naming a field the schema does not have must fail
|
|
79
|
+
* loudly here. Treating `{ q: "..." }` as an empty query would answer "here is the
|
|
80
|
+
* whole pool" and dress a typo up as a successful search.
|
|
81
|
+
*/
|
|
82
|
+
export declare function resolveSearchQuery(args: Record<string, unknown>): string;
|
|
83
|
+
/**
|
|
84
|
+
* A single catalog entry: its signature (possibly several lines) followed by the
|
|
85
|
+
* first line of its description.
|
|
86
|
+
*/
|
|
87
|
+
export declare function renderCatalogEntry(entry: ExecPoolEntry): string;
|
|
88
|
+
export interface RenderedCatalog {
|
|
89
|
+
text: string;
|
|
90
|
+
/** How many entries actually appear in `text`. */
|
|
91
|
+
shown: number;
|
|
92
|
+
total: number;
|
|
93
|
+
/** True when the budget forced entries out. Never silent. */
|
|
94
|
+
truncated: boolean;
|
|
95
|
+
/**
|
|
96
|
+
* Per-server tool counts, in pool order. The rendered entries cannot tell a later
|
|
97
|
+
* turn what moved — the announcement diff is count-level — so the snapshot is
|
|
98
|
+
* handed back here rather than recovered by parsing `text`.
|
|
99
|
+
*/
|
|
100
|
+
namespaces: Array<{
|
|
101
|
+
name: string;
|
|
102
|
+
count: number;
|
|
103
|
+
shown: number;
|
|
104
|
+
}>;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* The one-line index of a server: `- mcp__github (40 tools, 13 shown)`. The tail
|
|
108
|
+
* is dropped when the server is fully shown, and reads `none shown` when it got
|
|
109
|
+
* no seat at all.
|
|
110
|
+
*
|
|
111
|
+
* The prefix is the flattened name's, not the routing key alone, so the line is a
|
|
112
|
+
* substring of every tool name it covers (and of what search matches on). For a
|
|
113
|
+
* server whose name itself contains `__` the key is only the first segment — the
|
|
114
|
+
* same pre-existing ambiguity the grouping key has (see `execNamespace`).
|
|
115
|
+
*
|
|
116
|
+
* Exported for the announcement's per-namespace delta lines: the same renderer for
|
|
117
|
+
* the same counts, so a summary line and a delta line cannot drift apart.
|
|
118
|
+
*/
|
|
119
|
+
export declare function summarizeNamespace(name: string, count: number, shownCount: number): string;
|
|
120
|
+
/**
|
|
121
|
+
* Render the catalog within an estimated-token budget.
|
|
122
|
+
*
|
|
123
|
+
* Selection round-robins across servers: one entry per server per round, so
|
|
124
|
+
* every server gets a seat before any server gets its second. A plain first-N
|
|
125
|
+
* cut would drop whole servers that happen to be connected later, and the model
|
|
126
|
+
* reads a missing server as "those tools do not exist" — the failure mode this
|
|
127
|
+
* whole feature has to avoid.
|
|
128
|
+
*
|
|
129
|
+
* An entry is a whole multi-line block and is budgeted and placed atomically: a
|
|
130
|
+
* server either gets the block this round or sits the round out, never half a
|
|
131
|
+
* signature.
|
|
132
|
+
*
|
|
133
|
+
* A truncated catalog additionally prints one summary line per server (see
|
|
134
|
+
* `summarizeNamespace`), before that server's blocks and outside the budget.
|
|
135
|
+
*
|
|
136
|
+
* The truncation notice deliberately carries no budget number: the budget is a
|
|
137
|
+
* tuning knob, and rendering it would make an unchanged tool pool produce
|
|
138
|
+
* different model-visible text after a config change.
|
|
139
|
+
*/
|
|
140
|
+
export declare function renderCatalog(entries: ExecPoolEntry[], budgetTokens: number): RenderedCatalog;
|