wave-code 0.2.0 → 0.4.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.
Files changed (140) hide show
  1. package/dist/commands/plugin/disable.d.ts +2 -1
  2. package/dist/commands/plugin/disable.d.ts.map +1 -1
  3. package/dist/commands/plugin/disable.js +3 -2
  4. package/dist/commands/plugin/enable.d.ts +2 -1
  5. package/dist/commands/plugin/enable.d.ts.map +1 -1
  6. package/dist/commands/plugin/enable.js +3 -2
  7. package/dist/commands/plugin/install.d.ts +2 -1
  8. package/dist/commands/plugin/install.d.ts.map +1 -1
  9. package/dist/commands/plugin/list.d.ts.map +1 -1
  10. package/dist/commands/plugin/list.js +15 -3
  11. package/dist/commands/plugin/marketplace.d.ts +3 -0
  12. package/dist/commands/plugin/marketplace.d.ts.map +1 -1
  13. package/dist/commands/plugin/marketplace.js +15 -1
  14. package/dist/commands/plugin/uninstall.d.ts +4 -0
  15. package/dist/commands/plugin/uninstall.d.ts.map +1 -0
  16. package/dist/commands/plugin/uninstall.js +29 -0
  17. package/dist/commands/plugin/update.d.ts +4 -0
  18. package/dist/commands/plugin/update.d.ts.map +1 -0
  19. package/dist/commands/plugin/update.js +15 -0
  20. package/dist/components/ChatInterface.d.ts.map +1 -1
  21. package/dist/components/ChatInterface.js +2 -2
  22. package/dist/components/CommandSelector.d.ts.map +1 -1
  23. package/dist/components/CommandSelector.js +6 -0
  24. package/dist/components/Confirmation.js +1 -1
  25. package/dist/components/DiscoverView.d.ts +3 -0
  26. package/dist/components/DiscoverView.d.ts.map +1 -0
  27. package/dist/components/DiscoverView.js +25 -0
  28. package/dist/components/FileSelector.js +1 -1
  29. package/dist/components/HistorySearch.d.ts +8 -0
  30. package/dist/components/HistorySearch.d.ts.map +1 -0
  31. package/dist/components/HistorySearch.js +67 -0
  32. package/dist/components/InputBox.d.ts +1 -1
  33. package/dist/components/InputBox.d.ts.map +1 -1
  34. package/dist/components/InputBox.js +26 -17
  35. package/dist/components/InstalledView.d.ts +3 -0
  36. package/dist/components/InstalledView.d.ts.map +1 -0
  37. package/dist/components/InstalledView.js +30 -0
  38. package/dist/components/Markdown.d.ts.map +1 -1
  39. package/dist/components/Markdown.js +22 -9
  40. package/dist/components/MarketplaceAddForm.d.ts +3 -0
  41. package/dist/components/MarketplaceAddForm.d.ts.map +1 -0
  42. package/dist/components/MarketplaceAddForm.js +26 -0
  43. package/dist/components/MarketplaceDetail.d.ts +3 -0
  44. package/dist/components/MarketplaceDetail.d.ts.map +1 -0
  45. package/dist/components/MarketplaceDetail.js +38 -0
  46. package/dist/components/MarketplaceList.d.ts +9 -0
  47. package/dist/components/MarketplaceList.d.ts.map +1 -0
  48. package/dist/components/MarketplaceList.js +16 -0
  49. package/dist/components/MarketplaceView.d.ts +3 -0
  50. package/dist/components/MarketplaceView.d.ts.map +1 -0
  51. package/dist/components/MarketplaceView.js +28 -0
  52. package/dist/components/PluginDetail.d.ts +3 -0
  53. package/dist/components/PluginDetail.d.ts.map +1 -0
  54. package/dist/components/PluginDetail.js +63 -0
  55. package/dist/components/PluginList.d.ts +14 -0
  56. package/dist/components/PluginList.d.ts.map +1 -0
  57. package/dist/components/PluginList.js +12 -0
  58. package/dist/components/PluginManagerShell.d.ts +5 -0
  59. package/dist/components/PluginManagerShell.d.ts.map +1 -0
  60. package/dist/components/PluginManagerShell.js +89 -0
  61. package/dist/components/PluginManagerTypes.d.ts +33 -0
  62. package/dist/components/PluginManagerTypes.d.ts.map +1 -0
  63. package/dist/components/PluginManagerTypes.js +1 -0
  64. package/dist/components/RewindCommand.d.ts +9 -0
  65. package/dist/components/RewindCommand.d.ts.map +1 -0
  66. package/dist/components/RewindCommand.js +42 -0
  67. package/dist/components/SessionSelector.d.ts +11 -0
  68. package/dist/components/SessionSelector.d.ts.map +1 -0
  69. package/dist/components/SessionSelector.js +38 -0
  70. package/dist/components/SubagentBlock.d.ts.map +1 -1
  71. package/dist/components/SubagentBlock.js +20 -1
  72. package/dist/components/ToolResultDisplay.js +1 -1
  73. package/dist/contexts/PluginManagerContext.d.ts +4 -0
  74. package/dist/contexts/PluginManagerContext.d.ts.map +1 -0
  75. package/dist/contexts/PluginManagerContext.js +9 -0
  76. package/dist/contexts/useChat.d.ts +2 -0
  77. package/dist/contexts/useChat.d.ts.map +1 -1
  78. package/dist/contexts/useChat.js +21 -0
  79. package/dist/hooks/useInputManager.d.ts +6 -14
  80. package/dist/hooks/useInputManager.d.ts.map +1 -1
  81. package/dist/hooks/useInputManager.js +29 -45
  82. package/dist/hooks/usePluginManager.d.ts +3 -0
  83. package/dist/hooks/usePluginManager.d.ts.map +1 -0
  84. package/dist/hooks/usePluginManager.js +223 -0
  85. package/dist/index.d.ts.map +1 -1
  86. package/dist/index.js +150 -177
  87. package/dist/managers/InputManager.d.ts +12 -21
  88. package/dist/managers/InputManager.d.ts.map +1 -1
  89. package/dist/managers/InputManager.js +77 -108
  90. package/dist/plugin-manager-cli.d.ts +6 -0
  91. package/dist/plugin-manager-cli.d.ts.map +1 -0
  92. package/dist/plugin-manager-cli.js +12 -0
  93. package/dist/session-selector-cli.d.ts +2 -0
  94. package/dist/session-selector-cli.d.ts.map +1 -0
  95. package/dist/session-selector-cli.js +25 -0
  96. package/package.json +7 -3
  97. package/src/commands/plugin/disable.ts +7 -3
  98. package/src/commands/plugin/enable.ts +7 -3
  99. package/src/commands/plugin/install.ts +2 -1
  100. package/src/commands/plugin/list.ts +21 -3
  101. package/src/commands/plugin/marketplace.ts +17 -1
  102. package/src/commands/plugin/uninstall.ts +39 -0
  103. package/src/commands/plugin/update.ts +19 -0
  104. package/src/components/ChatInterface.tsx +2 -1
  105. package/src/components/CommandSelector.tsx +7 -0
  106. package/src/components/Confirmation.tsx +1 -1
  107. package/src/components/DiscoverView.tsx +31 -0
  108. package/src/components/FileSelector.tsx +1 -1
  109. package/src/components/HistorySearch.tsx +148 -0
  110. package/src/components/InputBox.tsx +43 -28
  111. package/src/components/InstalledView.tsx +61 -0
  112. package/src/components/Markdown.tsx +37 -26
  113. package/src/components/MarketplaceAddForm.tsx +39 -0
  114. package/src/components/MarketplaceDetail.tsx +79 -0
  115. package/src/components/MarketplaceList.tsx +52 -0
  116. package/src/components/MarketplaceView.tsx +43 -0
  117. package/src/components/PluginDetail.tsx +147 -0
  118. package/src/components/PluginList.tsx +51 -0
  119. package/src/components/PluginManagerShell.tsx +189 -0
  120. package/src/components/PluginManagerTypes.ts +47 -0
  121. package/src/components/RewindCommand.tsx +114 -0
  122. package/src/components/SessionSelector.tsx +127 -0
  123. package/src/components/SubagentBlock.tsx +29 -1
  124. package/src/components/ToolResultDisplay.tsx +2 -2
  125. package/src/contexts/PluginManagerContext.ts +15 -0
  126. package/src/contexts/useChat.tsx +26 -0
  127. package/src/hooks/useInputManager.ts +29 -61
  128. package/src/hooks/usePluginManager.ts +296 -0
  129. package/src/index.ts +241 -280
  130. package/src/managers/InputManager.ts +93 -149
  131. package/src/plugin-manager-cli.tsx +13 -0
  132. package/src/session-selector-cli.tsx +37 -0
  133. package/dist/components/BashHistorySelector.d.ts +0 -11
  134. package/dist/components/BashHistorySelector.d.ts.map +0 -1
  135. package/dist/components/BashHistorySelector.js +0 -93
  136. package/dist/hooks/usePagination.d.ts +0 -20
  137. package/dist/hooks/usePagination.d.ts.map +0 -1
  138. package/dist/hooks/usePagination.js +0 -168
  139. package/src/components/BashHistorySelector.tsx +0 -181
  140. package/src/hooks/usePagination.ts +0 -203
@@ -1,5 +1,6 @@
1
+ import { Scope } from "wave-agent-sdk";
1
2
  export declare function disablePluginCommand(argv: {
2
3
  plugin: string;
3
- scope: "user" | "project" | "local";
4
+ scope?: Scope;
4
5
  }): Promise<void>;
5
6
  //# sourceMappingURL=disable.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"disable.d.ts","sourceRoot":"","sources":["../../../src/commands/plugin/disable.ts"],"names":[],"mappings":"AAMA,wBAAsB,oBAAoB,CAAC,IAAI,EAAE;IAC/C,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC;CACrC,iBAqBA"}
1
+ {"version":3,"file":"disable.d.ts","sourceRoot":"","sources":["../../../src/commands/plugin/disable.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,EACN,MAAM,gBAAgB,CAAC;AAExB,wBAAsB,oBAAoB,CAAC,IAAI,EAAE;IAC/C,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,KAAK,CAAC;CACf,iBAwBA"}
@@ -8,9 +8,10 @@ export async function disablePluginCommand(argv) {
8
8
  configurationService,
9
9
  pluginManager,
10
10
  });
11
+ const scope = argv.scope || scopeManager.findPluginScope(argv.plugin) || "user";
11
12
  try {
12
- await scopeManager.disablePlugin(argv.scope, argv.plugin);
13
- console.log(`Successfully disabled plugin: ${argv.plugin} in ${argv.scope} scope`);
13
+ await scopeManager.disablePlugin(scope, argv.plugin);
14
+ console.log(`Successfully disabled plugin: ${argv.plugin} in ${scope} scope`);
14
15
  process.exit(0);
15
16
  }
16
17
  catch (error) {
@@ -1,5 +1,6 @@
1
+ import { Scope } from "wave-agent-sdk";
1
2
  export declare function enablePluginCommand(argv: {
2
3
  plugin: string;
3
- scope: "user" | "project" | "local";
4
+ scope?: Scope;
4
5
  }): Promise<void>;
5
6
  //# sourceMappingURL=enable.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"enable.d.ts","sourceRoot":"","sources":["../../../src/commands/plugin/enable.ts"],"names":[],"mappings":"AAMA,wBAAsB,mBAAmB,CAAC,IAAI,EAAE;IAC9C,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC;CACrC,iBAqBA"}
1
+ {"version":3,"file":"enable.d.ts","sourceRoot":"","sources":["../../../src/commands/plugin/enable.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,EACN,MAAM,gBAAgB,CAAC;AAExB,wBAAsB,mBAAmB,CAAC,IAAI,EAAE;IAC9C,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,KAAK,CAAC;CACf,iBAwBA"}
@@ -8,9 +8,10 @@ export async function enablePluginCommand(argv) {
8
8
  configurationService,
9
9
  pluginManager,
10
10
  });
11
+ const scope = argv.scope || scopeManager.findPluginScope(argv.plugin) || "user";
11
12
  try {
12
- await scopeManager.enablePlugin(argv.scope, argv.plugin);
13
- console.log(`Successfully enabled plugin: ${argv.plugin} in ${argv.scope} scope`);
13
+ await scopeManager.enablePlugin(scope, argv.plugin);
14
+ console.log(`Successfully enabled plugin: ${argv.plugin} in ${scope} scope`);
14
15
  process.exit(0);
15
16
  }
16
17
  catch (error) {
@@ -1,5 +1,6 @@
1
+ import { Scope } from "wave-agent-sdk";
1
2
  export declare function installPluginCommand(argv: {
2
3
  plugin: string;
3
- scope?: "user" | "project" | "local";
4
+ scope?: Scope;
4
5
  }): Promise<void>;
5
6
  //# sourceMappingURL=install.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../../src/commands/plugin/install.ts"],"names":[],"mappings":"AAOA,wBAAsB,oBAAoB,CAAC,IAAI,EAAE;IAC/C,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC;CACtC,iBA+BA"}
1
+ {"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../../src/commands/plugin/install.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,EACN,MAAM,gBAAgB,CAAC;AAExB,wBAAsB,oBAAoB,CAAC,IAAI,EAAE;IAC/C,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,KAAK,CAAC;CACf,iBA+BA"}
@@ -1 +1 @@
1
- {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../../src/commands/plugin/list.ts"],"names":[],"mappings":"AAEA,wBAAsB,kBAAkB,kBA6DvC"}
1
+ {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../../src/commands/plugin/list.ts"],"names":[],"mappings":"AAOA,wBAAsB,kBAAkB,kBA0EvC"}
@@ -1,8 +1,17 @@
1
- import { MarketplaceService, ConfigurationService } from "wave-agent-sdk";
1
+ import { MarketplaceService, ConfigurationService, PluginScopeManager, PluginManager, } from "wave-agent-sdk";
2
2
  export async function listPluginsCommand() {
3
- const marketplaceService = new MarketplaceService();
4
3
  const configurationService = new ConfigurationService();
4
+ const marketplaceService = new MarketplaceService();
5
5
  const workdir = process.cwd();
6
+ const pluginManager = new PluginManager({
7
+ workdir,
8
+ configurationService,
9
+ });
10
+ const pluginScopeManager = new PluginScopeManager({
11
+ workdir,
12
+ configurationService,
13
+ pluginManager,
14
+ });
6
15
  try {
7
16
  const installedPlugins = await marketplaceService.getInstalledPlugins();
8
17
  const marketplaces = await marketplaceService.listMarketplaces();
@@ -13,12 +22,14 @@ export async function listPluginsCommand() {
13
22
  try {
14
23
  const manifest = await marketplaceService.loadMarketplaceManifest(marketplaceService.getMarketplacePath(m));
15
24
  manifest.plugins.forEach((p) => {
25
+ const pluginId = `${p.name}@${m.name}`;
16
26
  const installed = installedPlugins.plugins.find((ip) => ip.name === p.name && ip.marketplace === m.name);
17
27
  allMarketplacePlugins.push({
18
28
  name: p.name,
19
29
  marketplace: m.name,
20
30
  installed: !!installed,
21
31
  version: installed?.version,
32
+ scope: pluginScopeManager.findPluginScope(pluginId) || undefined,
22
33
  });
23
34
  });
24
35
  }
@@ -40,7 +51,8 @@ export async function listPluginsCommand() {
40
51
  : "disabled"
41
52
  : "not installed";
42
53
  const versionStr = p.version ? ` v${p.version}` : "";
43
- console.log(`- ${pluginId}${versionStr} [${status}]`);
54
+ const scopeStr = p.scope ? ` (${p.scope})` : "";
55
+ console.log(`- ${pluginId}${versionStr}${scopeStr} [${status}]`);
44
56
  });
45
57
  }
46
58
  process.exit(0);
@@ -2,6 +2,9 @@ export declare function addMarketplaceCommand(argv: {
2
2
  input: string;
3
3
  }): Promise<void>;
4
4
  export declare function listMarketplacesCommand(): Promise<void>;
5
+ export declare function removeMarketplaceCommand(argv: {
6
+ name: string;
7
+ }): Promise<void>;
5
8
  export declare function updateMarketplaceCommand(argv: {
6
9
  name?: string;
7
10
  }): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"marketplace.d.ts","sourceRoot":"","sources":["../../../src/commands/plugin/marketplace.ts"],"names":[],"mappings":"AAEA,wBAAsB,qBAAqB,CAAC,IAAI,EAAE;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,iBAsBlE;AAED,wBAAsB,uBAAuB,kBA2B5C;AAED,wBAAsB,wBAAwB,CAAC,IAAI,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,iBAgBrE"}
1
+ {"version":3,"file":"marketplace.d.ts","sourceRoot":"","sources":["../../../src/commands/plugin/marketplace.ts"],"names":[],"mappings":"AAEA,wBAAsB,qBAAqB,CAAC,IAAI,EAAE;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,iBAsBlE;AAED,wBAAsB,uBAAuB,kBA8B5C;AAED,wBAAsB,wBAAwB,CAAC,IAAI,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,iBAWpE;AAED,wBAAsB,wBAAwB,CAAC,IAAI,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,iBAgBrE"}
@@ -44,7 +44,8 @@ export async function listMarketplacesCommand() {
44
44
  else {
45
45
  sourceInfo = source.url + (source.ref ? `#${source.ref}` : "");
46
46
  }
47
- console.log(`- ${m.name}: ${sourceInfo} (${m.source.source})`);
47
+ const builtinLabel = m.isBuiltin ? " [builtin]" : "";
48
+ console.log(`- ${m.name}${builtinLabel}: ${sourceInfo} (${m.source.source})`);
48
49
  });
49
50
  }
50
51
  process.exit(0);
@@ -55,6 +56,19 @@ export async function listMarketplacesCommand() {
55
56
  process.exit(1);
56
57
  }
57
58
  }
59
+ export async function removeMarketplaceCommand(argv) {
60
+ const service = new MarketplaceService();
61
+ try {
62
+ await service.removeMarketplace(argv.name);
63
+ console.log(`Successfully removed marketplace: ${argv.name}`);
64
+ process.exit(0);
65
+ }
66
+ catch (error) {
67
+ const message = error instanceof Error ? error.message : String(error);
68
+ console.error(`Failed to remove marketplace: ${message}`);
69
+ process.exit(1);
70
+ }
71
+ }
58
72
  export async function updateMarketplaceCommand(argv) {
59
73
  const service = new MarketplaceService();
60
74
  try {
@@ -0,0 +1,4 @@
1
+ export declare function uninstallPluginCommand(argv: {
2
+ plugin: string;
3
+ }): Promise<void>;
4
+ //# sourceMappingURL=uninstall.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uninstall.d.ts","sourceRoot":"","sources":["../../../src/commands/plugin/uninstall.ts"],"names":[],"mappings":"AAOA,wBAAsB,sBAAsB,CAAC,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,iBA+BpE"}
@@ -0,0 +1,29 @@
1
+ import { MarketplaceService, ConfigurationService, PluginManager, PluginScopeManager, } from "wave-agent-sdk";
2
+ export async function uninstallPluginCommand(argv) {
3
+ const marketplaceService = new MarketplaceService();
4
+ const workdir = process.cwd();
5
+ try {
6
+ await marketplaceService.uninstallPlugin(argv.plugin);
7
+ console.log(`Successfully uninstalled plugin: ${argv.plugin}`);
8
+ const configurationService = new ConfigurationService();
9
+ const pluginManager = new PluginManager({ workdir });
10
+ const scopeManager = new PluginScopeManager({
11
+ workdir,
12
+ configurationService,
13
+ pluginManager,
14
+ });
15
+ try {
16
+ await scopeManager.removePluginFromAllScopes(argv.plugin);
17
+ console.log(`Cleaned up plugin configuration from all scopes`);
18
+ }
19
+ catch (error) {
20
+ console.warn(`Warning: Could not clean up all plugin configurations: ${error instanceof Error ? error.message : String(error)}`);
21
+ }
22
+ process.exit(0);
23
+ }
24
+ catch (error) {
25
+ const message = error instanceof Error ? error.message : String(error);
26
+ console.error(`Failed to uninstall plugin: ${message}`);
27
+ process.exit(1);
28
+ }
29
+ }
@@ -0,0 +1,4 @@
1
+ export declare function updatePluginCommand(argv: {
2
+ plugin: string;
3
+ }): Promise<void>;
4
+ //# sourceMappingURL=update.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../../src/commands/plugin/update.ts"],"names":[],"mappings":"AAEA,wBAAsB,mBAAmB,CAAC,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,iBAgBjE"}
@@ -0,0 +1,15 @@
1
+ import { MarketplaceService } from "wave-agent-sdk";
2
+ export async function updatePluginCommand(argv) {
3
+ const marketplaceService = new MarketplaceService();
4
+ try {
5
+ const updated = await marketplaceService.updatePlugin(argv.plugin);
6
+ console.log(`Successfully updated plugin: ${updated.name} v${updated.version} from ${updated.marketplace}`);
7
+ console.log(`Cache path: ${updated.cachePath}`);
8
+ process.exit(0);
9
+ }
10
+ catch (error) {
11
+ const message = error instanceof Error ? error.message : String(error);
12
+ console.error(`Failed to update plugin: ${message}`);
13
+ process.exit(1);
14
+ }
15
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"ChatInterface.d.ts","sourceRoot":"","sources":["../../src/components/ChatInterface.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAO1B,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAoEjC,CAAC"}
1
+ {"version":3,"file":"ChatInterface.d.ts","sourceRoot":"","sources":["../../src/components/ChatInterface.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAO1B,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAqEjC,CAAC"}
@@ -5,8 +5,8 @@ import { InputBox } from "./InputBox.js";
5
5
  import { Confirmation } from "./Confirmation.js";
6
6
  import { useChat } from "../contexts/useChat.js";
7
7
  export const ChatInterface = () => {
8
- const { messages, isLoading, isCommandRunning, userInputHistory, isCompressing, sendMessage, abortMessage, saveMemory, mcpServers, connectMcpServer, disconnectMcpServer, isExpanded, sessionId, latestTotalTokens, slashCommands, hasSlashCommand, isConfirmationVisible, confirmingTool, handleConfirmationDecision, handleConfirmationCancel, } = useChat();
8
+ const { messages, isLoading, isCommandRunning, userInputHistory, isCompressing, sendMessage, abortMessage, saveMemory, mcpServers, connectMcpServer, disconnectMcpServer, isExpanded, sessionId, latestTotalTokens, slashCommands, hasSlashCommand, isConfirmationVisible, confirmingTool, handleConfirmationDecision, handleConfirmationCancel, rewindId, } = useChat();
9
9
  if (!sessionId)
10
10
  return null;
11
- return (_jsxs(Box, { flexDirection: "column", height: "100%", paddingY: 1, paddingRight: 1, children: [_jsx(MessageList, { messages: messages, isLoading: isLoading, isCommandRunning: isCommandRunning, isCompressing: isCompressing, latestTotalTokens: latestTotalTokens, isExpanded: isExpanded }, String(isExpanded) + sessionId), isConfirmationVisible && (_jsx(Confirmation, { toolName: confirmingTool.name, toolInput: confirmingTool.input, suggestedPrefix: confirmingTool.suggestedPrefix, hidePersistentOption: confirmingTool.hidePersistentOption, isExpanded: isExpanded, onDecision: handleConfirmationDecision, onCancel: handleConfirmationCancel, onAbort: abortMessage })), !isConfirmationVisible && !isExpanded && (_jsx(InputBox, { isLoading: isLoading, isCommandRunning: isCommandRunning, userInputHistory: userInputHistory, sendMessage: sendMessage, abortMessage: abortMessage, saveMemory: saveMemory, mcpServers: mcpServers, connectMcpServer: connectMcpServer, disconnectMcpServer: disconnectMcpServer, slashCommands: slashCommands, hasSlashCommand: hasSlashCommand }))] }));
11
+ return (_jsxs(Box, { flexDirection: "column", height: "100%", paddingY: 1, paddingRight: 1, children: [_jsx(MessageList, { messages: messages, isLoading: isLoading, isCommandRunning: isCommandRunning, isCompressing: isCompressing, latestTotalTokens: latestTotalTokens, isExpanded: isExpanded }, String(isExpanded) + sessionId + rewindId), isConfirmationVisible && (_jsx(Confirmation, { toolName: confirmingTool.name, toolInput: confirmingTool.input, suggestedPrefix: confirmingTool.suggestedPrefix, hidePersistentOption: confirmingTool.hidePersistentOption, isExpanded: isExpanded, onDecision: handleConfirmationDecision, onCancel: handleConfirmationCancel, onAbort: abortMessage })), !isConfirmationVisible && !isExpanded && (_jsx(InputBox, { isLoading: isLoading, isCommandRunning: isCommandRunning, userInputHistory: userInputHistory, sendMessage: sendMessage, abortMessage: abortMessage, saveMemory: saveMemory, mcpServers: mcpServers, connectMcpServer: connectMcpServer, disconnectMcpServer: disconnectMcpServer, slashCommands: slashCommands, hasSlashCommand: hasSlashCommand }))] }));
12
12
  };
@@ -1 +1 @@
1
- {"version":3,"file":"CommandSelector.d.ts","sourceRoot":"","sources":["../../src/components/CommandSelector.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAExC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAiBnD,MAAM,WAAW,oBAAoB;IACnC,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,QAAQ,CAAC,EAAE,YAAY,EAAE,CAAC;CAC3B;AAED,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CAwH1D,CAAC"}
1
+ {"version":3,"file":"CommandSelector.d.ts","sourceRoot":"","sources":["../../src/components/CommandSelector.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAExC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAwBnD,MAAM,WAAW,oBAAoB;IACnC,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,QAAQ,CAAC,EAAE,YAAY,EAAE,CAAC;CAC3B;AAED,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CAwH1D,CAAC"}
@@ -14,6 +14,12 @@ const AVAILABLE_COMMANDS = [
14
14
  description: "View and manage MCP servers",
15
15
  handler: () => { }, // Handler here won't be used, actual processing is in the hook
16
16
  },
17
+ {
18
+ id: "rewind",
19
+ name: "rewind",
20
+ description: "Revert conversation and file changes to a previous checkpoint",
21
+ handler: () => { }, // Handler here won't be used, actual processing is in the hook
22
+ },
17
23
  ];
18
24
  export const CommandSelector = ({ searchQuery, onSelect, onInsert, onCancel, commands = [], // Default to empty array
19
25
  }) => {
@@ -173,7 +173,7 @@ export const Confirmation = ({ toolName, toolInput, suggestedPrefix, hidePersist
173
173
  else if (state.selectedOption === "auto") {
174
174
  if (toolName === BASH_TOOL_NAME) {
175
175
  const rule = suggestedPrefix
176
- ? `Bash(${suggestedPrefix}:*)`
176
+ ? `Bash(${suggestedPrefix}*)`
177
177
  : `Bash(${toolInput?.command})`;
178
178
  onDecision({
179
179
  behavior: "allow",
@@ -0,0 +1,3 @@
1
+ import React from "react";
2
+ export declare const DiscoverView: React.FC;
3
+ //# sourceMappingURL=DiscoverView.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DiscoverView.d.ts","sourceRoot":"","sources":["../../src/components/DiscoverView.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAKxC,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAyBhC,CAAC"}
@@ -0,0 +1,25 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useState } from "react";
3
+ import { Box, useInput } from "ink";
4
+ import { usePluginManagerContext } from "../contexts/PluginManagerContext.js";
5
+ import { PluginList } from "./PluginList.js";
6
+ export const DiscoverView = () => {
7
+ const { discoverablePlugins, actions } = usePluginManagerContext();
8
+ const [selectedIndex, setSelectedIndex] = useState(0);
9
+ useInput((input, key) => {
10
+ if (key.upArrow) {
11
+ setSelectedIndex(Math.max(0, selectedIndex - 1));
12
+ }
13
+ else if (key.downArrow) {
14
+ setSelectedIndex(Math.min(discoverablePlugins.length - 1, selectedIndex + 1));
15
+ }
16
+ else if (key.return) {
17
+ const plugin = discoverablePlugins[selectedIndex];
18
+ if (plugin) {
19
+ actions.setSelectedId(`${plugin.name}@${plugin.marketplace}`);
20
+ actions.setView("PLUGIN_DETAIL");
21
+ }
22
+ }
23
+ });
24
+ return (_jsx(Box, { flexDirection: "column", children: _jsx(PluginList, { plugins: discoverablePlugins, selectedIndex: selectedIndex }) }));
25
+ };
@@ -44,5 +44,5 @@ export const FileSelector = ({ files, searchQuery, onSelect, onCancel, }) => {
44
44
  const isSelected = actualIndex === selectedIndex;
45
45
  const icon = fileItem.type === "directory" ? "📁" : "📄";
46
46
  return (_jsx(Box, { children: _jsxs(Text, { color: isSelected ? "black" : "white", backgroundColor: isSelected ? "cyan" : undefined, children: [" ", icon, " ", fileItem.path] }) }, fileItem.path));
47
- }), endIndex < files.length && (_jsxs(Text, { dimColor: true, children: ["... ", files.length - endIndex, " more files below"] })), _jsxs(Box, { marginTop: 1, children: [_jsx(Text, { dimColor: true, children: "Use \u2191\u2193 to navigate, Enter/Tab to select, Escape to cancel" }), _jsxs(Text, { dimColor: true, children: ["File ", selectedIndex + 1, " of ", files.length] })] })] }));
47
+ }), endIndex < files.length && (_jsxs(Text, { dimColor: true, children: ["... ", files.length - endIndex, " more files below"] })), _jsxs(Box, { marginTop: 1, children: [_jsx(Text, { dimColor: true, children: "Use \u2191\u2193 to navigate, Enter/Tab to select, Escape to cancel" }), _jsxs(Text, { dimColor: true, children: [", File ", selectedIndex + 1, " of ", files.length] })] })] }));
48
48
  };
@@ -0,0 +1,8 @@
1
+ import React from "react";
2
+ export interface HistorySearchProps {
3
+ searchQuery: string;
4
+ onSelect: (prompt: string) => void;
5
+ onCancel: () => void;
6
+ }
7
+ export declare const HistorySearch: React.FC<HistorySearchProps>;
8
+ //# sourceMappingURL=HistorySearch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HistorySearch.d.ts","sourceRoot":"","sources":["../../src/components/HistorySearch.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAInD,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,QAAQ,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CAyItD,CAAC"}
@@ -0,0 +1,67 @@
1
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
+ import React, { useState, useEffect } from "react";
3
+ import { Box, Text, useInput } from "ink";
4
+ import { PromptHistoryManager } from "wave-agent-sdk";
5
+ export const HistorySearch = ({ searchQuery, onSelect, onCancel, }) => {
6
+ const [selectedIndex, setSelectedIndex] = useState(0);
7
+ const [entries, setEntries] = useState([]);
8
+ const entriesRef = React.useRef([]);
9
+ const selectedIndexRef = React.useRef(0);
10
+ useEffect(() => {
11
+ entriesRef.current = entries;
12
+ }, [entries]);
13
+ useEffect(() => {
14
+ selectedIndexRef.current = selectedIndex;
15
+ }, [selectedIndex]);
16
+ useEffect(() => {
17
+ const fetchHistory = async () => {
18
+ const results = await PromptHistoryManager.searchHistory(searchQuery);
19
+ const limitedResults = results.slice(0, 10);
20
+ setEntries(limitedResults); // Limit to 10 results
21
+ setSelectedIndex(0);
22
+ };
23
+ fetchHistory();
24
+ }, [searchQuery]);
25
+ useInput((input, key) => {
26
+ if (key.return) {
27
+ if (entriesRef.current.length > 0 &&
28
+ selectedIndexRef.current < entriesRef.current.length) {
29
+ onSelect(entriesRef.current[selectedIndexRef.current].prompt);
30
+ }
31
+ return;
32
+ }
33
+ if (key.escape) {
34
+ onCancel();
35
+ return;
36
+ }
37
+ if (key.upArrow) {
38
+ setSelectedIndex((prev) => Math.max(0, prev - 1));
39
+ return;
40
+ }
41
+ if (key.downArrow) {
42
+ setSelectedIndex((prev) => Math.min(entriesRef.current.length - 1, prev + 1));
43
+ return;
44
+ }
45
+ });
46
+ if (entries.length === 0) {
47
+ return (_jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: "yellow", borderBottom: false, borderLeft: false, borderRight: false, paddingTop: 1, children: [_jsxs(Text, { color: "yellow", children: ["No history found ", searchQuery && `for "${searchQuery}"`] }), _jsx(Text, { dimColor: true, children: "Press Escape to cancel" })] }));
48
+ }
49
+ const formatTimestamp = (timestamp) => {
50
+ const date = new Date(timestamp);
51
+ const now = new Date();
52
+ const diffMs = now.getTime() - date.getTime();
53
+ const diffHours = Math.floor(diffMs / (1000 * 60 * 60));
54
+ const diffDays = Math.floor(diffHours / 24);
55
+ if (diffDays > 0) {
56
+ return `${diffDays}d ago`;
57
+ }
58
+ else if (diffHours > 0) {
59
+ return `${diffHours}h ago`;
60
+ }
61
+ else {
62
+ const diffMinutes = Math.floor(diffMs / (1000 * 60));
63
+ return diffMinutes > 0 ? `${diffMinutes}m ago` : "just now";
64
+ }
65
+ };
66
+ return (_jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: "blue", borderBottom: false, borderLeft: false, borderRight: false, paddingTop: 1, gap: 1, children: [_jsx(Box, { children: _jsxs(Text, { color: "blue", bold: true, children: ["Prompt History ", searchQuery && `(filtering: "${searchQuery}")`] }) }), entries.map((entry, index) => (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: index === selectedIndex ? "black" : "white", backgroundColor: index === selectedIndex ? "blue" : undefined, wrap: "truncate-end", children: entry.prompt.replace(/\n/g, " ") }), index === selectedIndex && (_jsx(Box, { marginLeft: 4, children: _jsx(Text, { color: "gray", dimColor: true, children: formatTimestamp(entry.timestamp) }) }))] }, index))), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: "Use \u2191\u2193 to navigate, Enter to select, Escape to cancel" }) })] }));
67
+ };
@@ -1,6 +1,6 @@
1
1
  import React from "react";
2
2
  import type { McpServerStatus, SlashCommand } from "wave-agent-sdk";
3
- export declare const INPUT_PLACEHOLDER_TEXT = "Type your message (use @ to reference files, / for commands, ! for bash history, # to add memory)...";
3
+ export declare const INPUT_PLACEHOLDER_TEXT = "Type your message (use @ to reference files, / for commands, # to add memory, Ctrl+R to search history)...";
4
4
  export declare const INPUT_PLACEHOLDER_TEXT_PREFIX: string;
5
5
  export interface InputBoxProps {
6
6
  isLoading?: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"InputBox.d.ts","sourceRoot":"","sources":["../../src/components/InputBox.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA6B,MAAM,OAAO,CAAC;AAYlD,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEpE,eAAO,MAAM,sBAAsB,yGACqE,CAAC;AAEzG,eAAO,MAAM,6BAA6B,QAGzC,CAAC;AAEF,MAAM,WAAW,aAAa;IAC5B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,WAAW,CAAC,EAAE,CACZ,OAAO,EAAE,MAAM,EACf,MAAM,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,KAC/C,IAAI,CAAC;IACV,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAE1E,UAAU,CAAC,EAAE,eAAe,EAAE,CAAC;IAC/B,gBAAgB,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC5D,mBAAmB,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAE/D,aAAa,CAAC,EAAE,YAAY,EAAE,CAAC;IAC/B,eAAe,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC;CAClD;AAED,eAAO,MAAM,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,aAAa,CAiN5C,CAAC"}
1
+ {"version":3,"file":"InputBox.d.ts","sourceRoot":"","sources":["../../src/components/InputBox.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAoB,MAAM,OAAO,CAAC;AAazC,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEpE,eAAO,MAAM,sBAAsB,+GAC2E,CAAC;AAE/G,eAAO,MAAM,6BAA6B,QAGzC,CAAC;AAEF,MAAM,WAAW,aAAa;IAC5B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,WAAW,CAAC,EAAE,CACZ,OAAO,EAAE,MAAM,EACf,MAAM,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,KAC/C,IAAI,CAAC;IACV,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAE1E,UAAU,CAAC,EAAE,eAAe,EAAE,CAAC;IAC/B,gBAAgB,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC5D,mBAAmB,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAE/D,aAAa,CAAC,EAAE,YAAY,EAAE,CAAC;IAC/B,eAAe,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC;CAClD;AAED,eAAO,MAAM,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,aAAa,CA+N5C,CAAC"}
@@ -1,21 +1,20 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useEffect, useMemo } from "react";
2
+ import { useEffect } from "react";
3
3
  import { Box, Text } from "ink";
4
4
  import { useInput } from "ink";
5
5
  import { FileSelector } from "./FileSelector.js";
6
6
  import { CommandSelector } from "./CommandSelector.js";
7
- import { BashHistorySelector } from "./BashHistorySelector.js";
7
+ import { HistorySearch } from "./HistorySearch.js";
8
8
  import { MemoryTypeSelector } from "./MemoryTypeSelector.js";
9
9
  import { BashShellManager } from "./BashShellManager.js";
10
10
  import { McpManager } from "./McpManager.js";
11
+ import { RewindCommand } from "./RewindCommand.js";
11
12
  import { useInputManager } from "../hooks/useInputManager.js";
12
13
  import { useChat } from "../contexts/useChat.js";
13
- export const INPUT_PLACEHOLDER_TEXT = "Type your message (use @ to reference files, / for commands, ! for bash history, # to add memory)...";
14
+ export const INPUT_PLACEHOLDER_TEXT = "Type your message (use @ to reference files, / for commands, # to add memory, Ctrl+R to search history)...";
14
15
  export const INPUT_PLACEHOLDER_TEXT_PREFIX = INPUT_PLACEHOLDER_TEXT.substring(0, 10);
15
- export const InputBox = ({ isLoading = false, isCommandRunning = false, workdir, userInputHistory = [], sendMessage = () => { }, abortMessage = () => { }, saveMemory = async () => { }, mcpServers = [], connectMcpServer = async () => false, disconnectMcpServer = async () => false, slashCommands = [], hasSlashCommand = () => false, }) => {
16
- // Get current working directory - memoized to avoid repeated process.cwd() calls
17
- const currentWorkdir = useMemo(() => workdir || process.cwd(), [workdir]);
18
- const { permissionMode: chatPermissionMode, setPermissionMode: setChatPermissionMode, } = useChat();
16
+ export const InputBox = ({ isLoading = false, isCommandRunning = false, userInputHistory = [], sendMessage = () => { }, abortMessage = () => { }, saveMemory = async () => { }, mcpServers = [], connectMcpServer = async () => false, disconnectMcpServer = async () => false, slashCommands = [], hasSlashCommand = () => false, }) => {
17
+ const { permissionMode: chatPermissionMode, setPermissionMode: setChatPermissionMode, handleRewindSelect, messages, } = useChat();
19
18
  // Input manager with all input state and functionality (including images)
20
19
  const { inputText, cursorPosition,
21
20
  // Image management
@@ -23,19 +22,17 @@ export const InputBox = ({ isLoading = false, isCommandRunning = false, workdir,
23
22
  // File selector
24
23
  showFileSelector, filteredFiles, fileSearchQuery: searchQuery, handleFileSelect, handleCancelFileSelect,
25
24
  // Command selector
26
- showCommandSelector, commandSearchQuery, handleCommandSelect, handleCommandInsert, handleCancelCommandSelect,
27
- // Bash history selector
28
- showBashHistorySelector, bashHistorySearchQuery, handleBashHistorySelect, handleCancelBashHistorySelect,
25
+ showCommandSelector, commandSearchQuery, handleCommandSelect, handleCommandInsert, handleCancelCommandSelect, handleHistorySearchSelect, handleCancelHistorySearch,
29
26
  // Memory type selector
30
27
  showMemoryTypeSelector, memoryMessage, handleMemoryTypeSelect, handleCancelMemoryTypeSelect,
28
+ // History search
29
+ showHistorySearch, historySearchQuery,
31
30
  // Bash/MCP Manager
32
- showBashManager, showMcpManager, setShowBashManager, setShowMcpManager,
31
+ showBashManager, showMcpManager, showRewindManager, setShowBashManager, setShowMcpManager, setShowRewindManager,
33
32
  // Permission mode
34
33
  permissionMode, setPermissionMode,
35
34
  // Input history
36
35
  setUserInputHistory,
37
- // Complex handlers combining multiple operations
38
- handleBashHistoryExecuteAndSend, handleBashHistoryDelete,
39
36
  // Main handler
40
37
  handleInput,
41
38
  // Manager ready state
@@ -58,8 +55,11 @@ export const InputBox = ({ isLoading = false, isCommandRunning = false, workdir,
58
55
  useInput(async (input, key) => {
59
56
  await handleInput(input, key, attachedImages, isLoading, isCommandRunning, clearImages);
60
57
  });
61
- // These methods are already memoized in useInputManager, no need to wrap again
62
- // These methods are already memoized in useInputManager and combine multiple operations
58
+ const handleRewindCancel = () => {
59
+ if (setShowRewindManager) {
60
+ setShowRewindManager(false);
61
+ }
62
+ };
63
63
  const isPlaceholder = !inputText;
64
64
  const placeholderText = INPUT_PLACEHOLDER_TEXT;
65
65
  // handleCommandSelectorInsert is already memoized in useInputManager, no need to wrap again
@@ -68,11 +68,20 @@ export const InputBox = ({ isLoading = false, isCommandRunning = false, workdir,
68
68
  const beforeCursor = displayText.substring(0, cursorPosition);
69
69
  const atCursor = cursorPosition < displayText.length ? displayText[cursorPosition] : " ";
70
70
  const afterCursor = displayText.substring(cursorPosition + 1);
71
- // Always show cursor, allow user to continue input during loading
71
+ // Always show cursor, allow user to continue input during memory mode
72
72
  const shouldShowCursor = true;
73
73
  // Only show the Box after InputManager is created on first mount
74
74
  if (!isManagerReady) {
75
75
  return null;
76
76
  }
77
- return (_jsxs(Box, { flexDirection: "column", children: [showFileSelector && (_jsx(FileSelector, { files: filteredFiles, searchQuery: searchQuery, onSelect: handleFileSelect, onCancel: handleCancelFileSelect })), showCommandSelector && (_jsx(CommandSelector, { searchQuery: commandSearchQuery, onSelect: handleCommandSelect, onInsert: handleCommandInsert, onCancel: handleCancelCommandSelect, commands: slashCommands })), showBashHistorySelector && (_jsx(BashHistorySelector, { searchQuery: bashHistorySearchQuery, workdir: currentWorkdir, onSelect: handleBashHistorySelect, onExecute: handleBashHistoryExecuteAndSend, onDelete: handleBashHistoryDelete, onCancel: handleCancelBashHistorySelect })), showMemoryTypeSelector && (_jsx(MemoryTypeSelector, { message: memoryMessage, onSelect: handleMemoryTypeSelect, onCancel: handleCancelMemoryTypeSelect })), showBashManager && (_jsx(BashShellManager, { onCancel: () => setShowBashManager(false) })), showMcpManager && (_jsx(McpManager, { onCancel: () => setShowMcpManager(false), servers: mcpServers, onConnectServer: connectMcpServer, onDisconnectServer: disconnectMcpServer })), showBashManager || showMcpManager || (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { borderStyle: "single", borderColor: "gray", borderLeft: false, borderRight: false, children: _jsx(Text, { color: isPlaceholder ? "gray" : "white", children: shouldShowCursor ? (_jsxs(_Fragment, { children: [beforeCursor, _jsx(Text, { backgroundColor: "white", color: "black", children: atCursor }), afterCursor] })) : (displayText) }) }), _jsx(Box, { paddingRight: 1, children: _jsxs(Text, { color: "gray", children: ["Mode:", " ", _jsx(Text, { color: permissionMode === "plan" ? "yellow" : "cyan", children: permissionMode }), " ", "(Shift+Tab to cycle)"] }) })] }))] }));
77
+ const handleRewindSelectWithClose = async (index) => {
78
+ if (setShowRewindManager) {
79
+ setShowRewindManager(false);
80
+ }
81
+ await handleRewindSelect(index);
82
+ };
83
+ if (showRewindManager) {
84
+ return (_jsx(RewindCommand, { messages: messages, onSelect: handleRewindSelectWithClose, onCancel: handleRewindCancel }));
85
+ }
86
+ return (_jsxs(Box, { flexDirection: "column", children: [showFileSelector && (_jsx(FileSelector, { files: filteredFiles, searchQuery: searchQuery, onSelect: handleFileSelect, onCancel: handleCancelFileSelect })), showCommandSelector && (_jsx(CommandSelector, { searchQuery: commandSearchQuery, onSelect: handleCommandSelect, onInsert: handleCommandInsert, onCancel: handleCancelCommandSelect, commands: slashCommands })), showHistorySearch && (_jsx(HistorySearch, { searchQuery: historySearchQuery, onSelect: handleHistorySearchSelect, onCancel: handleCancelHistorySearch })), showMemoryTypeSelector && (_jsx(MemoryTypeSelector, { message: memoryMessage, onSelect: handleMemoryTypeSelect, onCancel: handleCancelMemoryTypeSelect })), showBashManager && (_jsx(BashShellManager, { onCancel: () => setShowBashManager(false) })), showMcpManager && (_jsx(McpManager, { onCancel: () => setShowMcpManager(false), servers: mcpServers, onConnectServer: connectMcpServer, onDisconnectServer: disconnectMcpServer })), showBashManager || showMcpManager || showRewindManager || (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { borderStyle: "single", borderColor: "gray", borderLeft: false, borderRight: false, children: _jsx(Text, { color: isPlaceholder ? "gray" : "white", children: shouldShowCursor ? (_jsxs(_Fragment, { children: [beforeCursor, _jsx(Text, { backgroundColor: "white", color: "black", children: atCursor }), afterCursor] })) : (displayText) }) }), _jsx(Box, { paddingRight: 1, children: _jsxs(Text, { color: "gray", children: ["Mode:", " ", _jsx(Text, { color: permissionMode === "plan" ? "yellow" : "cyan", children: permissionMode }), " ", "(Shift+Tab to cycle)"] }) })] }))] }));
78
87
  };
@@ -0,0 +1,3 @@
1
+ import React from "react";
2
+ export declare const InstalledView: React.FC;
3
+ //# sourceMappingURL=InstalledView.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InstalledView.d.ts","sourceRoot":"","sources":["../../src/components/InstalledView.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAIxC,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAwDjC,CAAC"}
@@ -0,0 +1,30 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState } from "react";
3
+ import { Box, Text, useInput } from "ink";
4
+ import { usePluginManagerContext } from "../contexts/PluginManagerContext.js";
5
+ export const InstalledView = () => {
6
+ const { installedPlugins, actions } = usePluginManagerContext();
7
+ const [selectedIndex, setSelectedIndex] = useState(0);
8
+ useInput((input, key) => {
9
+ if (key.upArrow) {
10
+ setSelectedIndex(Math.max(0, selectedIndex - 1));
11
+ }
12
+ else if (key.downArrow) {
13
+ setSelectedIndex(Math.min(installedPlugins.length - 1, selectedIndex + 1));
14
+ }
15
+ else if (key.return) {
16
+ const plugin = installedPlugins[selectedIndex];
17
+ if (plugin) {
18
+ actions.setSelectedId(`${plugin.name}@${plugin.marketplace}`);
19
+ actions.setView("PLUGIN_DETAIL");
20
+ }
21
+ }
22
+ });
23
+ if (installedPlugins.length === 0) {
24
+ return (_jsx(Box, { padding: 1, children: _jsx(Text, { dimColor: true, children: "No plugins installed." }) }));
25
+ }
26
+ return (_jsx(Box, { flexDirection: "column", children: installedPlugins.map((plugin, index) => {
27
+ const isSelected = index === selectedIndex;
28
+ return (_jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [_jsx(Box, { children: _jsxs(Text, { color: isSelected ? "cyan" : undefined, children: [isSelected ? "> " : " ", _jsx(Text, { bold: true, children: plugin.name }), _jsxs(Text, { dimColor: true, children: [" @", plugin.marketplace] }), plugin.scope && _jsxs(Text, { color: "gray", children: [" (", plugin.scope, ")"] })] }) }), isSelected && (_jsx(Box, { marginLeft: 4, children: _jsx(Text, { dimColor: true, children: "Press Enter for actions" }) }))] }, `${plugin.name}@${plugin.marketplace}`));
29
+ }) }));
30
+ };
@@ -1 +1 @@
1
- {"version":3,"file":"Markdown.d.ts","sourceRoot":"","sources":["../../src/components/Markdown.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAkB,MAAM,OAAO,CAAC;AAIvC,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAoUD,eAAO,MAAM,QAAQ,2CAA6B,aAAa,6CAQ7D,CAAC"}
1
+ {"version":3,"file":"Markdown.d.ts","sourceRoot":"","sources":["../../src/components/Markdown.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAkB,MAAM,OAAO,CAAC;AAKvC,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;CAClB;AA8UD,eAAO,MAAM,QAAQ,2CAA6B,aAAa,6CAQ7D,CAAC"}