@zhijiewang/openharness 0.5.1 → 0.6.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 (185) hide show
  1. package/dist/commands/cybergotchi.d.ts.map +1 -1
  2. package/dist/commands/cybergotchi.js +22 -19
  3. package/dist/commands/cybergotchi.js.map +1 -1
  4. package/dist/components/App.d.ts +1 -1
  5. package/dist/components/App.d.ts.map +1 -1
  6. package/dist/components/App.js +58 -2
  7. package/dist/components/App.js.map +1 -1
  8. package/dist/components/CompanionFooter.d.ts +9 -0
  9. package/dist/components/CompanionFooter.d.ts.map +1 -0
  10. package/dist/components/CompanionFooter.js +13 -0
  11. package/dist/components/CompanionFooter.js.map +1 -0
  12. package/dist/components/CybergotchiBubble.d.ts +2 -1
  13. package/dist/components/CybergotchiBubble.d.ts.map +1 -1
  14. package/dist/components/CybergotchiBubble.js +4 -5
  15. package/dist/components/CybergotchiBubble.js.map +1 -1
  16. package/dist/components/CybergotchiPanel.d.ts +5 -4
  17. package/dist/components/CybergotchiPanel.d.ts.map +1 -1
  18. package/dist/components/CybergotchiPanel.js +4 -2
  19. package/dist/components/CybergotchiPanel.js.map +1 -1
  20. package/dist/components/CybergotchiPanelConnected.js +4 -4
  21. package/dist/components/CybergotchiPanelConnected.js.map +1 -1
  22. package/dist/components/CybergotchiSetup.d.ts.map +1 -1
  23. package/dist/components/CybergotchiSetup.js +25 -61
  24. package/dist/components/CybergotchiSetup.js.map +1 -1
  25. package/dist/components/CybergotchiSprite.d.ts +5 -4
  26. package/dist/components/CybergotchiSprite.d.ts.map +1 -1
  27. package/dist/components/CybergotchiSprite.js +16 -9
  28. package/dist/components/CybergotchiSprite.js.map +1 -1
  29. package/dist/components/DiffView.d.ts +27 -0
  30. package/dist/components/DiffView.d.ts.map +1 -0
  31. package/dist/components/DiffView.js +74 -0
  32. package/dist/components/DiffView.js.map +1 -0
  33. package/dist/components/Messages.js +1 -1
  34. package/dist/components/Messages.js.map +1 -1
  35. package/dist/components/PermissionPrompt.d.ts.map +1 -1
  36. package/dist/components/PermissionPrompt.js +61 -8
  37. package/dist/components/PermissionPrompt.js.map +1 -1
  38. package/dist/components/REPL.d.ts.map +1 -1
  39. package/dist/components/REPL.js +75 -21
  40. package/dist/components/REPL.js.map +1 -1
  41. package/dist/components/TextInput.d.ts +2 -1
  42. package/dist/components/TextInput.d.ts.map +1 -1
  43. package/dist/components/TextInput.js +110 -6
  44. package/dist/components/TextInput.js.map +1 -1
  45. package/dist/cybergotchi/bones.d.ts +12 -0
  46. package/dist/cybergotchi/bones.d.ts.map +1 -0
  47. package/dist/cybergotchi/bones.js +89 -0
  48. package/dist/cybergotchi/bones.js.map +1 -0
  49. package/dist/cybergotchi/config.d.ts +14 -4
  50. package/dist/cybergotchi/config.d.ts.map +1 -1
  51. package/dist/cybergotchi/config.js +62 -9
  52. package/dist/cybergotchi/config.js.map +1 -1
  53. package/dist/cybergotchi/needs.d.ts +4 -4
  54. package/dist/cybergotchi/needs.d.ts.map +1 -1
  55. package/dist/cybergotchi/needs.js.map +1 -1
  56. package/dist/cybergotchi/personality.d.ts +11 -0
  57. package/dist/cybergotchi/personality.d.ts.map +1 -0
  58. package/dist/cybergotchi/personality.js +26 -0
  59. package/dist/cybergotchi/personality.js.map +1 -0
  60. package/dist/cybergotchi/species.d.ts +0 -1
  61. package/dist/cybergotchi/species.d.ts.map +1 -1
  62. package/dist/cybergotchi/species.js +253 -229
  63. package/dist/cybergotchi/species.js.map +1 -1
  64. package/dist/cybergotchi/types.d.ts +45 -7
  65. package/dist/cybergotchi/types.d.ts.map +1 -1
  66. package/dist/cybergotchi/types.js +36 -5
  67. package/dist/cybergotchi/types.js.map +1 -1
  68. package/dist/cybergotchi/useCybergotchi.d.ts +7 -5
  69. package/dist/cybergotchi/useCybergotchi.d.ts.map +1 -1
  70. package/dist/cybergotchi/useCybergotchi.js +27 -16
  71. package/dist/cybergotchi/useCybergotchi.js.map +1 -1
  72. package/dist/git/index.d.ts +9 -0
  73. package/dist/git/index.d.ts.map +1 -1
  74. package/dist/git/index.js +31 -0
  75. package/dist/git/index.js.map +1 -1
  76. package/dist/harness/config.d.ts +5 -0
  77. package/dist/harness/config.d.ts.map +1 -1
  78. package/dist/harness/config.js.map +1 -1
  79. package/dist/harness/credentials.d.ts +24 -0
  80. package/dist/harness/credentials.d.ts.map +1 -0
  81. package/dist/harness/credentials.js +104 -0
  82. package/dist/harness/credentials.js.map +1 -0
  83. package/dist/harness/hooks.d.ts +8 -0
  84. package/dist/harness/hooks.d.ts.map +1 -1
  85. package/dist/harness/hooks.js +98 -22
  86. package/dist/harness/hooks.js.map +1 -1
  87. package/dist/harness/keybindings.d.ts +37 -0
  88. package/dist/harness/keybindings.d.ts.map +1 -0
  89. package/dist/harness/keybindings.js +134 -0
  90. package/dist/harness/keybindings.js.map +1 -0
  91. package/dist/harness/memory.d.ts +35 -0
  92. package/dist/harness/memory.d.ts.map +1 -0
  93. package/dist/harness/memory.js +115 -0
  94. package/dist/harness/memory.js.map +1 -0
  95. package/dist/harness/plugins.d.ts +57 -0
  96. package/dist/harness/plugins.d.ts.map +1 -0
  97. package/dist/harness/plugins.js +142 -0
  98. package/dist/harness/plugins.js.map +1 -0
  99. package/dist/harness/session.d.ts +5 -0
  100. package/dist/harness/session.d.ts.map +1 -1
  101. package/dist/harness/session.js +39 -1
  102. package/dist/harness/session.js.map +1 -1
  103. package/dist/lsp/client.d.ts +58 -0
  104. package/dist/lsp/client.d.ts.map +1 -0
  105. package/dist/lsp/client.js +174 -0
  106. package/dist/lsp/client.js.map +1 -0
  107. package/dist/main.js +160 -0
  108. package/dist/main.js.map +1 -1
  109. package/dist/mcp/DeferredMcpTool.d.ts +30 -0
  110. package/dist/mcp/DeferredMcpTool.d.ts.map +1 -0
  111. package/dist/mcp/DeferredMcpTool.js +75 -0
  112. package/dist/mcp/DeferredMcpTool.js.map +1 -0
  113. package/dist/mcp/client.d.ts +7 -0
  114. package/dist/mcp/client.d.ts.map +1 -1
  115. package/dist/mcp/client.js +56 -8
  116. package/dist/mcp/client.js.map +1 -1
  117. package/dist/mcp/loader.d.ts +9 -0
  118. package/dist/mcp/loader.d.ts.map +1 -1
  119. package/dist/mcp/loader.js +43 -2
  120. package/dist/mcp/loader.js.map +1 -1
  121. package/dist/mcp/schema.d.ts +7 -0
  122. package/dist/mcp/schema.d.ts.map +1 -0
  123. package/dist/mcp/schema.js +41 -0
  124. package/dist/mcp/schema.js.map +1 -0
  125. package/dist/mcp/server.d.ts +16 -0
  126. package/dist/mcp/server.d.ts.map +1 -0
  127. package/dist/mcp/server.js +94 -0
  128. package/dist/mcp/server.js.map +1 -0
  129. package/dist/providers/anthropic.d.ts +1 -1
  130. package/dist/providers/anthropic.d.ts.map +1 -1
  131. package/dist/providers/anthropic.js.map +1 -1
  132. package/dist/providers/base.d.ts +15 -0
  133. package/dist/providers/base.d.ts.map +1 -1
  134. package/dist/providers/base.js +13 -1
  135. package/dist/providers/base.js.map +1 -1
  136. package/dist/providers/openai.d.ts +1 -1
  137. package/dist/providers/openai.d.ts.map +1 -1
  138. package/dist/providers/openai.js.map +1 -1
  139. package/dist/query.d.ts.map +1 -1
  140. package/dist/query.js +91 -14
  141. package/dist/query.js.map +1 -1
  142. package/dist/remote/server.d.ts +31 -0
  143. package/dist/remote/server.d.ts.map +1 -0
  144. package/dist/remote/server.js +163 -0
  145. package/dist/remote/server.js.map +1 -0
  146. package/dist/services/AgentDispatcher.d.ts +42 -0
  147. package/dist/services/AgentDispatcher.d.ts.map +1 -0
  148. package/dist/services/AgentDispatcher.js +181 -0
  149. package/dist/services/AgentDispatcher.js.map +1 -0
  150. package/dist/services/StreamingToolExecutor.d.ts +2 -1
  151. package/dist/services/StreamingToolExecutor.d.ts.map +1 -1
  152. package/dist/services/StreamingToolExecutor.js +11 -2
  153. package/dist/services/StreamingToolExecutor.js.map +1 -1
  154. package/dist/tools/AgentTool/index.d.ts +3 -0
  155. package/dist/tools/AgentTool/index.d.ts.map +1 -1
  156. package/dist/tools/AgentTool/index.js +54 -16
  157. package/dist/tools/AgentTool/index.js.map +1 -1
  158. package/dist/tools/DiagnosticsTool/index.d.ts +21 -0
  159. package/dist/tools/DiagnosticsTool/index.d.ts.map +1 -0
  160. package/dist/tools/DiagnosticsTool/index.js +108 -0
  161. package/dist/tools/DiagnosticsTool/index.js.map +1 -0
  162. package/dist/tools/GrepTool/index.d.ts +2 -2
  163. package/dist/tools/ParallelAgentTool/index.d.ts +37 -0
  164. package/dist/tools/ParallelAgentTool/index.d.ts.map +1 -0
  165. package/dist/tools/ParallelAgentTool/index.js +53 -0
  166. package/dist/tools/ParallelAgentTool/index.js.map +1 -0
  167. package/dist/tools/SkillTool/index.d.ts.map +1 -1
  168. package/dist/tools/SkillTool/index.js +22 -27
  169. package/dist/tools/SkillTool/index.js.map +1 -1
  170. package/dist/tools/ToolSearchTool/index.d.ts +15 -0
  171. package/dist/tools/ToolSearchTool/index.d.ts.map +1 -0
  172. package/dist/tools/ToolSearchTool/index.js +50 -0
  173. package/dist/tools/ToolSearchTool/index.js.map +1 -0
  174. package/dist/tools.d.ts.map +1 -1
  175. package/dist/tools.js +9 -0
  176. package/dist/tools.js.map +1 -1
  177. package/dist/types/message.d.ts +2 -0
  178. package/dist/types/message.d.ts.map +1 -1
  179. package/dist/types/message.js +3 -0
  180. package/dist/types/message.js.map +1 -1
  181. package/dist/types/permissions.d.ts +2 -0
  182. package/dist/types/permissions.d.ts.map +1 -1
  183. package/dist/types/permissions.js +30 -0
  184. package/dist/types/permissions.js.map +1 -1
  185. package/package.json +1 -1
@@ -1,8 +1,9 @@
1
- import type { CybergotchiConfig, CybergotchiState } from '../cybergotchi/types.js';
1
+ import type { CompanionBones, CompanionConfig, CompanionState } from '../cybergotchi/types.js';
2
2
  interface Props {
3
- config: CybergotchiConfig;
4
- state: CybergotchiState;
3
+ bones: CompanionBones;
4
+ config: CompanionConfig;
5
+ state: CompanionState;
5
6
  }
6
- export default function CybergotchiSprite({ config, state }: Props): import("react/jsx-runtime").JSX.Element;
7
+ export default function CybergotchiSprite({ bones, config, state }: Props): import("react/jsx-runtime").JSX.Element;
7
8
  export {};
8
9
  //# sourceMappingURL=CybergotchiSprite.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"CybergotchiSprite.d.ts","sourceRoot":"","sources":["../../src/components/CybergotchiSprite.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAInF,UAAU,KAAK;IACb,MAAM,EAAE,iBAAiB,CAAC;IAC1B,KAAK,EAAE,gBAAgB,CAAC;CACzB;AAED,MAAM,CAAC,OAAO,UAAU,iBAAiB,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,KAAK,2CAyBjE"}
1
+ {"version":3,"file":"CybergotchiSprite.d.ts","sourceRoot":"","sources":["../../src/components/CybergotchiSprite.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAI/F,UAAU,KAAK;IACb,KAAK,EAAE,cAAc,CAAC;IACtB,MAAM,EAAE,eAAe,CAAC;IACxB,KAAK,EAAE,cAAc,CAAC;CACvB;AAED,MAAM,CAAC,OAAO,UAAU,iBAAiB,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,KAAK,2CAiCxE"}
@@ -1,20 +1,27 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Box, Text } from 'ink';
3
- import { EYE_STYLES, HAT_ART } from '../cybergotchi/types.js';
3
+ import { EYE_STYLES, HAT_ART, RARITY_COLORS } from '../cybergotchi/types.js';
4
4
  import { getSpecies } from '../cybergotchi/species.js';
5
- export default function CybergotchiSprite({ config, state }) {
6
- const species = getSpecies(config.species);
5
+ export default function CybergotchiSprite({ bones, config, state }) {
6
+ const species = getSpecies(bones.species);
7
7
  const frames = species.frames[state.emotion];
8
8
  const frame = frames[state.frame % frames.length] ?? frames[0];
9
- const eyes = EYE_STYLES[config.eyeStyle % EYE_STYLES.length] ?? 'o o';
9
+ const eyes = EYE_STYLES[bones.eyeStyle % EYE_STYLES.length] ?? 'o o';
10
10
  // Inject eyes into frame lines
11
11
  const lines = frame.map(line => line.replace('{E}', eyes));
12
12
  // Hat — stage 2 forces crown if no hat set
13
- const hatKey = config.evolutionStage === 2 && config.hat === 'none' ? 'crown' : config.hat;
13
+ const hatKey = config.evolutionStage === 2 && config.soul.hat === 'none' ? 'crown' : config.soul.hat;
14
14
  const hat = HAT_ART[hatKey];
15
- const spriteColor = config.evolutionStage === 2 ? 'yellow'
16
- : config.evolutionStage === 1 ? 'magenta'
17
- : 'cyan';
18
- return (_jsxs(Box, { flexDirection: "column", children: [hat && _jsx(Text, { color: "yellow", children: hat }), lines.map((line, i) => (_jsx(Text, { color: spriteColor, children: line }, i)))] }));
15
+ // Color based on rarity (overridden by evolution stage for higher stages)
16
+ const spriteColor = config.evolutionStage === 2
17
+ ? 'yellow'
18
+ : config.evolutionStage === 1
19
+ ? 'magenta'
20
+ : RARITY_COLORS[bones.rarity];
21
+ // Shiny: cycle colors for a shimmer effect
22
+ const shinyColors = ['red', 'yellow', 'green', 'cyan', 'blue', 'magenta'];
23
+ const shinyColor = bones.isShiny ? shinyColors[state.frame % shinyColors.length] : undefined;
24
+ const color = shinyColor ?? spriteColor;
25
+ return (_jsxs(Box, { flexDirection: "column", children: [hat && _jsx(Text, { color: "yellow", children: hat }), lines.map((line, i) => (_jsx(Text, { color: color, children: line }, i)))] }));
19
26
  }
20
27
  //# sourceMappingURL=CybergotchiSprite.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"CybergotchiSprite.js","sourceRoot":"","sources":["../../src/components/CybergotchiSprite.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAEhC,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAOvD,MAAM,CAAC,OAAO,UAAU,iBAAiB,CAAC,EAAE,MAAM,EAAE,KAAK,EAAS;IAChE,MAAM,OAAO,GAAG,UAAU,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC3C,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC7C,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,CAAC,CAAE,CAAC;IAChE,MAAM,IAAI,GAAG,UAAU,CAAC,MAAM,CAAC,QAAQ,GAAG,UAAU,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC;IAEtE,+BAA+B;IAC/B,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC;IAE3D,2CAA2C;IAC3C,MAAM,MAAM,GAAG,MAAM,CAAC,cAAc,KAAK,CAAC,IAAI,MAAM,CAAC,GAAG,KAAK,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;IAC3F,MAAM,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAE5B,MAAM,WAAW,GAAG,MAAM,CAAC,cAAc,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ;QACxD,CAAC,CAAC,MAAM,CAAC,cAAc,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS;YACzC,CAAC,CAAC,MAAM,CAAC;IAEX,OAAO,CACL,MAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,aACxB,GAAG,IAAI,KAAC,IAAI,IAAC,KAAK,EAAC,QAAQ,YAAE,GAAG,GAAQ,EACxC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CACtB,KAAC,IAAI,IAAS,KAAK,EAAE,WAAW,YAAG,IAAI,IAA5B,CAAC,CAAmC,CAChD,CAAC,IACE,CACP,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"CybergotchiSprite.js","sourceRoot":"","sources":["../../src/components/CybergotchiSprite.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAEhC,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAC7E,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAQvD,MAAM,CAAC,OAAO,UAAU,iBAAiB,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAS;IACvE,MAAM,OAAO,GAAG,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC1C,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC7C,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,CAAC,CAAE,CAAC;IAChE,MAAM,IAAI,GAAG,UAAU,CAAC,KAAK,CAAC,QAAQ,GAAG,UAAU,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC;IAErE,+BAA+B;IAC/B,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC;IAE3D,2CAA2C;IAC3C,MAAM,MAAM,GAAG,MAAM,CAAC,cAAc,KAAK,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC;IACrG,MAAM,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAE5B,0EAA0E;IAC1E,MAAM,WAAW,GAAG,MAAM,CAAC,cAAc,KAAK,CAAC;QAC7C,CAAC,CAAC,QAAQ;QACV,CAAC,CAAC,MAAM,CAAC,cAAc,KAAK,CAAC;YAC7B,CAAC,CAAC,SAAS;YACX,CAAC,CAAC,aAAa,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAEhC,2CAA2C;IAC3C,MAAM,WAAW,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,CAAU,CAAC;IACnF,MAAM,UAAU,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC,KAAK,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC7F,MAAM,KAAK,GAAG,UAAU,IAAI,WAAW,CAAC;IAExC,OAAO,CACL,MAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,aACxB,GAAG,IAAI,KAAC,IAAI,IAAC,KAAK,EAAC,QAAQ,YAAE,GAAG,GAAQ,EACxC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CACtB,KAAC,IAAI,IAAS,KAAK,EAAE,KAAK,YAAG,IAAI,IAAtB,CAAC,CAA6B,CAC1C,CAAC,IACE,CACP,CAAC;AACJ,CAAC"}
@@ -0,0 +1,27 @@
1
+ interface Props {
2
+ oldContent: string;
3
+ newContent: string;
4
+ filePath: string;
5
+ maxLines?: number;
6
+ }
7
+ /**
8
+ * Compute a simple unified diff between two strings.
9
+ * Returns an array of { type, line } entries.
10
+ */
11
+ declare function computeDiff(oldText: string, newText: string): Array<{
12
+ type: 'add' | 'remove' | 'context';
13
+ line: string;
14
+ }>;
15
+ /**
16
+ * Filter diff to show only changed lines with N lines of context.
17
+ */
18
+ declare function filterWithContext(diff: Array<{
19
+ type: 'add' | 'remove' | 'context';
20
+ line: string;
21
+ }>, contextLines?: number): Array<{
22
+ type: 'add' | 'remove' | 'context' | 'separator';
23
+ line: string;
24
+ }>;
25
+ export default function DiffView({ oldContent, newContent, filePath, maxLines }: Props): import("react/jsx-runtime").JSX.Element;
26
+ export { computeDiff, filterWithContext };
27
+ //# sourceMappingURL=DiffView.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DiffView.d.ts","sourceRoot":"","sources":["../../src/components/DiffView.tsx"],"names":[],"mappings":"AAGA,UAAU,KAAK;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,iBAAS,WAAW,CAClB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,GACd,KAAK,CAAC;IAAE,IAAI,EAAE,KAAK,GAAG,QAAQ,GAAG,SAAS,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAyB7D;AAED;;GAEG;AACH,iBAAS,iBAAiB,CACxB,IAAI,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,KAAK,GAAG,QAAQ,GAAG,SAAS,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,EACjE,YAAY,SAAI,GACf,KAAK,CAAC;IAAE,IAAI,EAAE,KAAK,GAAG,QAAQ,GAAG,SAAS,GAAG,WAAW,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAwB3E;AAED,MAAM,CAAC,OAAO,UAAU,QAAQ,CAAC,EAAE,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAa,EAAE,EAAE,KAAK,2CA4B1F;AAED,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,CAAC"}
@@ -0,0 +1,74 @@
1
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
+ import { Box, Text } from 'ink';
3
+ /**
4
+ * Compute a simple unified diff between two strings.
5
+ * Returns an array of { type, line } entries.
6
+ */
7
+ function computeDiff(oldText, newText) {
8
+ const oldLines = oldText.split('\n');
9
+ const newLines = newText.split('\n');
10
+ const result = [];
11
+ // Simple LCS-based diff
12
+ const maxLen = Math.max(oldLines.length, newLines.length);
13
+ let oi = 0;
14
+ let ni = 0;
15
+ while (oi < oldLines.length || ni < newLines.length) {
16
+ if (oi < oldLines.length && ni < newLines.length && oldLines[oi] === newLines[ni]) {
17
+ result.push({ type: 'context', line: oldLines[oi] });
18
+ oi++;
19
+ ni++;
20
+ }
21
+ else if (ni < newLines.length && (oi >= oldLines.length || !oldLines.slice(oi).includes(newLines[ni]))) {
22
+ result.push({ type: 'add', line: newLines[ni] });
23
+ ni++;
24
+ }
25
+ else {
26
+ result.push({ type: 'remove', line: oldLines[oi] });
27
+ oi++;
28
+ }
29
+ }
30
+ return result;
31
+ }
32
+ /**
33
+ * Filter diff to show only changed lines with N lines of context.
34
+ */
35
+ function filterWithContext(diff, contextLines = 3) {
36
+ const changed = new Set();
37
+ diff.forEach((d, i) => {
38
+ if (d.type !== 'context') {
39
+ for (let j = Math.max(0, i - contextLines); j <= Math.min(diff.length - 1, i + contextLines); j++) {
40
+ changed.add(j);
41
+ }
42
+ }
43
+ });
44
+ const result = [];
45
+ let lastShown = -2;
46
+ diff.forEach((d, i) => {
47
+ if (changed.has(i)) {
48
+ if (i > lastShown + 1 && lastShown >= 0) {
49
+ result.push({ type: 'separator', line: '...' });
50
+ }
51
+ result.push(d);
52
+ lastShown = i;
53
+ }
54
+ });
55
+ return result;
56
+ }
57
+ export default function DiffView({ oldContent, newContent, filePath, maxLines = 30 }) {
58
+ const rawDiff = computeDiff(oldContent, newContent);
59
+ const filtered = filterWithContext(rawDiff);
60
+ const display = filtered.slice(0, maxLines);
61
+ const truncated = filtered.length > maxLines;
62
+ const adds = rawDiff.filter(d => d.type === 'add').length;
63
+ const removes = rawDiff.filter(d => d.type === 'remove').length;
64
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { dimColor: true, children: ['─── ', filePath, ' ───'] }), _jsxs(Text, { children: [_jsx(Text, { color: "green", children: `+${adds}` }), ' ', _jsx(Text, { color: "red", children: `-${removes}` })] }), display.map((d, i) => {
65
+ if (d.type === 'separator') {
66
+ return _jsx(Text, { dimColor: true, children: ' ...' }, i);
67
+ }
68
+ const prefix = d.type === 'add' ? '+ ' : d.type === 'remove' ? '- ' : ' ';
69
+ const color = d.type === 'add' ? 'green' : d.type === 'remove' ? 'red' : undefined;
70
+ return _jsxs(Text, { color: color, children: [prefix, d.line] }, i);
71
+ }), truncated && _jsx(Text, { dimColor: true, children: ` ... (${filtered.length - maxLines} more lines)` })] }));
72
+ }
73
+ export { computeDiff, filterWithContext };
74
+ //# sourceMappingURL=DiffView.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DiffView.js","sourceRoot":"","sources":["../../src/components/DiffView.tsx"],"names":[],"mappings":"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"}
@@ -8,7 +8,7 @@ export default function Messages({ messages, toolCalls }) {
8
8
  const theme = useTheme();
9
9
  return (_jsx(Box, { flexDirection: "column", children: messages.map((msg, i) => {
10
10
  const showDivider = msg.role === "user" && i > 0;
11
- return (_jsxs(React.Fragment, { children: [showDivider && (_jsx(Text, { color: theme.dim, children: "─".repeat(60) })), _jsx(MessageRow, { message: msg, toolCalls: toolCalls, theme: theme })] }, msg.uuid));
11
+ return (_jsxs(React.Fragment, { children: [showDivider && (_jsx(Text, { color: theme.dim, children: "─".repeat(Math.min(60, process.stdout.columns ?? 80)) })), _jsx(MessageRow, { message: msg, toolCalls: toolCalls, theme: theme })] }, msg.uuid));
12
12
  }) }));
13
13
  }
14
14
  function MessageRow({ message, toolCalls, theme, }) {
@@ -1 +1 @@
1
- {"version":3,"file":"Messages.js","sourceRoot":"","sources":["../../src/components/Messages.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Messages.js","sourceRoot":"","sources":["../../src/components/Messages.tsx"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"PermissionPrompt.d.ts","sourceRoot":"","sources":["../../src/components/PermissionPrompt.tsx"],"names":[],"mappings":"AAIA,KAAK,KAAK,GAAG;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;CACvC,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,gBAAgB,CAAC,EACvC,QAAQ,EACR,WAAW,EACX,SAAS,EACT,SAAS,GACV,EAAE,KAAK,2CAsDP"}
1
+ {"version":3,"file":"PermissionPrompt.d.ts","sourceRoot":"","sources":["../../src/components/PermissionPrompt.tsx"],"names":[],"mappings":"AASA,KAAK,KAAK,GAAG;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;CACvC,CAAC;AAiCF,MAAM,CAAC,OAAO,UAAU,gBAAgB,CAAC,EACvC,QAAQ,EACR,WAAW,EACX,SAAS,EACT,SAAS,GACV,EAAE,KAAK,2CAwFP"}
@@ -1,36 +1,89 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useState } from "react";
2
3
  import { Box, Text, useInput } from "ink";
3
4
  import { useTheme } from "../utils/theme.js";
5
+ import DiffView from "./DiffView.js";
6
+ import { readFileSync, existsSync, writeFileSync, unlinkSync } from "node:fs";
7
+ import { execSync } from "node:child_process";
8
+ import { join } from "node:path";
9
+ import { tmpdir } from "node:os";
10
+ /** Try to parse file path and content from tool args for diff display */
11
+ function extractFileInfo(toolName, description) {
12
+ try {
13
+ const args = JSON.parse(description);
14
+ const name = toolName.toLowerCase();
15
+ if (name.includes('write') && args.file_path && args.content) {
16
+ const old = existsSync(args.file_path) ? readFileSync(args.file_path, 'utf-8') : '';
17
+ return { filePath: args.file_path, oldContent: old, newContent: args.content };
18
+ }
19
+ if (name.includes('edit') && args.file_path && args.old_string && args.new_string) {
20
+ if (existsSync(args.file_path)) {
21
+ const old = readFileSync(args.file_path, 'utf-8');
22
+ const newContent = old.replace(args.old_string, args.new_string);
23
+ return { filePath: args.file_path, oldContent: old, newContent, oldString: args.old_string, newString: args.new_string };
24
+ }
25
+ }
26
+ return null;
27
+ }
28
+ catch {
29
+ return null;
30
+ }
31
+ }
4
32
  export default function PermissionPrompt({ toolName, description, riskLevel, onResolve, }) {
5
33
  const theme = useTheme();
34
+ const [showDiff, setShowDiff] = useState(false);
35
+ const fileInfo = extractFileInfo(toolName, description);
36
+ const hasDiff = fileInfo !== null && fileInfo.oldContent !== undefined && fileInfo.newContent !== undefined;
6
37
  useInput((input) => {
7
38
  const key = input.toLowerCase();
8
39
  if (key === "y")
9
40
  onResolve(true);
10
41
  if (key === "n")
11
42
  onResolve(false);
43
+ if (key === "d" && hasDiff)
44
+ setShowDiff(prev => !prev);
45
+ if (key === "e" && hasDiff && fileInfo?.newContent) {
46
+ // Open new content in $EDITOR
47
+ const editor = process.env.EDITOR || process.env.VISUAL || 'vi';
48
+ const tmpFile = join(tmpdir(), `oh-edit-${Date.now()}.tmp`);
49
+ try {
50
+ writeFileSync(tmpFile, fileInfo.newContent);
51
+ execSync(`${editor} "${tmpFile}"`, { stdio: 'inherit' });
52
+ // User may have modified — we can't easily integrate the edit back into the tool call
53
+ // Just show a message
54
+ unlinkSync(tmpFile);
55
+ }
56
+ catch { /* ignore */ }
57
+ }
12
58
  });
13
59
  const borderColor = riskLevel === "high"
14
60
  ? theme.error
15
61
  : riskLevel === "medium"
16
62
  ? theme.warning
17
63
  : theme.success;
18
- // Extract contextual info from description
19
64
  const suggestion = extractSuggestion(toolName, description);
20
- return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: borderColor, paddingX: 2, paddingY: 0, marginY: 1, children: [_jsxs(Box, { children: [_jsx(Text, { color: borderColor, bold: true, children: "⚠ " }), _jsx(Text, { bold: true, children: toolName }), _jsxs(Text, { color: theme.dim, children: [" ", riskLevel, " risk"] })] }), suggestion && (_jsx(Box, { marginLeft: 2, children: _jsx(Text, { color: theme.dim, children: suggestion }) })), _jsx(Box, { marginLeft: 2, marginY: 0, children: _jsx(Text, { children: description.slice(0, 300) }) }), _jsx(Box, { marginTop: 0, children: _jsxs(Text, { children: ["Allow? [", _jsx(Text, { color: theme.success, bold: true, children: "Y" }), "/", _jsx(Text, { color: theme.error, bold: true, children: "N" }), "]", " "] }) })] }));
65
+ return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: borderColor, paddingX: 2, paddingY: 0, marginY: 1, children: [_jsxs(Box, { children: [_jsx(Text, { color: borderColor, bold: true, children: "⚠ " }), _jsx(Text, { bold: true, children: toolName }), _jsxs(Text, { color: theme.dim, children: [" ", riskLevel, " risk"] })] }), suggestion && (_jsx(Box, { marginLeft: 2, children: _jsx(Text, { color: theme.dim, children: suggestion }) })), !showDiff && (_jsx(Box, { marginLeft: 2, marginY: 0, children: _jsx(Text, { children: description.slice(0, 300) }) })), showDiff && hasDiff && (_jsx(Box, { marginLeft: 2, marginY: 0, children: _jsx(DiffView, { oldContent: fileInfo.oldContent, newContent: fileInfo.newContent, filePath: fileInfo.filePath ?? '' }) })), _jsx(Box, { marginTop: 0, children: _jsxs(Text, { children: ["[", _jsx(Text, { color: theme.success, bold: true, children: "Y" }), "]es", " ", "[", _jsx(Text, { color: theme.error, bold: true, children: "N" }), "]o", hasDiff && (_jsxs(_Fragment, { children: [" ", "[", _jsx(Text, { color: "cyan", bold: true, children: "D" }), "]iff", " ", "[", _jsx(Text, { color: "yellow", bold: true, children: "E" }), "]dit"] }))] }) })] }));
21
66
  }
22
67
  function extractSuggestion(toolName, description) {
23
68
  const lower = toolName.toLowerCase();
24
69
  if (lower === "bash" || lower === "shell" || lower === "execute") {
25
- // Try to extract the command
26
70
  const cmdMatch = description.match(/command[:\s]+["`]?(.+?)["`]?(?:\n|$)/i);
27
71
  if (cmdMatch)
28
72
  return `$ ${cmdMatch[1]}`;
29
73
  }
30
- if (lower === "read" || lower === "write" || lower === "edit") {
31
- const pathMatch = description.match(/(?:path|file)[:\s]+["`]?([^\s"`]+)/i);
32
- if (pathMatch)
33
- return `${lower === "read" ? "reading" : lower === "write" ? "writing" : "editing"} ${pathMatch[1]}`;
74
+ if (lower.includes("read") || lower.includes("write") || lower.includes("edit")) {
75
+ try {
76
+ const args = JSON.parse(description);
77
+ if (args.file_path) {
78
+ const action = lower.includes("read") ? "reading" : lower.includes("write") ? "writing" : "editing";
79
+ return `${action} ${args.file_path}`;
80
+ }
81
+ }
82
+ catch {
83
+ const pathMatch = description.match(/(?:path|file)[:\s]+["`]?([^\s"`]+)/i);
84
+ if (pathMatch)
85
+ return `${lower.includes("read") ? "reading" : lower.includes("write") ? "writing" : "editing"} ${pathMatch[1]}`;
86
+ }
34
87
  }
35
88
  return null;
36
89
  }
@@ -1 +1 @@
1
- {"version":3,"file":"PermissionPrompt.js","sourceRoot":"","sources":["../../src/components/PermissionPrompt.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"PermissionPrompt.js","sourceRoot":"","sources":["../../src/components/PermissionPrompt.tsx"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"REPL.d.ts","sourceRoot":"","sources":["../../src/components/REPL.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAEnD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAwF9D,KAAK,SAAS,GAAG;IACf,QAAQ,EAAE,QAAQ,CAAC;IACnB,KAAK,EAAE,KAAK,CAAC;IACb,cAAc,EAAE,cAAc,CAAC;IAC/B,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE,OAAO,EAAE,CAAC;IAC5B,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAUF,MAAM,CAAC,OAAO,UAAU,IAAI,CAAC,EAC3B,QAAQ,EACR,KAAK,EACL,cAAc,EACd,YAAY,EACZ,KAAK,EACL,eAAe,EACf,eAAe,GAChB,EAAE,SAAS,2CAwdX"}
1
+ {"version":3,"file":"REPL.d.ts","sourceRoot":"","sources":["../../src/components/REPL.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAEnD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAyF9D,KAAK,SAAS,GAAG;IACf,QAAQ,EAAE,QAAQ,CAAC;IACnB,KAAK,EAAE,KAAK,CAAC;IACb,cAAc,EAAE,cAAc,CAAC;IAC/B,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE,OAAO,EAAE,CAAC;IAC5B,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAUF,MAAM,CAAC,OAAO,UAAU,IAAI,CAAC,EAC3B,QAAQ,EACR,KAAK,EACL,cAAc,EACd,YAAY,EACZ,KAAK,EACL,eAAe,EACf,eAAe,GAChB,EAAE,SAAS,2CAkhBX"}
@@ -17,16 +17,14 @@ import PermissionPrompt from "./PermissionPrompt.js";
17
17
  import CybergotchiPanelConnected from "./CybergotchiPanelConnected.js";
18
18
  import CybergotchiSetup from "./CybergotchiSetup.js";
19
19
  import { cybergotchiEvents } from "../cybergotchi/events.js";
20
- /** Width of the cybergotchi panel (22 content + 2 border + 2 padding + 1 margin) */
21
- const PANEL_TOTAL_WIDTH = 27;
22
- /** Minimum terminal width to show the cybergotchi panel */
23
- const MIN_WIDTH_FOR_PANEL = 60;
20
+ /** Minimum terminal width to show the companion */
21
+ const MIN_WIDTH_FOR_COMPANION = 40;
24
22
  function getTerminalWidth() {
25
23
  return process.stdout.columns ?? 80;
26
24
  }
25
+ /** Chat gets full terminal width now (no sidebar) */
27
26
  function getChatWidth() {
28
- const tw = getTerminalWidth();
29
- return tw >= MIN_WIDTH_FOR_PANEL ? tw - PANEL_TOTAL_WIDTH : tw;
27
+ return getTerminalWidth();
30
28
  }
31
29
  /** Truncate a string to fit within maxWidth columns */
32
30
  function truncateLine(line, maxWidth) {
@@ -85,7 +83,10 @@ function printMessageToStdout(msg, showDivider) {
85
83
  if (out)
86
84
  process.stdout.write(out);
87
85
  }
88
- import { loadCybergotchiConfig, saveCybergotchiConfig } from "../cybergotchi/config.js";
86
+ import { loadCompanionConfig, saveCompanionConfig } from "../cybergotchi/config.js";
87
+ import { detectMemories, saveMemory } from "../harness/memory.js";
88
+ import { resolveMcpMention } from "../mcp/loader.js";
89
+ import { createKeybindingMatcher } from "../harness/keybindings.js";
89
90
  export default function REPL({ provider, tools, permissionMode, systemPrompt, model, initialMessages, resumeSessionId, }) {
90
91
  const { exit } = useApp();
91
92
  // Session and cost tracking
@@ -114,7 +115,8 @@ export default function REPL({ provider, tools, permissionMode, systemPrompt, mo
114
115
  const [error, setError] = useState(null);
115
116
  const [currentModel, setCurrentModel] = useState(model ?? "");
116
117
  const [showCybergotchiSetup, setShowCybergotchiSetup] = useState(false);
117
- const cybergotchiConfigRef = useRef(loadCybergotchiConfig());
118
+ const [vimMode, setVimMode] = useState(false);
119
+ const cybergotchiConfigRef = useRef(loadCompanionConfig());
118
120
  // Print new finalized messages to stdout (outside Ink's live area) to prevent
119
121
  // Ink height miscounting from causing the cybergotchi panel to expand on each tick.
120
122
  const printedRef = useRef(new Set());
@@ -136,7 +138,7 @@ export default function REPL({ provider, tools, permissionMode, systemPrompt, mo
136
138
  const cfg = cybergotchiConfigRef.current;
137
139
  if (cfg) {
138
140
  cfg.lifetime.totalSessions += 1;
139
- saveCybergotchiConfig(cfg);
141
+ saveCompanionConfig(cfg);
140
142
  }
141
143
  // eslint-disable-next-line react-hooks/exhaustive-deps
142
144
  }, []);
@@ -170,10 +172,21 @@ export default function REPL({ provider, tools, permissionMode, systemPrompt, mo
170
172
  clearTimeout(loadingTimerRef.current);
171
173
  };
172
174
  }, [loading]);
173
- // Ctrl+C during loading aborts the current query
175
+ // Keybinding matcher + pending action ref
176
+ const keybindingMatcher = useRef(createKeybindingMatcher()).current;
177
+ const pendingKeybindAction = useRef(null);
178
+ // Ctrl+C during loading aborts; custom keybindings queue actions
174
179
  useInput((_input, key) => {
175
180
  if (key.ctrl && _input === "c" && loading && abortControllerRef.current) {
176
181
  abortControllerRef.current.abort();
182
+ return;
183
+ }
184
+ // Custom keybinding check (only when not loading and not in a prompt)
185
+ if (!loading && !pendingPermission && !pendingQuestion) {
186
+ const action = keybindingMatcher.match(_input, { ctrl: key.ctrl, meta: key.meta, shift: key.shift });
187
+ if (action) {
188
+ pendingKeybindAction.current = action;
189
+ }
177
190
  }
178
191
  });
179
192
  // Queue prompt submissions — useEffect picks them up for async processing
@@ -226,9 +239,25 @@ export default function REPL({ provider, tools, permissionMode, systemPrompt, mo
226
239
  model: currentModel || undefined,
227
240
  abortSignal: abortController.signal,
228
241
  };
242
+ // Resolve @mentions to MCP resource content
243
+ let resolvedPrompt = prompt;
244
+ const mentionPattern = /@(\w[\w.-]*)/g;
245
+ const mentions = [...prompt.matchAll(mentionPattern)].map(m => m[1]);
246
+ const companionName = cybergotchiConfigRef.current?.soul?.name?.toLowerCase();
247
+ for (const mention of mentions) {
248
+ if (companionName && mention.toLowerCase() === companionName)
249
+ continue;
250
+ try {
251
+ const content = await resolveMcpMention(mention);
252
+ if (content) {
253
+ resolvedPrompt += `\n\n[Resource @${mention}]:\n${content.slice(0, 5000)}`;
254
+ }
255
+ }
256
+ catch { /* ignore */ }
257
+ }
229
258
  let accumulated = "";
230
259
  try {
231
- for await (const event of query(prompt, config, messagesRef.current)) {
260
+ for await (const event of query(resolvedPrompt, config, messagesRef.current)) {
232
261
  switch (event.type) {
233
262
  case "rate_limited":
234
263
  setStreamingText(`⏳ Rate limited — retrying in ${event.retryIn}s… (attempt ${event.attempt}/3)`);
@@ -355,6 +384,17 @@ export default function REPL({ provider, tools, permissionMode, systemPrompt, mo
355
384
  abortControllerRef.current = null;
356
385
  setLoading(false);
357
386
  setStreamingText("");
387
+ // Auto-memory: detect learnable patterns every 5 turns (async, non-blocking)
388
+ const msgCount = messagesRef.current.length;
389
+ if (msgCount > 0 && msgCount % 10 === 0) {
390
+ detectMemories(provider, messagesRef.current.slice(-10), model)
391
+ .then(memories => {
392
+ for (const m of memories) {
393
+ saveMemory(m.name, m.type, m.description, m.content);
394
+ }
395
+ })
396
+ .catch(() => { });
397
+ }
358
398
  }
359
399
  };
360
400
  run();
@@ -369,7 +409,7 @@ export default function REPL({ provider, tools, permissionMode, systemPrompt, mo
369
409
  {
370
410
  const gotchiCfg = cybergotchiConfigRef.current;
371
411
  if (gotchiCfg) {
372
- const name = gotchiCfg.name.toLowerCase();
412
+ const name = gotchiCfg.soul.name.toLowerCase();
373
413
  const lower = trimmed.toLowerCase();
374
414
  if (lower.startsWith(`@${name}`) || lower.startsWith(`${name},`) || lower.startsWith(`${name} `)) {
375
415
  cybergotchiEvents.emit('cybergotchi', { type: 'userAddressed', text: trimmed });
@@ -377,6 +417,12 @@ export default function REPL({ provider, tools, permissionMode, systemPrompt, mo
377
417
  }
378
418
  }
379
419
  }
420
+ // Handle /vim toggle directly
421
+ if (trimmed === "/vim") {
422
+ setVimMode(v => !v);
423
+ setMessages((prev) => [...prev, createInfoMessage(vimMode ? "Vim mode OFF" : "Vim mode ON")]);
424
+ return;
425
+ }
380
426
  // Process slash commands
381
427
  if (trimmed.startsWith("/")) {
382
428
  const ctx = {
@@ -435,17 +481,25 @@ export default function REPL({ provider, tools, permissionMode, systemPrompt, mo
435
481
  pendingPromptRef.current = input;
436
482
  setSubmitCount((c) => c + 1);
437
483
  }, [exit, currentModel, permissionMode, sessionId]);
484
+ // Process pending keybinding actions
485
+ useEffect(() => {
486
+ const action = pendingKeybindAction.current;
487
+ if (action && !loading) {
488
+ pendingKeybindAction.current = null;
489
+ handleSubmit(action);
490
+ }
491
+ });
438
492
  // Show cybergotchi setup if needed (first run or /cybergotchi reset)
439
493
  if (cybergotchiConfigRef.current === null || showCybergotchiSetup) {
440
- return (_jsx(CybergotchiSetup, { onComplete: () => { cybergotchiConfigRef.current = loadCybergotchiConfig(); setShowCybergotchiSetup(false); }, onSkip: () => { cybergotchiConfigRef.current = loadCybergotchiConfig(); setShowCybergotchiSetup(false); } }));
494
+ return (_jsx(CybergotchiSetup, { onComplete: () => { cybergotchiConfigRef.current = loadCompanionConfig(); setShowCybergotchiSetup(false); }, onSkip: () => { cybergotchiConfigRef.current = loadCompanionConfig(); setShowCybergotchiSetup(false); } }));
441
495
  }
442
- return (_jsxs(Box, { flexDirection: "row", children: [_jsxs(Box, { flexDirection: "column", flexGrow: 1, width: getChatWidth(), children: [thinkingText && (_jsx(Box, { marginY: 0, children: _jsxs(Text, { dimColor: true, children: ["💭 ", thinkingText.length > 200 ? thinkingText.slice(-200) + "…" : thinkingText] }) })), loading && streamingText && (_jsxs(Box, { marginY: 0, children: [_jsx(Text, { color: "magenta", bold: true, children: "◆ " }), _jsx(Text, { children: streamingText })] })), loading && !streamingText && _jsx(Spinner, { model: currentModel, tokens: costRef.current.totalOutputTokens }), error && (_jsx(Box, { marginY: 1, borderStyle: "round", borderColor: "red", paddingX: 1, children: _jsxs(Text, { color: "red", children: ["✗ ", error] }) })), pendingPermission && (_jsx(PermissionPrompt, { toolName: pendingPermission.toolName, description: pendingPermission.description, riskLevel: pendingPermission.riskLevel, onResolve: pendingPermission.resolve })), pendingQuestion && (_jsxs(Box, { flexDirection: "column", marginTop: 1, borderStyle: "round", borderColor: "yellow", paddingX: 1, children: [_jsxs(Text, { color: "yellow", children: ["\u2753 ", pendingQuestion.question] }), pendingQuestion.options && pendingQuestion.options.length > 0 && (_jsx(Box, { flexDirection: "column", children: pendingQuestion.options.map((o, i) => (_jsxs(Text, { dimColor: true, children: [" ", i + 1, ". ", o] }, i))) })), _jsxs(Box, { children: [_jsx(Text, { color: "yellow", children: '❯ ' }), _jsx(TextInputComponent, { value: questionAnswer, onChange: setQuestionAnswer, onSubmit: (val) => { if (val.trim())
443
- pendingQuestion.resolve(val.trim()); }, focus: true })] })] })), _jsx(Box, { marginTop: 1, children: _jsx(TextInput, { onSubmit: handleSubmit, disabled: loading || !!pendingQuestion }) }), _jsxs(Text, { dimColor: true, children: ["exit to quit", loading ? " | Ctrl+C to interrupt" : "", cybergotchiConfigRef.current?.name ? ` | @${cybergotchiConfigRef.current.name} to chat` : ""] }), (() => {
444
- const usage = contextUsage(currentModel, costRef.current.totalInputTokens);
445
- if (usage < 0.75)
446
- return null;
447
- const critical = usage >= 0.9;
448
- return (_jsx(Text, { color: critical ? "yellow" : undefined, bold: critical, dimColor: !critical, children: `⚠ Context ~${Math.round(usage * 100)}% full — consider /compact` }));
449
- })()] }), getTerminalWidth() >= MIN_WIDTH_FOR_PANEL && _jsx(CybergotchiPanelConnected, {})] }));
496
+ return (_jsx(Box, { flexDirection: "column", children: _jsxs(Box, { flexDirection: "column", flexGrow: 1, children: [thinkingText && (_jsx(Box, { marginY: 0, children: _jsxs(Text, { dimColor: true, children: ["💭 ", thinkingText.length > 200 ? thinkingText.slice(-200) + "…" : thinkingText] }) })), loading && streamingText && (_jsxs(Box, { marginY: 0, children: [_jsx(Text, { color: "magenta", bold: true, children: "◆ " }), _jsx(Text, { children: streamingText })] })), loading && !streamingText && _jsx(Spinner, { model: currentModel, tokens: costRef.current.totalOutputTokens }), error && (_jsx(Box, { marginY: 1, borderStyle: "round", borderColor: "red", paddingX: 1, children: _jsxs(Text, { color: "red", children: ["✗ ", error] }) })), pendingPermission && (_jsx(PermissionPrompt, { toolName: pendingPermission.toolName, description: pendingPermission.description, riskLevel: pendingPermission.riskLevel, onResolve: pendingPermission.resolve })), pendingQuestion && (_jsxs(Box, { flexDirection: "column", marginTop: 1, borderStyle: "round", borderColor: "yellow", paddingX: 1, children: [_jsxs(Text, { color: "yellow", children: ["\u2753 ", pendingQuestion.question] }), pendingQuestion.options && pendingQuestion.options.length > 0 && (_jsx(Box, { flexDirection: "column", children: pendingQuestion.options.map((o, i) => (_jsxs(Text, { dimColor: true, children: [" ", i + 1, ". ", o] }, i))) })), _jsxs(Box, { children: [_jsx(Text, { color: "yellow", children: '❯ ' }), _jsx(TextInputComponent, { value: questionAnswer, onChange: setQuestionAnswer, onSubmit: (val) => { if (val.trim())
497
+ pendingQuestion.resolve(val.trim()); }, focus: true })] })] })), _jsxs(Box, { flexDirection: "row", marginTop: 1, children: [_jsx(Box, { flexDirection: "column", flexGrow: 1, children: _jsx(TextInput, { onSubmit: handleSubmit, disabled: loading || !!pendingQuestion, vimMode: vimMode }) }), getTerminalWidth() >= MIN_WIDTH_FOR_COMPANION && _jsx(CybergotchiPanelConnected, {})] }), _jsxs(Text, { dimColor: true, children: ["exit to quit", loading ? " | Ctrl+C to interrupt" : "", cybergotchiConfigRef.current?.soul?.name ? ` | @${cybergotchiConfigRef.current.soul.name} to chat` : ""] }), (() => {
498
+ const usage = contextUsage(currentModel, costRef.current.totalInputTokens);
499
+ if (usage < 0.75)
500
+ return null;
501
+ const critical = usage >= 0.9;
502
+ return (_jsx(Text, { color: critical ? "yellow" : undefined, bold: critical, dimColor: !critical, children: `⚠ Context ~${Math.round(usage * 100)}% full — consider /compact` }));
503
+ })()] }) }));
450
504
  }
451
505
  //# sourceMappingURL=REPL.js.map