@gxp-dev/tools 2.0.63 → 2.0.64

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 (182) hide show
  1. package/README.md +32 -31
  2. package/bin/gx-devtools.js +74 -54
  3. package/bin/lib/cli.js +23 -21
  4. package/bin/lib/commands/add-dependency.js +366 -325
  5. package/bin/lib/commands/assets.js +137 -139
  6. package/bin/lib/commands/build.js +169 -174
  7. package/bin/lib/commands/datastore.js +181 -183
  8. package/bin/lib/commands/dev.js +127 -131
  9. package/bin/lib/commands/extensions.js +147 -149
  10. package/bin/lib/commands/extract-config.js +73 -67
  11. package/bin/lib/commands/index.js +12 -12
  12. package/bin/lib/commands/init.js +342 -240
  13. package/bin/lib/commands/publish.js +69 -75
  14. package/bin/lib/commands/socket.js +69 -69
  15. package/bin/lib/commands/ssl.js +14 -14
  16. package/bin/lib/constants.js +10 -24
  17. package/bin/lib/tui/App.tsx +761 -705
  18. package/bin/lib/tui/components/AIPanel.tsx +191 -171
  19. package/bin/lib/tui/components/CommandInput.tsx +394 -343
  20. package/bin/lib/tui/components/GeminiPanel.tsx +175 -151
  21. package/bin/lib/tui/components/Header.tsx +23 -21
  22. package/bin/lib/tui/components/LogPanel.tsx +244 -220
  23. package/bin/lib/tui/components/TabBar.tsx +50 -48
  24. package/bin/lib/tui/components/WelcomeScreen.tsx +126 -71
  25. package/bin/lib/tui/index.tsx +37 -39
  26. package/bin/lib/tui/services/AIService.ts +518 -462
  27. package/bin/lib/tui/services/ExtensionService.ts +140 -129
  28. package/bin/lib/tui/services/GeminiService.ts +367 -337
  29. package/bin/lib/tui/services/ServiceManager.ts +344 -322
  30. package/bin/lib/tui/services/SocketService.ts +168 -168
  31. package/bin/lib/tui/services/ViteService.ts +88 -88
  32. package/bin/lib/tui/services/index.ts +47 -22
  33. package/bin/lib/utils/ai-scaffold.js +291 -280
  34. package/bin/lib/utils/extract-config.js +157 -140
  35. package/bin/lib/utils/files.js +82 -86
  36. package/bin/lib/utils/index.js +7 -7
  37. package/bin/lib/utils/paths.js +34 -34
  38. package/bin/lib/utils/prompts.js +194 -169
  39. package/bin/lib/utils/ssl.js +79 -81
  40. package/browser-extensions/README.md +0 -1
  41. package/browser-extensions/chrome/background.js +244 -237
  42. package/browser-extensions/chrome/content.js +32 -29
  43. package/browser-extensions/chrome/devtools.html +7 -7
  44. package/browser-extensions/chrome/devtools.js +19 -19
  45. package/browser-extensions/chrome/inspector.js +802 -767
  46. package/browser-extensions/chrome/manifest.json +71 -63
  47. package/browser-extensions/chrome/panel.html +674 -636
  48. package/browser-extensions/chrome/panel.js +722 -712
  49. package/browser-extensions/chrome/popup.html +586 -543
  50. package/browser-extensions/chrome/popup.js +282 -244
  51. package/browser-extensions/chrome/rules.json +1 -1
  52. package/browser-extensions/chrome/test-chrome.html +216 -136
  53. package/browser-extensions/chrome/test-mixed-content.html +284 -189
  54. package/browser-extensions/chrome/test-uri-pattern.html +221 -198
  55. package/browser-extensions/firefox/README.md +9 -6
  56. package/browser-extensions/firefox/background.js +221 -218
  57. package/browser-extensions/firefox/content.js +55 -52
  58. package/browser-extensions/firefox/debug-errors.html +386 -228
  59. package/browser-extensions/firefox/debug-https.html +153 -105
  60. package/browser-extensions/firefox/devtools.html +7 -7
  61. package/browser-extensions/firefox/devtools.js +23 -20
  62. package/browser-extensions/firefox/inspector.js +802 -767
  63. package/browser-extensions/firefox/manifest.json +68 -68
  64. package/browser-extensions/firefox/panel.html +674 -636
  65. package/browser-extensions/firefox/panel.js +722 -712
  66. package/browser-extensions/firefox/popup.html +572 -535
  67. package/browser-extensions/firefox/popup.js +281 -236
  68. package/browser-extensions/firefox/test-gramercy.html +170 -125
  69. package/browser-extensions/firefox/test-imports.html +59 -55
  70. package/browser-extensions/firefox/test-masking.html +231 -140
  71. package/browser-extensions/firefox/test-uri-pattern.html +221 -198
  72. package/dist/tui/App.d.ts +1 -1
  73. package/dist/tui/App.d.ts.map +1 -1
  74. package/dist/tui/App.js +154 -150
  75. package/dist/tui/App.js.map +1 -1
  76. package/dist/tui/components/AIPanel.d.ts.map +1 -1
  77. package/dist/tui/components/AIPanel.js +42 -35
  78. package/dist/tui/components/AIPanel.js.map +1 -1
  79. package/dist/tui/components/CommandInput.d.ts +1 -1
  80. package/dist/tui/components/CommandInput.d.ts.map +1 -1
  81. package/dist/tui/components/CommandInput.js +92 -62
  82. package/dist/tui/components/CommandInput.js.map +1 -1
  83. package/dist/tui/components/GeminiPanel.d.ts.map +1 -1
  84. package/dist/tui/components/GeminiPanel.js +37 -30
  85. package/dist/tui/components/GeminiPanel.js.map +1 -1
  86. package/dist/tui/components/Header.d.ts.map +1 -1
  87. package/dist/tui/components/Header.js +1 -1
  88. package/dist/tui/components/Header.js.map +1 -1
  89. package/dist/tui/components/LogPanel.d.ts +1 -1
  90. package/dist/tui/components/LogPanel.d.ts.map +1 -1
  91. package/dist/tui/components/LogPanel.js +26 -24
  92. package/dist/tui/components/LogPanel.js.map +1 -1
  93. package/dist/tui/components/TabBar.d.ts +2 -2
  94. package/dist/tui/components/TabBar.d.ts.map +1 -1
  95. package/dist/tui/components/TabBar.js +11 -11
  96. package/dist/tui/components/TabBar.js.map +1 -1
  97. package/dist/tui/components/WelcomeScreen.d.ts.map +1 -1
  98. package/dist/tui/components/WelcomeScreen.js +6 -6
  99. package/dist/tui/components/WelcomeScreen.js.map +1 -1
  100. package/dist/tui/index.d.ts.map +1 -1
  101. package/dist/tui/index.js +8 -8
  102. package/dist/tui/index.js.map +1 -1
  103. package/dist/tui/services/AIService.d.ts +2 -2
  104. package/dist/tui/services/AIService.d.ts.map +1 -1
  105. package/dist/tui/services/AIService.js +165 -125
  106. package/dist/tui/services/AIService.js.map +1 -1
  107. package/dist/tui/services/ExtensionService.d.ts +1 -1
  108. package/dist/tui/services/ExtensionService.d.ts.map +1 -1
  109. package/dist/tui/services/ExtensionService.js +33 -26
  110. package/dist/tui/services/ExtensionService.js.map +1 -1
  111. package/dist/tui/services/GeminiService.d.ts +1 -1
  112. package/dist/tui/services/GeminiService.d.ts.map +1 -1
  113. package/dist/tui/services/GeminiService.js +87 -76
  114. package/dist/tui/services/GeminiService.js.map +1 -1
  115. package/dist/tui/services/ServiceManager.d.ts +3 -3
  116. package/dist/tui/services/ServiceManager.d.ts.map +1 -1
  117. package/dist/tui/services/ServiceManager.js +72 -58
  118. package/dist/tui/services/ServiceManager.js.map +1 -1
  119. package/dist/tui/services/SocketService.d.ts.map +1 -1
  120. package/dist/tui/services/SocketService.js +32 -32
  121. package/dist/tui/services/SocketService.js.map +1 -1
  122. package/dist/tui/services/ViteService.d.ts.map +1 -1
  123. package/dist/tui/services/ViteService.js +26 -28
  124. package/dist/tui/services/ViteService.js.map +1 -1
  125. package/dist/tui/services/index.d.ts +6 -6
  126. package/dist/tui/services/index.d.ts.map +1 -1
  127. package/dist/tui/services/index.js +6 -6
  128. package/dist/tui/services/index.js.map +1 -1
  129. package/mcp/gxp-api-server.js +83 -81
  130. package/package.json +109 -93
  131. package/runtime/PortalContainer.vue +258 -234
  132. package/runtime/dev-tools/DevToolsModal.vue +153 -155
  133. package/runtime/dev-tools/LayoutSwitcher.vue +144 -140
  134. package/runtime/dev-tools/MockDataEditor.vue +456 -433
  135. package/runtime/dev-tools/SocketSimulator.vue +379 -371
  136. package/runtime/dev-tools/StoreInspector.vue +517 -455
  137. package/runtime/dev-tools/index.js +5 -5
  138. package/runtime/fallback-layouts/PrivateLayout.vue +2 -2
  139. package/runtime/fallback-layouts/PublicLayout.vue +2 -2
  140. package/runtime/fallback-layouts/SystemLayout.vue +2 -2
  141. package/runtime/gxpStringsPlugin.js +159 -134
  142. package/runtime/index.html +17 -19
  143. package/runtime/main.js +24 -22
  144. package/runtime/mock-api/auth-middleware.js +15 -15
  145. package/runtime/mock-api/image-generator.js +46 -46
  146. package/runtime/mock-api/index.js +55 -55
  147. package/runtime/mock-api/response-generator.js +116 -105
  148. package/runtime/mock-api/route-generator.js +107 -84
  149. package/runtime/mock-api/socket-triggers.js +94 -93
  150. package/runtime/mock-api/spec-loader.js +79 -80
  151. package/runtime/package.json +3 -0
  152. package/runtime/server.js +68 -68
  153. package/runtime/stores/gxpPortalConfigStore.js +204 -186
  154. package/runtime/stores/index.js +2 -2
  155. package/runtime/vite-inspector-plugin.js +858 -707
  156. package/runtime/vite-source-tracker-plugin.js +132 -113
  157. package/runtime/vite.config.js +191 -139
  158. package/scripts/launch-chrome.js +41 -41
  159. package/scripts/pack-chrome.js +38 -39
  160. package/socket-events/AiSessionMessageCreated.json +17 -17
  161. package/socket-events/SocialStreamPostCreated.json +23 -23
  162. package/socket-events/SocialStreamPostVariantCompleted.json +22 -22
  163. package/template/.claude/agents/gxp-developer.md +100 -99
  164. package/template/.claude/settings.json +7 -7
  165. package/template/AGENTS.md +30 -23
  166. package/template/GEMINI.md +20 -20
  167. package/template/README.md +70 -53
  168. package/template/app-manifest.json +2 -4
  169. package/template/configuration.json +10 -10
  170. package/template/default-styling.css +1 -1
  171. package/template/index.html +18 -20
  172. package/template/main.js +24 -22
  173. package/template/src/DemoPage.vue +415 -362
  174. package/template/src/Plugin.vue +76 -85
  175. package/template/src/stores/index.js +3 -3
  176. package/template/src/stores/test-data.json +164 -172
  177. package/template/theme-layouts/AdditionalStyling.css +50 -50
  178. package/template/theme-layouts/PrivateLayout.vue +8 -12
  179. package/template/theme-layouts/PublicLayout.vue +8 -12
  180. package/template/theme-layouts/SystemLayout.vue +8 -12
  181. package/template/vite.extend.js +45 -0
  182. package/template/vite.config.js +0 -409
package/dist/tui/index.js CHANGED
@@ -1,12 +1,12 @@
1
1
  #!/usr/bin/env node
2
2
  import { jsx as _jsx } from "react/jsx-runtime";
3
- import { render } from 'ink';
4
- import dotenv from 'dotenv';
5
- import path from 'path';
6
- import App from './App.js';
7
- import { serviceManager } from './services/index.js';
3
+ import { render } from "ink";
4
+ import dotenv from "dotenv";
5
+ import path from "path";
6
+ import App from "./App.js";
7
+ import { serviceManager } from "./services/index.js";
8
8
  // Load .env from the current working directory (project directory)
9
- dotenv.config({ path: path.join(process.cwd(), '.env') });
9
+ dotenv.config({ path: path.join(process.cwd(), ".env") });
10
10
  export function startTUI(options = {}) {
11
11
  // Check if stdin supports raw mode (required for Ink input handling)
12
12
  // This can fail when:
@@ -18,7 +18,7 @@ export function startTUI(options = {}) {
18
18
  // If stdin doesn't support raw mode, we need to handle it gracefully
19
19
  // Ink 5.x uses stdin by default and requires raw mode for input
20
20
  if (!stdinIsTTY) {
21
- throw new Error('NO_TTY');
21
+ throw new Error("NO_TTY");
22
22
  }
23
23
  const { waitUntilExit } = render(_jsx(App, { autoStart: options.autoStart, args: options.args }));
24
24
  waitUntilExit().then(() => {
@@ -28,7 +28,7 @@ export function startTUI(options = {}) {
28
28
  });
29
29
  }
30
30
  // Check if run directly (ESM way)
31
- import { fileURLToPath } from 'url';
31
+ import { fileURLToPath } from "url";
32
32
  const isMain = process.argv[1] && process.argv[1] === fileURLToPath(import.meta.url);
33
33
  if (isMain) {
34
34
  startTUI();
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../bin/lib/tui/index.tsx"],"names":[],"mappings":";;AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,KAAK,CAAC;AAC7B,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,GAAG,MAAM,UAAU,CAAC;AAC3B,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAErD,mEAAmE;AACnE,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;AAO1D,MAAM,UAAU,QAAQ,CAAC,UAAsB,EAAE;IAC/C,qEAAqE;IACrE,sBAAsB;IACtB,+BAA+B;IAC/B,qCAAqC;IACrC,4BAA4B;IAC5B,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;IAC5B,MAAM,UAAU,GAAG,KAAK,CAAC,KAAK,KAAK,IAAI,CAAC;IAExC,qEAAqE;IACrE,gEAAgE;IAChE,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,MAAM,IAAI,KAAK,CAAC,QAAQ,CAAC,CAAC;IAC5B,CAAC;IAED,MAAM,EAAE,aAAa,EAAE,GAAG,MAAM,CAC9B,KAAC,GAAG,IACF,SAAS,EAAE,OAAO,CAAC,SAAS,EAC5B,IAAI,EAAE,OAAO,CAAC,IAAI,GAClB,CACH,CAAC;IAEF,aAAa,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE;QACxB,iDAAiD;QACjD,cAAc,CAAC,YAAY,EAAE,CAAC;QAC9B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC;AAED,kCAAkC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACrF,IAAI,MAAM,EAAE,CAAC;IACX,QAAQ,EAAE,CAAC;AACb,CAAC;AAED,eAAe,QAAQ,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../bin/lib/tui/index.tsx"],"names":[],"mappings":";;AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,KAAK,CAAA;AAC5B,OAAO,MAAM,MAAM,QAAQ,CAAA;AAC3B,OAAO,IAAI,MAAM,MAAM,CAAA;AACvB,OAAO,GAAG,MAAM,UAAU,CAAA;AAC1B,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AAEpD,mEAAmE;AACnE,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,MAAM,CAAC,EAAE,CAAC,CAAA;AAOzD,MAAM,UAAU,QAAQ,CAAC,UAAsB,EAAE;IAChD,qEAAqE;IACrE,sBAAsB;IACtB,+BAA+B;IAC/B,qCAAqC;IACrC,4BAA4B;IAC5B,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAA;IAC3B,MAAM,UAAU,GAAG,KAAK,CAAC,KAAK,KAAK,IAAI,CAAA;IAEvC,qEAAqE;IACrE,gEAAgE;IAChE,IAAI,CAAC,UAAU,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,QAAQ,CAAC,CAAA;IAC1B,CAAC;IAED,MAAM,EAAE,aAAa,EAAE,GAAG,MAAM,CAC/B,KAAC,GAAG,IAAC,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,GAAI,CACzD,CAAA;IAED,aAAa,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE;QACzB,iDAAiD;QACjD,cAAc,CAAC,YAAY,EAAE,CAAA;QAC7B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IAChB,CAAC,CAAC,CAAA;AACH,CAAC;AAED,kCAAkC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAA;AACnC,MAAM,MAAM,GACX,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;AACtE,IAAI,MAAM,EAAE,CAAC;IACZ,QAAQ,EAAE,CAAA;AACX,CAAC;AAED,eAAe,QAAQ,CAAA"}
@@ -1,5 +1,5 @@
1
- import { EventEmitter } from 'events';
2
- export type AIProvider = 'claude' | 'codex' | 'gemini';
1
+ import { EventEmitter } from "events";
2
+ export type AIProvider = "claude" | "codex" | "gemini";
3
3
  export interface AIProviderInfo {
4
4
  id: AIProvider;
5
5
  name: string;
@@ -1 +1 @@
1
- {"version":3,"file":"AIService.d.ts","sourceRoot":"","sources":["../../../bin/lib/tui/services/AIService.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAGtC,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,CAAC;AAEvD,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,UAAU,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAGD,MAAM,WAAW,QAAQ;IACvB,QAAQ,EAAE,UAAU,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,OAAO,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAsBD,wBAAgB,YAAY,IAAI,QAAQ,CAgBvC;AAGD,wBAAgB,YAAY,CAAC,MAAM,EAAE,QAAQ,GAAG,IAAI,CAInD;AAaD,wBAAgB,qBAAqB,IAAI,cAAc,EAAE,CA+ExD;AAGD,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,cAAc,GAAG,MAAM,CAelE;AAGD,qBAAa,SAAU,SAAQ,YAAY;IACzC,OAAO,CAAC,mBAAmB,CAAgD;IAC3E,OAAO,CAAC,cAAc,CAAc;IACpC,OAAO,CAAC,eAAe,CAAa;IACpC,OAAO,CAAC,YAAY,CAAC,CAAS;;IAgB9B,WAAW,IAAI,UAAU;IAKzB,WAAW,CAAC,QAAQ,EAAE,UAAU,GAAG;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE;IA2BxE,WAAW,IAAI,OAAO;IAOtB,eAAe,IAAI,cAAc,GAAG,SAAS;IAM7C,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAqB/B,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;YAsBrC,cAAc;YAqCd,aAAa;YAqCb,cAAc;YAed,iBAAiB;YAmCjB,iBAAiB;YAiCjB,oBAAoB;IAoDlC,iBAAiB,IAAI,IAAI;IAKzB,sBAAsB,IAAI,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CAGnE;AAGD,eAAO,MAAM,SAAS,WAAkB,CAAC"}
1
+ {"version":3,"file":"AIService.d.ts","sourceRoot":"","sources":["../../../bin/lib/tui/services/AIService.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAA;AAGrC,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,CAAA;AAEtD,MAAM,WAAW,cAAc;IAC9B,EAAE,EAAE,UAAU,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,OAAO,CAAA;IAClB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;CACf;AAGD,MAAM,WAAW,QAAQ;IACxB,QAAQ,EAAE,UAAU,CAAA;IACpB,YAAY,EAAE,MAAM,CAAA;IACpB,cAAc,EAAE,OAAO,CAAA;IACvB,gBAAgB,EAAE,MAAM,CAAA;CACxB;AAsBD,wBAAgB,YAAY,IAAI,QAAQ,CAiBvC;AAGD,wBAAgB,YAAY,CAAC,MAAM,EAAE,QAAQ,GAAG,IAAI,CAInD;AAaD,wBAAgB,qBAAqB,IAAI,cAAc,EAAE,CAiFxD;AAGD,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,cAAc,GAAG,MAAM,CAelE;AAGD,qBAAa,SAAU,SAAQ,YAAY;IAC1C,OAAO,CAAC,mBAAmB,CAA+C;IAC1E,OAAO,CAAC,cAAc,CAAa;IACnC,OAAO,CAAC,eAAe,CAAY;IACnC,OAAO,CAAC,YAAY,CAAC,CAAQ;;IAgB7B,WAAW,IAAI,UAAU;IAKzB,WAAW,CAAC,QAAQ,EAAE,UAAU,GAAG;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE;IA8BxE,WAAW,IAAI,OAAO;IAOtB,eAAe,IAAI,cAAc,GAAG,SAAS;IAM7C,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IA4B/B,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;YAsBrC,cAAc;YA0Cd,aAAa;YA0Cb,cAAc;YAoBd,iBAAiB;YAmCjB,iBAAiB;YAmCjB,oBAAoB;IA8ElC,iBAAiB,IAAI,IAAI;IAKzB,sBAAsB,IAAI,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CAGlE;AAGD,eAAO,MAAM,SAAS,WAAkB,CAAA"}
@@ -1,11 +1,11 @@
1
- import fs from 'fs';
2
- import path from 'path';
3
- import { spawn, execSync } from 'child_process';
4
- import { EventEmitter } from 'events';
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import { spawn, execSync } from "child_process";
4
+ import { EventEmitter } from "events";
5
5
  // Get the gxdev config directory
6
6
  function getConfigDir() {
7
- const home = process.env.HOME || process.env.USERPROFILE || '';
8
- return path.join(home, '.gxdev');
7
+ const home = process.env.HOME || process.env.USERPROFILE || "";
8
+ return path.join(home, ".gxdev");
9
9
  }
10
10
  // Ensure config directory exists
11
11
  function ensureConfigDir() {
@@ -16,14 +16,14 @@ function ensureConfigDir() {
16
16
  }
17
17
  // Get AI config file path
18
18
  function getAIConfigPath() {
19
- return path.join(getConfigDir(), 'ai-config.json');
19
+ return path.join(getConfigDir(), "ai-config.json");
20
20
  }
21
21
  // Load AI config
22
22
  export function loadAIConfig() {
23
23
  try {
24
24
  const configPath = getAIConfigPath();
25
25
  if (fs.existsSync(configPath)) {
26
- const content = fs.readFileSync(configPath, 'utf-8');
26
+ const content = fs.readFileSync(configPath, "utf-8");
27
27
  return JSON.parse(content);
28
28
  }
29
29
  }
@@ -31,8 +31,8 @@ export function loadAIConfig() {
31
31
  // Invalid or missing config file
32
32
  }
33
33
  return {
34
- provider: 'claude', // Default to Claude
35
- systemPrompt: 'You are a helpful assistant for GxP plugin development. Help the user build Vue.js components for the GxP kiosk platform.',
34
+ provider: "claude", // Default to Claude
35
+ systemPrompt: "You are a helpful assistant for GxP plugin development. Help the user build Vue.js components for the GxP kiosk platform.",
36
36
  projectContext: true,
37
37
  maxContextTokens: 4000,
38
38
  };
@@ -46,7 +46,7 @@ export function saveAIConfig(config) {
46
46
  // Check if a command exists
47
47
  function commandExists(cmd) {
48
48
  try {
49
- execSync(`which ${cmd}`, { stdio: 'pipe' });
49
+ execSync(`which ${cmd}`, { stdio: "pipe" });
50
50
  return true;
51
51
  }
52
52
  catch {
@@ -57,81 +57,83 @@ function commandExists(cmd) {
57
57
  export function getAvailableProviders() {
58
58
  const providers = [];
59
59
  // Check Claude CLI
60
- if (commandExists('claude')) {
60
+ if (commandExists("claude")) {
61
61
  providers.push({
62
- id: 'claude',
63
- name: 'Claude',
62
+ id: "claude",
63
+ name: "Claude",
64
64
  available: true,
65
65
  });
66
66
  }
67
67
  else {
68
68
  providers.push({
69
- id: 'claude',
70
- name: 'Claude',
69
+ id: "claude",
70
+ name: "Claude",
71
71
  available: false,
72
- reason: 'Install: npm i -g @anthropic-ai/claude-code && claude login',
72
+ reason: "Install: npm i -g @anthropic-ai/claude-code && claude login",
73
73
  });
74
74
  }
75
75
  // Check Codex CLI
76
- if (commandExists('codex')) {
76
+ if (commandExists("codex")) {
77
77
  providers.push({
78
- id: 'codex',
79
- name: 'Codex',
78
+ id: "codex",
79
+ name: "Codex",
80
80
  available: true,
81
81
  });
82
82
  }
83
83
  else {
84
84
  providers.push({
85
- id: 'codex',
86
- name: 'Codex',
85
+ id: "codex",
86
+ name: "Codex",
87
87
  available: false,
88
- reason: 'Install: npm i -g @openai/codex && codex auth',
88
+ reason: "Install: npm i -g @openai/codex && codex auth",
89
89
  });
90
90
  }
91
91
  // Check Gemini (CLI, API key, or gcloud)
92
- if (commandExists('gemini')) {
92
+ if (commandExists("gemini")) {
93
93
  providers.push({
94
- id: 'gemini',
95
- name: 'Gemini',
94
+ id: "gemini",
95
+ name: "Gemini",
96
96
  available: true,
97
- method: 'cli',
97
+ method: "cli",
98
98
  });
99
99
  }
100
100
  else if (process.env.GEMINI_API_KEY || process.env.GOOGLE_API_KEY) {
101
101
  providers.push({
102
- id: 'gemini',
103
- name: 'Gemini',
102
+ id: "gemini",
103
+ name: "Gemini",
104
104
  available: true,
105
- method: 'api_key',
105
+ method: "api_key",
106
106
  });
107
107
  }
108
- else if (commandExists('gcloud')) {
108
+ else if (commandExists("gcloud")) {
109
109
  try {
110
- const authList = execSync("gcloud auth list --format='value(account)'", { stdio: 'pipe' }).toString();
110
+ const authList = execSync("gcloud auth list --format='value(account)'", {
111
+ stdio: "pipe",
112
+ }).toString();
111
113
  if (authList.trim()) {
112
114
  providers.push({
113
- id: 'gemini',
114
- name: 'Gemini',
115
+ id: "gemini",
116
+ name: "Gemini",
115
117
  available: true,
116
- method: 'gcloud',
118
+ method: "gcloud",
117
119
  });
118
120
  }
119
121
  }
120
122
  catch {
121
123
  providers.push({
122
- id: 'gemini',
123
- name: 'Gemini',
124
+ id: "gemini",
125
+ name: "Gemini",
124
126
  available: false,
125
- reason: 'Install: npm i -g @google/gemini-cli && gemini',
127
+ reason: "Install: npm i -g @google/gemini-cli && gemini",
126
128
  });
127
129
  }
128
130
  }
129
131
  else {
130
132
  providers.push({
131
- id: 'gemini',
132
- name: 'Gemini',
133
+ id: "gemini",
134
+ name: "Gemini",
133
135
  available: false,
134
- reason: 'Install: npm i -g @google/gemini-cli && gemini',
136
+ reason: "Install: npm i -g @google/gemini-cli && gemini",
135
137
  });
136
138
  }
137
139
  return providers;
@@ -143,11 +145,11 @@ export function getProviderStatus(provider) {
143
145
  }
144
146
  if (provider.method) {
145
147
  switch (provider.method) {
146
- case 'cli':
148
+ case "cli":
147
149
  return `${provider.name} (CLI)`;
148
- case 'api_key':
150
+ case "api_key":
149
151
  return `${provider.name} (API key)`;
150
- case 'gcloud':
152
+ case "gcloud":
151
153
  return `${provider.name} (gcloud)`;
152
154
  }
153
155
  }
@@ -158,12 +160,12 @@ export class AIService extends EventEmitter {
158
160
  constructor() {
159
161
  super();
160
162
  this.conversationHistory = [];
161
- this.projectContext = '';
163
+ this.projectContext = "";
162
164
  const config = loadAIConfig();
163
165
  this.currentProvider = config.provider;
164
166
  // Determine gemini method if that's the current provider
165
167
  const providers = getAvailableProviders();
166
- const geminiProvider = providers.find(p => p.id === 'gemini');
168
+ const geminiProvider = providers.find((p) => p.id === "gemini");
167
169
  if (geminiProvider?.available) {
168
170
  this.geminiMethod = geminiProvider.method;
169
171
  }
@@ -175,15 +177,18 @@ export class AIService extends EventEmitter {
175
177
  // Set current provider
176
178
  setProvider(provider) {
177
179
  const providers = getAvailableProviders();
178
- const providerInfo = providers.find(p => p.id === provider);
180
+ const providerInfo = providers.find((p) => p.id === provider);
179
181
  if (!providerInfo) {
180
182
  return { success: false, message: `Unknown provider: ${provider}` };
181
183
  }
182
184
  if (!providerInfo.available) {
183
- return { success: false, message: `${providerInfo.name} is not available. ${providerInfo.reason || ''}` };
185
+ return {
186
+ success: false,
187
+ message: `${providerInfo.name} is not available. ${providerInfo.reason || ""}`,
188
+ };
184
189
  }
185
190
  this.currentProvider = provider;
186
- if (provider === 'gemini') {
191
+ if (provider === "gemini") {
187
192
  this.geminiMethod = providerInfo.method;
188
193
  }
189
194
  // Save to config
@@ -196,23 +201,30 @@ export class AIService extends EventEmitter {
196
201
  // Check if current provider is available
197
202
  isAvailable() {
198
203
  const providers = getAvailableProviders();
199
- const current = providers.find(p => p.id === this.currentProvider);
204
+ const current = providers.find((p) => p.id === this.currentProvider);
200
205
  return current?.available || false;
201
206
  }
202
207
  // Get provider info
203
208
  getProviderInfo() {
204
209
  const providers = getAvailableProviders();
205
- return providers.find(p => p.id === this.currentProvider);
210
+ return providers.find((p) => p.id === this.currentProvider);
206
211
  }
207
212
  // Load project context
208
213
  loadProjectContext(cwd) {
209
- const files = ['CLAUDE.md', 'AGENTS.md', 'GEMINI.md', 'README.md', 'package.json', 'app-manifest.json'];
214
+ const files = [
215
+ "CLAUDE.md",
216
+ "AGENTS.md",
217
+ "GEMINI.md",
218
+ "README.md",
219
+ "package.json",
220
+ "app-manifest.json",
221
+ ];
210
222
  const contextParts = [];
211
223
  for (const file of files) {
212
224
  const filePath = path.join(cwd, file);
213
225
  if (fs.existsSync(filePath)) {
214
226
  try {
215
- const content = fs.readFileSync(filePath, 'utf-8');
227
+ const content = fs.readFileSync(filePath, "utf-8");
216
228
  // Limit each file to 2000 chars
217
229
  contextParts.push(`=== ${file} ===\n${content.slice(0, 2000)}`);
218
230
  }
@@ -221,22 +233,22 @@ export class AIService extends EventEmitter {
221
233
  }
222
234
  }
223
235
  }
224
- this.projectContext = contextParts.join('\n\n');
236
+ this.projectContext = contextParts.join("\n\n");
225
237
  }
226
238
  // Send message using current provider
227
239
  async sendMessage(message) {
228
240
  const config = loadAIConfig();
229
241
  // Build context
230
- let systemContext = config.systemPrompt || '';
242
+ let systemContext = config.systemPrompt || "";
231
243
  if (config.projectContext && this.projectContext) {
232
- systemContext += '\n\nProject Context:\n' + this.projectContext;
244
+ systemContext += "\n\nProject Context:\n" + this.projectContext;
233
245
  }
234
246
  switch (this.currentProvider) {
235
- case 'claude':
247
+ case "claude":
236
248
  return this.sendWithClaude(message, systemContext);
237
- case 'codex':
249
+ case "codex":
238
250
  return this.sendWithCodex(message, systemContext);
239
- case 'gemini':
251
+ case "gemini":
240
252
  return this.sendWithGemini(message, systemContext);
241
253
  default:
242
254
  throw new Error(`Unknown provider: ${this.currentProvider}`);
@@ -245,29 +257,31 @@ export class AIService extends EventEmitter {
245
257
  // Send message with Claude CLI
246
258
  async sendWithClaude(message, systemContext) {
247
259
  return new Promise((resolve, reject) => {
248
- let output = '';
249
- let errorOutput = '';
250
- const fullPrompt = systemContext ? `${systemContext}\n\nUser: ${message}` : message;
251
- const claude = spawn('claude', ['--print', '-p', fullPrompt], {
252
- stdio: ['pipe', 'pipe', 'pipe'],
260
+ let output = "";
261
+ let errorOutput = "";
262
+ const fullPrompt = systemContext
263
+ ? `${systemContext}\n\nUser: ${message}`
264
+ : message;
265
+ const claude = spawn("claude", ["--print", "-p", fullPrompt], {
266
+ stdio: ["pipe", "pipe", "pipe"],
253
267
  shell: true,
254
268
  });
255
- claude.stdout.on('data', (data) => {
269
+ claude.stdout.on("data", (data) => {
256
270
  output += data.toString();
257
271
  });
258
- claude.stderr.on('data', (data) => {
272
+ claude.stderr.on("data", (data) => {
259
273
  errorOutput += data.toString();
260
274
  });
261
- claude.on('close', (code) => {
275
+ claude.on("close", (code) => {
262
276
  if (code !== 0) {
263
- reject(new Error(`Claude error: ${errorOutput || 'Unknown error'}`));
277
+ reject(new Error(`Claude error: ${errorOutput || "Unknown error"}`));
264
278
  return;
265
279
  }
266
- this.conversationHistory.push({ role: 'user', content: message });
267
- this.conversationHistory.push({ role: 'assistant', content: output });
280
+ this.conversationHistory.push({ role: "user", content: message });
281
+ this.conversationHistory.push({ role: "assistant", content: output });
268
282
  resolve(output.trim());
269
283
  });
270
- claude.on('error', (err) => {
284
+ claude.on("error", (err) => {
271
285
  reject(new Error(`Failed to run Claude: ${err.message}`));
272
286
  });
273
287
  });
@@ -275,72 +289,76 @@ export class AIService extends EventEmitter {
275
289
  // Send message with Codex CLI
276
290
  async sendWithCodex(message, systemContext) {
277
291
  return new Promise((resolve, reject) => {
278
- let output = '';
279
- let errorOutput = '';
280
- const fullPrompt = systemContext ? `${systemContext}\n\nUser: ${message}` : message;
281
- const codex = spawn('codex', ['--quiet', '-p', fullPrompt], {
282
- stdio: ['pipe', 'pipe', 'pipe'],
292
+ let output = "";
293
+ let errorOutput = "";
294
+ const fullPrompt = systemContext
295
+ ? `${systemContext}\n\nUser: ${message}`
296
+ : message;
297
+ const codex = spawn("codex", ["--quiet", "-p", fullPrompt], {
298
+ stdio: ["pipe", "pipe", "pipe"],
283
299
  shell: true,
284
300
  });
285
- codex.stdout.on('data', (data) => {
301
+ codex.stdout.on("data", (data) => {
286
302
  output += data.toString();
287
303
  });
288
- codex.stderr.on('data', (data) => {
304
+ codex.stderr.on("data", (data) => {
289
305
  errorOutput += data.toString();
290
306
  });
291
- codex.on('close', (code) => {
307
+ codex.on("close", (code) => {
292
308
  if (code !== 0) {
293
- reject(new Error(`Codex error: ${errorOutput || 'Unknown error'}`));
309
+ reject(new Error(`Codex error: ${errorOutput || "Unknown error"}`));
294
310
  return;
295
311
  }
296
- this.conversationHistory.push({ role: 'user', content: message });
297
- this.conversationHistory.push({ role: 'assistant', content: output });
312
+ this.conversationHistory.push({ role: "user", content: message });
313
+ this.conversationHistory.push({ role: "assistant", content: output });
298
314
  resolve(output.trim());
299
315
  });
300
- codex.on('error', (err) => {
316
+ codex.on("error", (err) => {
301
317
  reject(new Error(`Failed to run Codex: ${err.message}`));
302
318
  });
303
319
  });
304
320
  }
305
321
  // Send message with Gemini
306
322
  async sendWithGemini(message, systemContext) {
307
- const fullPrompt = systemContext ? `${systemContext}\n\nUser: ${message}` : message;
308
- if (this.geminiMethod === 'cli') {
323
+ const fullPrompt = systemContext
324
+ ? `${systemContext}\n\nUser: ${message}`
325
+ : message;
326
+ if (this.geminiMethod === "cli") {
309
327
  return this.sendWithGeminiCli(fullPrompt);
310
328
  }
311
- else if (this.geminiMethod === 'api_key') {
329
+ else if (this.geminiMethod === "api_key") {
312
330
  return this.sendWithGeminiApi(fullPrompt);
313
331
  }
314
- else if (this.geminiMethod === 'gcloud') {
332
+ else if (this.geminiMethod === "gcloud") {
315
333
  return this.sendWithGeminiGcloud(fullPrompt);
316
334
  }
317
- throw new Error('Gemini is not properly configured');
335
+ throw new Error("Gemini is not properly configured");
318
336
  }
319
337
  // Send with Gemini CLI
320
338
  async sendWithGeminiCli(prompt) {
321
339
  return new Promise((resolve, reject) => {
322
- let output = '';
323
- let errorOutput = '';
324
- const gemini = spawn('gemini', ['-p', prompt], {
325
- stdio: ['pipe', 'pipe', 'pipe'],
340
+ let output = "";
341
+ let errorOutput = "";
342
+ const gemini = spawn("gemini", ["-p", prompt], {
343
+ stdio: ["pipe", "pipe", "pipe"],
326
344
  shell: true,
327
345
  });
328
- gemini.stdout.on('data', (data) => {
346
+ gemini.stdout.on("data", (data) => {
329
347
  output += data.toString();
330
348
  });
331
- gemini.stderr.on('data', (data) => {
349
+ gemini.stderr.on("data", (data) => {
332
350
  errorOutput += data.toString();
333
351
  });
334
- gemini.on('close', (code) => {
352
+ gemini.on("close", (code) => {
335
353
  if (code !== 0) {
336
- reject(new Error(`Gemini error: ${errorOutput || 'Unknown error'}`));
354
+ reject(new Error(`Gemini error: ${errorOutput || "Unknown error"}`));
337
355
  return;
338
356
  }
339
- this.conversationHistory.push({ role: 'user', content: prompt });
340
- this.conversationHistory.push({ role: 'assistant', content: output });
357
+ this.conversationHistory.push({ role: "user", content: prompt });
358
+ this.conversationHistory.push({ role: "assistant", content: output });
341
359
  resolve(output.trim());
342
360
  });
343
- gemini.on('error', (err) => {
361
+ gemini.on("error", (err) => {
344
362
  reject(new Error(`Failed to run Gemini: ${err.message}`));
345
363
  });
346
364
  });
@@ -349,13 +367,13 @@ export class AIService extends EventEmitter {
349
367
  async sendWithGeminiApi(prompt) {
350
368
  const apiKey = process.env.GEMINI_API_KEY || process.env.GOOGLE_API_KEY;
351
369
  if (!apiKey) {
352
- throw new Error('GEMINI_API_KEY not set');
370
+ throw new Error("GEMINI_API_KEY not set");
353
371
  }
354
372
  const response = await fetch(`https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=${apiKey}`, {
355
- method: 'POST',
356
- headers: { 'Content-Type': 'application/json' },
373
+ method: "POST",
374
+ headers: { "Content-Type": "application/json" },
357
375
  body: JSON.stringify({
358
- contents: [{ role: 'user', parts: [{ text: prompt }] }],
376
+ contents: [{ role: "user", parts: [{ text: prompt }] }],
359
377
  generationConfig: { maxOutputTokens: 2048, temperature: 0.7 },
360
378
  }),
361
379
  });
@@ -363,10 +381,11 @@ export class AIService extends EventEmitter {
363
381
  const errorText = await response.text();
364
382
  throw new Error(`Gemini API error: ${response.status} - ${errorText}`);
365
383
  }
366
- const data = await response.json();
367
- const responseText = data.candidates?.[0]?.content?.parts?.[0]?.text || 'No response generated.';
368
- this.conversationHistory.push({ role: 'user', content: prompt });
369
- this.conversationHistory.push({ role: 'assistant', content: responseText });
384
+ const data = (await response.json());
385
+ const responseText = data.candidates?.[0]?.content?.parts?.[0]?.text ||
386
+ "No response generated.";
387
+ this.conversationHistory.push({ role: "user", content: prompt });
388
+ this.conversationHistory.push({ role: "assistant", content: responseText });
370
389
  return responseText;
371
390
  }
372
391
  // Send with Gemini via gcloud
@@ -375,38 +394,59 @@ export class AIService extends EventEmitter {
375
394
  let accessToken;
376
395
  let projectId;
377
396
  try {
378
- accessToken = execSync('gcloud auth print-access-token', { stdio: 'pipe' }).toString().trim();
379
- projectId = execSync('gcloud config get-value project', { stdio: 'pipe' }).toString().trim();
397
+ accessToken = execSync("gcloud auth print-access-token", {
398
+ stdio: "pipe",
399
+ })
400
+ .toString()
401
+ .trim();
402
+ projectId = execSync("gcloud config get-value project", {
403
+ stdio: "pipe",
404
+ })
405
+ .toString()
406
+ .trim();
380
407
  }
381
408
  catch (error) {
382
- reject(new Error('Failed to get gcloud credentials'));
409
+ reject(new Error("Failed to get gcloud credentials"));
383
410
  return;
384
411
  }
385
412
  const requestBody = JSON.stringify({
386
- contents: [{ role: 'user', parts: [{ text: prompt }] }],
413
+ contents: [{ role: "user", parts: [{ text: prompt }] }],
387
414
  generationConfig: { maxOutputTokens: 2048, temperature: 0.7 },
388
415
  });
389
- const curl = spawn('curl', [
390
- '-s', '-X', 'POST',
416
+ const curl = spawn("curl", [
417
+ "-s",
418
+ "-X",
419
+ "POST",
391
420
  `https://us-central1-aiplatform.googleapis.com/v1/projects/${projectId}/locations/us-central1/publishers/google/models/gemini-1.5-flash:generateContent`,
392
- '-H', `Authorization: Bearer ${accessToken}`,
393
- '-H', 'Content-Type: application/json',
394
- '-d', requestBody,
395
- ], { stdio: ['pipe', 'pipe', 'pipe'] });
396
- let output = '';
397
- let errorOutput = '';
398
- curl.stdout.on('data', (data) => { output += data.toString(); });
399
- curl.stderr.on('data', (data) => { errorOutput += data.toString(); });
400
- curl.on('close', (code) => {
421
+ "-H",
422
+ `Authorization: Bearer ${accessToken}`,
423
+ "-H",
424
+ "Content-Type: application/json",
425
+ "-d",
426
+ requestBody,
427
+ ], { stdio: ["pipe", "pipe", "pipe"] });
428
+ let output = "";
429
+ let errorOutput = "";
430
+ curl.stdout.on("data", (data) => {
431
+ output += data.toString();
432
+ });
433
+ curl.stderr.on("data", (data) => {
434
+ errorOutput += data.toString();
435
+ });
436
+ curl.on("close", (code) => {
401
437
  if (code !== 0) {
402
438
  reject(new Error(`Gemini gcloud error: ${errorOutput}`));
403
439
  return;
404
440
  }
405
441
  try {
406
442
  const data = JSON.parse(output);
407
- const responseText = data.candidates?.[0]?.content?.parts?.[0]?.text || 'No response generated.';
408
- this.conversationHistory.push({ role: 'user', content: prompt });
409
- this.conversationHistory.push({ role: 'assistant', content: responseText });
443
+ const responseText = data.candidates?.[0]?.content?.parts?.[0]?.text ||
444
+ "No response generated.";
445
+ this.conversationHistory.push({ role: "user", content: prompt });
446
+ this.conversationHistory.push({
447
+ role: "assistant",
448
+ content: responseText,
449
+ });
410
450
  resolve(responseText);
411
451
  }
412
452
  catch (parseError) {