gaslighting-engine 0.3.1 → 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 (194) hide show
  1. package/README.md +133 -18
  2. package/desktop-dist/assets/index-BoI6eWtN.js +44 -0
  3. package/desktop-dist/assets/index-oFTvTTu8.css +1 -0
  4. package/desktop-dist/index.html +13 -0
  5. package/dist/agent-runtimes/permissions.js +34 -0
  6. package/dist/agent-runtimes/prompts.js +30 -0
  7. package/dist/agent-runtimes/registry.js +214 -0
  8. package/dist/agent-runtimes/types.js +1 -0
  9. package/dist/cli.js +142 -4
  10. package/dist/commands/agent.js +11 -0
  11. package/dist/commands/apiRun.js +32 -0
  12. package/dist/commands/cockpit.js +37 -6
  13. package/dist/commands/desktop.js +37 -0
  14. package/dist/commands/doctor.js +8 -1
  15. package/dist/commands/loop.js +64 -0
  16. package/dist/commands/mcp.js +43 -0
  17. package/dist/commands/skill.js +23 -0
  18. package/dist/core/codexRuntime.js +2 -19
  19. package/dist/core/generateDocs.js +16 -10
  20. package/dist/core/generateOtherMarkdown.js +27 -27
  21. package/dist/core/generateStructuredDocs.js +405 -0
  22. package/dist/core/mcpRegistry.js +103 -0
  23. package/dist/core/missionLoop.js +179 -0
  24. package/dist/core/skillRegistry.js +62 -0
  25. package/dist/desktop/main.js +186 -0
  26. package/dist/desktop/preload.js +22 -0
  27. package/dist/utils/logger.js +1 -1
  28. package/dist/version.js +1 -1
  29. package/docs/codex-usage.md +28 -3
  30. package/examples/ecommerce/.agents/config.json +10 -0
  31. package/examples/ecommerce/.agents/mcp/manifest.json +5 -0
  32. package/examples/ecommerce/.agents/runtimes/claude.json +6 -0
  33. package/examples/ecommerce/.agents/runtimes/codex.json +6 -0
  34. package/examples/ecommerce/.agents/runtimes/kimi.json +6 -0
  35. package/examples/ecommerce/.agents/runtimes/local.json +6 -0
  36. package/examples/ecommerce/.agents/runtimes/openai_compatible.json +6 -0
  37. package/examples/ecommerce/.agents/runtimes/opencode.json +6 -0
  38. package/examples/ecommerce/.agents/runtimes/qwen.json +6 -0
  39. package/examples/ecommerce/.codex/prompts/gaslighting.md +9 -9
  40. package/examples/ecommerce/.gaslighting/AGENTS.md +9 -9
  41. package/examples/ecommerce/.gaslighting/AGENT_RUNTIME.md +1 -1
  42. package/examples/ecommerce/.gaslighting/CODEX_PROMPT.md +9 -9
  43. package/examples/ecommerce/.gaslighting/DECISION_LOG.md +1 -1
  44. package/examples/ecommerce/.gaslighting/GASLIGHTING.md +2 -2
  45. package/examples/ecommerce/.gaslighting/INDEX.md +39 -0
  46. package/examples/ecommerce/.gaslighting/MEMORY.md +1 -1
  47. package/examples/ecommerce/.gaslighting/PRD.md +1 -1
  48. package/examples/ecommerce/.gaslighting/PROJECT_CARE.md +1 -1
  49. package/examples/ecommerce/.gaslighting/checkpoints/latest.md +7 -0
  50. package/examples/ecommerce/.gaslighting/config.json +7 -0
  51. package/examples/ecommerce/.gaslighting/decisions/ADR-0001-stack.md +11 -0
  52. package/examples/ecommerce/.gaslighting/decisions/ADR-0002-agent-runtime.md +11 -0
  53. package/examples/ecommerce/.gaslighting/features/core-scope/DECISIONS.md +5 -0
  54. package/examples/ecommerce/.gaslighting/features/core-scope/FEATURE.md +7 -0
  55. package/examples/ecommerce/.gaslighting/features/core-scope/RISKS.md +5 -0
  56. package/examples/ecommerce/.gaslighting/features/core-scope/TASKS.md +18 -0
  57. package/examples/ecommerce/.gaslighting/loops/current-session.json +9 -0
  58. package/examples/ecommerce/.gaslighting/memory/OPEN_QUESTIONS.md +5 -0
  59. package/examples/ecommerce/.gaslighting/memory/PROJECT_MEMORY.md +5 -0
  60. package/examples/ecommerce/.gaslighting/memory/SESSION_LOG.md +3 -0
  61. package/examples/ecommerce/.gaslighting/mission/COMPLETION_STANDARD.md +11 -0
  62. package/examples/ecommerce/.gaslighting/mission/EXECUTION_RULES.md +20 -0
  63. package/examples/ecommerce/.gaslighting/mission/PROJECT_PURPOSE.md +20 -0
  64. package/examples/ecommerce/.gaslighting/operations/DEPLOYMENT.md +6 -0
  65. package/examples/ecommerce/.gaslighting/operations/DOMAIN.md +6 -0
  66. package/examples/ecommerce/.gaslighting/operations/ENV.md +5 -0
  67. package/examples/ecommerce/.gaslighting/operations/GIT.md +7 -0
  68. package/examples/ecommerce/.gaslighting/operations/GITHUB.md +7 -0
  69. package/examples/ecommerce/.gaslighting/operations/PROJECT_CARE.md +76 -0
  70. package/examples/ecommerce/.gaslighting/pages/admin-products/ACCEPTANCE.md +7 -0
  71. package/examples/ecommerce/.gaslighting/pages/admin-products/PAGE_PRD.md +15 -0
  72. package/examples/ecommerce/.gaslighting/pages/cart/ACCEPTANCE.md +7 -0
  73. package/examples/ecommerce/.gaslighting/pages/cart/PAGE_PRD.md +15 -0
  74. package/examples/ecommerce/.gaslighting/pages/checkout/ACCEPTANCE.md +7 -0
  75. package/examples/ecommerce/.gaslighting/pages/checkout/PAGE_PRD.md +15 -0
  76. package/examples/ecommerce/.gaslighting/pages/home/ACCEPTANCE.md +7 -0
  77. package/examples/ecommerce/.gaslighting/pages/home/PAGE_PRD.md +15 -0
  78. package/examples/ecommerce/.gaslighting/pages/my-orders/ACCEPTANCE.md +7 -0
  79. package/examples/ecommerce/.gaslighting/pages/my-orders/PAGE_PRD.md +15 -0
  80. package/examples/ecommerce/.gaslighting/pages/order-complete/ACCEPTANCE.md +7 -0
  81. package/examples/ecommerce/.gaslighting/pages/order-complete/PAGE_PRD.md +15 -0
  82. package/examples/ecommerce/.gaslighting/pages/product-detail/ACCEPTANCE.md +7 -0
  83. package/examples/ecommerce/.gaslighting/pages/product-detail/PAGE_PRD.md +15 -0
  84. package/examples/ecommerce/.gaslighting/pages/product-list/ACCEPTANCE.md +7 -0
  85. package/examples/ecommerce/.gaslighting/pages/product-list/PAGE_PRD.md +15 -0
  86. package/examples/ecommerce/.gaslighting/product/PAGE_MAP.md +11 -0
  87. package/examples/ecommerce/.gaslighting/product/PRD.md +115 -0
  88. package/examples/ecommerce/.gaslighting/product/USER_FLOWS.md +22 -0
  89. package/examples/ecommerce/.gaslighting/tasks/TASK-0001.md +17 -0
  90. package/examples/ecommerce/.gaslighting/verification/latest-report.md +3 -0
  91. package/examples/ecommerce/AGENTS.md +12 -10
  92. package/examples/hospital-homepage/.agents/config.json +10 -0
  93. package/examples/hospital-homepage/.agents/mcp/manifest.json +5 -0
  94. package/examples/hospital-homepage/.agents/runtimes/claude.json +6 -0
  95. package/examples/hospital-homepage/.agents/runtimes/codex.json +6 -0
  96. package/examples/hospital-homepage/.agents/runtimes/kimi.json +6 -0
  97. package/examples/hospital-homepage/.agents/runtimes/local.json +6 -0
  98. package/examples/hospital-homepage/.agents/runtimes/openai_compatible.json +6 -0
  99. package/examples/hospital-homepage/.agents/runtimes/opencode.json +6 -0
  100. package/examples/hospital-homepage/.agents/runtimes/qwen.json +6 -0
  101. package/examples/hospital-homepage/.codex/prompts/gaslighting.md +9 -9
  102. package/examples/hospital-homepage/.gaslighting/AGENTS.md +9 -9
  103. package/examples/hospital-homepage/.gaslighting/CODEX_PROMPT.md +9 -9
  104. package/examples/hospital-homepage/.gaslighting/INDEX.md +37 -0
  105. package/examples/hospital-homepage/.gaslighting/checkpoints/latest.md +7 -0
  106. package/examples/hospital-homepage/.gaslighting/config.json +7 -0
  107. package/examples/hospital-homepage/.gaslighting/decisions/ADR-0001-stack.md +11 -0
  108. package/examples/hospital-homepage/.gaslighting/decisions/ADR-0002-agent-runtime.md +11 -0
  109. package/examples/hospital-homepage/.gaslighting/features/core-scope/DECISIONS.md +5 -0
  110. package/examples/hospital-homepage/.gaslighting/features/core-scope/FEATURE.md +7 -0
  111. package/examples/hospital-homepage/.gaslighting/features/core-scope/RISKS.md +5 -0
  112. package/examples/hospital-homepage/.gaslighting/features/core-scope/TASKS.md +17 -0
  113. package/examples/hospital-homepage/.gaslighting/loops/current-session.json +9 -0
  114. package/examples/hospital-homepage/.gaslighting/memory/OPEN_QUESTIONS.md +5 -0
  115. package/examples/hospital-homepage/.gaslighting/memory/PROJECT_MEMORY.md +5 -0
  116. package/examples/hospital-homepage/.gaslighting/memory/SESSION_LOG.md +3 -0
  117. package/examples/hospital-homepage/.gaslighting/mission/COMPLETION_STANDARD.md +11 -0
  118. package/examples/hospital-homepage/.gaslighting/mission/EXECUTION_RULES.md +20 -0
  119. package/examples/hospital-homepage/.gaslighting/mission/PROJECT_PURPOSE.md +20 -0
  120. package/examples/hospital-homepage/.gaslighting/operations/DEPLOYMENT.md +6 -0
  121. package/examples/hospital-homepage/.gaslighting/operations/DOMAIN.md +6 -0
  122. package/examples/hospital-homepage/.gaslighting/operations/ENV.md +5 -0
  123. package/examples/hospital-homepage/.gaslighting/operations/GIT.md +7 -0
  124. package/examples/hospital-homepage/.gaslighting/operations/GITHUB.md +7 -0
  125. package/examples/hospital-homepage/.gaslighting/operations/PROJECT_CARE.md +76 -0
  126. package/examples/hospital-homepage/.gaslighting/pages/consultation-contact/ACCEPTANCE.md +7 -0
  127. package/examples/hospital-homepage/.gaslighting/pages/consultation-contact/PAGE_PRD.md +15 -0
  128. package/examples/hospital-homepage/.gaslighting/pages/departments-treatments/ACCEPTANCE.md +7 -0
  129. package/examples/hospital-homepage/.gaslighting/pages/departments-treatments/PAGE_PRD.md +15 -0
  130. package/examples/hospital-homepage/.gaslighting/pages/doctor-profiles/ACCEPTANCE.md +7 -0
  131. package/examples/hospital-homepage/.gaslighting/pages/doctor-profiles/PAGE_PRD.md +15 -0
  132. package/examples/hospital-homepage/.gaslighting/pages/home/ACCEPTANCE.md +7 -0
  133. package/examples/hospital-homepage/.gaslighting/pages/home/PAGE_PRD.md +15 -0
  134. package/examples/hospital-homepage/.gaslighting/pages/hospital-introduction/ACCEPTANCE.md +7 -0
  135. package/examples/hospital-homepage/.gaslighting/pages/hospital-introduction/PAGE_PRD.md +15 -0
  136. package/examples/hospital-homepage/.gaslighting/pages/location/ACCEPTANCE.md +7 -0
  137. package/examples/hospital-homepage/.gaslighting/pages/location/PAGE_PRD.md +15 -0
  138. package/examples/hospital-homepage/.gaslighting/pages/privacy-policy/ACCEPTANCE.md +7 -0
  139. package/examples/hospital-homepage/.gaslighting/pages/privacy-policy/PAGE_PRD.md +15 -0
  140. package/examples/hospital-homepage/.gaslighting/product/PAGE_MAP.md +9 -0
  141. package/examples/hospital-homepage/.gaslighting/product/PRD.md +119 -0
  142. package/examples/hospital-homepage/.gaslighting/product/USER_FLOWS.md +20 -0
  143. package/examples/hospital-homepage/.gaslighting/tasks/TASK-0001.md +17 -0
  144. package/examples/hospital-homepage/.gaslighting/verification/latest-report.md +3 -0
  145. package/examples/hospital-homepage/AGENTS.md +12 -10
  146. package/examples/landing-page/.agents/config.json +10 -0
  147. package/examples/landing-page/.agents/mcp/manifest.json +5 -0
  148. package/examples/landing-page/.agents/runtimes/claude.json +6 -0
  149. package/examples/landing-page/.agents/runtimes/codex.json +6 -0
  150. package/examples/landing-page/.agents/runtimes/kimi.json +6 -0
  151. package/examples/landing-page/.agents/runtimes/local.json +6 -0
  152. package/examples/landing-page/.agents/runtimes/openai_compatible.json +6 -0
  153. package/examples/landing-page/.agents/runtimes/opencode.json +6 -0
  154. package/examples/landing-page/.agents/runtimes/qwen.json +6 -0
  155. package/examples/landing-page/.codex/prompts/gaslighting.md +9 -9
  156. package/examples/landing-page/.gaslighting/AGENTS.md +9 -9
  157. package/examples/landing-page/.gaslighting/AGENT_RUNTIME.md +1 -1
  158. package/examples/landing-page/.gaslighting/CODEX_PROMPT.md +9 -9
  159. package/examples/landing-page/.gaslighting/DECISION_LOG.md +1 -1
  160. package/examples/landing-page/.gaslighting/GASLIGHTING.md +2 -2
  161. package/examples/landing-page/.gaslighting/INDEX.md +31 -0
  162. package/examples/landing-page/.gaslighting/MEMORY.md +1 -1
  163. package/examples/landing-page/.gaslighting/PRD.md +1 -1
  164. package/examples/landing-page/.gaslighting/PROJECT_CARE.md +1 -1
  165. package/examples/landing-page/.gaslighting/checkpoints/latest.md +7 -0
  166. package/examples/landing-page/.gaslighting/config.json +7 -0
  167. package/examples/landing-page/.gaslighting/decisions/ADR-0001-stack.md +11 -0
  168. package/examples/landing-page/.gaslighting/decisions/ADR-0002-agent-runtime.md +11 -0
  169. package/examples/landing-page/.gaslighting/features/core-scope/DECISIONS.md +5 -0
  170. package/examples/landing-page/.gaslighting/features/core-scope/FEATURE.md +7 -0
  171. package/examples/landing-page/.gaslighting/features/core-scope/RISKS.md +5 -0
  172. package/examples/landing-page/.gaslighting/features/core-scope/TASKS.md +11 -0
  173. package/examples/landing-page/.gaslighting/loops/current-session.json +9 -0
  174. package/examples/landing-page/.gaslighting/memory/OPEN_QUESTIONS.md +5 -0
  175. package/examples/landing-page/.gaslighting/memory/PROJECT_MEMORY.md +5 -0
  176. package/examples/landing-page/.gaslighting/memory/SESSION_LOG.md +3 -0
  177. package/examples/landing-page/.gaslighting/mission/COMPLETION_STANDARD.md +11 -0
  178. package/examples/landing-page/.gaslighting/mission/EXECUTION_RULES.md +20 -0
  179. package/examples/landing-page/.gaslighting/mission/PROJECT_PURPOSE.md +19 -0
  180. package/examples/landing-page/.gaslighting/operations/DEPLOYMENT.md +6 -0
  181. package/examples/landing-page/.gaslighting/operations/DOMAIN.md +6 -0
  182. package/examples/landing-page/.gaslighting/operations/ENV.md +5 -0
  183. package/examples/landing-page/.gaslighting/operations/GIT.md +7 -0
  184. package/examples/landing-page/.gaslighting/operations/GITHUB.md +7 -0
  185. package/examples/landing-page/.gaslighting/operations/PROJECT_CARE.md +75 -0
  186. package/examples/landing-page/.gaslighting/pages/single-landing-page-with-hero-problem-solution-benefits-social-p/ACCEPTANCE.md +7 -0
  187. package/examples/landing-page/.gaslighting/pages/single-landing-page-with-hero-problem-solution-benefits-social-p/PAGE_PRD.md +15 -0
  188. package/examples/landing-page/.gaslighting/product/PAGE_MAP.md +3 -0
  189. package/examples/landing-page/.gaslighting/product/PRD.md +103 -0
  190. package/examples/landing-page/.gaslighting/product/USER_FLOWS.md +14 -0
  191. package/examples/landing-page/.gaslighting/tasks/TASK-0001.md +17 -0
  192. package/examples/landing-page/.gaslighting/verification/latest-report.md +3 -0
  193. package/examples/landing-page/AGENTS.md +12 -10
  194. package/package.json +22 -5
@@ -0,0 +1 @@
1
+ .xterm{cursor:text;-webkit-user-select:none;user-select:none;position:relative}.xterm.focus,.xterm:focus{outline:none}.xterm .xterm-helpers{z-index:5;position:absolute;top:0}.xterm .xterm-helper-textarea{opacity:0;z-index:-5;white-space:nowrap;resize:none;border:0;width:0;height:0;margin:0;padding:0;position:absolute;top:0;left:-9999em;overflow:hidden}.xterm .composition-view{color:#fff;white-space:nowrap;z-index:1;background:#000;display:none;position:absolute}.xterm .composition-view.active{display:block}.xterm .xterm-viewport{cursor:default;background-color:#000;position:absolute;inset:0;overflow-y:scroll}.xterm .xterm-screen{position:relative}.xterm .xterm-screen canvas{position:absolute;top:0;left:0}.xterm-char-measure-element{visibility:hidden;line-height:normal;display:inline-block;position:absolute;top:0;left:-9999em}.xterm.enable-mouse-events{cursor:default}.xterm.xterm-cursor-pointer,.xterm .xterm-cursor-pointer{cursor:pointer}.xterm.column-select.focus{cursor:crosshair}.xterm .xterm-accessibility:not(.debug),.xterm .xterm-message{z-index:10;color:#0000;pointer-events:none;position:absolute;inset:0}.xterm .xterm-accessibility-tree:not(.debug) ::selection{color:#0000}.xterm .xterm-accessibility-tree{-webkit-user-select:text;user-select:text;white-space:pre;font-family:monospace}.xterm .xterm-accessibility-tree>div{transform-origin:0;width:fit-content}.xterm .live-region{width:1px;height:1px;position:absolute;left:-9999px;overflow:hidden}.xterm-dim{opacity:1!important}.xterm-underline-1{text-decoration:underline}.xterm-underline-2{-webkit-text-decoration:underline double;text-decoration:underline double}.xterm-underline-3{-webkit-text-decoration:underline wavy;text-decoration:underline wavy}.xterm-underline-4{-webkit-text-decoration:underline dotted;text-decoration:underline dotted}.xterm-underline-5{-webkit-text-decoration:underline dashed;text-decoration:underline dashed}.xterm-overline{text-decoration:overline}.xterm-overline.xterm-underline-1{text-decoration:underline overline}.xterm-overline.xterm-underline-2{-webkit-text-decoration:overline double underline;text-decoration:overline double underline}.xterm-overline.xterm-underline-3{-webkit-text-decoration:overline wavy underline;text-decoration:overline wavy underline}.xterm-overline.xterm-underline-4{-webkit-text-decoration:overline dotted underline;text-decoration:overline dotted underline}.xterm-overline.xterm-underline-5{-webkit-text-decoration:overline dashed underline;text-decoration:overline dashed underline}.xterm-strikethrough{text-decoration:line-through}.xterm-screen .xterm-decoration-container .xterm-decoration{z-index:6;position:absolute}.xterm-screen .xterm-decoration-container .xterm-decoration.xterm-decoration-top-layer{z-index:7}.xterm-decoration-overview-ruler{z-index:8;pointer-events:none;position:absolute;top:0;right:0}.xterm-decoration-top{z-index:2;position:relative}.xterm .xterm-scrollable-element>.scrollbar{cursor:default}.xterm .xterm-scrollable-element>.scrollbar>.scra{cursor:pointer;font-size:11px!important}.xterm .xterm-scrollable-element>.visible{opacity:1;z-index:11;background:0 0;transition:opacity .1s linear}.xterm .xterm-scrollable-element>.invisible{opacity:0;pointer-events:none}.xterm .xterm-scrollable-element>.invisible.fade{transition:opacity .8s linear}.xterm .xterm-scrollable-element>.shadow{display:none;position:absolute}.xterm .xterm-scrollable-element>.shadow.top{width:100%;height:3px;box-shadow:var(--vscode-scrollbar-shadow,#000) 0 6px 6px -6px inset;display:block;top:0;left:3px}.xterm .xterm-scrollable-element>.shadow.left{width:3px;height:100%;box-shadow:var(--vscode-scrollbar-shadow,#000) 6px 0 6px -6px inset;display:block;top:3px;left:0}.xterm .xterm-scrollable-element>.shadow.top-left-corner{width:3px;height:3px;display:block;top:0;left:0}.xterm .xterm-scrollable-element>.shadow.top.left{box-shadow:var(--vscode-scrollbar-shadow,#000) 6px 0 6px -6px inset}:root{color:#191919;background:#f5f5f3;font-family:Inter,Segoe UI,Arial,sans-serif}*{box-sizing:border-box}body{min-width:1000px;min-height:720px;margin:0}button,input,select,textarea{font:inherit}button{color:#191919;cursor:pointer;background:#fff;border:1px solid #d7d7d2;border-radius:6px;justify-content:center;align-items:center;gap:7px;height:36px;padding:0 12px;display:inline-flex}button:hover{border-color:#a7a7a0}.primary{color:#fff;background:#111;border-color:#111}.app-shell{grid-template-columns:248px 1fr;height:100vh;display:grid}.sidebar{background:#eceff1;border-right:1px solid #d8dddf;padding:22px 16px}.brand{align-items:center;gap:12px;margin-bottom:28px;display:flex}.brand-mark{color:#fff;background:#111;border-radius:8px;place-items:center;width:38px;height:38px;font-weight:800;display:grid}.brand strong,.brand span{display:block}.brand span{color:#667078;font-size:13px}.nav-button{background:0 0;border-color:#0000;justify-content:flex-start;width:100%;margin-bottom:8px}.nav-button.active,.nav-button:hover{background:#fff;border-color:#d7d7d2}.workspace{min-width:0;padding:26px;overflow:auto}.topbar{justify-content:space-between;align-items:flex-start;margin-bottom:22px;display:flex}.topbar h1{margin:0 0 6px;font-size:24px}.topbar p{color:#667078;margin:0;font-size:13px}.top-actions,.button-row,.control-row,.inline-form{flex-wrap:wrap;align-items:center;gap:10px;display:flex}.mission-grid{grid-template-columns:minmax(520px,1fr) 330px;align-items:stretch;gap:18px;display:grid}.mission-panel,.status-panel,.domain-panel,.terminal-panel{background:#fff;border:1px solid #deded8;border-radius:8px;padding:16px}.mission-panel label{color:#555d63;margin:0 0 7px;font-size:13px;display:block}textarea{resize:vertical;border:1px solid #d7d7d2;border-radius:6px;width:100%;min-height:132px;margin-bottom:12px;padding:12px}input,select{background:#fff;border:1px solid #d7d7d2;border-radius:6px;min-width:170px;height:36px;padding:0 10px}.mission-panel input{width:100%;margin-bottom:12px}.status-panel h2,.domain-panel h2,.terminal-panel h2{align-items:center;gap:8px;margin:0 0 14px;font-size:16px;display:flex}.status-line,.care-line{border-top:1px solid #f0f0ec;grid-template-columns:12px minmax(110px,1fr) auto;align-items:center;gap:10px;min-height:34px;display:grid}.care-line{grid-template-columns:12px 1fr;align-items:start;padding:9px 0}.care-line strong{font-size:13px;display:block}.care-line p{color:#667078;margin:3px 0 0;font-size:12px}.dot{border-radius:999px;width:9px;height:9px;margin-top:5px}.dot.ok{background:#138a48}.dot.warn{background:#d88700}.lower-grid{grid-template-columns:1fr 1fr;gap:18px;margin-top:18px;display:grid}.terminal-panel{grid-column:1/-1}.terminal-host{background:#111;border-radius:6px;height:300px;padding:8px;overflow:hidden}.list-box{flex-wrap:wrap;gap:8px;min-height:42px;margin:12px 0;display:flex}.list-box button{height:32px}@media (width<=1100px){.app-shell{grid-template-columns:200px 1fr}.mission-grid,.lower-grid{grid-template-columns:1fr}}
@@ -0,0 +1,13 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>Gaslighting Mission Control</title>
7
+ <script type="module" crossorigin src="/assets/index-BoI6eWtN.js"></script>
8
+ <link rel="stylesheet" crossorigin href="/assets/index-oFTvTTu8.css">
9
+ </head>
10
+ <body>
11
+ <div id="root"></div>
12
+ </body>
13
+ </html>
@@ -0,0 +1,34 @@
1
+ const sensitivePatterns = [
2
+ /\bgit\s+push\b/i,
3
+ /\bnpm\s+publish\b/i,
4
+ /\bpnpm\s+publish\b/i,
5
+ /\byarn\s+npm\s+publish\b/i,
6
+ /\bvercel\s+(deploy|prod|promote)\b/i,
7
+ /\bnetlify\s+deploy\b/i,
8
+ /\bmigrate\b/i,
9
+ /\bprisma\s+migrate\b/i,
10
+ /\bdrizzle-kit\s+(push|migrate)\b/i,
11
+ /\brm\s+-rf\b/i,
12
+ /\bRemove-Item\b.+\b-Recurse\b/i,
13
+ /\b(del|erase)\b.+\/s\b/i,
14
+ /\b\.env\b/i,
15
+ /\b(secret|token|api[_-]?key|password)\b/i,
16
+ /\bdns\b/i,
17
+ /\bdomain\b/i,
18
+ /\bmcp\s+install\b/i,
19
+ /\bcodex\s+mcp\s+add\b/i,
20
+ /\bclaude\s+mcp\s+add\b/i,
21
+ ];
22
+ export function reviewPermission(mode, action) {
23
+ if (mode === "full_autonomy") {
24
+ return { allowed: true, requiresApproval: false, reason: "Full autonomy is enabled. The action will still be logged." };
25
+ }
26
+ if (mode === "ask_each_task") {
27
+ return { allowed: false, requiresApproval: true, reason: "Basic permission mode requires approval for each task action." };
28
+ }
29
+ const sensitive = sensitivePatterns.some((pattern) => pattern.test(action));
30
+ if (sensitive) {
31
+ return { allowed: false, requiresApproval: true, reason: "Auto-review mode requires approval for sensitive operations." };
32
+ }
33
+ return { allowed: true, requiresApproval: false, reason: "Auto-review mode allows this non-sensitive operation." };
34
+ }
@@ -0,0 +1,30 @@
1
+ export function buildAgentPrompt(request) {
2
+ return [
3
+ "Use the gaslighting skill or follow the Gaslighting-engine control files.",
4
+ "",
5
+ "Read these files before doing any implementation:",
6
+ "1. AGENTS.md",
7
+ "2. .gaslighting/INDEX.md",
8
+ "3. .gaslighting/mission/PROJECT_PURPOSE.md",
9
+ "4. .gaslighting/mission/EXECUTION_RULES.md",
10
+ "5. .gaslighting/product/PRD.md",
11
+ "6. .gaslighting/operations/GIT.md",
12
+ "7. .gaslighting/operations/DOMAIN.md",
13
+ "8. .gaslighting/loops/current-session.json",
14
+ "",
15
+ "Also read the compatibility files when present:",
16
+ "- .gaslighting/GASLIGHTING.md",
17
+ "- .gaslighting/PRD.md",
18
+ "- .gaslighting/STACK_POLICY.md",
19
+ "- .gaslighting/MISSING_INFO.md",
20
+ "- .gaslighting/ASSUMPTIONS.md",
21
+ "- .gaslighting/DECISION_LOG.md",
22
+ "- .gaslighting/MEMORY.md",
23
+ "- .gaslighting/AGENT_RUNTIME.md",
24
+ "- .gaslighting/PROJECT_CARE.md",
25
+ "",
26
+ `Project request: ${request}`,
27
+ "",
28
+ "Implement the requested work. Preserve full scope. Do not use TODOs as fake implementation. Do not deliver representative examples when full coverage is required. If something is incomplete, declare it explicitly.",
29
+ ].join("\n");
30
+ }
@@ -0,0 +1,214 @@
1
+ import { execFileSync, spawn } from "node:child_process";
2
+ import { platform } from "node:os";
3
+ import { dirname, join } from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+ import { splitCommandArgs } from "../core/codexRuntime.js";
6
+ import { buildAgentPrompt } from "./prompts.js";
7
+ const definitions = [
8
+ {
9
+ id: "codex",
10
+ label: "Codex CLI",
11
+ command: "codex",
12
+ supportsMcp: true,
13
+ supportsSkills: true,
14
+ models: [{ id: "codex-default", label: "Codex default", description: "Use the model configured by Codex." }],
15
+ buildArgs: (input, prompt) => [...splitCommandArgs(input.extraArgs || getDefaultCodexArgs()), "-C", input.root, prompt],
16
+ },
17
+ {
18
+ id: "claude",
19
+ label: "Claude Code",
20
+ command: "claude",
21
+ supportsMcp: true,
22
+ supportsSkills: true,
23
+ models: [{ id: "claude-default", label: "Claude default", description: "Use the model configured by Claude Code." }],
24
+ buildArgs: (input, prompt) => [...splitCommandArgs(input.extraArgs || ""), prompt],
25
+ },
26
+ {
27
+ id: "qwen",
28
+ label: "Qwen Code",
29
+ command: "qwen",
30
+ supportsMcp: true,
31
+ supportsSkills: false,
32
+ models: [{ id: "qwen-default", label: "Qwen default", description: "Use Qwen Code /model selection." }],
33
+ buildArgs: (input, prompt) => [...splitCommandArgs(input.extraArgs || ""), prompt],
34
+ },
35
+ {
36
+ id: "opencode",
37
+ label: "OpenCode",
38
+ command: "opencode",
39
+ supportsMcp: true,
40
+ supportsSkills: false,
41
+ models: [{ id: "opencode-default", label: "OpenCode default", description: "Use OpenCode's configured provider." }],
42
+ buildArgs: (input, prompt) => [...splitCommandArgs(input.extraArgs || ""), prompt],
43
+ },
44
+ {
45
+ id: "kimi",
46
+ label: "Kimi via compatible agent",
47
+ command: "claude",
48
+ supportsMcp: true,
49
+ supportsSkills: true,
50
+ models: [
51
+ { id: "kimi-k2.6", label: "Kimi K2.6", description: "Kimi's long-context coding and agent model." },
52
+ { id: "kimi-k2.5", label: "Kimi K2.5", description: "Fallback Kimi agent model." },
53
+ ],
54
+ buildArgs: (input, prompt) => [...splitCommandArgs(input.extraArgs || ""), prompt],
55
+ },
56
+ {
57
+ id: "openai_compatible",
58
+ label: "OpenAI-compatible API",
59
+ command: process.execPath,
60
+ supportsMcp: false,
61
+ supportsSkills: false,
62
+ models: [
63
+ { id: "gpt-5.3-codex", label: "GPT-5.3 Codex" },
64
+ { id: "kimi-k2.6", label: "Kimi K2.6" },
65
+ { id: "qwen-code-default", label: "Qwen provider default" },
66
+ ],
67
+ buildArgs: (input, prompt) => [resolveCliEntry(), "api-run", "--model", input.model || "gpt-5.3-codex", "--prompt", prompt],
68
+ },
69
+ {
70
+ id: "local",
71
+ label: "Local model",
72
+ command: "ollama",
73
+ supportsMcp: false,
74
+ supportsSkills: false,
75
+ models: [
76
+ { id: "qwen2.5-coder", label: "Qwen Coder local" },
77
+ { id: "gemma4", label: "Gemma 4 local" },
78
+ ],
79
+ buildArgs: (input, prompt) => ["run", input.model || "qwen2.5-coder", prompt],
80
+ },
81
+ ];
82
+ export function listAgentRuntimeAdapters() {
83
+ return definitions.map(createAdapter);
84
+ }
85
+ export function getAgentRuntimeAdapter(runtime) {
86
+ const definition = definitions.find((item) => item.id === runtime) ?? definitions[0];
87
+ return createAdapter(definition);
88
+ }
89
+ export function detectAgentRuntimes() {
90
+ return listAgentRuntimeAdapters().map((adapter) => adapter.detect());
91
+ }
92
+ function createAdapter(definition) {
93
+ return {
94
+ id: definition.id,
95
+ label: definition.label,
96
+ command: definition.command,
97
+ supportsMcp: definition.supportsMcp,
98
+ supportsSkills: definition.supportsSkills,
99
+ detect: () => detectRuntime(definition),
100
+ listModels: () => definition.models,
101
+ buildCommand: (input) => buildDisplayCommand(definition, input),
102
+ buildSpawn: (input) => {
103
+ const prompt = buildAgentPrompt(input.request);
104
+ return { file: runtimeFile(definition.command), args: definition.buildArgs(input, prompt), cwd: input.root };
105
+ },
106
+ run: (input) => launchInCurrentTerminal(definition, input),
107
+ };
108
+ }
109
+ function detectRuntime(definition) {
110
+ if (definition.id === "openai_compatible") {
111
+ const hasKey = Boolean(process.env.OPENAI_COMPATIBLE_API_KEY || process.env.OPENAI_API_KEY || process.env.KIMI_API_KEY);
112
+ return {
113
+ id: definition.id,
114
+ label: definition.label,
115
+ available: hasKey,
116
+ command: process.execPath,
117
+ version: commandVersion(process.execPath),
118
+ message: hasKey ? "OpenAI-compatible API key is configured." : "Set OPENAI_COMPATIBLE_API_KEY, OPENAI_API_KEY, or KIMI_API_KEY to use direct API mode.",
119
+ };
120
+ }
121
+ if (definition.id === "kimi") {
122
+ const command = commandPath(definition.command);
123
+ const version = command ? commandVersion(definition.command) : undefined;
124
+ const hasEndpoint = Boolean(process.env.KIMI_API_KEY || process.env.MOONSHOT_API_KEY) ||
125
+ Boolean(process.env.ANTHROPIC_BASE_URL?.toLowerCase().includes("moonshot")) ||
126
+ Boolean(process.env.OPENAI_COMPATIBLE_BASE_URL?.toLowerCase().includes("moonshot"));
127
+ return {
128
+ id: definition.id,
129
+ label: definition.label,
130
+ available: Boolean(command && hasEndpoint),
131
+ command,
132
+ version,
133
+ message: !command
134
+ ? "Claude-compatible CLI is not installed or not on PATH."
135
+ : hasEndpoint
136
+ ? `Kimi-compatible endpoint is configured${version ? ` (${version})` : ""}.`
137
+ : "Install/configure a Kimi-compatible endpoint first: set KIMI_API_KEY, MOONSHOT_API_KEY, or a Moonshot base URL.",
138
+ };
139
+ }
140
+ const command = commandPath(definition.command);
141
+ const version = command ? commandVersion(definition.command) : undefined;
142
+ return {
143
+ id: definition.id,
144
+ label: definition.label,
145
+ available: Boolean(command),
146
+ command,
147
+ version,
148
+ message: command ? `${definition.label} is available${version ? ` (${version})` : ""}.` : `${definition.label} is not installed or not on PATH.`,
149
+ };
150
+ }
151
+ function launchInCurrentTerminal(definition, input) {
152
+ const spawnInput = createAdapter(definition).buildSpawn(input);
153
+ const command = buildDisplayCommand(definition, input);
154
+ try {
155
+ const child = platform() === "win32"
156
+ ? spawn("cmd.exe", ["/d", "/s", "/c", spawnInput.file, ...spawnInput.args], { cwd: spawnInput.cwd, stdio: "inherit" })
157
+ : spawn(spawnInput.file, spawnInput.args, { cwd: spawnInput.cwd, stdio: "inherit" });
158
+ child.on("exit", (code) => process.exit(code ?? 0));
159
+ child.on("error", (error) => {
160
+ console.error(`Could not start ${definition.label}: ${error.message}`);
161
+ console.error(command);
162
+ process.exit(1);
163
+ });
164
+ return { ok: true, command, message: `${definition.label} started in this terminal.` };
165
+ }
166
+ catch (error) {
167
+ return { ok: false, command, message: error instanceof Error ? error.message : `Could not start ${definition.label}.` };
168
+ }
169
+ }
170
+ function buildDisplayCommand(definition, input) {
171
+ const prompt = buildAgentPrompt(input.request);
172
+ return [definition.command, ...definition.buildArgs(input, prompt).map(quoteArg)].join(" ");
173
+ }
174
+ function getDefaultCodexArgs() {
175
+ return process.env.GASLIGHTING_CODEX_ARGS || "--search --dangerously-bypass-approvals-and-sandbox";
176
+ }
177
+ function runtimeFile(command) {
178
+ return command;
179
+ }
180
+ function commandPath(command) {
181
+ try {
182
+ const result = platform() === "win32"
183
+ ? execFileSync("where", [command], { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] })
184
+ : execFileSync("sh", ["-lc", `command -v ${quoteShell(command)}`], { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] });
185
+ return result.split(/\r?\n/).find(Boolean)?.trim();
186
+ }
187
+ catch {
188
+ return undefined;
189
+ }
190
+ }
191
+ function commandVersion(command) {
192
+ for (const args of [["--version"], ["-v"]]) {
193
+ try {
194
+ const result = execFileSync(command, args, { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], timeout: 2000 }).trim();
195
+ if (result)
196
+ return result.split(/\r?\n/)[0];
197
+ }
198
+ catch {
199
+ // Try the next common version flag.
200
+ }
201
+ }
202
+ return undefined;
203
+ }
204
+ function resolveCliEntry() {
205
+ return join(dirname(fileURLToPath(import.meta.url)), "..", "index.js");
206
+ }
207
+ function quoteArg(value) {
208
+ if (/^[A-Za-z0-9_./:@=-]+$/.test(value))
209
+ return value;
210
+ return `"${value.replaceAll("\\", "\\\\").replaceAll('"', '\\"').replaceAll("\n", "\\n")}"`;
211
+ }
212
+ function quoteShell(value) {
213
+ return `'${value.replaceAll("'", "'\\''")}'`;
214
+ }
@@ -0,0 +1 @@
1
+ export {};
package/dist/cli.js CHANGED
@@ -1,12 +1,17 @@
1
1
  import { Command, InvalidArgumentError } from "commander";
2
+ import { runAgentDoctor, runAgentList } from "./commands/agent.js";
2
3
  import { runAgents } from "./commands/agents.js";
4
+ import { runApiRun } from "./commands/apiRun.js";
3
5
  import { runCare } from "./commands/care.js";
4
6
  import { runCockpit, runCodexRun, runStart } from "./commands/cockpit.js";
5
7
  import { runCodexDoctor, runCodexInstall } from "./commands/codexInstall.js";
8
+ import { runDesktop } from "./commands/desktop.js";
6
9
  import { runDoctor } from "./commands/doctor.js";
7
10
  import { runGenerate } from "./commands/generate.js";
8
11
  import { runInit } from "./commands/init.js";
9
- import { runSkill } from "./commands/skill.js";
12
+ import { runLoopResume, runLoopStart, runLoopStatus, runLoopStop } from "./commands/loop.js";
13
+ import { runMcpDoctor, runMcpInstall, runMcpList, runMcpSearch } from "./commands/mcp.js";
14
+ import { runSkill, runSkillCreate, runSkillDoctor, runSkillInstall } from "./commands/skill.js";
10
15
  import { runUpdate } from "./commands/update.js";
11
16
  import { runUpgrade } from "./commands/upgrade.js";
12
17
  import { packageVersion } from "./version.js";
@@ -25,11 +30,23 @@ const projectTypes = [
25
30
  "education_site",
26
31
  "generic_web_project",
27
32
  ];
33
+ const agentRuntimes = ["codex", "claude", "qwen", "kimi", "opencode", "openai_compatible", "local"];
34
+ const permissionModes = ["ask_each_task", "auto_review", "full_autonomy"];
28
35
  function parseProjectType(value) {
29
36
  if (projectTypes.includes(value))
30
37
  return value;
31
38
  throw new InvalidArgumentError(`Invalid project type. Use one of: ${projectTypes.join(", ")}`);
32
39
  }
40
+ function parseAgentRuntime(value) {
41
+ if (agentRuntimes.includes(value))
42
+ return value;
43
+ throw new InvalidArgumentError(`Invalid runtime. Use one of: ${agentRuntimes.join(", ")}`);
44
+ }
45
+ function parsePermissionMode(value) {
46
+ if (permissionModes.includes(value))
47
+ return value;
48
+ throw new InvalidArgumentError(`Invalid permission mode. Use one of: ${permissionModes.join(", ")}`);
49
+ }
33
50
  function addCommonOptions(command) {
34
51
  return command
35
52
  .option("--hardcore", "generate aggressive anti-escape discipline (default)")
@@ -45,8 +62,19 @@ function addCommonOptions(command) {
45
62
  .option("--dry-run", "print files without writing")
46
63
  .option("--lang <lang>", "language: en or ko", "en")
47
64
  .option("--type <type>", "project type override", parseProjectType)
65
+ .option("--runtime <runtime>", "agent runtime", parseAgentRuntime, "codex")
66
+ .option("--permission-mode <mode>", "permission mode", parsePermissionMode, "auto_review")
48
67
  .option("--path <path>", "target directory");
49
68
  }
69
+ function actionOptions(value) {
70
+ return typeof value.opts === "function" ? value.opts() : value;
71
+ }
72
+ function mergedActionOptions(parent, value) {
73
+ return removeUndefined({ ...parent.opts(), ...actionOptions(value) });
74
+ }
75
+ function removeUndefined(value) {
76
+ return Object.fromEntries(Object.entries(value).filter(([, item]) => item !== undefined));
77
+ }
50
78
  export function buildCli() {
51
79
  const program = new Command();
52
80
  program
@@ -62,6 +90,10 @@ Examples:
62
90
  $ gaslighting-engine doctor
63
91
  $ gaslighting-engine care --github-url https://github.com/user/repo.git
64
92
  $ gaslighting-engine start "Build a hospital homepage"
93
+ $ gaslighting-engine desktop "Build a hospital homepage"
94
+ $ gaslighting-engine loop start "Build a hospital homepage"
95
+ $ gaslighting-engine agent list
96
+ $ gaslighting-engine mcp search github
65
97
  $ gaslighting-engine upgrade
66
98
  $ gaslighting-engine codex-install --force
67
99
 
@@ -81,13 +113,30 @@ Defaults:
81
113
  .description("Check whether the repository is properly disciplined")
82
114
  .option("--path <path>", "target directory")
83
115
  .action(runDoctor);
84
- program
116
+ const skillCommand = program
85
117
  .command("skill")
86
- .description("Generate only Codex Skill files")
118
+ .description("Generate, install, or inspect Gaslighting skills")
87
119
  .option("--force", "overwrite existing files")
88
120
  .option("--dry-run", "print files without writing")
89
121
  .option("--path <path>", "target directory")
90
122
  .action(runSkill);
123
+ skillCommand
124
+ .command("create <name>")
125
+ .description("Create a shared skill under .agents/skills")
126
+ .option("--path <path>", "target directory")
127
+ .option("--description <description>", "skill description")
128
+ .action((name, options) => runSkillCreate(name, mergedActionOptions(skillCommand, options)));
129
+ skillCommand
130
+ .command("install <name>")
131
+ .description("Export a shared skill into a runtime-specific skill location")
132
+ .option("--path <path>", "target directory")
133
+ .option("--runtime <runtime>", "target runtime", parseAgentRuntime, "codex")
134
+ .action((name, options) => runSkillInstall(name, mergedActionOptions(skillCommand, options)));
135
+ skillCommand
136
+ .command("doctor")
137
+ .description("Check shared skill and runtime export locations")
138
+ .option("--path <path>", "target directory")
139
+ .action((options) => runSkillDoctor(mergedActionOptions(skillCommand, options)));
91
140
  program
92
141
  .command("agents")
93
142
  .description("Generate or update AGENTS.md")
@@ -117,6 +166,9 @@ Defaults:
117
166
  .option("--lang <lang>", "language: en or ko", "en")
118
167
  .option("--type <type>", "project type override", parseProjectType)
119
168
  .option("--codex-args <args>", "Codex CLI args used by the Start Codex button")
169
+ .option("--runtime <runtime>", "agent runtime", parseAgentRuntime, "codex")
170
+ .option("--permission-mode <mode>", "permission mode", parsePermissionMode, "auto_review")
171
+ .option("--loop <mode>", "loop mode: off or on", "off")
120
172
  .option("--new-terminal", "launch Codex in a separate terminal instead of handing off the current terminal")
121
173
  .action(runStart);
122
174
  program
@@ -131,6 +183,9 @@ Defaults:
131
183
  .option("--lang <lang>", "language: en or ko", "en")
132
184
  .option("--type <type>", "project type override", parseProjectType)
133
185
  .option("--codex-args <args>", "Codex CLI args used by the Start Codex button")
186
+ .option("--runtime <runtime>", "agent runtime", parseAgentRuntime, "codex")
187
+ .option("--permission-mode <mode>", "permission mode", parsePermissionMode, "auto_review")
188
+ .option("--loop <mode>", "loop mode: off or on", "off")
134
189
  .option("--new-terminal", "launch Codex in a separate terminal instead of handing off the current terminal")
135
190
  .action(runCockpit);
136
191
  program
@@ -142,8 +197,72 @@ Defaults:
142
197
  .option("--lang <lang>", "language: en or ko", "en")
143
198
  .option("--type <type>", "project type override", parseProjectType)
144
199
  .option("--codex-args <args>", "Codex CLI args")
200
+ .option("--runtime <runtime>", "agent runtime", parseAgentRuntime, "codex")
201
+ .option("--permission-mode <mode>", "permission mode", parsePermissionMode, "auto_review")
202
+ .option("--loop <mode>", "loop mode: off or on", "off")
145
203
  .option("--new-terminal", "launch Codex in a separate terminal instead of handing off the current terminal")
146
204
  .action(runCodexRun);
205
+ program
206
+ .command("desktop [request]")
207
+ .description("Open the Electron Gaslighting Mission Control app")
208
+ .option("--path <path>", "target directory")
209
+ .option("--dev", "load the Vite dev server instead of built desktop assets")
210
+ .action(runDesktop);
211
+ const loopCommand = program.command("loop").description("Manage Mission Loop sessions");
212
+ loopCommand
213
+ .command("start [request]")
214
+ .description("Create a Mission Loop session")
215
+ .option("--path <path>", "target directory")
216
+ .option("--runtime <runtime>", "agent runtime", parseAgentRuntime, "codex")
217
+ .option("--permission-mode <mode>", "permission mode", parsePermissionMode, "auto_review")
218
+ .action((request, options) => runLoopStart(request, actionOptions(options)));
219
+ loopCommand
220
+ .command("status")
221
+ .description("Show Mission Loop status")
222
+ .option("--path <path>", "target directory")
223
+ .action((options) => runLoopStatus(actionOptions(options)));
224
+ loopCommand
225
+ .command("stop")
226
+ .description("Stop the Mission Loop")
227
+ .option("--path <path>", "target directory")
228
+ .action((options) => runLoopStop(actionOptions(options)));
229
+ loopCommand
230
+ .command("resume")
231
+ .description("Run the next Mission Loop iteration")
232
+ .option("--path <path>", "target directory")
233
+ .option("--runtime <runtime>", "agent runtime", parseAgentRuntime)
234
+ .option("--permission-mode <mode>", "permission mode", parsePermissionMode)
235
+ .option("--max-iterations <count>", "maximum iterations to run", "1")
236
+ .option("--approve", "approve the current iteration when permission mode requires approval")
237
+ .option("--extra-args <args>", "extra runtime args")
238
+ .action((options) => runLoopResume(actionOptions(options)));
239
+ const agentCommand = program.command("agent").description("Inspect available agent runtimes");
240
+ agentCommand.command("list").description("List runtimes").action(runAgentList);
241
+ agentCommand.command("doctor").description("Check runtime availability").action(runAgentDoctor);
242
+ const mcpCommand = program.command("mcp").description("Search, install, and inspect MCP definitions");
243
+ mcpCommand.command("search <query>").description("Search known MCP servers").action(runMcpSearch);
244
+ mcpCommand
245
+ .command("install <name>")
246
+ .description("Install an MCP definition into .agents and export for a runtime")
247
+ .option("--path <path>", "target directory")
248
+ .option("--runtime <runtime>", "target runtime", parseAgentRuntime, "codex")
249
+ .action((name, options) => runMcpInstall(name, actionOptions(options)));
250
+ mcpCommand
251
+ .command("list")
252
+ .description("List installed MCP definitions")
253
+ .option("--path <path>", "target directory")
254
+ .action((options) => runMcpList(actionOptions(options)));
255
+ mcpCommand
256
+ .command("doctor")
257
+ .description("Check MCP install state")
258
+ .option("--path <path>", "target directory")
259
+ .action((options) => runMcpDoctor(actionOptions(options)));
260
+ program
261
+ .command("api-run")
262
+ .description("Run a single OpenAI-compatible model call for internal desktop/provider workflows")
263
+ .option("--model <model>", "model id")
264
+ .option("--prompt <prompt>", "prompt")
265
+ .action(runApiRun);
147
266
  program
148
267
  .command("upgrade")
149
268
  .description("Update the local Codex Gaslighting install with one simple command")
@@ -174,7 +293,26 @@ export function normalizeDefaultInitArgv(argv) {
174
293
  return argv;
175
294
  if (args.some((arg) => ["--help", "-h", "--version", "-V"].includes(arg)))
176
295
  return argv;
177
- const commands = new Set(["init", "generate", "update", "doctor", "skill", "agents", "care", "start", "cockpit", "run", "upgrade", "codex-install", "codex-doctor"]);
296
+ const commands = new Set([
297
+ "init",
298
+ "generate",
299
+ "update",
300
+ "doctor",
301
+ "skill",
302
+ "agents",
303
+ "care",
304
+ "start",
305
+ "cockpit",
306
+ "run",
307
+ "desktop",
308
+ "loop",
309
+ "agent",
310
+ "mcp",
311
+ "api-run",
312
+ "upgrade",
313
+ "codex-install",
314
+ "codex-doctor",
315
+ ]);
178
316
  const firstMeaningful = args.find((arg) => !arg.startsWith("-"));
179
317
  if (firstMeaningful && commands.has(firstMeaningful))
180
318
  return argv;
@@ -0,0 +1,11 @@
1
+ import { detectAgentRuntimes } from "../agent-runtimes/registry.js";
2
+ import { printBanner } from "../utils/banner.js";
3
+ export function runAgentList() {
4
+ printBanner("AGENT RUNTIMES");
5
+ for (const status of detectAgentRuntimes()) {
6
+ console.log(`${status.available ? "PASS" : "WARN"} ${status.label}: ${status.message}`);
7
+ }
8
+ }
9
+ export function runAgentDoctor() {
10
+ runAgentList();
11
+ }
@@ -0,0 +1,32 @@
1
+ export async function runApiRun(options) {
2
+ const baseUrl = process.env.OPENAI_COMPATIBLE_BASE_URL || process.env.OPENAI_BASE_URL || "https://api.openai.com/v1";
3
+ const apiKey = process.env.OPENAI_COMPATIBLE_API_KEY || process.env.OPENAI_API_KEY || process.env.KIMI_API_KEY;
4
+ const model = options.model || "gpt-5.3-codex";
5
+ const prompt = options.prompt || "Read the Gaslighting-engine mission files and continue the project.";
6
+ if (!apiKey) {
7
+ console.log("OPENAI_COMPATIBLE_API_KEY, OPENAI_API_KEY, or KIMI_API_KEY is required for api-run.");
8
+ process.exitCode = 1;
9
+ return;
10
+ }
11
+ const response = await fetch(`${baseUrl.replace(/\/$/, "")}/chat/completions`, {
12
+ method: "POST",
13
+ headers: {
14
+ "content-type": "application/json",
15
+ authorization: `Bearer ${apiKey}`,
16
+ },
17
+ body: JSON.stringify({
18
+ model,
19
+ messages: [
20
+ { role: "system", content: "You are running under Gaslighting-engine discipline. Do not fake completion." },
21
+ { role: "user", content: prompt },
22
+ ],
23
+ }),
24
+ });
25
+ if (!response.ok) {
26
+ console.log(`API run failed: ${response.status} ${await response.text()}`);
27
+ process.exitCode = 1;
28
+ return;
29
+ }
30
+ const data = (await response.json());
31
+ console.log(data.choices?.[0]?.message?.content || "No response content returned.");
32
+ }