@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.
- package/lib/answerers/persona/index.d.ts +5 -1
- package/lib/answerers/persona/index.d.ts.map +1 -1
- package/lib/assertions/rubric/index.d.ts +3 -1
- package/lib/assertions/rubric/index.d.ts.map +1 -1
- package/lib/authoring.d.ts +3 -1
- package/lib/authoring.d.ts.map +1 -1
- package/lib/authoring.js +2 -1
- package/lib/authoring.js.map +1 -1
- package/lib/cli/harness-plan.d.ts +26 -0
- package/lib/cli/harness-plan.d.ts.map +1 -0
- package/lib/cli/harness-plan.js +75 -0
- package/lib/cli/harness-plan.js.map +1 -0
- package/lib/cli/init-templates.d.ts +2 -2
- package/lib/cli/init-templates.d.ts.map +1 -1
- package/lib/cli/init-templates.js +11 -4
- package/lib/cli/init-templates.js.map +1 -1
- package/lib/cli/init.d.ts +2 -0
- package/lib/cli/init.d.ts.map +1 -1
- package/lib/cli/init.js +6 -3
- package/lib/cli/init.js.map +1 -1
- package/lib/cli/output-schemas.d.ts +7 -0
- package/lib/cli/output-schemas.d.ts.map +1 -1
- package/lib/cli/program.d.ts +5 -10
- package/lib/cli/program.d.ts.map +1 -1
- package/lib/cli/program.js +44 -77
- package/lib/cli/program.js.map +1 -1
- package/lib/cli/run-options.d.ts +19 -0
- package/lib/cli/run-options.d.ts.map +1 -1
- package/lib/cli/run-options.js +92 -0
- package/lib/cli/run-options.js.map +1 -1
- package/lib/core/case.d.ts +2 -0
- package/lib/core/case.d.ts.map +1 -1
- package/lib/core/case.js +3 -0
- package/lib/core/case.js.map +1 -1
- package/lib/core/driver.d.ts +13 -0
- package/lib/core/driver.d.ts.map +1 -1
- package/lib/core/driver.js +10 -0
- package/lib/core/driver.js.map +1 -1
- package/lib/core/harness-catalog.d.ts +35 -0
- package/lib/core/harness-catalog.d.ts.map +1 -0
- package/lib/core/harness-catalog.js +45 -0
- package/lib/core/harness-catalog.js.map +1 -0
- package/lib/core/harness-catalogs/antigravity.d.ts +11 -0
- package/lib/core/harness-catalogs/antigravity.d.ts.map +1 -0
- package/lib/core/harness-catalogs/antigravity.js +23 -0
- package/lib/core/harness-catalogs/antigravity.js.map +1 -0
- package/lib/core/harness-catalogs/claude-code.d.ts +12 -0
- package/lib/core/harness-catalogs/claude-code.d.ts.map +1 -0
- package/lib/core/harness-catalogs/claude-code.js +24 -0
- package/lib/core/harness-catalogs/claude-code.js.map +1 -0
- package/lib/core/harness-catalogs/codex.d.ts +11 -0
- package/lib/core/harness-catalogs/codex.d.ts.map +1 -0
- package/lib/core/harness-catalogs/codex.js +26 -0
- package/lib/core/harness-catalogs/codex.js.map +1 -0
- package/lib/core/harness-catalogs/copilot.d.ts +29 -0
- package/lib/core/harness-catalogs/copilot.d.ts.map +1 -0
- package/lib/core/harness-catalogs/copilot.js +45 -0
- package/lib/core/harness-catalogs/copilot.js.map +1 -0
- package/lib/core/harness-catalogs/cursor.d.ts +2 -0
- package/lib/core/harness-catalogs/cursor.d.ts.map +1 -0
- package/lib/core/harness-catalogs/cursor.js +13 -0
- package/lib/core/harness-catalogs/cursor.js.map +1 -0
- package/lib/core/harness-catalogs/index.d.ts +67 -0
- package/lib/core/harness-catalogs/index.d.ts.map +1 -0
- package/lib/core/harness-catalogs/index.js +15 -0
- package/lib/core/harness-catalogs/index.js.map +1 -0
- package/lib/core/harness-matrix.d.ts +70 -0
- package/lib/core/harness-matrix.d.ts.map +1 -0
- package/lib/core/harness-matrix.js +194 -0
- package/lib/core/harness-matrix.js.map +1 -0
- package/lib/core/index.d.ts +3 -0
- package/lib/core/index.d.ts.map +1 -1
- package/lib/core/index.js +3 -0
- package/lib/core/index.js.map +1 -1
- package/lib/core/model-cli.d.ts +4 -11
- package/lib/core/model-cli.d.ts.map +1 -1
- package/lib/core/model-cli.js +23 -17
- package/lib/core/model-cli.js.map +1 -1
- package/lib/core/platform-process.d.ts +1 -0
- package/lib/core/platform-process.d.ts.map +1 -1
- package/lib/core/platform-process.js +1 -1
- package/lib/core/platform-process.js.map +1 -1
- package/lib/core/run.d.ts +4 -0
- package/lib/core/run.d.ts.map +1 -1
- package/lib/core/run.js +2 -0
- package/lib/core/run.js.map +1 -1
- package/lib/drivers/antigravity/config.d.ts +46 -0
- package/lib/drivers/antigravity/config.d.ts.map +1 -0
- package/lib/drivers/antigravity/config.js +39 -0
- package/lib/drivers/antigravity/config.js.map +1 -0
- package/lib/drivers/antigravity/events.d.ts +4 -0
- package/lib/drivers/antigravity/events.d.ts.map +1 -0
- package/lib/drivers/antigravity/events.js +193 -0
- package/lib/drivers/antigravity/events.js.map +1 -0
- package/lib/drivers/antigravity/index.d.ts +60 -0
- package/lib/drivers/antigravity/index.d.ts.map +1 -0
- package/lib/drivers/antigravity/index.js +90 -0
- package/lib/drivers/antigravity/index.js.map +1 -0
- package/lib/drivers/claude-code/index.d.ts +93 -7
- package/lib/drivers/claude-code/index.d.ts.map +1 -1
- package/lib/drivers/claude-code/index.js +14 -8
- package/lib/drivers/claude-code/index.js.map +1 -1
- package/lib/drivers/codex/config.d.ts +61 -4
- package/lib/drivers/codex/config.d.ts.map +1 -1
- package/lib/drivers/codex/config.js +19 -5
- package/lib/drivers/codex/config.js.map +1 -1
- package/lib/drivers/codex/index.d.ts +63 -5
- package/lib/drivers/codex/index.d.ts.map +1 -1
- package/lib/drivers/codex/index.js +11 -3
- package/lib/drivers/codex/index.js.map +1 -1
- package/lib/drivers/copilot/config.d.ts +81 -0
- package/lib/drivers/copilot/config.d.ts.map +1 -0
- package/lib/drivers/copilot/config.js +54 -0
- package/lib/drivers/copilot/config.js.map +1 -0
- package/lib/drivers/copilot/index.d.ts +103 -0
- package/lib/drivers/copilot/index.d.ts.map +1 -0
- package/lib/drivers/copilot/index.js +256 -0
- package/lib/drivers/copilot/index.js.map +1 -0
- package/lib/drivers/cursor/config.d.ts +6 -1
- package/lib/drivers/cursor/config.d.ts.map +1 -1
- package/lib/drivers/cursor/config.js +2 -3
- package/lib/drivers/cursor/config.js.map +1 -1
- package/lib/drivers/cursor/index.d.ts +7 -2
- package/lib/drivers/cursor/index.d.ts.map +1 -1
- package/lib/drivers/cursor/index.js +9 -6
- package/lib/drivers/cursor/index.js.map +1 -1
- package/lib/drivers/cursor/interaction.d.ts +1 -2
- package/lib/drivers/cursor/interaction.d.ts.map +1 -1
- package/lib/drivers/cursor/interaction.js +3 -14
- package/lib/drivers/cursor/interaction.js.map +1 -1
- package/lib/drivers/{cursor/events.d.ts → shared/acp-events.d.ts} +5 -3
- package/lib/drivers/shared/acp-events.d.ts.map +1 -0
- package/lib/drivers/{cursor/events.js → shared/acp-events.js} +20 -10
- package/lib/drivers/shared/acp-events.js.map +1 -0
- package/lib/drivers/shared/acp-interaction.d.ts +7 -0
- package/lib/drivers/shared/acp-interaction.d.ts.map +1 -0
- package/lib/drivers/shared/acp-interaction.js +20 -0
- package/lib/drivers/shared/acp-interaction.js.map +1 -0
- package/lib/drivers/{cursor → shared}/acp-transport.d.ts +2 -0
- package/lib/drivers/shared/acp-transport.d.ts.map +1 -0
- package/lib/drivers/{cursor → shared}/acp-transport.js +10 -10
- package/lib/drivers/shared/acp-transport.js.map +1 -0
- package/lib/index.d.ts +7 -2
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +7 -2
- package/lib/index.js.map +1 -1
- package/lib/optimization/reflective.d.ts +2 -0
- package/lib/optimization/reflective.d.ts.map +1 -1
- package/lib/orchestrator/comparison-identity.d.ts.map +1 -1
- package/lib/orchestrator/comparison-identity.js +1 -0
- package/lib/orchestrator/comparison-identity.js.map +1 -1
- package/lib/orchestrator/config.d.ts +7 -0
- package/lib/orchestrator/config.d.ts.map +1 -1
- package/lib/orchestrator/config.js +8 -1
- package/lib/orchestrator/config.js.map +1 -1
- package/lib/orchestrator/doctor.d.ts.map +1 -1
- package/lib/orchestrator/doctor.js +72 -2
- package/lib/orchestrator/doctor.js.map +1 -1
- package/lib/orchestrator/experiment-context.d.ts +1 -1
- package/lib/orchestrator/harness-catalog-drift.d.ts +22 -0
- package/lib/orchestrator/harness-catalog-drift.d.ts.map +1 -0
- package/lib/orchestrator/harness-catalog-drift.js +90 -0
- package/lib/orchestrator/harness-catalog-drift.js.map +1 -0
- package/lib/orchestrator/orchestrator.d.ts +9 -1
- package/lib/orchestrator/orchestrator.d.ts.map +1 -1
- package/lib/orchestrator/orchestrator.js +14 -22
- package/lib/orchestrator/orchestrator.js.map +1 -1
- package/lib/orchestrator/run-dir.d.ts +2 -0
- package/lib/orchestrator/run-dir.d.ts.map +1 -1
- package/lib/orchestrator/run-dir.js +1 -1
- package/lib/orchestrator/run-dir.js.map +1 -1
- package/lib/orchestrator/run-execution.d.ts +1 -0
- package/lib/orchestrator/run-execution.d.ts.map +1 -1
- package/lib/orchestrator/run-execution.js +2 -0
- package/lib/orchestrator/run-execution.js.map +1 -1
- package/lib/orchestrator/suite-compare.d.ts +3 -0
- package/lib/orchestrator/suite-compare.d.ts.map +1 -1
- package/lib/orchestrator/suite-compare.js +27 -17
- package/lib/orchestrator/suite-compare.js.map +1 -1
- package/lib/orchestrator/suite-runs.d.ts +3 -0
- package/lib/orchestrator/suite-runs.d.ts.map +1 -1
- package/lib/orchestrator/suite-runs.js +2 -0
- package/lib/orchestrator/suite-runs.js.map +1 -1
- package/lib/orchestrator/suite-summary.d.ts +9 -0
- package/lib/orchestrator/suite-summary.d.ts.map +1 -1
- package/lib/orchestrator/suite-summary.js +14 -4
- package/lib/orchestrator/suite-summary.js.map +1 -1
- package/package.json +1 -1
- package/skills/lux-answerer/SKILL.md +1 -1
- package/src/authoring.ts +10 -3
- package/src/cli/harness-plan.ts +117 -0
- package/src/cli/init-templates.ts +12 -5
- package/src/cli/init.ts +12 -5
- package/src/cli/program.ts +50 -92
- package/src/cli/run-options.ts +123 -0
- package/src/core/case.ts +3 -0
- package/src/core/driver.ts +26 -0
- package/src/core/harness-catalog.ts +100 -0
- package/src/core/harness-catalogs/antigravity.ts +24 -0
- package/src/core/harness-catalogs/claude-code.ts +25 -0
- package/src/core/harness-catalogs/codex.ts +27 -0
- package/src/core/harness-catalogs/copilot.ts +46 -0
- package/src/core/harness-catalogs/cursor.ts +13 -0
- package/src/core/harness-catalogs/index.ts +22 -0
- package/src/core/harness-matrix.ts +298 -0
- package/src/core/index.ts +3 -0
- package/src/core/model-cli.ts +38 -21
- package/src/core/platform-process.ts +4 -4
- package/src/core/run.ts +2 -0
- package/src/drivers/antigravity/README.md +46 -0
- package/src/drivers/antigravity/config.ts +44 -0
- package/src/drivers/antigravity/events.ts +235 -0
- package/src/drivers/antigravity/index.ts +109 -0
- package/src/drivers/claude-code/index.ts +18 -7
- package/src/drivers/codex/config.ts +23 -5
- package/src/drivers/codex/index.ts +15 -2
- package/src/drivers/copilot/README.md +52 -0
- package/src/drivers/copilot/config.ts +58 -0
- package/src/drivers/copilot/index.ts +292 -0
- package/src/drivers/cursor/README.md +9 -6
- package/src/drivers/cursor/config.ts +2 -3
- package/src/drivers/cursor/index.ts +10 -6
- package/src/drivers/cursor/interaction.ts +3 -19
- package/src/drivers/{cursor/events.ts → shared/acp-events.ts} +20 -9
- package/src/drivers/shared/acp-interaction.ts +27 -0
- package/src/drivers/{cursor → shared}/acp-transport.ts +15 -10
- package/src/index.ts +44 -3
- package/src/orchestrator/comparison-identity.ts +1 -0
- package/src/orchestrator/config.ts +8 -0
- package/src/orchestrator/doctor.ts +125 -3
- package/src/orchestrator/harness-catalog-drift.ts +132 -0
- package/src/orchestrator/orchestrator.ts +31 -26
- package/src/orchestrator/run-dir.ts +8 -1
- package/src/orchestrator/run-execution.ts +3 -0
- package/src/orchestrator/suite-compare.ts +29 -19
- package/src/orchestrator/suite-runs.ts +3 -1
- package/src/orchestrator/suite-summary.ts +19 -4
- package/lib/drivers/cursor/acp-transport.d.ts.map +0 -1
- package/lib/drivers/cursor/acp-transport.js.map +0 -1
- package/lib/drivers/cursor/events.d.ts.map +0 -1
- package/lib/drivers/cursor/events.js.map +0 -1
- package/skills/lux/SKILL.md +0 -89
- package/skills/lux/references/cli.md +0 -128
- 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
|
-
|
|
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
|
|
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,
|
|
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([
|
|
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,
|
|
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 {
|
|
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:
|
|
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(
|
|
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(
|
|
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
|
-
|
|
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:
|
|
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
|
+
};
|