@prismatic-io/lux 0.0.2-preview.18 → 0.0.2-preview.21

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 (244) hide show
  1. package/lib/answerers/persona/index.d.ts +5 -1
  2. package/lib/answerers/persona/index.d.ts.map +1 -1
  3. package/lib/assertions/rubric/index.d.ts +3 -1
  4. package/lib/assertions/rubric/index.d.ts.map +1 -1
  5. package/lib/authoring.d.ts +3 -1
  6. package/lib/authoring.d.ts.map +1 -1
  7. package/lib/authoring.js +2 -1
  8. package/lib/authoring.js.map +1 -1
  9. package/lib/cli/harness-plan.d.ts +26 -0
  10. package/lib/cli/harness-plan.d.ts.map +1 -0
  11. package/lib/cli/harness-plan.js +75 -0
  12. package/lib/cli/harness-plan.js.map +1 -0
  13. package/lib/cli/init-templates.d.ts +2 -2
  14. package/lib/cli/init-templates.d.ts.map +1 -1
  15. package/lib/cli/init-templates.js +11 -4
  16. package/lib/cli/init-templates.js.map +1 -1
  17. package/lib/cli/init.d.ts +2 -0
  18. package/lib/cli/init.d.ts.map +1 -1
  19. package/lib/cli/init.js +6 -3
  20. package/lib/cli/init.js.map +1 -1
  21. package/lib/cli/output-schemas.d.ts +7 -0
  22. package/lib/cli/output-schemas.d.ts.map +1 -1
  23. package/lib/cli/program.d.ts +5 -10
  24. package/lib/cli/program.d.ts.map +1 -1
  25. package/lib/cli/program.js +44 -77
  26. package/lib/cli/program.js.map +1 -1
  27. package/lib/cli/run-options.d.ts +19 -0
  28. package/lib/cli/run-options.d.ts.map +1 -1
  29. package/lib/cli/run-options.js +92 -0
  30. package/lib/cli/run-options.js.map +1 -1
  31. package/lib/core/case.d.ts +2 -0
  32. package/lib/core/case.d.ts.map +1 -1
  33. package/lib/core/case.js +3 -0
  34. package/lib/core/case.js.map +1 -1
  35. package/lib/core/driver.d.ts +13 -0
  36. package/lib/core/driver.d.ts.map +1 -1
  37. package/lib/core/driver.js +10 -0
  38. package/lib/core/driver.js.map +1 -1
  39. package/lib/core/harness-catalog.d.ts +35 -0
  40. package/lib/core/harness-catalog.d.ts.map +1 -0
  41. package/lib/core/harness-catalog.js +45 -0
  42. package/lib/core/harness-catalog.js.map +1 -0
  43. package/lib/core/harness-catalogs/antigravity.d.ts +11 -0
  44. package/lib/core/harness-catalogs/antigravity.d.ts.map +1 -0
  45. package/lib/core/harness-catalogs/antigravity.js +23 -0
  46. package/lib/core/harness-catalogs/antigravity.js.map +1 -0
  47. package/lib/core/harness-catalogs/claude-code.d.ts +12 -0
  48. package/lib/core/harness-catalogs/claude-code.d.ts.map +1 -0
  49. package/lib/core/harness-catalogs/claude-code.js +24 -0
  50. package/lib/core/harness-catalogs/claude-code.js.map +1 -0
  51. package/lib/core/harness-catalogs/codex.d.ts +11 -0
  52. package/lib/core/harness-catalogs/codex.d.ts.map +1 -0
  53. package/lib/core/harness-catalogs/codex.js +26 -0
  54. package/lib/core/harness-catalogs/codex.js.map +1 -0
  55. package/lib/core/harness-catalogs/copilot.d.ts +29 -0
  56. package/lib/core/harness-catalogs/copilot.d.ts.map +1 -0
  57. package/lib/core/harness-catalogs/copilot.js +45 -0
  58. package/lib/core/harness-catalogs/copilot.js.map +1 -0
  59. package/lib/core/harness-catalogs/cursor.d.ts +2 -0
  60. package/lib/core/harness-catalogs/cursor.d.ts.map +1 -0
  61. package/lib/core/harness-catalogs/cursor.js +13 -0
  62. package/lib/core/harness-catalogs/cursor.js.map +1 -0
  63. package/lib/core/harness-catalogs/index.d.ts +67 -0
  64. package/lib/core/harness-catalogs/index.d.ts.map +1 -0
  65. package/lib/core/harness-catalogs/index.js +15 -0
  66. package/lib/core/harness-catalogs/index.js.map +1 -0
  67. package/lib/core/harness-matrix.d.ts +70 -0
  68. package/lib/core/harness-matrix.d.ts.map +1 -0
  69. package/lib/core/harness-matrix.js +194 -0
  70. package/lib/core/harness-matrix.js.map +1 -0
  71. package/lib/core/index.d.ts +3 -0
  72. package/lib/core/index.d.ts.map +1 -1
  73. package/lib/core/index.js +3 -0
  74. package/lib/core/index.js.map +1 -1
  75. package/lib/core/model-cli.d.ts +4 -11
  76. package/lib/core/model-cli.d.ts.map +1 -1
  77. package/lib/core/model-cli.js +23 -17
  78. package/lib/core/model-cli.js.map +1 -1
  79. package/lib/core/platform-process.d.ts +1 -0
  80. package/lib/core/platform-process.d.ts.map +1 -1
  81. package/lib/core/platform-process.js +1 -1
  82. package/lib/core/platform-process.js.map +1 -1
  83. package/lib/core/run.d.ts +4 -0
  84. package/lib/core/run.d.ts.map +1 -1
  85. package/lib/core/run.js +2 -0
  86. package/lib/core/run.js.map +1 -1
  87. package/lib/drivers/antigravity/config.d.ts +46 -0
  88. package/lib/drivers/antigravity/config.d.ts.map +1 -0
  89. package/lib/drivers/antigravity/config.js +39 -0
  90. package/lib/drivers/antigravity/config.js.map +1 -0
  91. package/lib/drivers/antigravity/events.d.ts +4 -0
  92. package/lib/drivers/antigravity/events.d.ts.map +1 -0
  93. package/lib/drivers/antigravity/events.js +193 -0
  94. package/lib/drivers/antigravity/events.js.map +1 -0
  95. package/lib/drivers/antigravity/index.d.ts +60 -0
  96. package/lib/drivers/antigravity/index.d.ts.map +1 -0
  97. package/lib/drivers/antigravity/index.js +90 -0
  98. package/lib/drivers/antigravity/index.js.map +1 -0
  99. package/lib/drivers/claude-code/index.d.ts +93 -7
  100. package/lib/drivers/claude-code/index.d.ts.map +1 -1
  101. package/lib/drivers/claude-code/index.js +14 -8
  102. package/lib/drivers/claude-code/index.js.map +1 -1
  103. package/lib/drivers/codex/config.d.ts +61 -4
  104. package/lib/drivers/codex/config.d.ts.map +1 -1
  105. package/lib/drivers/codex/config.js +19 -5
  106. package/lib/drivers/codex/config.js.map +1 -1
  107. package/lib/drivers/codex/index.d.ts +63 -5
  108. package/lib/drivers/codex/index.d.ts.map +1 -1
  109. package/lib/drivers/codex/index.js +11 -3
  110. package/lib/drivers/codex/index.js.map +1 -1
  111. package/lib/drivers/copilot/config.d.ts +81 -0
  112. package/lib/drivers/copilot/config.d.ts.map +1 -0
  113. package/lib/drivers/copilot/config.js +54 -0
  114. package/lib/drivers/copilot/config.js.map +1 -0
  115. package/lib/drivers/copilot/index.d.ts +103 -0
  116. package/lib/drivers/copilot/index.d.ts.map +1 -0
  117. package/lib/drivers/copilot/index.js +256 -0
  118. package/lib/drivers/copilot/index.js.map +1 -0
  119. package/lib/drivers/cursor/config.d.ts +6 -1
  120. package/lib/drivers/cursor/config.d.ts.map +1 -1
  121. package/lib/drivers/cursor/config.js +2 -3
  122. package/lib/drivers/cursor/config.js.map +1 -1
  123. package/lib/drivers/cursor/index.d.ts +7 -2
  124. package/lib/drivers/cursor/index.d.ts.map +1 -1
  125. package/lib/drivers/cursor/index.js +9 -6
  126. package/lib/drivers/cursor/index.js.map +1 -1
  127. package/lib/drivers/cursor/interaction.d.ts +1 -2
  128. package/lib/drivers/cursor/interaction.d.ts.map +1 -1
  129. package/lib/drivers/cursor/interaction.js +3 -14
  130. package/lib/drivers/cursor/interaction.js.map +1 -1
  131. package/lib/drivers/{cursor/events.d.ts → shared/acp-events.d.ts} +5 -3
  132. package/lib/drivers/shared/acp-events.d.ts.map +1 -0
  133. package/lib/drivers/{cursor/events.js → shared/acp-events.js} +20 -10
  134. package/lib/drivers/shared/acp-events.js.map +1 -0
  135. package/lib/drivers/shared/acp-interaction.d.ts +7 -0
  136. package/lib/drivers/shared/acp-interaction.d.ts.map +1 -0
  137. package/lib/drivers/shared/acp-interaction.js +20 -0
  138. package/lib/drivers/shared/acp-interaction.js.map +1 -0
  139. package/lib/drivers/{cursor → shared}/acp-transport.d.ts +2 -0
  140. package/lib/drivers/shared/acp-transport.d.ts.map +1 -0
  141. package/lib/drivers/{cursor → shared}/acp-transport.js +10 -10
  142. package/lib/drivers/shared/acp-transport.js.map +1 -0
  143. package/lib/index.d.ts +7 -2
  144. package/lib/index.d.ts.map +1 -1
  145. package/lib/index.js +7 -2
  146. package/lib/index.js.map +1 -1
  147. package/lib/optimization/reflective.d.ts +2 -0
  148. package/lib/optimization/reflective.d.ts.map +1 -1
  149. package/lib/orchestrator/comparison-identity.d.ts.map +1 -1
  150. package/lib/orchestrator/comparison-identity.js +1 -0
  151. package/lib/orchestrator/comparison-identity.js.map +1 -1
  152. package/lib/orchestrator/config.d.ts +7 -0
  153. package/lib/orchestrator/config.d.ts.map +1 -1
  154. package/lib/orchestrator/config.js +8 -1
  155. package/lib/orchestrator/config.js.map +1 -1
  156. package/lib/orchestrator/doctor.d.ts.map +1 -1
  157. package/lib/orchestrator/doctor.js +72 -2
  158. package/lib/orchestrator/doctor.js.map +1 -1
  159. package/lib/orchestrator/experiment-context.d.ts +1 -1
  160. package/lib/orchestrator/harness-catalog-drift.d.ts +22 -0
  161. package/lib/orchestrator/harness-catalog-drift.d.ts.map +1 -0
  162. package/lib/orchestrator/harness-catalog-drift.js +90 -0
  163. package/lib/orchestrator/harness-catalog-drift.js.map +1 -0
  164. package/lib/orchestrator/orchestrator.d.ts +9 -1
  165. package/lib/orchestrator/orchestrator.d.ts.map +1 -1
  166. package/lib/orchestrator/orchestrator.js +14 -22
  167. package/lib/orchestrator/orchestrator.js.map +1 -1
  168. package/lib/orchestrator/run-dir.d.ts +2 -0
  169. package/lib/orchestrator/run-dir.d.ts.map +1 -1
  170. package/lib/orchestrator/run-dir.js +1 -1
  171. package/lib/orchestrator/run-dir.js.map +1 -1
  172. package/lib/orchestrator/run-execution.d.ts +1 -0
  173. package/lib/orchestrator/run-execution.d.ts.map +1 -1
  174. package/lib/orchestrator/run-execution.js +2 -0
  175. package/lib/orchestrator/run-execution.js.map +1 -1
  176. package/lib/orchestrator/suite-compare.d.ts +3 -0
  177. package/lib/orchestrator/suite-compare.d.ts.map +1 -1
  178. package/lib/orchestrator/suite-compare.js +27 -17
  179. package/lib/orchestrator/suite-compare.js.map +1 -1
  180. package/lib/orchestrator/suite-runs.d.ts +3 -0
  181. package/lib/orchestrator/suite-runs.d.ts.map +1 -1
  182. package/lib/orchestrator/suite-runs.js +2 -0
  183. package/lib/orchestrator/suite-runs.js.map +1 -1
  184. package/lib/orchestrator/suite-summary.d.ts +9 -0
  185. package/lib/orchestrator/suite-summary.d.ts.map +1 -1
  186. package/lib/orchestrator/suite-summary.js +14 -4
  187. package/lib/orchestrator/suite-summary.js.map +1 -1
  188. package/package.json +1 -1
  189. package/skills/lux-answerer/SKILL.md +1 -1
  190. package/src/authoring.ts +10 -3
  191. package/src/cli/harness-plan.ts +117 -0
  192. package/src/cli/init-templates.ts +12 -5
  193. package/src/cli/init.ts +12 -5
  194. package/src/cli/program.ts +50 -92
  195. package/src/cli/run-options.ts +123 -0
  196. package/src/core/case.ts +3 -0
  197. package/src/core/driver.ts +26 -0
  198. package/src/core/harness-catalog.ts +100 -0
  199. package/src/core/harness-catalogs/antigravity.ts +24 -0
  200. package/src/core/harness-catalogs/claude-code.ts +25 -0
  201. package/src/core/harness-catalogs/codex.ts +27 -0
  202. package/src/core/harness-catalogs/copilot.ts +46 -0
  203. package/src/core/harness-catalogs/cursor.ts +13 -0
  204. package/src/core/harness-catalogs/index.ts +22 -0
  205. package/src/core/harness-matrix.ts +298 -0
  206. package/src/core/index.ts +3 -0
  207. package/src/core/model-cli.ts +38 -21
  208. package/src/core/platform-process.ts +4 -4
  209. package/src/core/run.ts +2 -0
  210. package/src/drivers/antigravity/README.md +46 -0
  211. package/src/drivers/antigravity/config.ts +44 -0
  212. package/src/drivers/antigravity/events.ts +235 -0
  213. package/src/drivers/antigravity/index.ts +109 -0
  214. package/src/drivers/claude-code/index.ts +18 -7
  215. package/src/drivers/codex/config.ts +23 -5
  216. package/src/drivers/codex/index.ts +15 -2
  217. package/src/drivers/copilot/README.md +52 -0
  218. package/src/drivers/copilot/config.ts +58 -0
  219. package/src/drivers/copilot/index.ts +292 -0
  220. package/src/drivers/cursor/README.md +9 -6
  221. package/src/drivers/cursor/config.ts +2 -3
  222. package/src/drivers/cursor/index.ts +10 -6
  223. package/src/drivers/cursor/interaction.ts +3 -19
  224. package/src/drivers/{cursor/events.ts → shared/acp-events.ts} +20 -9
  225. package/src/drivers/shared/acp-interaction.ts +27 -0
  226. package/src/drivers/{cursor → shared}/acp-transport.ts +15 -10
  227. package/src/index.ts +44 -3
  228. package/src/orchestrator/comparison-identity.ts +1 -0
  229. package/src/orchestrator/config.ts +8 -0
  230. package/src/orchestrator/doctor.ts +125 -3
  231. package/src/orchestrator/harness-catalog-drift.ts +132 -0
  232. package/src/orchestrator/orchestrator.ts +31 -26
  233. package/src/orchestrator/run-dir.ts +8 -1
  234. package/src/orchestrator/run-execution.ts +3 -0
  235. package/src/orchestrator/suite-compare.ts +29 -19
  236. package/src/orchestrator/suite-runs.ts +3 -1
  237. package/src/orchestrator/suite-summary.ts +19 -4
  238. package/lib/drivers/cursor/acp-transport.d.ts.map +0 -1
  239. package/lib/drivers/cursor/acp-transport.js.map +0 -1
  240. package/lib/drivers/cursor/events.d.ts.map +0 -1
  241. package/lib/drivers/cursor/events.js.map +0 -1
  242. package/skills/lux/SKILL.md +0 -89
  243. package/skills/lux/references/cli.md +0 -128
  244. package/skills/lux/references/eval-authoring.md +0 -266
@@ -0,0 +1,235 @@
1
+ import { z } from "zod";
2
+ import {
3
+ type ParsedDriverEvent,
4
+ type TokenUsage,
5
+ toolCallProgress,
6
+ toolResultProgress,
7
+ } from "../../core/index.js";
8
+ import type { AntigravityDriverConfig } from "./config.js";
9
+
10
+ const UsageSchema = z.object({
11
+ input_tokens: z.number().nonnegative().catch(0),
12
+ output_tokens: z.number().nonnegative().catch(0),
13
+ thinking_tokens: z.number().nonnegative().catch(0),
14
+ cache_read_tokens: z.number().nonnegative().catch(0),
15
+ });
16
+
17
+ const StepUpdateSchema = z.looseObject({
18
+ step_index: z.number().int().nonnegative(),
19
+ state: z.string().optional(),
20
+ step_type: z.string().optional(),
21
+ tool_name: z.string().optional(),
22
+ text_delta: z.string().optional(),
23
+ usage: z.unknown().optional(),
24
+ tool_info: z
25
+ .looseObject({
26
+ name: z.string().optional(),
27
+ parameters: z.unknown().optional(),
28
+ output: z.unknown().optional(),
29
+ error: z
30
+ .looseObject({ type: z.string().optional(), message: z.string().optional() })
31
+ .optional(),
32
+ })
33
+ .optional(),
34
+ });
35
+
36
+ const ResultSchema = z.looseObject({
37
+ conversation_id: z.string().optional(),
38
+ status: z.string().optional(),
39
+ response: z.string().optional(),
40
+ error: z.string().optional(),
41
+ num_turns: z.number().optional(),
42
+ usage: z.unknown().optional(),
43
+ });
44
+
45
+ const InitSchema = z.looseObject({
46
+ cwd: z.string().optional(),
47
+ tools: z.array(z.string()).optional(),
48
+ permission_mode: z.string().optional(),
49
+ model: z.string().optional(),
50
+ agent: z.string().optional(),
51
+ });
52
+
53
+ const AntigravityEventSchema = z.discriminatedUnion("event", [
54
+ z.looseObject({
55
+ event: z.literal("init"),
56
+ conversation_id: z.string().optional(),
57
+ init: InitSchema.optional(),
58
+ }),
59
+ z.looseObject({ event: z.literal("step_update"), step_update: StepUpdateSchema.optional() }),
60
+ z.looseObject({ event: z.literal("result"), result: ResultSchema.optional() }),
61
+ ]);
62
+
63
+ const parseUsage = (raw: unknown): TokenUsage | null => {
64
+ const usage = UsageSchema.safeParse(raw).data;
65
+ if (!usage) return null;
66
+ return {
67
+ input: Math.max(0, usage.input_tokens - usage.cache_read_tokens),
68
+ output: usage.output_tokens + usage.thinking_tokens,
69
+ cacheRead: usage.cache_read_tokens,
70
+ cacheCreation: 0,
71
+ };
72
+ };
73
+
74
+ const outputText = (output: unknown): string => {
75
+ if (typeof output === "string") return output;
76
+ return output === undefined ? "" : JSON.stringify(output);
77
+ };
78
+
79
+ const waitingReason =
80
+ "Antigravity is waiting for a tool permission it cannot receive headlessly; allow the tool in its settings or set skipPermissions";
81
+
82
+ type StepUpdate = z.infer<typeof StepUpdateSchema>;
83
+ type ResultEvent = z.infer<typeof ResultSchema>;
84
+ type InitEvent = z.infer<typeof AntigravityEventSchema> & { event: "init" };
85
+
86
+ const readyEvent = (
87
+ event: InitEvent,
88
+ config: AntigravityDriverConfig,
89
+ cliVersion: string | undefined,
90
+ ): ParsedDriverEvent => ({
91
+ tag: "ready",
92
+ ready: {
93
+ agentId: "antigravity",
94
+ model: event.init?.model ?? config.model,
95
+ detail: {
96
+ transport: "stream-json",
97
+ ...(event.conversation_id ? { conversationId: event.conversation_id } : {}),
98
+ ...(cliVersion ? { cliVersion } : {}),
99
+ ...(event.init?.cwd ? { cwd: event.init.cwd } : {}),
100
+ ...(event.init?.tools ? { tools: event.init.tools } : {}),
101
+ ...(event.init?.permission_mode ? { permissionMode: event.init.permission_mode } : {}),
102
+ ...(event.init?.agent ? { agent: event.init.agent } : {}),
103
+ reasoningEffort: config.reasoningEffort,
104
+ modelResolution: event.init?.model ? "reported" : "requested",
105
+ },
106
+ },
107
+ });
108
+
109
+ const toolStepEvents = (
110
+ step: StepUpdate,
111
+ openTools: Set<number>,
112
+ ts: number,
113
+ ): ParsedDriverEvent[] => {
114
+ const toolUseId = `step-${step.step_index}`;
115
+ const name = step.tool_info?.name ?? step.tool_name ?? "tool";
116
+ const events: ParsedDriverEvent[] = [];
117
+ if (!openTools.has(step.step_index)) {
118
+ openTools.add(step.step_index);
119
+ events.push({
120
+ tag: "progress",
121
+ progress: toolCallProgress(
122
+ step.step_index,
123
+ { name, input: step.tool_info?.parameters ?? {}, toolUseId },
124
+ ts,
125
+ ),
126
+ });
127
+ }
128
+ if (step.state === "DONE") {
129
+ openTools.delete(step.step_index);
130
+ const error = step.tool_info?.error;
131
+ events.push({
132
+ tag: "progress",
133
+ progress: toolResultProgress(
134
+ step.step_index,
135
+ {
136
+ name,
137
+ toolUseId,
138
+ content: step.tool_info?.output ?? null,
139
+ isError: error !== undefined,
140
+ text: error?.message ?? outputText(step.tool_info?.output),
141
+ },
142
+ ts,
143
+ ),
144
+ });
145
+ }
146
+ return events;
147
+ };
148
+
149
+ const stepEvents = (
150
+ step: StepUpdate,
151
+ openTools: Set<number>,
152
+ ts: number,
153
+ ): ParsedDriverEvent | ParsedDriverEvent[] => {
154
+ if (step.step_type === "tool") return toolStepEvents(step, openTools, ts);
155
+ if (step.step_type === "agent_response" && step.text_delta) {
156
+ return {
157
+ tag: "progress",
158
+ progress: {
159
+ id: `antigravity-message-${step.step_index}-${ts}`,
160
+ kind: "agent-message",
161
+ payload: { text: step.text_delta },
162
+ ts,
163
+ },
164
+ };
165
+ }
166
+ return {
167
+ tag: "progress",
168
+ progress: {
169
+ id: `antigravity-step-${step.step_index}-${ts}`,
170
+ kind: "antigravity-step",
171
+ payload: step,
172
+ ts,
173
+ },
174
+ };
175
+ };
176
+
177
+ const resultEvent = (
178
+ result: ResultEvent | undefined,
179
+ conversationId: string | undefined,
180
+ usage: TokenUsage | null,
181
+ ): ParsedDriverEvent => {
182
+ if (result?.status === "SUCCESS") {
183
+ return {
184
+ tag: "done",
185
+ done: {
186
+ exitReason: "done",
187
+ summary: {
188
+ ...(conversationId ? { conversationId } : {}),
189
+ ...(result.response !== undefined ? { response: result.response } : {}),
190
+ ...(result.num_turns !== undefined ? { numTurns: result.num_turns } : {}),
191
+ ...(usage ? { usage } : { usageAvailability: "unavailable" }),
192
+ },
193
+ },
194
+ };
195
+ }
196
+ const status = result?.status ?? "UNKNOWN";
197
+ return {
198
+ tag: "error",
199
+ error: {
200
+ exitReason: "error",
201
+ reason:
202
+ status === "WAITING"
203
+ ? waitingReason
204
+ : `Antigravity ended with status ${status}${result?.error ? `: ${result.error}` : ""}`,
205
+ ...(usage ? { summary: { usage } } : {}),
206
+ },
207
+ };
208
+ };
209
+
210
+ export const makeParseEvent = (config: AntigravityDriverConfig, cliVersion?: string) => {
211
+ const openTools = new Set<number>();
212
+ let conversationId: string | undefined;
213
+ let usage: TokenUsage | null = null;
214
+ return (line: string): ParsedDriverEvent | ParsedDriverEvent[] | null => {
215
+ let raw: unknown;
216
+ try {
217
+ raw = JSON.parse(line);
218
+ } catch {
219
+ return null;
220
+ }
221
+ const parsed = AntigravityEventSchema.safeParse(raw);
222
+ if (!parsed.success) return null;
223
+ const event = parsed.data;
224
+ if (event.event === "init") {
225
+ conversationId = event.conversation_id;
226
+ return readyEvent(event, config, cliVersion);
227
+ }
228
+ if (event.event === "step_update") {
229
+ if (!event.step_update) return null;
230
+ usage = parseUsage(event.step_update.usage) ?? usage;
231
+ return stepEvents(event.step_update, openTools, Date.now());
232
+ }
233
+ return resultEvent(event.result, conversationId, parseUsage(event.result?.usage) ?? usage);
234
+ };
235
+ };
@@ -0,0 +1,109 @@
1
+ import {
2
+ type AgentDriver,
3
+ type Answer,
4
+ type Artifact,
5
+ type DriverEventMap,
6
+ defineDriver,
7
+ discoverCliVersion,
8
+ type ReadyState,
9
+ type StartContext,
10
+ selectModelAndReasoningEffort,
11
+ } from "../../core/index.js";
12
+ import { walkArtifacts } from "../shared/artifacts.js";
13
+ import { subprocessDriver } from "../subprocess/index.js";
14
+ import {
15
+ type AntigravityDriverConfig,
16
+ AntigravityDriverConfigSchema,
17
+ buildAntigravityArgs,
18
+ formatAntigravityPrompt,
19
+ } from "./config.js";
20
+ import { makeParseEvent } from "./events.js";
21
+
22
+ class AntigravityDriver implements AgentDriver {
23
+ private inner: AgentDriver | null = null;
24
+ private pendingAttach: Array<(inner: AgentDriver) => void> = [];
25
+ private cwd: string | null = null;
26
+ private artifactsDir: string | null = null;
27
+ private readonly config: AntigravityDriverConfig;
28
+
29
+ constructor(config: AntigravityDriverConfig) {
30
+ this.config = config;
31
+ }
32
+
33
+ on<K extends keyof DriverEventMap>(event: K, handler: (e: DriverEventMap[K]) => void): void {
34
+ if (this.inner) this.inner.on(event, handler);
35
+ else this.pendingAttach.push((inner) => inner.on(event, handler));
36
+ }
37
+
38
+ off<K extends keyof DriverEventMap>(event: K, handler: (e: DriverEventMap[K]) => void): void {
39
+ if (this.inner) this.inner.off(event, handler);
40
+ else this.pendingAttach.push((inner) => inner.off(event, handler));
41
+ }
42
+
43
+ async start(ctx: StartContext): Promise<ReadyState> {
44
+ if (this.inner) throw new Error("Antigravity driver cannot be started twice");
45
+ this.cwd = this.config.cwd ?? ctx.artifactsDir;
46
+ this.artifactsDir = ctx.artifactsDir;
47
+ const cliVersion = await discoverCliVersion(this.config.command);
48
+ const inner = await subprocessDriver.create({
49
+ command: this.config.command,
50
+ args: buildAntigravityArgs(this.config),
51
+ cwd: this.cwd,
52
+ env: this.config.env,
53
+ protocol: "custom",
54
+ parseEvent: makeParseEvent(this.config, cliVersion),
55
+ formatPrompt: formatAntigravityPrompt,
56
+ closeStdinAfterPrompt: true,
57
+ idleTimeoutMs: this.config.idleTimeoutMs,
58
+ maxLineBytes: this.config.maxLineBytes,
59
+ maxInterrupts: 1,
60
+ });
61
+ for (const attach of this.pendingAttach) attach(inner);
62
+ this.pendingAttach = [];
63
+ this.inner = inner;
64
+ return inner.start(ctx);
65
+ }
66
+
67
+ async respond(_answer: Answer): Promise<void> {
68
+ throw new Error("Antigravity headless sessions cannot receive mid-run responses");
69
+ }
70
+
71
+ async quiesce(): Promise<void> {
72
+ await this.inner?.close();
73
+ }
74
+
75
+ async collect(): Promise<Artifact[]> {
76
+ await this.quiesce();
77
+ if (!this.cwd) return [];
78
+ const artifacts = await walkArtifacts(this.cwd);
79
+ return this.cwd === this.artifactsDir
80
+ ? artifacts
81
+ : artifacts.map((artifact) => ({ ...artifact, root: this.cwd as string }));
82
+ }
83
+
84
+ async close(): Promise<void> {
85
+ await this.inner?.close();
86
+ }
87
+ }
88
+
89
+ export const antigravityDriver = defineDriver({
90
+ name: "antigravity",
91
+ configSchema: AntigravityDriverConfigSchema,
92
+ runtime: (config) => ({
93
+ commands: [config.command],
94
+ capabilities: {
95
+ interactive: false,
96
+ "tool-calls": true,
97
+ "tool-results": true,
98
+ artifacts: true,
99
+ usage: true,
100
+ cost: false,
101
+ isolation: false,
102
+ },
103
+ }),
104
+ selectHarness: selectModelAndReasoningEffort,
105
+ create: (config) => new AntigravityDriver(config),
106
+ });
107
+
108
+ export type { AntigravityDriverConfig };
109
+ export { AntigravityDriverConfigSchema, buildAntigravityArgs, makeParseEvent };
@@ -7,6 +7,8 @@ import {
7
7
  type AgentDriver,
8
8
  type Answer,
9
9
  type Artifact,
10
+ applyCatalogEffort,
11
+ claudeCodeCatalog,
10
12
  DEFAULT_CLAUDE_MODEL,
11
13
  type DriverEventMap,
12
14
  defineDriver,
@@ -15,6 +17,7 @@ import {
15
17
  type ParsedDriverEvent,
16
18
  type ReadyState,
17
19
  type StartContext,
20
+ selectModelAndReasoningEffort,
18
21
  TypedEmitter,
19
22
  } from "../../core/index.js";
20
23
  import { walkArtifacts } from "../shared/artifacts.js";
@@ -74,13 +77,12 @@ export const ClaudeCodeDriverConfigSchema = z
74
77
  env: z.record(z.string(), z.string()).optional(),
75
78
  /** Low-cost by default; choose a larger model explicitly when needed. */
76
79
  model: z.string().min(1).default(DEFAULT_CLAUDE_MODEL),
77
- /** Claude effort level; low by default to control eval cost. */
78
- effort: z.enum(["low", "medium", "high", "max"]).default("low"),
80
+ reasoningEffort: z.enum(claudeCodeCatalog.efforts).optional(),
79
81
  /** Permission mode passed to claude. */
80
82
  permissionMode: z
81
83
  .enum(["acceptEdits", "auto", "bypassPermissions", "default", "dontAsk", "manual", "plan"])
82
84
  .optional(),
83
- /** Additional tools pre-approved beyond Lux's minimal coding and ask tools. */
85
+ /** Additional pre-approvals; auto mode omits the baseline coding-tool grants. */
84
86
  allowedTools: z.array(z.string().min(1)).optional(),
85
87
  /** Plugin directories to load (`--plugin-dir`): skills, subagents, commands, hooks. */
86
88
  pluginDirs: z.array(z.string()).optional(),
@@ -159,7 +161,8 @@ export const ClaudeCodeDriverConfigSchema = z
159
161
  message: `isolation owns ${reserved}; configure isolation instead`,
160
162
  });
161
163
  }
162
- });
164
+ })
165
+ .transform(applyCatalogEffort(claudeCodeCatalog));
163
166
 
164
167
  export type ClaudeCodeDriverConfig = z.infer<typeof ClaudeCodeDriverConfigSchema>;
165
168
 
@@ -172,7 +175,7 @@ const buildArgs = (config: ClaudeCodeDriverConfig): string[] => {
172
175
  "stream-json",
173
176
  "--verbose",
174
177
  ];
175
- out.push("--model", config.model, "--effort", config.effort);
178
+ out.push("--model", config.model, ...effortArgs(config));
176
179
  if (config.permissionMode) out.push("--permission-mode", config.permissionMode);
177
180
  out.push("--allowed-tools", ...allowedTools(config));
178
181
  for (const dir of config.pluginDirs ?? []) out.push("--plugin-dir", dir);
@@ -203,8 +206,15 @@ const deferredHookSettings = (
203
206
  },
204
207
  });
205
208
 
209
+ const effortArgs = (config: ClaudeCodeDriverConfig): string[] =>
210
+ config.reasoningEffort ? ["--effort", config.reasoningEffort] : [];
211
+
206
212
  const allowedTools = (config: ClaudeCodeDriverConfig): string[] => [
207
- ...new Set([...MINIMAL_ALLOWED_TOOLS, config.askToolName, ...(config.allowedTools ?? [])]),
213
+ ...new Set([
214
+ ...(config.permissionMode === "auto" ? [] : MINIMAL_ALLOWED_TOOLS),
215
+ config.askToolName,
216
+ ...(config.allowedTools ?? []),
217
+ ]),
208
218
  ];
209
219
 
210
220
  const buildDeferredArgs = (
@@ -213,7 +223,7 @@ const buildDeferredArgs = (
213
223
  sessionId?: string,
214
224
  ): string[] => {
215
225
  const out = ["--print", "--output-format", "stream-json", "--verbose"];
216
- out.push("--model", config.model, "--effort", config.effort);
226
+ out.push("--model", config.model, ...effortArgs(config));
217
227
  if (config.permissionMode) out.push("--permission-mode", config.permissionMode);
218
228
  out.push("--allowed-tools", ...allowedTools(config));
219
229
  for (const dir of config.pluginDirs ?? []) out.push("--plugin-dir", dir);
@@ -881,6 +891,7 @@ export const claudeCodeDriver = defineDriver({
881
891
  };
882
892
  },
883
893
  },
894
+ selectHarness: selectModelAndReasoningEffort,
884
895
  create: (config) => new ClaudeCodeDriverImpl(config),
885
896
  });
886
897
 
@@ -1,5 +1,5 @@
1
1
  import { z } from "zod";
2
- import { DEFAULT_CODEX_MODEL, ReasoningEffortSchema } from "../../core/index.js";
2
+ import { applyCatalogEffort, codexCatalog, DEFAULT_CODEX_MODEL } from "../../core/index.js";
3
3
 
4
4
  export type CodexConfigValue =
5
5
  | string
@@ -28,7 +28,7 @@ export const CodexDriverConfigSchema = z
28
28
  .object({
29
29
  command: z.string().default("codex"),
30
30
  model: z.string().min(1).default(DEFAULT_CODEX_MODEL),
31
- reasoningEffort: ReasoningEffortSchema.default("low"),
31
+ reasoningEffort: z.enum(codexCatalog.efforts).optional(),
32
32
  sandbox: z
33
33
  .enum(["read-only", "workspace-write", "danger-full-access"])
34
34
  .default("workspace-write"),
@@ -46,6 +46,8 @@ export const CodexDriverConfigSchema = z
46
46
  strictConfig: z.boolean().default(false),
47
47
  interactionMode: z.enum(["app-server", "exec"]).default("app-server"),
48
48
  approvalPolicy: z.enum(["untrusted", "on-request", "never"]).default("on-request"),
49
+ /** Native reviewer for eligible approvals; auto_review requires app-server and on-request. */
50
+ approvalsReviewer: z.enum(["user", "auto_review"]).default("user"),
49
51
  isolation: IsolationSchema.optional(),
50
52
  maxInterrupts: z.number().positive().default(20),
51
53
  maxLineBytes: z.number().positive().default(10_000_000),
@@ -53,6 +55,16 @@ export const CodexDriverConfigSchema = z
53
55
  })
54
56
  .strict()
55
57
  .superRefine((config, ctx) => {
58
+ if (
59
+ config.approvalsReviewer === "auto_review" &&
60
+ (config.interactionMode !== "app-server" || config.approvalPolicy !== "on-request")
61
+ ) {
62
+ ctx.addIssue({
63
+ code: "custom",
64
+ path: ["approvalsReviewer"],
65
+ message: "auto_review requires app-server interaction mode and on-request approval policy",
66
+ });
67
+ }
56
68
  if (config.interactionMode === "app-server" && config.profile) {
57
69
  ctx.addIssue({
58
70
  code: "custom",
@@ -82,7 +94,13 @@ export const CodexDriverConfigSchema = z
82
94
  message: "isolation requires app-server interaction mode",
83
95
  });
84
96
  }
85
- });
97
+ })
98
+ .transform(applyCatalogEffort(codexCatalog));
99
+
100
+ const effortArgs = (config: CodexDriverConfig): string[] =>
101
+ config.reasoningEffort
102
+ ? ["--config", `model_reasoning_effort=${tomlValue(config.reasoningEffort)}`]
103
+ : [];
86
104
 
87
105
  export type CodexDriverConfig = z.infer<typeof CodexDriverConfigSchema>;
88
106
 
@@ -110,7 +128,7 @@ export const buildExecArgs = (config: CodexDriverConfig): string[] => {
110
128
  for (const [key, value] of Object.entries(config.config ?? {})) {
111
129
  args.push("--config", `${key}=${tomlValue(value)}`);
112
130
  }
113
- args.push("--config", `model_reasoning_effort=${tomlValue(config.reasoningEffort)}`);
131
+ args.push(...effortArgs(config));
114
132
  if (config.extraArgs) args.push(...config.extraArgs);
115
133
  args.push("-");
116
134
  return args;
@@ -122,7 +140,7 @@ export const buildAppServerArgs = (config: CodexDriverConfig): string[] => {
122
140
  for (const [key, value] of Object.entries(config.config ?? {})) {
123
141
  args.push("--config", `${key}=${tomlValue(value)}`);
124
142
  }
125
- args.push("--config", `model_reasoning_effort=${tomlValue(config.reasoningEffort)}`);
143
+ args.push(...effortArgs(config));
126
144
  if (config.extraArgs) args.push(...config.extraArgs);
127
145
  return args;
128
146
  };
@@ -12,6 +12,7 @@ import {
12
12
  discoverCliVersion,
13
13
  type ReadyState,
14
14
  type StartContext,
15
+ selectModelAndReasoningEffort,
15
16
  spawnManagedProcess,
16
17
  type TokenUsage,
17
18
  TypedEmitter,
@@ -189,7 +190,9 @@ class CodexAppServerDriverImpl implements AgentDriver {
189
190
  : [];
190
191
  const threadConfig: Record<string, CodexConfigValue> = {
191
192
  ...(this.config.config ?? {}),
192
- model_reasoning_effort: this.config.reasoningEffort,
193
+ ...(this.config.reasoningEffort
194
+ ? { model_reasoning_effort: this.config.reasoningEffort }
195
+ : {}),
193
196
  ...(this.config.isolation
194
197
  ? {
195
198
  project_doc_max_bytes: 0,
@@ -212,13 +215,21 @@ class CodexAppServerDriverImpl implements AgentDriver {
212
215
  cwd,
213
216
  runtimeWorkspaceRoots: this.config.addDirs ?? [],
214
217
  approvalPolicy: this.config.approvalPolicy,
215
- approvalsReviewer: "user",
218
+ approvalsReviewer: this.config.approvalsReviewer,
216
219
  ...(this.config.isolation
217
220
  ? { permissions: "lux-isolated" }
218
221
  : { sandbox: this.config.sandbox }),
219
222
  config: threadConfig,
220
223
  ephemeral: this.config.ephemeral,
221
224
  });
225
+ if (
226
+ this.config.approvalsReviewer === "auto_review" &&
227
+ started.approvalsReviewer !== "auto_review"
228
+ ) {
229
+ throw new Error(
230
+ "codex app-server did not enable the requested auto_review approvals reviewer",
231
+ );
232
+ }
222
233
  const thread = asRecord(started.thread);
223
234
  if (!thread || typeof thread.id !== "string") {
224
235
  throw new Error("codex app-server returned an invalid thread/start response");
@@ -229,6 +240,7 @@ class CodexAppServerDriverImpl implements AgentDriver {
229
240
  model: typeof started.model === "string" ? started.model : this.config.model,
230
241
  detail: {
231
242
  threadId: thread.id,
243
+ approvalsReviewer: this.config.approvalsReviewer,
232
244
  ...(typeof thread.sessionId === "string" ? { sessionId: thread.sessionId } : {}),
233
245
  ...(this.cliVersion ? { cliVersion: this.cliVersion } : {}),
234
246
  },
@@ -762,6 +774,7 @@ export const codexDriver = defineDriver({
762
774
  identity: (config, { rootDir }) =>
763
775
  configuredClaudeSourceHashes({ name: "codex", config }, rootDir),
764
776
  },
777
+ selectHarness: selectModelAndReasoningEffort,
765
778
  create: (config) =>
766
779
  config.interactionMode === "app-server"
767
780
  ? new CodexAppServerDriverImpl(config)
@@ -0,0 +1,52 @@
1
+ # Copilot driver
2
+
3
+ The `copilot` driver runs GitHub Copilot CLI as an Agent Client Protocol (ACP)
4
+ server (`copilot --acp`). Install the CLI and run `copilot login` before Lux
5
+ starts it. Your GitHub plan must allow Copilot CLI model access.
6
+
7
+ ```ts
8
+ {
9
+ name: "copilot",
10
+ config: {
11
+ model: "YOUR_COPILOT_MODEL",
12
+ reasoningEffort: "low",
13
+ allowTools: ["shell(git:*)"],
14
+ },
15
+ }
16
+ ```
17
+
18
+ `model` is required because Copilot's `auto` selection can pick any model in
19
+ the plan. Lux passes `--model` and `--effort` on the command line. Copilot's
20
+ `--effort` accepts `none` through `max`, but each model honors only a subset
21
+ and silently falls back on the rest, so the harness catalog in
22
+ `core/harness-catalogs/copilot.ts` records the levels per model id and Lux
23
+ rejects a level the model does not honor. Models whose levels are not published
24
+ (Gemini, Grok, Kimi, MAI) are listed with no effort. When no effort is set, a
25
+ model with levels runs at `low`. The session reports the requested model, not
26
+ a confirmed one. `lux doctor` compares the catalog's model ids with
27
+ `copilot help config` and warns when they differ.
28
+
29
+ Tool permission requests arrive as ACP `session/request_permission` calls and
30
+ become `approve` interrupts. Lux answers with the one-operation option only and
31
+ never selects a remembered grant. `allowTools` and `denyTools` pass Copilot
32
+ permission patterns; `allowAllTools` approves everything, which turns the
33
+ interactive capability off. The `ask_user` tool is disabled by default because
34
+ Copilot has no ACP wire for it; set `askUser: true` only when the harness can
35
+ answer it another way.
36
+
37
+ Copilot loads no `AGENTS.md` instructions and no bundled GitHub MCP server
38
+ unless `customInstructions` or `builtinMcps` are enabled. Auto-update is always
39
+ off. The driver provides no ambient-configuration isolation: Copilot still
40
+ reads `~/.copilot` settings, MCP configuration, and credentials. Usage and
41
+ cost are recorded as unknown; `--usage-output-file` cannot be combined with
42
+ `--acp`.
43
+
44
+ The adapter is covered by synthetic protocol and lifecycle tests. It has not
45
+ been validated against an authenticated Copilot session.
46
+
47
+ Protocol references:
48
+
49
+ - [Copilot CLI command-line reference](https://docs.github.com/en/copilot/reference/copilot-cli-reference/cli-programmatic-reference)
50
+ - [Copilot CLI permissions](https://docs.github.com/en/copilot/concepts/agents/copilot-cli/about-copilot-cli)
51
+ - [ACP session modes](https://agentclientprotocol.com/protocol/session-modes)
52
+ - [ACP tool calls and permissions](https://agentclientprotocol.com/protocol/tool-calls)
@@ -0,0 +1,58 @@
1
+ import { z } from "zod";
2
+ import { applyCatalogEffort, copilotCatalog } from "../../core/index.js";
3
+
4
+ export const CopilotDriverConfigSchema = z
5
+ .object({
6
+ command: z.string().min(1).default("copilot"),
7
+ /** Copilot's catalog changes per plan; never inherit its `auto` selection. */
8
+ model: z.string().min(1),
9
+ reasoningEffort: z.enum(copilotCatalog.efforts).optional(),
10
+ mode: z.enum(["agent", "plan", "autopilot"]).default("agent"),
11
+ /** Permission patterns approved without an interrupt (`--allow-tool`). */
12
+ allowTools: z.array(z.string().min(1)).optional(),
13
+ denyTools: z.array(z.string().min(1)).optional(),
14
+ /** Approve every tool without interrupts; permissions stop being evidence. */
15
+ allowAllTools: z.boolean().default(false),
16
+ /** Keep the `ask_user` tool available; it is disabled by default because ACP has no wire for it. */
17
+ askUser: z.boolean().default(false),
18
+ /** Load AGENTS.md and related instruction files from the workspace. */
19
+ customInstructions: z.boolean().default(false),
20
+ /** Enable Copilot's bundled GitHub MCP server. */
21
+ builtinMcps: z.boolean().default(false),
22
+ addDirs: z.array(z.string()).optional(),
23
+ extraArgs: z.array(z.string()).optional(),
24
+ cwd: z.string().optional(),
25
+ env: z.record(z.string(), z.string()).optional(),
26
+ startupTimeoutMs: z.number().int().positive().default(30_000),
27
+ idleTimeoutMs: z.number().int().positive().default(600_000),
28
+ maxInterrupts: z.number().int().positive().default(20),
29
+ maxLineBytes: z.number().int().positive().default(10_000_000),
30
+ maxQueuedBytes: z.number().int().positive().default(20_000_000),
31
+ maxToolCalls: z.number().int().positive().default(10_000),
32
+ })
33
+ .strict()
34
+ .transform(applyCatalogEffort(copilotCatalog));
35
+
36
+ export type CopilotDriverConfig = z.infer<typeof CopilotDriverConfigSchema>;
37
+
38
+ export const buildCopilotArgs = (config: CopilotDriverConfig): string[] => [
39
+ "--acp",
40
+ "--no-auto-update",
41
+ "--model",
42
+ config.model,
43
+ ...(config.reasoningEffort ? ["--effort", config.reasoningEffort] : []),
44
+ ...(config.askUser ? [] : ["--no-ask-user"]),
45
+ ...(config.customInstructions ? [] : ["--no-custom-instructions"]),
46
+ ...(config.builtinMcps ? [] : ["--disable-builtin-mcps"]),
47
+ ...(config.allowAllTools ? ["--allow-all-tools"] : []),
48
+ ...(config.allowTools ?? []).map((tool) => `--allow-tool=${tool}`),
49
+ ...(config.denyTools ?? []).map((tool) => `--deny-tool=${tool}`),
50
+ ...(config.addDirs ?? []).flatMap((dir) => ["--add-dir", dir]),
51
+ ...(config.extraArgs ?? []),
52
+ ];
53
+
54
+ export const COPILOT_MODE_IDS: Record<CopilotDriverConfig["mode"], string> = {
55
+ agent: "https://agentclientprotocol.com/protocol/session-modes#agent",
56
+ plan: "https://agentclientprotocol.com/protocol/session-modes#plan",
57
+ autopilot: "https://agentclientprotocol.com/protocol/session-modes#autopilot",
58
+ };