@aligndottech/cli 0.47.1 → 0.49.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 (220) hide show
  1. package/README.md +6 -5
  2. package/dist/cli.d.ts.map +1 -1
  3. package/dist/cli.js +9 -18
  4. package/dist/cli.js.map +1 -1
  5. package/dist/commands/agents.d.ts +20 -0
  6. package/dist/commands/agents.d.ts.map +1 -0
  7. package/dist/commands/agents.js +62 -0
  8. package/dist/commands/agents.js.map +1 -0
  9. package/dist/commands/ai.d.ts +11 -0
  10. package/dist/commands/ai.d.ts.map +1 -0
  11. package/dist/commands/ai.js +121 -0
  12. package/dist/commands/ai.js.map +1 -0
  13. package/dist/commands/default-action.js +2 -2
  14. package/dist/commands/default-action.js.map +1 -1
  15. package/dist/commands/registry.d.ts.map +1 -1
  16. package/dist/commands/registry.js +7 -0
  17. package/dist/commands/registry.js.map +1 -1
  18. package/dist/commands/setup.d.ts.map +1 -1
  19. package/dist/commands/setup.js +53 -191
  20. package/dist/commands/setup.js.map +1 -1
  21. package/dist/commands/use.js +1 -1
  22. package/dist/commands/use.js.map +1 -1
  23. package/dist/commands/why.d.ts.map +1 -1
  24. package/dist/commands/why.js +21 -0
  25. package/dist/commands/why.js.map +1 -1
  26. package/dist/index.d.ts +1 -1
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/index.js +1 -0
  29. package/dist/index.js.map +1 -1
  30. package/dist/lib/ask-key-offer.d.ts +38 -0
  31. package/dist/lib/ask-key-offer.d.ts.map +1 -0
  32. package/dist/lib/ask-key-offer.js +130 -0
  33. package/dist/lib/ask-key-offer.js.map +1 -0
  34. package/dist/lib/config.d.ts +25 -24
  35. package/dist/lib/config.d.ts.map +1 -1
  36. package/dist/lib/config.js +37 -45
  37. package/dist/lib/config.js.map +1 -1
  38. package/dist/lib/launch/adapters/amp.d.ts +18 -0
  39. package/dist/lib/launch/adapters/amp.d.ts.map +1 -0
  40. package/dist/lib/launch/adapters/amp.js +29 -0
  41. package/dist/lib/launch/adapters/amp.js.map +1 -0
  42. package/dist/lib/launch/adapters/claude-code.d.ts +8 -0
  43. package/dist/lib/launch/adapters/claude-code.d.ts.map +1 -1
  44. package/dist/lib/launch/adapters/claude-code.js.map +1 -1
  45. package/dist/lib/launch/adapters/codex.d.ts +17 -0
  46. package/dist/lib/launch/adapters/codex.d.ts.map +1 -0
  47. package/dist/lib/launch/adapters/codex.js +44 -0
  48. package/dist/lib/launch/adapters/codex.js.map +1 -0
  49. package/dist/lib/launch/adapters/copilot.d.ts +17 -0
  50. package/dist/lib/launch/adapters/copilot.d.ts.map +1 -0
  51. package/dist/lib/launch/adapters/copilot.js +29 -0
  52. package/dist/lib/launch/adapters/copilot.js.map +1 -0
  53. package/dist/lib/launch/adapters/droid.d.ts +19 -0
  54. package/dist/lib/launch/adapters/droid.d.ts.map +1 -0
  55. package/dist/lib/launch/adapters/droid.js +38 -0
  56. package/dist/lib/launch/adapters/droid.js.map +1 -0
  57. package/dist/lib/launch/adapters/gemini-cli.d.ts +25 -0
  58. package/dist/lib/launch/adapters/gemini-cli.d.ts.map +1 -0
  59. package/dist/lib/launch/adapters/gemini-cli.js +73 -0
  60. package/dist/lib/launch/adapters/gemini-cli.js.map +1 -0
  61. package/dist/lib/launch/adapters/grok-build.d.ts +16 -0
  62. package/dist/lib/launch/adapters/grok-build.d.ts.map +1 -0
  63. package/dist/lib/launch/adapters/grok-build.js +25 -0
  64. package/dist/lib/launch/adapters/grok-build.js.map +1 -0
  65. package/dist/lib/launch/adapters/kiro.d.ts +17 -0
  66. package/dist/lib/launch/adapters/kiro.d.ts.map +1 -0
  67. package/dist/lib/launch/adapters/kiro.js +25 -0
  68. package/dist/lib/launch/adapters/kiro.js.map +1 -0
  69. package/dist/lib/launch/adapters/qwen.d.ts +25 -0
  70. package/dist/lib/launch/adapters/qwen.d.ts.map +1 -0
  71. package/dist/lib/launch/adapters/qwen.js +67 -0
  72. package/dist/lib/launch/adapters/qwen.js.map +1 -0
  73. package/dist/lib/launch/agents.d.ts +16 -3
  74. package/dist/lib/launch/agents.d.ts.map +1 -1
  75. package/dist/lib/launch/agents.js +26 -4
  76. package/dist/lib/launch/agents.js.map +1 -1
  77. package/dist/lib/launch/amp-state.d.ts +21 -0
  78. package/dist/lib/launch/amp-state.d.ts.map +1 -0
  79. package/dist/lib/launch/amp-state.js +61 -0
  80. package/dist/lib/launch/amp-state.js.map +1 -0
  81. package/dist/lib/launch/codex-state.d.ts +31 -0
  82. package/dist/lib/launch/codex-state.d.ts.map +1 -0
  83. package/dist/lib/launch/codex-state.js +92 -0
  84. package/dist/lib/launch/codex-state.js.map +1 -0
  85. package/dist/lib/launch/config-writes.d.ts +7 -1
  86. package/dist/lib/launch/config-writes.d.ts.map +1 -1
  87. package/dist/lib/launch/config-writes.js +60 -7
  88. package/dist/lib/launch/config-writes.js.map +1 -1
  89. package/dist/lib/launch/copilot-state.d.ts +19 -0
  90. package/dist/lib/launch/copilot-state.d.ts.map +1 -0
  91. package/dist/lib/launch/copilot-state.js +51 -0
  92. package/dist/lib/launch/copilot-state.js.map +1 -0
  93. package/dist/lib/launch/detect.d.ts.map +1 -1
  94. package/dist/lib/launch/detect.js +2 -1
  95. package/dist/lib/launch/detect.js.map +1 -1
  96. package/dist/lib/launch/droid-state.d.ts +24 -0
  97. package/dist/lib/launch/droid-state.d.ts.map +1 -0
  98. package/dist/lib/launch/droid-state.js +74 -0
  99. package/dist/lib/launch/droid-state.js.map +1 -0
  100. package/dist/lib/launch/gemini-state.d.ts +32 -0
  101. package/dist/lib/launch/gemini-state.d.ts.map +1 -0
  102. package/dist/lib/launch/gemini-state.js +59 -0
  103. package/dist/lib/launch/gemini-state.js.map +1 -0
  104. package/dist/lib/launch/gemini-trust.d.ts +26 -0
  105. package/dist/lib/launch/gemini-trust.d.ts.map +1 -0
  106. package/dist/lib/launch/gemini-trust.js +103 -0
  107. package/dist/lib/launch/gemini-trust.js.map +1 -0
  108. package/dist/lib/launch/grok-state.d.ts +42 -0
  109. package/dist/lib/launch/grok-state.d.ts.map +1 -0
  110. package/dist/lib/launch/grok-state.js +128 -0
  111. package/dist/lib/launch/grok-state.js.map +1 -0
  112. package/dist/lib/launch/install.d.ts +33 -0
  113. package/dist/lib/launch/install.d.ts.map +1 -0
  114. package/dist/lib/launch/install.js +48 -0
  115. package/dist/lib/launch/install.js.map +1 -0
  116. package/dist/lib/launch/kiro-state.d.ts +22 -0
  117. package/dist/lib/launch/kiro-state.d.ts.map +1 -0
  118. package/dist/lib/launch/kiro-state.js +59 -0
  119. package/dist/lib/launch/kiro-state.js.map +1 -0
  120. package/dist/lib/launch/launch-files.d.ts +15 -0
  121. package/dist/lib/launch/launch-files.d.ts.map +1 -1
  122. package/dist/lib/launch/launch-files.js +64 -4
  123. package/dist/lib/launch/launch-files.js.map +1 -1
  124. package/dist/lib/launch/launch.d.ts +61 -6
  125. package/dist/lib/launch/launch.d.ts.map +1 -1
  126. package/dist/lib/launch/launch.js +98 -31
  127. package/dist/lib/launch/launch.js.map +1 -1
  128. package/dist/lib/launch/layer-files.d.ts +12 -0
  129. package/dist/lib/launch/layer-files.d.ts.map +1 -0
  130. package/dist/lib/launch/layer-files.js +43 -0
  131. package/dist/lib/launch/layer-files.js.map +1 -0
  132. package/dist/lib/launch/pick-agent.d.ts +12 -5
  133. package/dist/lib/launch/pick-agent.d.ts.map +1 -1
  134. package/dist/lib/launch/pick-agent.js +47 -19
  135. package/dist/lib/launch/pick-agent.js.map +1 -1
  136. package/dist/lib/launch/picker-options.d.ts +30 -0
  137. package/dist/lib/launch/picker-options.d.ts.map +1 -0
  138. package/dist/lib/launch/picker-options.js +42 -0
  139. package/dist/lib/launch/picker-options.js.map +1 -0
  140. package/dist/lib/launch/prompts.d.ts +11 -0
  141. package/dist/lib/launch/prompts.d.ts.map +1 -0
  142. package/dist/lib/launch/prompts.js +27 -0
  143. package/dist/lib/launch/prompts.js.map +1 -0
  144. package/dist/lib/launch/qwen-state.d.ts +30 -0
  145. package/dist/lib/launch/qwen-state.d.ts.map +1 -0
  146. package/dist/lib/launch/qwen-state.js +57 -0
  147. package/dist/lib/launch/qwen-state.js.map +1 -0
  148. package/dist/lib/launch/qwen-trust.d.ts +24 -0
  149. package/dist/lib/launch/qwen-trust.d.ts.map +1 -0
  150. package/dist/lib/launch/qwen-trust.js +100 -0
  151. package/dist/lib/launch/qwen-trust.js.map +1 -0
  152. package/dist/lib/launch/registry/agents/amp.d.ts +3 -0
  153. package/dist/lib/launch/registry/agents/amp.d.ts.map +1 -0
  154. package/dist/lib/launch/registry/agents/amp.js +14 -0
  155. package/dist/lib/launch/registry/agents/amp.js.map +1 -0
  156. package/dist/lib/launch/registry/agents/claude-code.js +1 -1
  157. package/dist/lib/launch/registry/agents/claude-code.js.map +1 -1
  158. package/dist/lib/launch/registry/agents/codex.d.ts.map +1 -1
  159. package/dist/lib/launch/registry/agents/codex.js +4 -2
  160. package/dist/lib/launch/registry/agents/codex.js.map +1 -1
  161. package/dist/lib/launch/registry/agents/copilot.d.ts +3 -0
  162. package/dist/lib/launch/registry/agents/copilot.d.ts.map +1 -0
  163. package/dist/lib/launch/registry/agents/copilot.js +11 -0
  164. package/dist/lib/launch/registry/agents/copilot.js.map +1 -0
  165. package/dist/lib/launch/registry/agents/cursor.js +1 -1
  166. package/dist/lib/launch/registry/agents/cursor.js.map +1 -1
  167. package/dist/lib/launch/registry/agents/droid.d.ts +3 -0
  168. package/dist/lib/launch/registry/agents/droid.d.ts.map +1 -0
  169. package/dist/lib/launch/registry/agents/droid.js +13 -0
  170. package/dist/lib/launch/registry/agents/droid.js.map +1 -0
  171. package/dist/lib/launch/registry/agents/gemini-cli.d.ts.map +1 -1
  172. package/dist/lib/launch/registry/agents/gemini-cli.js +4 -2
  173. package/dist/lib/launch/registry/agents/gemini-cli.js.map +1 -1
  174. package/dist/lib/launch/registry/agents/grok-build.d.ts +3 -0
  175. package/dist/lib/launch/registry/agents/grok-build.d.ts.map +1 -0
  176. package/dist/lib/launch/registry/agents/grok-build.js +14 -0
  177. package/dist/lib/launch/registry/agents/grok-build.js.map +1 -0
  178. package/dist/lib/launch/registry/agents/kiro.d.ts +3 -0
  179. package/dist/lib/launch/registry/agents/kiro.d.ts.map +1 -0
  180. package/dist/lib/launch/registry/agents/kiro.js +11 -0
  181. package/dist/lib/launch/registry/agents/kiro.js.map +1 -0
  182. package/dist/lib/launch/registry/agents/opencode.js +1 -1
  183. package/dist/lib/launch/registry/agents/opencode.js.map +1 -1
  184. package/dist/lib/launch/registry/agents/pi.js +1 -1
  185. package/dist/lib/launch/registry/agents/pi.js.map +1 -1
  186. package/dist/lib/launch/registry/agents/qwen.d.ts +3 -0
  187. package/dist/lib/launch/registry/agents/qwen.d.ts.map +1 -0
  188. package/dist/lib/launch/registry/agents/qwen.js +11 -0
  189. package/dist/lib/launch/registry/agents/qwen.js.map +1 -0
  190. package/dist/lib/launch/registry/index.d.ts +4 -1
  191. package/dist/lib/launch/registry/index.d.ts.map +1 -1
  192. package/dist/lib/launch/registry/index.js +11 -2
  193. package/dist/lib/launch/registry/index.js.map +1 -1
  194. package/dist/lib/launch/registry/types.d.ts +18 -2
  195. package/dist/lib/launch/registry/types.d.ts.map +1 -1
  196. package/dist/lib/launch/run-agent.d.ts +15 -0
  197. package/dist/lib/launch/run-agent.d.ts.map +1 -1
  198. package/dist/lib/launch/run-agent.js +23 -2
  199. package/dist/lib/launch/run-agent.js.map +1 -1
  200. package/dist/lib/launch/strict-entry.d.ts +49 -0
  201. package/dist/lib/launch/strict-entry.d.ts.map +1 -0
  202. package/dist/lib/launch/strict-entry.js +108 -0
  203. package/dist/lib/launch/strict-entry.js.map +1 -0
  204. package/dist/lib/llm-providers.d.ts +66 -0
  205. package/dist/lib/llm-providers.d.ts.map +1 -0
  206. package/dist/lib/llm-providers.js +150 -0
  207. package/dist/lib/llm-providers.js.map +1 -0
  208. package/dist/lib/local-llm.d.ts +63 -12
  209. package/dist/lib/local-llm.d.ts.map +1 -1
  210. package/dist/lib/local-llm.js +229 -104
  211. package/dist/lib/local-llm.js.map +1 -1
  212. package/dist/lib/safe-config-write.d.ts +12 -1
  213. package/dist/lib/safe-config-write.d.ts.map +1 -1
  214. package/dist/lib/safe-config-write.js +123 -7
  215. package/dist/lib/safe-config-write.js.map +1 -1
  216. package/dist/lib/startup-env.d.ts +8 -0
  217. package/dist/lib/startup-env.d.ts.map +1 -0
  218. package/dist/lib/startup-env.js +8 -0
  219. package/dist/lib/startup-env.js.map +1 -0
  220. package/package.json +3 -2
@@ -0,0 +1,74 @@
1
+ import { existsSync, lstatSync } from 'node:fs';
2
+ import path from 'node:path';
3
+ import { ALIGN_NUDGE_START } from '../agent-rules.js';
4
+ import { ancestors, optionValue, readText } from './layer-files.js';
5
+ import { foldLayers, isCanonicalLocalEntry, parseJsonc } from './strict-entry.js';
6
+ /** Droid's guideline file names and the dirs it looks in beside each directory (droid 0.237.0). */
7
+ const GUIDELINES = ['CLAUDE.md', 'Claude.md', 'AGENTS.md', 'Agents.md', 'agents.md'];
8
+ const CONTEXT_DIRS = ['.factory', '.agents', '.agent'];
9
+ /** The nearest directory at or above `start` holding `.git` (a dir, or a worktree's file). */
10
+ function gitRoot(start) {
11
+ return ancestors(start).find((d) => existsSync(path.join(d, '.git')));
12
+ }
13
+ /** Droid's walk: `start` up to the git root, or `start` alone when there is none. */
14
+ function projectDirs(start) {
15
+ const root = gitRoot(start);
16
+ if (!root)
17
+ return [start];
18
+ const all = ancestors(start);
19
+ return all.slice(0, all.indexOf(root) + 1);
20
+ }
21
+ /** A regular file, not a link (Droid's lstat check ignores links), holding the block. */
22
+ function guidelineHasBlock(dir, name) {
23
+ const file = path.join(dir, name);
24
+ try {
25
+ if (!lstatSync(file).isFile())
26
+ return false;
27
+ }
28
+ catch {
29
+ return false;
30
+ }
31
+ return readText(file)?.includes(ALIGN_NUDGE_START) ?? false;
32
+ }
33
+ function isRealDir(dir) {
34
+ try {
35
+ return lstatSync(dir).isDirectory();
36
+ }
37
+ catch {
38
+ return false;
39
+ }
40
+ }
41
+ /**
42
+ * What Factory Droid (droid 0.237.0) would already load for align. The project is `--cwd` when
43
+ * the user passes one (relative to the cwd), else the cwd; "home" is FACTORY_HOME_OVERRIDE when
44
+ * set (Droid's own home resolution).
45
+ * - MCP: $home/.factory/mcp.json, and a `.factory/mcp.json` from the project up to the git root
46
+ * (to the filesystem root with no git root). The per-process runtime settings win a same-named
47
+ * server (verified with `droid --settings f mcp list`), so a non-canonical align-local is
48
+ * overridden. Only the user's own canonical `align` stands in for us.
49
+ * - Instructions: Droid's own guideline discovery (agentsMdGuidelines): the project up to the
50
+ * git root, or only the project with none, each dir plus its .factory/.agents/.agent, plus
51
+ * $home/.factory, .agents and .agent; CLAUDE.md, AGENTS.md and case variants; a linked file or
52
+ * directory is ignored, as Droid's lstat checks ignore it.
53
+ */
54
+ export function readDroidState(cwd, home, opts, env, platform, passthrough) {
55
+ const userCwd = optionValue(passthrough, '--cwd');
56
+ const start = path.resolve(cwd, userCwd ?? '.');
57
+ const droidHome = env['FACTORY_HOME_OVERRIDE'] ? path.resolve(env['FACTORY_HOME_OVERRIDE']) : home;
58
+ const userFile = path.join(droidHome, '.factory', 'mcp.json');
59
+ const layer = (file) => ({ file, servers: parseJsonc(readText(file))?.['mcpServers'] });
60
+ const user = layer(userFile);
61
+ const root = gitRoot(start);
62
+ const mcpDirs = root ? projectDirs(start) : ancestors(start);
63
+ const layers = [user, ...mcpDirs.map((d) => layer(path.join(d, '.factory', 'mcp.json'))).filter((l) => l.file !== userFile)];
64
+ const o = { ...opts, platform, host: 'droid' };
65
+ const { overridden } = foldLayers(layers, o, () => true);
66
+ const present = isCanonicalLocalEntry(user.servers?.['align'], o);
67
+ const own = optionValue(passthrough, '--settings') ?? (env['FACTORY_RUNTIME_SETTINGS_PATH'] ? env['FACTORY_RUNTIME_SETTINGS_PATH'] : undefined);
68
+ const personal = CONTEXT_DIRS.map((d) => path.join(droidHome, d));
69
+ const dirs = projectDirs(start).filter((d) => d !== droidHome).flatMap((d) => [d, ...CONTEXT_DIRS.map((c) => path.join(d, c))]).filter((d) => !personal.includes(d));
70
+ // Droid looks only in a real directory (not a link) at a regular file (not a link): lstat both.
71
+ const projectHasBlock = [...dirs, ...personal].some((dir) => isRealDir(dir) && GUIDELINES.some((name) => guidelineHasBlock(dir, name)));
72
+ return { present, overridden, ...(own !== undefined ? { ownSettings: own } : {}), projectHasBlock };
73
+ }
74
+ //# sourceMappingURL=droid-state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"droid-state.js","sourceRoot":"","sources":["../../../src/lib/launch/droid-state.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ import { type GeminiTrust } from './gemini-trust.js';
2
+ import { type AlignLocalState } from './strict-entry.js';
3
+ /** The system settings file Gemini would read with no help from align, and what it holds. */
4
+ export interface GeminiSystemSettings {
5
+ path: string;
6
+ /** Its text; null when it does not exist (or is unreadable). */
7
+ text: string | null;
8
+ /** It exists but could not be read (a directory, no permission). */
9
+ unreadable: boolean;
10
+ }
11
+ export interface GeminiProjectState extends AlignLocalState {
12
+ systemSettings: GeminiSystemSettings;
13
+ trust: GeminiTrust;
14
+ }
15
+ /**
16
+ * The launch-cache name of the merged copy of one system settings file. One name per SOURCE,
17
+ * so two concurrent launches that read different system files never write the same copy.
18
+ */
19
+ export declare const COPY_PREFIX = "gemini-system-settings-";
20
+ export declare function geminiCopyName(source: string): string;
21
+ /**
22
+ * What Gemini CLI would already load here, in its merge order (gemini 0.58.0 mergeSettings:
23
+ * system-defaults, user, workspace, system): system-defaults, ~/.gemini (or $GEMINI_CLI_HOME)
24
+ * settings, the project's .gemini/settings.json ONLY when the folder is trusted (Gemini drops
25
+ * the workspace layer otherwise), and the system file. Files are JSONC, as Gemini reads them.
26
+ * mcpServers merges shallowly with the system tier last, so the injected system copy replaces
27
+ * any align-local whole: a non-canonical one is overridden, never a conflict.
28
+ */
29
+ export declare function readGeminiState(cwd: string, home: string, opts: {
30
+ localIsDefault: boolean;
31
+ }, env: Record<string, string | undefined>, platform: string): GeminiProjectState;
32
+ //# sourceMappingURL=gemini-state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gemini-state.d.ts","sourceRoot":"","sources":["../../../src/lib/launch/gemini-state.ts"],"names":[],"mappings":"AAGA,OAAO,EAAoF,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACvI,OAAO,EAAE,KAAK,eAAe,EAA6D,MAAM,mBAAmB,CAAC;AAEpH,6FAA6F;AAC7F,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,gEAAgE;IAChE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,oEAAoE;IACpE,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,kBAAmB,SAAQ,eAAe;IACzD,cAAc,EAAE,oBAAoB,CAAC;IACrC,KAAK,EAAE,WAAW,CAAC;CACpB;AAED;;;GAGG;AACH,eAAO,MAAM,WAAW,4BAA4B,CAAC;AAErD,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAErD;AAoBD;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC7B,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE;IAAE,cAAc,EAAE,OAAO,CAAA;CAAE,EACjC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,EACvC,QAAQ,EAAE,MAAM,GACf,kBAAkB,CAmBpB"}
@@ -0,0 +1,59 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { readFileSync } from 'node:fs';
3
+ import path from 'node:path';
4
+ import { geminiDir, geminiFolderTrust, geminiSystemDefaultsPath, geminiSystemSettingsPath } from './gemini-trust.js';
5
+ import { foldLayers, isCanonicalLocalEntry, parseJsonc } from './strict-entry.js';
6
+ /**
7
+ * The launch-cache name of the merged copy of one system settings file. One name per SOURCE,
8
+ * so two concurrent launches that read different system files never write the same copy.
9
+ */
10
+ export const COPY_PREFIX = 'gemini-system-settings-';
11
+ export function geminiCopyName(source) {
12
+ return `${COPY_PREFIX}${createHash('sha256').update(path.resolve(source)).digest('hex').slice(0, 12)}.json`;
13
+ }
14
+ function readSystem(file) {
15
+ try {
16
+ return { path: file, text: readFileSync(file, 'utf8'), unreadable: false };
17
+ }
18
+ catch (e) {
19
+ return { path: file, text: null, unreadable: e.code !== 'ENOENT' };
20
+ }
21
+ }
22
+ function readText(file) {
23
+ try {
24
+ return readFileSync(file, 'utf8');
25
+ }
26
+ catch {
27
+ return null;
28
+ }
29
+ }
30
+ const layer = (file, text) => ({ file, servers: parseJsonc(text)?.['mcpServers'] });
31
+ /**
32
+ * What Gemini CLI would already load here, in its merge order (gemini 0.58.0 mergeSettings:
33
+ * system-defaults, user, workspace, system): system-defaults, ~/.gemini (or $GEMINI_CLI_HOME)
34
+ * settings, the project's .gemini/settings.json ONLY when the folder is trusted (Gemini drops
35
+ * the workspace layer otherwise), and the system file. Files are JSONC, as Gemini reads them.
36
+ * mcpServers merges shallowly with the system tier last, so the injected system copy replaces
37
+ * any align-local whole: a non-canonical one is overridden, never a conflict.
38
+ */
39
+ export function readGeminiState(cwd, home, opts, env, platform) {
40
+ const system = readSystem(geminiSystemSettingsPath(env, platform));
41
+ const trust = geminiFolderTrust(cwd, home, env, platform);
42
+ const defaultsPath = env['GEMINI_CLI_SYSTEM_DEFAULTS_PATH'] ? env['GEMINI_CLI_SYSTEM_DEFAULTS_PATH'] : geminiSystemDefaultsPath(system.path, platform);
43
+ const userPath = path.join(geminiDir(home, env), 'settings.json');
44
+ const workspacePath = path.join(cwd, '.gemini', 'settings.json');
45
+ const layers = [
46
+ layer(defaultsPath, readText(defaultsPath)),
47
+ layer(userPath, readText(userPath)),
48
+ ...(trust === 'trusted' || trust === 'off' ? [layer(workspacePath, readText(workspacePath))] : []),
49
+ layer(system.path, system.text),
50
+ ];
51
+ const o = { ...opts, platform, host: 'mcpServers' };
52
+ const { overridden } = foldLayers(layers, o, () => true);
53
+ // Only the user's own `align` stands in for us. A canonical align-local does not: the system
54
+ // copy replaces it whole anyway, and skipping would let a workspace align-local trusted later
55
+ // take its place.
56
+ const present = layers.some((l) => isCanonicalLocalEntry(l.servers?.['align'], o));
57
+ return { present, overridden, systemSettings: system, trust };
58
+ }
59
+ //# sourceMappingURL=gemini-state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gemini-state.js","sourceRoot":"","sources":["../../../src/lib/launch/gemini-state.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Whether Gemini CLI will run MCP servers in this folder. Gemini turns off EVERY MCP server,
3
+ * the injected align-local included, in a folder it does not trust.
4
+ * - trusted / untrusted: what Gemini will decide.
5
+ * - off: folder trust is turned off in the user's settings, so nothing is disabled.
6
+ * - unknown: trustedFolders.json is unreadable or invalid (Gemini itself refuses to start then).
7
+ */
8
+ export type GeminiTrust = 'trusted' | 'untrusted' | 'off' | 'unknown';
9
+ /** Gemini's own default system settings file, used when GEMINI_CLI_SYSTEM_SETTINGS_PATH is unset. */
10
+ export declare function geminiSystemSettingsPath(env: Record<string, string | undefined>, platform: string): string;
11
+ /** GEMINI_CLI_SYSTEM_DEFAULTS_PATH, else `system-defaults.json` beside the system settings file. */
12
+ export declare function geminiSystemDefaultsPath(systemSettingsPath: string, platform: string): string;
13
+ /** ~/.gemini, or $GEMINI_CLI_HOME/.gemini when set. */
14
+ export declare function geminiDir(home: string, env: Record<string, string | undefined>): string;
15
+ /**
16
+ * Gemini CLI 0.58.0's folder-trust verdict for `cwd`, read from its own files and never written
17
+ * (packages/core/src/utils/trust.ts, cli/src/config/trustedFolders.ts):
18
+ * - GEMINI_CLI_TRUST_WORKSPACE=true|false decides outright;
19
+ * - folder trust turned off in settings means nothing is disabled;
20
+ * - else the LONGEST matching rule in trustedFolders.json decides, where TRUST_PARENT matches
21
+ * the rule's parent directory, and no matching rule is untrusted.
22
+ * Gemini also accepts a trust decision from a connected IDE; align cannot see that, so in an IDE
23
+ * terminal this can say untrusted for a folder Gemini will treat as trusted (one extra line).
24
+ */
25
+ export declare function geminiFolderTrust(cwd: string, home: string, env: Record<string, string | undefined>, platform: string): GeminiTrust;
26
+ //# sourceMappingURL=gemini-trust.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gemini-trust.d.ts","sourceRoot":"","sources":["../../../src/lib/launch/gemini-trust.ts"],"names":[],"mappings":"AAIA;;;;;;GAMG;AACH,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,WAAW,GAAG,KAAK,GAAG,SAAS,CAAC;AAgBtE,qGAAqG;AACrG,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAK1G;AAED,oGAAoG;AACpG,wBAAgB,wBAAwB,CAAC,kBAAkB,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAG7F;AAED,uDAAuD;AACvD,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,GAAG,MAAM,CAEvF;AAqCD;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,EAAE,QAAQ,EAAE,MAAM,GAAG,WAAW,CAuBnI"}
@@ -0,0 +1,103 @@
1
+ import { existsSync, readFileSync, realpathSync } from 'node:fs';
2
+ import path from 'node:path';
3
+ import { parseJsonc } from './strict-entry.js';
4
+ const LEVELS = new Set(['TRUST_FOLDER', 'TRUST_PARENT', 'DO_NOT_TRUST']);
5
+ /** Gemini reads these files through strip-json-comments, so comments are allowed. */
6
+ function readJson(file) {
7
+ try {
8
+ return parseJsonc(readFileSync(file, 'utf8'));
9
+ }
10
+ catch {
11
+ return null;
12
+ }
13
+ }
14
+ const pathFor = (platform) => (platform === 'win32' ? path.win32 : path.posix);
15
+ /** Gemini's own default system settings file, used when GEMINI_CLI_SYSTEM_SETTINGS_PATH is unset. */
16
+ export function geminiSystemSettingsPath(env, platform) {
17
+ if (env['GEMINI_CLI_SYSTEM_SETTINGS_PATH'])
18
+ return env['GEMINI_CLI_SYSTEM_SETTINGS_PATH'];
19
+ if (platform === 'darwin')
20
+ return '/Library/Application Support/GeminiCli/settings.json';
21
+ if (platform === 'win32')
22
+ return 'C:\\ProgramData\\gemini-cli\\settings.json';
23
+ return '/etc/gemini-cli/settings.json';
24
+ }
25
+ /** GEMINI_CLI_SYSTEM_DEFAULTS_PATH, else `system-defaults.json` beside the system settings file. */
26
+ export function geminiSystemDefaultsPath(systemSettingsPath, platform) {
27
+ const p = pathFor(platform);
28
+ return p.join(p.dirname(systemSettingsPath), 'system-defaults.json');
29
+ }
30
+ /** ~/.gemini, or $GEMINI_CLI_HOME/.gemini when set. */
31
+ export function geminiDir(home, env) {
32
+ return path.join(env['GEMINI_CLI_HOME'] ? env['GEMINI_CLI_HOME'] : home, '.gemini');
33
+ }
34
+ const folderTrustSetting = (s) => s?.['security']?.['folderTrust']?.['enabled'];
35
+ /** security.folderTrust.enabled, merged system-defaults < user < system as Gemini does; default on. */
36
+ function folderTrustEnabled(home, env, platform) {
37
+ const system = geminiSystemSettingsPath(env, platform);
38
+ const defaults = env['GEMINI_CLI_SYSTEM_DEFAULTS_PATH'] ? env['GEMINI_CLI_SYSTEM_DEFAULTS_PATH'] : geminiSystemDefaultsPath(system, platform);
39
+ let enabled = true;
40
+ for (const file of [defaults, path.join(geminiDir(home, env), 'settings.json'), system]) {
41
+ const v = folderTrustSetting(readJson(file));
42
+ if (typeof v === 'boolean')
43
+ enabled = v;
44
+ }
45
+ return enabled;
46
+ }
47
+ function realPath(p) {
48
+ try {
49
+ return existsSync(p) ? realpathSync(p) : p;
50
+ }
51
+ catch {
52
+ return p;
53
+ }
54
+ }
55
+ /** Gemini's normalizePath: absolute, and lower-cased where the filesystem is case-insensitive. */
56
+ function normalize(p, platform) {
57
+ const abs = pathFor(platform).resolve(p);
58
+ return platform === 'win32' || platform === 'darwin' ? abs.toLowerCase() : abs;
59
+ }
60
+ /** Gemini's isSubpath: `child` is `parent` or below it. A shared string prefix is not enough. */
61
+ function isSubpath(parent, child, platform) {
62
+ const p = pathFor(platform);
63
+ const rel = p.relative(parent, child);
64
+ return !rel.startsWith(`..${p.sep}`) && rel !== '..' && !p.isAbsolute(rel);
65
+ }
66
+ /**
67
+ * Gemini CLI 0.58.0's folder-trust verdict for `cwd`, read from its own files and never written
68
+ * (packages/core/src/utils/trust.ts, cli/src/config/trustedFolders.ts):
69
+ * - GEMINI_CLI_TRUST_WORKSPACE=true|false decides outright;
70
+ * - folder trust turned off in settings means nothing is disabled;
71
+ * - else the LONGEST matching rule in trustedFolders.json decides, where TRUST_PARENT matches
72
+ * the rule's parent directory, and no matching rule is untrusted.
73
+ * Gemini also accepts a trust decision from a connected IDE; align cannot see that, so in an IDE
74
+ * terminal this can say untrusted for a folder Gemini will treat as trusted (one extra line).
75
+ */
76
+ export function geminiFolderTrust(cwd, home, env, platform) {
77
+ if (env['GEMINI_CLI_TRUST_WORKSPACE'] === 'true')
78
+ return 'trusted';
79
+ if (env['GEMINI_CLI_TRUST_WORKSPACE'] === 'false')
80
+ return 'untrusted';
81
+ if (!folderTrustEnabled(home, env, platform))
82
+ return 'off';
83
+ const file = env['GEMINI_CLI_TRUSTED_FOLDERS_PATH'] ? env['GEMINI_CLI_TRUSTED_FOLDERS_PATH'] : path.join(geminiDir(home, env), 'trustedFolders.json');
84
+ if (!existsSync(file))
85
+ return 'untrusted';
86
+ const rules = readJson(file);
87
+ if (!rules || !Object.values(rules).every((v) => typeof v === 'string' && LEVELS.has(v)))
88
+ return 'unknown';
89
+ const p = pathFor(platform);
90
+ const location = normalize(realPath(cwd), platform);
91
+ let longest = -1;
92
+ let verdict;
93
+ for (const [raw, level] of Object.entries(rules)) {
94
+ const rule = normalize(raw, platform);
95
+ const effective = normalize(realPath(level === 'TRUST_PARENT' ? p.dirname(rule) : rule), platform);
96
+ if (isSubpath(effective, location, platform) && rule.length > longest) {
97
+ longest = rule.length;
98
+ verdict = level;
99
+ }
100
+ }
101
+ return verdict === 'TRUST_FOLDER' || verdict === 'TRUST_PARENT' ? 'trusted' : 'untrusted';
102
+ }
103
+ //# sourceMappingURL=gemini-trust.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gemini-trust.js","sourceRoot":"","sources":["../../../src/lib/launch/gemini-trust.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,42 @@
1
+ import { type AlignLocalState } from './strict-entry.js';
2
+ export interface GrokProjectState extends AlignLocalState {
3
+ /** $GROK_HOME/config.toml (else ~/.grok/config.toml): the file align adds to. */
4
+ configFile: string;
5
+ }
6
+ /**
7
+ * $GROK_HOME verbatim when non-empty, else `<home>/.grok` with the home's symlinks resolved, as
8
+ * Grok Build's own installer and `grok_home()` do (xai-org/grok-build xai-dirs, npm postinstall.js).
9
+ */
10
+ export declare function grokHome(env: Record<string, string | undefined>, platform: string, home?: string): string;
11
+ export interface BinFs {
12
+ realpath(p: string): string;
13
+ exists(p: string): boolean;
14
+ }
15
+ /**
16
+ * `grok` is a generic name, so a `grok` on PATH is Grok Build only when its realpath sits where
17
+ * Grok Build's own installers put it:
18
+ * - the install script (x.ai/cli/install.sh): `$GROK_HOME/downloads/grok-<platform>`, linked from
19
+ * `$GROK_HOME/bin/grok` (and from `$GROK_BIN_DIR` or ~/.local/bin, which resolve to the same);
20
+ * - its Windows script: a copy at `%USERPROFILE%\.grok\bin\grok.exe`;
21
+ * - the npm package `@xai-official/grok`: its postinstall installs into `$GROK_HOME/bin`, and the
22
+ * npm entry itself lives in `node_modules/@xai-official/grok[-<platform>]/`. On Windows npm's
23
+ * `grok.cmd` shim sits beside `node_modules`, so it counts when that package is next to it.
24
+ * Anything else (another tool's `grok`) is not Grok Build, and counts as not installed.
25
+ */
26
+ export declare function isGrokBuildBin(found: string, env: Record<string, string | undefined>, platform: string, fsx?: BinFs): boolean;
27
+ /**
28
+ * What Grok Build (grok 1.0.50) would already load for align, measured with `grok mcp list` and
29
+ * `grok inspect` in a sandbox:
30
+ * - `$GROK_HOME/config.toml` `[mcp_servers.*]`: the user file align writes to;
31
+ * - a project `.grok/config.toml` (repo root down to the cwd; every ancestor is read here):
32
+ * "A project file entirely replaces a same-named server from the user config", so a
33
+ * non-canonical align-local there would replace ours: a conflict, nothing is written;
34
+ * - ~/.claude.json and ~/.cursor/mcp.json (Grok imports them): a same-named server there LOSES
35
+ * to config.toml (verified), so it is no conflict; a canonical local `align` there is present.
36
+ * A project `.mcp.json` is repo input and never counts as present. The project is `--cwd` when
37
+ * the user passes one.
38
+ */
39
+ export declare function readGrokState(cwd: string, home: string, opts: {
40
+ localIsDefault: boolean;
41
+ }, env: Record<string, string | undefined>, platform: string, passthrough?: string[]): GrokProjectState;
42
+ //# sourceMappingURL=grok-state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grok-state.d.ts","sourceRoot":"","sources":["../../../src/lib/launch/grok-state.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,KAAK,eAAe,EAAqC,MAAM,mBAAmB,CAAC;AAE5F,MAAM,WAAW,gBAAiB,SAAQ,eAAe;IACvD,iFAAiF;IACjF,UAAU,EAAE,MAAM,CAAC;CACpB;AAqBD;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,SAAwB,GAAG,MAAM,CAGxH;AASD,MAAM,WAAW,KAAK;IACpB,QAAQ,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,MAAM,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CAC5B;AAGD;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,GAAE,KAAc,GAAG,OAAO,CAkBrI;AAaD;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAC3B,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE;IAAE,cAAc,EAAE,OAAO,CAAA;CAAE,EACjC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,EACvC,QAAQ,EAAE,MAAM,EAChB,WAAW,GAAE,MAAM,EAAO,GACzB,gBAAgB,CA0BlB"}
@@ -0,0 +1,128 @@
1
+ import { existsSync, realpathSync } from 'node:fs';
2
+ import os from 'node:os';
3
+ import path from 'node:path';
4
+ import { parse } from 'smol-toml';
5
+ import { ancestors, optionValue, readText } from './layer-files.js';
6
+ import { isCanonicalLocalEntry, parseJsonc } from './strict-entry.js';
7
+ const isObject = (v) => typeof v === 'object' && v !== null && !Array.isArray(v);
8
+ const pathFor = (platform) => (platform === 'win32' ? path.win32 : path.posix);
9
+ function real(p) {
10
+ try {
11
+ return realpathSync(p);
12
+ }
13
+ catch {
14
+ return p;
15
+ }
16
+ }
17
+ /** The user's home as Grok Build resolves it: $HOME (USERPROFILE on Windows), else the OS's. */
18
+ function homeOf(env, platform) {
19
+ const h = platform === 'win32' ? env['USERPROFILE'] || env['HOME'] : env['HOME'];
20
+ return h ? h : os.homedir();
21
+ }
22
+ /**
23
+ * $GROK_HOME verbatim when non-empty, else `<home>/.grok` with the home's symlinks resolved, as
24
+ * Grok Build's own installer and `grok_home()` do (xai-org/grok-build xai-dirs, npm postinstall.js).
25
+ */
26
+ export function grokHome(env, platform, home = homeOf(env, platform)) {
27
+ if (env['GROK_HOME'])
28
+ return pathFor(platform).resolve(env['GROK_HOME']);
29
+ return pathFor(platform).join(platform === 'win32' ? home : real(home), '.grok');
30
+ }
31
+ const inside = (child, parent, platform) => {
32
+ const p = pathFor(platform);
33
+ const norm = (x) => (platform === 'win32' ? p.resolve(x).toLowerCase() : p.resolve(x));
34
+ const rel = p.relative(norm(parent), norm(child));
35
+ return rel !== '' && !rel.startsWith(`..${p.sep}`) && rel !== '..' && !p.isAbsolute(rel);
36
+ };
37
+ const realFs = { realpath: (p) => realpathSync(p), exists: (p) => existsSync(p) };
38
+ /**
39
+ * `grok` is a generic name, so a `grok` on PATH is Grok Build only when its realpath sits where
40
+ * Grok Build's own installers put it:
41
+ * - the install script (x.ai/cli/install.sh): `$GROK_HOME/downloads/grok-<platform>`, linked from
42
+ * `$GROK_HOME/bin/grok` (and from `$GROK_BIN_DIR` or ~/.local/bin, which resolve to the same);
43
+ * - its Windows script: a copy at `%USERPROFILE%\.grok\bin\grok.exe`;
44
+ * - the npm package `@xai-official/grok`: its postinstall installs into `$GROK_HOME/bin`, and the
45
+ * npm entry itself lives in `node_modules/@xai-official/grok[-<platform>]/`. On Windows npm's
46
+ * `grok.cmd` shim sits beside `node_modules`, so it counts when that package is next to it.
47
+ * Anything else (another tool's `grok`) is not Grok Build, and counts as not installed.
48
+ */
49
+ export function isGrokBuildBin(found, env, platform, fsx = realFs) {
50
+ let resolved;
51
+ try {
52
+ resolved = fsx.realpath(found);
53
+ }
54
+ catch {
55
+ return false;
56
+ }
57
+ const g = grokHome(env, platform);
58
+ const p = pathFor(platform);
59
+ if (inside(resolved, p.join(g, 'bin'), platform) || inside(resolved, p.join(g, 'downloads'), platform))
60
+ return true;
61
+ const parts = resolved.split(/[\\/]/);
62
+ for (let i = 0; i + 2 < parts.length; i++) {
63
+ if (parts[i] === 'node_modules' && parts[i + 1] === '@xai-official' && /^grok(-[a-z0-9]+-[a-z0-9]+)?$/.test(parts[i + 2]))
64
+ return true;
65
+ }
66
+ if (platform === 'win32' && /^grok\.cmd$/i.test(p.basename(resolved))) {
67
+ return fsx.exists(p.join(p.dirname(resolved), 'node_modules', '@xai-official', 'grok', 'package.json'));
68
+ }
69
+ return false;
70
+ }
71
+ function readToml(file) {
72
+ const text = readText(file);
73
+ if (text === null)
74
+ return null;
75
+ try {
76
+ const parsed = parse(text);
77
+ return isObject(parsed) ? parsed : null;
78
+ }
79
+ catch {
80
+ return null;
81
+ }
82
+ }
83
+ /**
84
+ * What Grok Build (grok 1.0.50) would already load for align, measured with `grok mcp list` and
85
+ * `grok inspect` in a sandbox:
86
+ * - `$GROK_HOME/config.toml` `[mcp_servers.*]`: the user file align writes to;
87
+ * - a project `.grok/config.toml` (repo root down to the cwd; every ancestor is read here):
88
+ * "A project file entirely replaces a same-named server from the user config", so a
89
+ * non-canonical align-local there would replace ours: a conflict, nothing is written;
90
+ * - ~/.claude.json and ~/.cursor/mcp.json (Grok imports them): a same-named server there LOSES
91
+ * to config.toml (verified), so it is no conflict; a canonical local `align` there is present.
92
+ * A project `.mcp.json` is repo input and never counts as present. The project is `--cwd` when
93
+ * the user passes one.
94
+ */
95
+ export function readGrokState(cwd, home, opts, env, platform, passthrough = []) {
96
+ // `grok --cwd <dir>` moves the project Grok loads; relative to the cwd, as a shell gives it.
97
+ const project = path.resolve(cwd, optionValue(passthrough, '--cwd') ?? '.');
98
+ const o = { ...opts, platform, host: 'mcpServers' };
99
+ // A path on this machine's own filesystem: built with the host's path rules (in production the
100
+ // platform is the host's anyway). grokHome uses `platform`'s rules for the binary gate.
101
+ const configFile = path.join(env['GROK_HOME'] ? path.resolve(env['GROK_HOME']) : path.join(home, '.grok'), 'config.toml');
102
+ const userServers = readToml(configFile)?.['mcp_servers'];
103
+ const state = { present: false, overridden: [], configFile };
104
+ const canonical = (s) => isObject(s) && (isCanonicalLocalEntry(s['align'], o) || isCanonicalLocalEntry(s['align-local'], o));
105
+ if (canonical(userServers))
106
+ state.present = true;
107
+ else if (isObject(userServers) && 'align-local' in userServers)
108
+ state.conflict = configFile;
109
+ for (const dir of ancestors(project)) {
110
+ const file = path.join(dir, '.grok', 'config.toml');
111
+ if (file === configFile)
112
+ continue;
113
+ const servers = readToml(file)?.['mcp_servers'];
114
+ if (isObject(servers) && 'align-local' in servers && !isCanonicalLocalEntry(servers['align-local'], o))
115
+ state.conflict ??= file;
116
+ }
117
+ // `[compat.claude] mcps = false` / `[compat.cursor] mcps = false` turn those imports off.
118
+ const compat = (readToml(configFile)?.['compat'] ?? {});
119
+ const imported = (tool) => !(isObject(compat[tool]) && compat[tool]['mcps'] === false);
120
+ const claude = parseJsonc(readText(path.join(home, '.claude.json')))?.['mcpServers'];
121
+ const cursor = parseJsonc(readText(path.join(home, '.cursor', 'mcp.json')))?.['mcpServers'];
122
+ if (imported('claude') && isObject(claude) && isCanonicalLocalEntry(claude['align'], o))
123
+ state.present = true;
124
+ if (imported('cursor') && isObject(cursor) && isCanonicalLocalEntry(cursor['align'], o))
125
+ state.present = true;
126
+ return state;
127
+ }
128
+ //# sourceMappingURL=grok-state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grok-state.js","sourceRoot":"","sources":["../../../src/lib/launch/grok-state.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ import type { ChildProcess, SpawnOptions } from 'node:child_process';
2
+ import type { AgentSpec } from './registry/types.js';
3
+ /**
4
+ * How an agent is installed (plan Decision 4). `npm`: one package-manager argv, which Align may
5
+ * run after the user says yes. `docs`: a script or URL installer; piping a remote script into a
6
+ * shell is the user's decision, so Align only ever prints it.
7
+ */
8
+ export type AgentInstall = {
9
+ kind: 'npm';
10
+ argv: readonly string[];
11
+ } | {
12
+ kind: 'docs';
13
+ url: string;
14
+ text?: string;
15
+ };
16
+ /** `cancelled`: Ctrl-C at the question, which leaves the picker; `declined`: a plain No. */
17
+ export type InstallOutcome = 'installed' | 'declined' | 'cancelled' | 'manual' | 'failed';
18
+ export interface InstallOfferDeps {
19
+ isTTY: boolean;
20
+ platform: string;
21
+ /** true only on an explicit yes, false on No (the default), null on Ctrl-C. */
22
+ confirm(message: string): Promise<boolean | null>;
23
+ spawn(command: string, args: string[], options: SpawnOptions): ChildProcess;
24
+ onPath(bin: string): string | null;
25
+ say(line: string): void;
26
+ }
27
+ export declare function installText(i: AgentInstall): string;
28
+ /**
29
+ * Offer to install an agent the user picked. Never runs anything without a TTY and a yes, and
30
+ * never runs a script or URL installer. The argv runs with no shell, output visible.
31
+ */
32
+ export declare function offerInstall(spec: Pick<AgentSpec, 'label' | 'install'>, d: InstallOfferDeps): Promise<InstallOutcome>;
33
+ //# sourceMappingURL=install.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../../src/lib/launch/install.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACrE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAGrD;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AACnH,4FAA4F;AAC5F,MAAM,MAAM,cAAc,GAAG,WAAW,GAAG,UAAU,GAAG,WAAW,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAE1F,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,OAAO,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,+EAA+E;IAC/E,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;IAClD,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,YAAY,GAAG,YAAY,CAAC;IAC5E,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IACnC,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED,wBAAgB,WAAW,CAAC,CAAC,EAAE,YAAY,GAAG,MAAM,CAEnD;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,EAAE,OAAO,GAAG,SAAS,CAAC,EAAE,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,cAAc,CAAC,CAmC3H"}
@@ -0,0 +1,48 @@
1
+ import { winShimCommand } from './run-agent.js';
2
+ export function installText(i) {
3
+ return i.kind === 'npm' ? i.argv.join(' ') : (i.text ?? i.url);
4
+ }
5
+ /**
6
+ * Offer to install an agent the user picked. Never runs anything without a TTY and a yes, and
7
+ * never runs a script or URL installer. The argv runs with no shell, output visible.
8
+ */
9
+ export async function offerInstall(spec, d) {
10
+ const text = installText(spec.install);
11
+ const manager = spec.install.kind === 'npm' ? d.onPath(spec.install.argv[0]) : null;
12
+ if (spec.install.kind !== 'npm' || !d.isTTY || !manager) {
13
+ d.say(`${spec.label} is not installed. Install it with: ${text}`);
14
+ return 'manual';
15
+ }
16
+ const answer = await d.confirm(`Install ${spec.label} now? (runs: ${text})`);
17
+ if (answer === null)
18
+ return 'cancelled';
19
+ if (answer !== true)
20
+ return 'declined';
21
+ const args = spec.install.argv.slice(1);
22
+ let code;
23
+ try {
24
+ // Run the npm the PATH scan found, by its path: the one the question just named. npm on
25
+ // Windows is npm.cmd, which cannot be spawned without a shell, so it goes through the same
26
+ // quoted cmd.exe line the agent launch uses (which refuses a path cmd.exe would reinterpret).
27
+ const shim = d.platform === 'win32' && /\.(cmd|bat)$/i.test(manager);
28
+ const cmd = shim ? winShimCommand({ bin: manager, args }) : { command: manager, args };
29
+ const options = { shell: false, stdio: 'inherit' };
30
+ if (shim)
31
+ options.windowsVerbatimArguments = true;
32
+ code = await new Promise((resolve, reject) => {
33
+ const child = d.spawn(cmd.command, cmd.args, options);
34
+ child.on('error', reject);
35
+ child.on('exit', (c) => resolve(c ?? 1));
36
+ });
37
+ }
38
+ catch (e) {
39
+ d.say(`Could not run ${text} (${e.message}). ${spec.label} is not installed.`);
40
+ return 'failed';
41
+ }
42
+ if (code !== 0) {
43
+ d.say(`${spec.install.argv[0]} exited ${code}. ${spec.label} is not installed.`);
44
+ return 'failed';
45
+ }
46
+ return 'installed';
47
+ }
48
+ //# sourceMappingURL=install.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install.js","sourceRoot":"","sources":["../../../src/lib/launch/install.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAqBhD,MAAM,UAAU,WAAW,CAAC,CAAe;IACzC,OAAO,CAAC,CAAC,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;AACjE,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,IAA0C,EAAE,CAAmB;IAChG,MAAM,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACvC,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACrF,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,OAAO,EAAE,CAAC;QACxD,CAAC,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,KAAK,uCAAuC,IAAI,EAAE,CAAC,CAAC;QAClE,OAAO,QAAQ,CAAC;IAClB,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,OAAO,CAAC,WAAW,IAAI,CAAC,KAAK,gBAAgB,IAAI,GAAG,CAAC,CAAC;IAC7E,IAAI,MAAM,KAAK,IAAI;QAAE,OAAO,WAAW,CAAC;IACxC,IAAI,MAAM,KAAK,IAAI;QAAE,OAAO,UAAU,CAAC;IAEvC,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACxC,IAAI,IAAY,CAAC;IACjB,IAAI,CAAC;QACH,wFAAwF;QACxF,2FAA2F;QAC3F,8FAA8F;QAC9F,MAAM,IAAI,GAAG,CAAC,CAAC,QAAQ,KAAK,OAAO,IAAI,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACrE,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,cAAc,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QACvF,MAAM,OAAO,GAAiB,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;QACjE,IAAI,IAAI;YAAE,OAAO,CAAC,wBAAwB,GAAG,IAAI,CAAC;QAClD,IAAI,GAAG,MAAM,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACnD,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;YACtD,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YAC1B,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,CAAgB,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC1D,CAAC,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,CAAC,CAAC,GAAG,CAAC,iBAAiB,IAAI,KAAM,CAAW,CAAC,OAAO,MAAM,IAAI,CAAC,KAAK,oBAAoB,CAAC,CAAC;QAC1F,OAAO,QAAQ,CAAC;IAClB,CAAC;IACD,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;QACf,CAAC,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,IAAI,KAAK,IAAI,CAAC,KAAK,oBAAoB,CAAC,CAAC;QACjF,OAAO,QAAQ,CAAC;IAClB,CAAC;IACD,OAAO,WAAW,CAAC;AACrB,CAAC"}