@ai-sdk/harness-grok-build 0.0.0 → 1.0.1
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/CHANGELOG.md +30 -0
- package/LICENSE +13 -0
- package/README.md +41 -3
- package/dist/bridge/package.json +13 -0
- package/dist/bridge/pnpm-lock.yaml +890 -0
- package/dist/index.d.ts +4550 -0
- package/dist/index.js +297 -0
- package/dist/index.js.map +1 -0
- package/package.json +64 -10
- package/src/bridge/package.json +13 -0
- package/src/bridge/pnpm-lock.yaml +890 -0
- package/src/grok-build-harness.ts +334 -0
- package/src/index.ts +10 -0
- package/src/version.ts +5 -0
- package/index.js +0 -1
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import {
|
|
3
|
+
commonTool,
|
|
4
|
+
type HarnessV1,
|
|
5
|
+
type HarnessV1BuiltinTool,
|
|
6
|
+
} from '@ai-sdk/harness';
|
|
7
|
+
import {
|
|
8
|
+
createACP,
|
|
9
|
+
type ACPProviderAuthenticationMode,
|
|
10
|
+
} from '@ai-sdk/harness-acp';
|
|
11
|
+
import { tool } from '@ai-sdk/provider-utils';
|
|
12
|
+
import { z } from 'zod/v4';
|
|
13
|
+
import { VERSION } from './version';
|
|
14
|
+
|
|
15
|
+
const GROK_BUILD_CLIENT_APP = `ai-sdk/harness-grok-build/${VERSION}`;
|
|
16
|
+
const GROK_BUILD_IMPLEMENTATION_PACKAGE_JSON = readFileSync(
|
|
17
|
+
new URL('./bridge/package.json', import.meta.url),
|
|
18
|
+
'utf8',
|
|
19
|
+
);
|
|
20
|
+
const GROK_BUILD_IMPLEMENTATION_PNPM_LOCK = readFileSync(
|
|
21
|
+
new URL('./bridge/pnpm-lock.yaml', import.meta.url),
|
|
22
|
+
'utf8',
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
export type GrokBuildHarnessSettings = {
|
|
26
|
+
/**
|
|
27
|
+
* Selects direct xAI or AI Gateway authentication. Defaults to automatic
|
|
28
|
+
* environment-based selection.
|
|
29
|
+
*/
|
|
30
|
+
readonly auth?: ACPProviderAuthenticationMode;
|
|
31
|
+
/**
|
|
32
|
+
* Grok model id selected through ACP. Unset preserves Grok Build's default.
|
|
33
|
+
*/
|
|
34
|
+
readonly model?: string;
|
|
35
|
+
/**
|
|
36
|
+
* Overrides the sandbox port used by the ACP bridge.
|
|
37
|
+
*/
|
|
38
|
+
readonly port?: number;
|
|
39
|
+
/**
|
|
40
|
+
* Maximum milliseconds to wait for the ACP bridge to start.
|
|
41
|
+
*/
|
|
42
|
+
readonly startupTimeoutMs?: number;
|
|
43
|
+
/**
|
|
44
|
+
* MCP server definitions keyed by server name. Each definition uses the
|
|
45
|
+
* underlying runtime's native MCP server configuration format.
|
|
46
|
+
*/
|
|
47
|
+
readonly mcpServers?: Record<string, unknown>;
|
|
48
|
+
/**
|
|
49
|
+
* Creates the authentication token used by the sandbox bridge. Defaults to
|
|
50
|
+
* a random 32-byte hexadecimal token.
|
|
51
|
+
*/
|
|
52
|
+
readonly mintBridgeToken?: (sandboxId: string) => string;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
/*
|
|
56
|
+
* Tool names and inputs were captured from the model request produced by
|
|
57
|
+
* @xai-official/grok 0.2.111, the version used by the pinned Grok Build ACP
|
|
58
|
+
* implementation.
|
|
59
|
+
*/
|
|
60
|
+
const GROK_BUILD_BUILTIN_TOOLS = {
|
|
61
|
+
bash: commonTool('bash', {
|
|
62
|
+
nativeName: 'run_terminal_command',
|
|
63
|
+
toolUseKind: 'bash',
|
|
64
|
+
inputSchema: z.looseObject({
|
|
65
|
+
command: z.string(),
|
|
66
|
+
timeout: z.number().int().min(0).max(36_000_000).nullable().optional(),
|
|
67
|
+
description: z.string().optional(),
|
|
68
|
+
background: z.boolean().optional(),
|
|
69
|
+
}),
|
|
70
|
+
}),
|
|
71
|
+
edit: commonTool('edit', {
|
|
72
|
+
nativeName: 'search_replace',
|
|
73
|
+
toolUseKind: 'edit',
|
|
74
|
+
inputSchema: z.looseObject({
|
|
75
|
+
file_path: z.string(),
|
|
76
|
+
old_string: z.string(),
|
|
77
|
+
new_string: z.string(),
|
|
78
|
+
replace_all: z.boolean().optional(),
|
|
79
|
+
}),
|
|
80
|
+
}),
|
|
81
|
+
grep: commonTool('grep', {
|
|
82
|
+
nativeName: 'grep',
|
|
83
|
+
toolUseKind: 'readonly',
|
|
84
|
+
inputSchema: z.looseObject({
|
|
85
|
+
pattern: z.string(),
|
|
86
|
+
path: z.string().nullable().optional(),
|
|
87
|
+
glob: z.string().nullable().optional(),
|
|
88
|
+
'-B': z.number().int().optional(),
|
|
89
|
+
'-A': z.number().int().optional(),
|
|
90
|
+
'-C': z.number().int().optional(),
|
|
91
|
+
'-i': z.boolean().optional(),
|
|
92
|
+
type: z.string().nullable().optional(),
|
|
93
|
+
head_limit: z.number().int().optional(),
|
|
94
|
+
multiline: z.boolean().optional(),
|
|
95
|
+
}),
|
|
96
|
+
}),
|
|
97
|
+
webSearch: commonTool('webSearch', {
|
|
98
|
+
nativeName: 'web_search',
|
|
99
|
+
toolUseKind: 'readonly',
|
|
100
|
+
inputSchema: z.looseObject({
|
|
101
|
+
query: z.string(),
|
|
102
|
+
allowed_domains: z.array(z.string()).nullable().optional(),
|
|
103
|
+
}),
|
|
104
|
+
}),
|
|
105
|
+
write: commonTool('write', {
|
|
106
|
+
nativeName: 'write',
|
|
107
|
+
toolUseKind: 'edit',
|
|
108
|
+
inputSchema: z.looseObject({
|
|
109
|
+
file_path: z.string(),
|
|
110
|
+
content: z.string(),
|
|
111
|
+
}),
|
|
112
|
+
}),
|
|
113
|
+
read_file: {
|
|
114
|
+
...tool({
|
|
115
|
+
inputSchema: z.looseObject({
|
|
116
|
+
target_file: z.string(),
|
|
117
|
+
offset: z.number().int().optional(),
|
|
118
|
+
limit: z.number().int().optional(),
|
|
119
|
+
pages: z.string().nullable().optional(),
|
|
120
|
+
format: z.string().nullable().optional(),
|
|
121
|
+
}),
|
|
122
|
+
}),
|
|
123
|
+
toolUseKind: 'readonly',
|
|
124
|
+
},
|
|
125
|
+
list_dir: {
|
|
126
|
+
...tool({
|
|
127
|
+
inputSchema: z.looseObject({
|
|
128
|
+
target_directory: z.string(),
|
|
129
|
+
}),
|
|
130
|
+
}),
|
|
131
|
+
toolUseKind: 'readonly',
|
|
132
|
+
},
|
|
133
|
+
kill_command_or_subagent: tool({
|
|
134
|
+
inputSchema: z.looseObject({
|
|
135
|
+
task_id: z.string(),
|
|
136
|
+
}),
|
|
137
|
+
}),
|
|
138
|
+
todo_write: tool({
|
|
139
|
+
inputSchema: z.looseObject({
|
|
140
|
+
merge: z.boolean().optional(),
|
|
141
|
+
todos: z.array(
|
|
142
|
+
z.looseObject({
|
|
143
|
+
id: z.string(),
|
|
144
|
+
content: z.string().nullable().optional(),
|
|
145
|
+
status: z
|
|
146
|
+
.enum(['pending', 'in_progress', 'completed', 'cancelled'])
|
|
147
|
+
.nullable()
|
|
148
|
+
.optional(),
|
|
149
|
+
}),
|
|
150
|
+
),
|
|
151
|
+
}),
|
|
152
|
+
}),
|
|
153
|
+
get_command_or_subagent_output: {
|
|
154
|
+
...tool({
|
|
155
|
+
inputSchema: z.looseObject({
|
|
156
|
+
task_ids: z.array(z.string()).optional(),
|
|
157
|
+
timeout_ms: z.number().int().nonnegative().nullable().optional(),
|
|
158
|
+
}),
|
|
159
|
+
}),
|
|
160
|
+
toolUseKind: 'readonly',
|
|
161
|
+
},
|
|
162
|
+
spawn_subagent: tool({
|
|
163
|
+
inputSchema: z.looseObject({
|
|
164
|
+
prompt: z.string(),
|
|
165
|
+
description: z.string(),
|
|
166
|
+
subagent_type: z.string().optional(),
|
|
167
|
+
background: z.boolean().optional(),
|
|
168
|
+
capability_mode: z
|
|
169
|
+
.enum(['read-only', 'read-write', 'execute', 'all'])
|
|
170
|
+
.nullable()
|
|
171
|
+
.optional(),
|
|
172
|
+
isolation: z.enum(['none', 'worktree']).nullable().optional(),
|
|
173
|
+
resume_from: z.string().nullable().optional(),
|
|
174
|
+
cwd: z.string().nullable().optional(),
|
|
175
|
+
model: z.string().nullable().optional(),
|
|
176
|
+
}),
|
|
177
|
+
}),
|
|
178
|
+
scheduler_create: tool({
|
|
179
|
+
inputSchema: z.looseObject({
|
|
180
|
+
task_id: z.string().nullable().optional(),
|
|
181
|
+
interval: z.string().nullable().optional(),
|
|
182
|
+
prompt: z.string().nullable().optional(),
|
|
183
|
+
durable: z.boolean().nullable().optional(),
|
|
184
|
+
foreground: z.boolean().nullable().optional(),
|
|
185
|
+
fire_immediately: z.boolean().optional(),
|
|
186
|
+
}),
|
|
187
|
+
}),
|
|
188
|
+
scheduler_delete: tool({
|
|
189
|
+
inputSchema: z.looseObject({ id: z.string() }),
|
|
190
|
+
}),
|
|
191
|
+
scheduler_list: {
|
|
192
|
+
...tool({ inputSchema: z.looseObject({}) }),
|
|
193
|
+
toolUseKind: 'readonly',
|
|
194
|
+
},
|
|
195
|
+
monitor: tool({
|
|
196
|
+
inputSchema: z.looseObject({
|
|
197
|
+
command: z.string(),
|
|
198
|
+
description: z.string(),
|
|
199
|
+
timeout_ms: z.number().int().nonnegative().nullable().optional(),
|
|
200
|
+
persistent: z.boolean().optional(),
|
|
201
|
+
}),
|
|
202
|
+
}),
|
|
203
|
+
search_tool: {
|
|
204
|
+
...tool({
|
|
205
|
+
inputSchema: z.looseObject({
|
|
206
|
+
query: z.string(),
|
|
207
|
+
limit: z.number().int().min(0).max(255).nullable().optional(),
|
|
208
|
+
}),
|
|
209
|
+
}),
|
|
210
|
+
toolUseKind: 'readonly',
|
|
211
|
+
},
|
|
212
|
+
use_tool: tool({
|
|
213
|
+
inputSchema: z.looseObject({
|
|
214
|
+
tool_name: z.string(),
|
|
215
|
+
tool_input: z.looseObject({}),
|
|
216
|
+
}),
|
|
217
|
+
}),
|
|
218
|
+
workflow: tool({
|
|
219
|
+
inputSchema: z.looseObject({
|
|
220
|
+
agent_budget: z.number().int().min(1).max(1024).nullable().optional(),
|
|
221
|
+
name: z.string().nullable().optional(),
|
|
222
|
+
script: z.string().nullable().optional(),
|
|
223
|
+
script_path: z.string().nullable().optional(),
|
|
224
|
+
args: z.unknown().optional(),
|
|
225
|
+
resume_from_run_id: z.string().nullable().optional(),
|
|
226
|
+
validate_only: z.boolean().optional(),
|
|
227
|
+
}),
|
|
228
|
+
}),
|
|
229
|
+
enter_plan_mode: tool({ inputSchema: z.looseObject({}) }),
|
|
230
|
+
exit_plan_mode: tool({ inputSchema: z.looseObject({}) }),
|
|
231
|
+
ask_user_question: tool({
|
|
232
|
+
inputSchema: z.looseObject({
|
|
233
|
+
questions: z.array(
|
|
234
|
+
z.looseObject({
|
|
235
|
+
question: z.string(),
|
|
236
|
+
options: z.array(
|
|
237
|
+
z.looseObject({
|
|
238
|
+
label: z.string(),
|
|
239
|
+
description: z.string(),
|
|
240
|
+
preview: z.string().nullable().optional(),
|
|
241
|
+
}),
|
|
242
|
+
),
|
|
243
|
+
multi_select: z.boolean().nullable().optional(),
|
|
244
|
+
}),
|
|
245
|
+
),
|
|
246
|
+
}),
|
|
247
|
+
}),
|
|
248
|
+
image_gen: tool({
|
|
249
|
+
inputSchema: z.looseObject({
|
|
250
|
+
prompt: z.string(),
|
|
251
|
+
aspect_ratio: z.string().optional(),
|
|
252
|
+
}),
|
|
253
|
+
}),
|
|
254
|
+
image_edit: tool({
|
|
255
|
+
inputSchema: z.looseObject({
|
|
256
|
+
prompt: z.string(),
|
|
257
|
+
image: z.array(z.string()),
|
|
258
|
+
aspect_ratio: z.string().optional(),
|
|
259
|
+
}),
|
|
260
|
+
}),
|
|
261
|
+
image_to_video: tool({
|
|
262
|
+
inputSchema: z.looseObject({
|
|
263
|
+
prompt: z.string().nullable().optional(),
|
|
264
|
+
image: z.string(),
|
|
265
|
+
duration: z.number().int().nonnegative().nullable().optional(),
|
|
266
|
+
resolution_name: z.string().optional(),
|
|
267
|
+
}),
|
|
268
|
+
}),
|
|
269
|
+
reference_to_video: tool({
|
|
270
|
+
inputSchema: z.looseObject({
|
|
271
|
+
prompt: z.string(),
|
|
272
|
+
images: z.array(z.string()),
|
|
273
|
+
aspect_ratio: z.string(),
|
|
274
|
+
duration: z.number().int().nonnegative().nullable().optional(),
|
|
275
|
+
resolution_name: z.string().optional(),
|
|
276
|
+
}),
|
|
277
|
+
}),
|
|
278
|
+
} as const satisfies Record<string, HarnessV1BuiltinTool<any, any>>;
|
|
279
|
+
|
|
280
|
+
export function createGrokBuild(
|
|
281
|
+
settings: GrokBuildHarnessSettings = {},
|
|
282
|
+
): HarnessV1<typeof GROK_BUILD_BUILTIN_TOOLS> {
|
|
283
|
+
const clientAppSegments = GROK_BUILD_CLIENT_APP.split('/');
|
|
284
|
+
const clientAppVersion = clientAppSegments.pop()!;
|
|
285
|
+
|
|
286
|
+
return createACP({
|
|
287
|
+
auth: settings.auth,
|
|
288
|
+
modelId: settings.model,
|
|
289
|
+
port: settings.port,
|
|
290
|
+
startupTimeoutMs: settings.startupTimeoutMs,
|
|
291
|
+
mcpServers: settings.mcpServers,
|
|
292
|
+
isMcpToolCall: toolCall => {
|
|
293
|
+
const metadata = toolCall._meta?.['x.ai/tool'];
|
|
294
|
+
return isRecord(metadata) && metadata.namespace === 'mcp';
|
|
295
|
+
},
|
|
296
|
+
mintBridgeToken: settings.mintBridgeToken,
|
|
297
|
+
version: 'v1',
|
|
298
|
+
harnessId: 'grok-build',
|
|
299
|
+
builtinTools: GROK_BUILD_BUILTIN_TOOLS,
|
|
300
|
+
clientApp: {
|
|
301
|
+
name: clientAppSegments.join('/'),
|
|
302
|
+
version: clientAppVersion,
|
|
303
|
+
},
|
|
304
|
+
source: {
|
|
305
|
+
type: 'npm-locked',
|
|
306
|
+
packageJson: GROK_BUILD_IMPLEMENTATION_PACKAGE_JSON,
|
|
307
|
+
pnpmLockYaml: GROK_BUILD_IMPLEMENTATION_PNPM_LOCK,
|
|
308
|
+
},
|
|
309
|
+
executable: 'grok',
|
|
310
|
+
args: ['agent', 'stdio'],
|
|
311
|
+
forwardEnv: ['XAI_API_KEY'],
|
|
312
|
+
providerAuthentication: {
|
|
313
|
+
gateway: {
|
|
314
|
+
env: {
|
|
315
|
+
GROK_CLIENT_NAME: { $source: 'client-app-name' },
|
|
316
|
+
GROK_CLIENT_VERSION: { $source: 'client-app-version' },
|
|
317
|
+
XAI_API_KEY: { $source: 'gateway-api-key' },
|
|
318
|
+
GROK_XAI_API_BASE_URL: {
|
|
319
|
+
$source: 'gateway-base-url',
|
|
320
|
+
ensureSuffix: '/v1',
|
|
321
|
+
},
|
|
322
|
+
GROK_MODELS_BASE_URL: {
|
|
323
|
+
$source: 'gateway-base-url',
|
|
324
|
+
ensureSuffix: '/v1',
|
|
325
|
+
},
|
|
326
|
+
},
|
|
327
|
+
},
|
|
328
|
+
},
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
333
|
+
return value != null && typeof value === 'object' && !Array.isArray(value);
|
|
334
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { createGrokBuild } from './grok-build-harness';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Default Grok Build harness instance. Equivalent to `createGrokBuild()`.
|
|
5
|
+
*/
|
|
6
|
+
export const grokBuild = createGrokBuild();
|
|
7
|
+
|
|
8
|
+
export { createGrokBuild } from './grok-build-harness';
|
|
9
|
+
export type { GrokBuildHarnessSettings } from './grok-build-harness';
|
|
10
|
+
export { VERSION } from './version';
|
package/src/version.ts
ADDED
package/index.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|