@haystackeditor/cli 0.15.20 → 0.15.22
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/README.md +42 -2
- package/dist/commands/verify-core.d.ts +449 -0
- package/dist/commands/verify-core.js +789 -0
- package/dist/commands/verify-hosted.d.ts +60 -0
- package/dist/commands/verify-hosted.js +342 -0
- package/dist/commands/verify-mcp.d.ts +8 -0
- package/dist/commands/verify-mcp.js +517 -0
- package/dist/commands/verify-ops.d.ts +158 -0
- package/dist/commands/verify-ops.js +1148 -0
- package/dist/commands/verify-reproducibility.d.ts +85 -0
- package/dist/commands/verify-reproducibility.js +494 -0
- package/dist/commands/verify-reseal.d.ts +9 -0
- package/dist/commands/verify-reseal.js +148 -0
- package/dist/commands/verify-sandboxes.d.ts +95 -0
- package/dist/commands/verify-sandboxes.js +352 -0
- package/dist/commands/verify.d.ts +22 -0
- package/dist/commands/verify.js +130 -0
- package/dist/index.js +326 -0
- package/dist/schema.d.ts +1 -0
- package/dist/schema.js +1 -0
- package/dist/types.d.ts +54 -0
- package/dist/types.js +15 -0
- package/dist/utils/haystack-api.d.ts +1 -1
- package/dist/utils/haystack-api.js +2 -2
- package/package.json +2 -2
- package/schemas/cloud-verifier.v1.json +96 -0
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
export interface HostedStartOptions {
|
|
2
|
+
base: string;
|
|
3
|
+
head: string;
|
|
4
|
+
idempotencyKey?: string;
|
|
5
|
+
account?: string;
|
|
6
|
+
wait?: boolean;
|
|
7
|
+
interval?: string;
|
|
8
|
+
timeout?: string;
|
|
9
|
+
json?: boolean;
|
|
10
|
+
}
|
|
11
|
+
export interface HostedStatusOptions {
|
|
12
|
+
account?: string;
|
|
13
|
+
wait?: boolean;
|
|
14
|
+
interval?: string;
|
|
15
|
+
timeout?: string;
|
|
16
|
+
json?: boolean;
|
|
17
|
+
}
|
|
18
|
+
interface HostedRunState {
|
|
19
|
+
runId: string;
|
|
20
|
+
status: string;
|
|
21
|
+
repository?: string;
|
|
22
|
+
baseCommit?: string;
|
|
23
|
+
headCommit?: string;
|
|
24
|
+
createdAt?: string;
|
|
25
|
+
completedAt?: string;
|
|
26
|
+
output?: Record<string, unknown>;
|
|
27
|
+
error?: string;
|
|
28
|
+
}
|
|
29
|
+
interface HostedPollOptions {
|
|
30
|
+
intervalMs: number;
|
|
31
|
+
timeoutMs: number;
|
|
32
|
+
onStatus?: (state: HostedRunState) => void;
|
|
33
|
+
}
|
|
34
|
+
interface HostedWaitResult {
|
|
35
|
+
state: HostedRunState;
|
|
36
|
+
timedOut: boolean;
|
|
37
|
+
}
|
|
38
|
+
export declare function parseHostedRunState(value: unknown, expectedRunId?: string): HostedRunState;
|
|
39
|
+
export declare function parseHostedRepository(value: string): {
|
|
40
|
+
owner: string;
|
|
41
|
+
repository: string;
|
|
42
|
+
fullName: string;
|
|
43
|
+
};
|
|
44
|
+
export declare function defaultHostedIdempotencyKey(repository: string, baseCommit: string, headCommit: string): string;
|
|
45
|
+
export declare function startHostedVerification(repositoryArg: string, options: HostedStartOptions, token: string): Promise<{
|
|
46
|
+
state: HostedRunState;
|
|
47
|
+
idempotencyKey: string;
|
|
48
|
+
}>;
|
|
49
|
+
export declare function getHostedVerification(runId: string, token: string): Promise<HostedRunState>;
|
|
50
|
+
export declare function waitForHostedVerification(runId: string, token: string, options: HostedPollOptions): Promise<HostedWaitResult>;
|
|
51
|
+
export declare function buildHostedJson(operation: 'start' | 'status', state: HostedRunState, extras?: {
|
|
52
|
+
account?: string;
|
|
53
|
+
idempotencyKey?: string;
|
|
54
|
+
nextCommand?: string;
|
|
55
|
+
timedOut?: boolean;
|
|
56
|
+
}): Record<string, unknown>;
|
|
57
|
+
export declare function hostedResumeCommand(runId: string, account?: string): string;
|
|
58
|
+
export declare function verifyHostedStartCommand(repositoryArg: string, options: HostedStartOptions): Promise<void>;
|
|
59
|
+
export declare function verifyHostedStatusCommand(runId: string, options: HostedStatusOptions): Promise<void>;
|
|
60
|
+
export {};
|
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import { withSchema } from '../schema.js';
|
|
4
|
+
import { resolveAuthContext } from '../utils/auth.js';
|
|
5
|
+
import { HaystackApiError, haystackJson } from '../utils/haystack-api.js';
|
|
6
|
+
const REPOSITORY_COMPONENT = /^[A-Za-z0-9_.-]{1,100}$/;
|
|
7
|
+
const COMMIT_SHA = /^[0-9a-f]{40}$/;
|
|
8
|
+
const IDEMPOTENCY_KEY = /^[A-Za-z0-9][A-Za-z0-9._:-]{7,127}$/;
|
|
9
|
+
const RUN_ID = /^cv_[0-9a-f]{48}$/;
|
|
10
|
+
const STATUS = /^[a-z][a-z0-9_-]{1,31}$/;
|
|
11
|
+
const TERMINAL_STATUSES = new Set(['complete', 'errored', 'expired', 'terminated']);
|
|
12
|
+
const DEFAULT_INTERVAL_SECONDS = 5;
|
|
13
|
+
const DEFAULT_TIMEOUT_MINUTES = 35;
|
|
14
|
+
function requireRecord(value, context) {
|
|
15
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
16
|
+
throw new Error(`${context} returned an invalid response object.`);
|
|
17
|
+
}
|
|
18
|
+
return value;
|
|
19
|
+
}
|
|
20
|
+
function requireString(value, field, pattern) {
|
|
21
|
+
const candidate = value[field];
|
|
22
|
+
if (typeof candidate !== 'string'
|
|
23
|
+
|| candidate.length === 0
|
|
24
|
+
|| (pattern && !pattern.test(candidate))) {
|
|
25
|
+
throw new Error(`Hosted verifier response is missing a valid ${field}.`);
|
|
26
|
+
}
|
|
27
|
+
return candidate;
|
|
28
|
+
}
|
|
29
|
+
function optionalString(value, field) {
|
|
30
|
+
const candidate = value[field];
|
|
31
|
+
if (candidate === undefined)
|
|
32
|
+
return undefined;
|
|
33
|
+
if (typeof candidate !== 'string' || candidate.length === 0) {
|
|
34
|
+
throw new Error(`Hosted verifier response has an invalid ${field}.`);
|
|
35
|
+
}
|
|
36
|
+
return candidate;
|
|
37
|
+
}
|
|
38
|
+
function optionalTimestamp(value, field) {
|
|
39
|
+
const candidate = optionalString(value, field);
|
|
40
|
+
if (candidate === undefined)
|
|
41
|
+
return undefined;
|
|
42
|
+
const parsed = new Date(candidate);
|
|
43
|
+
if (!Number.isFinite(parsed.getTime())
|
|
44
|
+
|| parsed.toISOString() !== candidate) {
|
|
45
|
+
throw new Error(`Hosted verifier response has an invalid ${field}.`);
|
|
46
|
+
}
|
|
47
|
+
return candidate;
|
|
48
|
+
}
|
|
49
|
+
export function parseHostedRunState(value, expectedRunId) {
|
|
50
|
+
const response = requireRecord(value, 'Hosted verifier');
|
|
51
|
+
const runId = requireString(response, 'runId', RUN_ID);
|
|
52
|
+
if (expectedRunId && runId !== expectedRunId) {
|
|
53
|
+
throw new Error(`Hosted verifier returned run ${runId} while status for ${expectedRunId} was requested.`);
|
|
54
|
+
}
|
|
55
|
+
const status = requireString(response, 'status', STATUS);
|
|
56
|
+
const repository = optionalString(response, 'repository');
|
|
57
|
+
if (repository) {
|
|
58
|
+
const parts = repository.split('/');
|
|
59
|
+
if (parts.length !== 2
|
|
60
|
+
|| !parts.every(part => REPOSITORY_COMPONENT.test(part))) {
|
|
61
|
+
throw new Error('Hosted verifier response has an invalid repository.');
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
const baseCommit = optionalString(response, 'baseCommit');
|
|
65
|
+
const headCommit = optionalString(response, 'headCommit');
|
|
66
|
+
if (baseCommit && !COMMIT_SHA.test(baseCommit)) {
|
|
67
|
+
throw new Error('Hosted verifier response has an invalid baseCommit.');
|
|
68
|
+
}
|
|
69
|
+
if (headCommit && !COMMIT_SHA.test(headCommit)) {
|
|
70
|
+
throw new Error('Hosted verifier response has an invalid headCommit.');
|
|
71
|
+
}
|
|
72
|
+
const outputValue = response.output;
|
|
73
|
+
const output = outputValue === undefined
|
|
74
|
+
? undefined
|
|
75
|
+
: requireRecord(outputValue, 'Hosted verifier output');
|
|
76
|
+
const createdAt = optionalTimestamp(response, 'createdAt');
|
|
77
|
+
const completedAt = optionalTimestamp(response, 'completedAt');
|
|
78
|
+
if (status === 'complete') {
|
|
79
|
+
if (!repository
|
|
80
|
+
|| !baseCommit
|
|
81
|
+
|| !headCommit
|
|
82
|
+
|| !createdAt
|
|
83
|
+
|| !completedAt
|
|
84
|
+
|| !output
|
|
85
|
+
|| output.runId !== runId
|
|
86
|
+
|| output.repository !== repository
|
|
87
|
+
|| output.baseCommit !== baseCommit
|
|
88
|
+
|| output.headCommit !== headCommit
|
|
89
|
+
|| output.sourceOfflineReady !== true
|
|
90
|
+
|| output.sandboxDeleted !== true) {
|
|
91
|
+
throw new Error('Hosted verifier returned a complete run without a matching terminal receipt.');
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return {
|
|
95
|
+
runId,
|
|
96
|
+
status,
|
|
97
|
+
repository,
|
|
98
|
+
baseCommit,
|
|
99
|
+
headCommit,
|
|
100
|
+
createdAt,
|
|
101
|
+
completedAt,
|
|
102
|
+
output,
|
|
103
|
+
error: optionalString(response, 'error'),
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
export function parseHostedRepository(value) {
|
|
107
|
+
const parts = value.split('/');
|
|
108
|
+
if (parts.length !== 2
|
|
109
|
+
|| !parts.every(part => REPOSITORY_COMPONENT.test(part))) {
|
|
110
|
+
throw new Error(`Invalid repository "${value}". Use an exact GitHub owner/repository name.`);
|
|
111
|
+
}
|
|
112
|
+
return {
|
|
113
|
+
owner: parts[0],
|
|
114
|
+
repository: parts[1],
|
|
115
|
+
fullName: value,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
function requireCommit(value, flag) {
|
|
119
|
+
if (typeof value !== 'string' || !COMMIT_SHA.test(value)) {
|
|
120
|
+
throw new Error(`${flag} must be an exact 40-character lowercase commit SHA.`);
|
|
121
|
+
}
|
|
122
|
+
return value;
|
|
123
|
+
}
|
|
124
|
+
export function defaultHostedIdempotencyKey(repository, baseCommit, headCommit) {
|
|
125
|
+
const digest = createHash('sha256')
|
|
126
|
+
.update(JSON.stringify([repository, baseCommit, headCommit]))
|
|
127
|
+
.digest('hex');
|
|
128
|
+
return `cli:${digest}`;
|
|
129
|
+
}
|
|
130
|
+
function requireIdempotencyKey(value) {
|
|
131
|
+
if (!IDEMPOTENCY_KEY.test(value)) {
|
|
132
|
+
throw new Error('--idempotency-key must be 8-128 characters and use only letters, numbers, ".", "_", ":", or "-".');
|
|
133
|
+
}
|
|
134
|
+
return value;
|
|
135
|
+
}
|
|
136
|
+
function parsePositiveNumber(value, fallback, flag, maximum) {
|
|
137
|
+
if (value === undefined)
|
|
138
|
+
return fallback;
|
|
139
|
+
const parsed = Number(value);
|
|
140
|
+
if (!Number.isFinite(parsed) || parsed <= 0 || parsed > maximum) {
|
|
141
|
+
throw new Error(`${flag} must be a positive number no greater than ${maximum}.`);
|
|
142
|
+
}
|
|
143
|
+
return parsed;
|
|
144
|
+
}
|
|
145
|
+
function pollingOptions(interval, timeout, onStatus) {
|
|
146
|
+
return {
|
|
147
|
+
intervalMs: parsePositiveNumber(interval, DEFAULT_INTERVAL_SECONDS, '--interval', 300) * 1000,
|
|
148
|
+
timeoutMs: parsePositiveNumber(timeout, DEFAULT_TIMEOUT_MINUTES, '--timeout', 1_440) * 60_000,
|
|
149
|
+
onStatus,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
export async function startHostedVerification(repositoryArg, options, token) {
|
|
153
|
+
const repository = parseHostedRepository(repositoryArg);
|
|
154
|
+
const baseCommit = requireCommit(options.base, '--base');
|
|
155
|
+
const headCommit = requireCommit(options.head, '--head');
|
|
156
|
+
const idempotencyKey = requireIdempotencyKey(options.idempotencyKey
|
|
157
|
+
?? defaultHostedIdempotencyKey(repository.fullName, baseCommit, headCommit));
|
|
158
|
+
const response = await haystackJson('/api/agent/cloud-verifier/runs', token, {
|
|
159
|
+
method: 'POST',
|
|
160
|
+
headers: { 'Content-Type': 'application/json' },
|
|
161
|
+
body: JSON.stringify({
|
|
162
|
+
owner: repository.owner,
|
|
163
|
+
repository: repository.repository,
|
|
164
|
+
baseCommit,
|
|
165
|
+
headCommit,
|
|
166
|
+
idempotencyKey,
|
|
167
|
+
}),
|
|
168
|
+
});
|
|
169
|
+
const state = parseHostedRunState(response);
|
|
170
|
+
return {
|
|
171
|
+
state: {
|
|
172
|
+
...state,
|
|
173
|
+
repository: state.repository ?? repository.fullName,
|
|
174
|
+
baseCommit: state.baseCommit ?? baseCommit,
|
|
175
|
+
headCommit: state.headCommit ?? headCommit,
|
|
176
|
+
},
|
|
177
|
+
idempotencyKey,
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
export async function getHostedVerification(runId, token) {
|
|
181
|
+
if (!RUN_ID.test(runId)) {
|
|
182
|
+
throw new Error('Run id must match cv_ followed by 48 lowercase hex characters.');
|
|
183
|
+
}
|
|
184
|
+
let response;
|
|
185
|
+
try {
|
|
186
|
+
response = await haystackJson(`/api/agent/cloud-verifier/runs/${encodeURIComponent(runId)}`, token, {}, [410]);
|
|
187
|
+
}
|
|
188
|
+
catch (error) {
|
|
189
|
+
if (error instanceof HaystackApiError && error.status === 404) {
|
|
190
|
+
throw new Error(`Hosted verifier run ${runId} was not found for the selected account. `
|
|
191
|
+
+ 'If the run was started with another saved account, retry with `--account <login>`.');
|
|
192
|
+
}
|
|
193
|
+
throw error;
|
|
194
|
+
}
|
|
195
|
+
return parseHostedRunState(response, runId);
|
|
196
|
+
}
|
|
197
|
+
function delay(milliseconds) {
|
|
198
|
+
return new Promise(resolve => setTimeout(resolve, milliseconds));
|
|
199
|
+
}
|
|
200
|
+
export async function waitForHostedVerification(runId, token, options) {
|
|
201
|
+
const startedAt = Date.now();
|
|
202
|
+
let lastStatus;
|
|
203
|
+
while (true) {
|
|
204
|
+
const state = await getHostedVerification(runId, token);
|
|
205
|
+
if (state.status !== lastStatus) {
|
|
206
|
+
options.onStatus?.(state);
|
|
207
|
+
lastStatus = state.status;
|
|
208
|
+
}
|
|
209
|
+
if (TERMINAL_STATUSES.has(state.status)) {
|
|
210
|
+
return { state, timedOut: false };
|
|
211
|
+
}
|
|
212
|
+
const elapsed = Date.now() - startedAt;
|
|
213
|
+
if (elapsed >= options.timeoutMs) {
|
|
214
|
+
return { state, timedOut: true };
|
|
215
|
+
}
|
|
216
|
+
await delay(Math.min(options.intervalMs, options.timeoutMs - elapsed));
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
export function buildHostedJson(operation, state, extras = {}) {
|
|
220
|
+
return withSchema('cloud-verifier', {
|
|
221
|
+
operation,
|
|
222
|
+
run_id: state.runId,
|
|
223
|
+
status: state.status,
|
|
224
|
+
...(state.repository ? { repository: state.repository } : {}),
|
|
225
|
+
...(state.baseCommit ? { base_commit: state.baseCommit } : {}),
|
|
226
|
+
...(state.headCommit ? { head_commit: state.headCommit } : {}),
|
|
227
|
+
...(state.createdAt ? { created_at: state.createdAt } : {}),
|
|
228
|
+
...(state.completedAt ? { completed_at: state.completedAt } : {}),
|
|
229
|
+
...(extras.account ? { account: extras.account } : {}),
|
|
230
|
+
...(extras.idempotencyKey
|
|
231
|
+
? { idempotency_key: extras.idempotencyKey }
|
|
232
|
+
: {}),
|
|
233
|
+
...(extras.nextCommand ? { next_command: extras.nextCommand } : {}),
|
|
234
|
+
...(extras.timedOut !== undefined ? { timed_out: extras.timedOut } : {}),
|
|
235
|
+
...(state.output ? { output: state.output } : {}),
|
|
236
|
+
...(state.error ? { error: state.error } : {}),
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
export function hostedResumeCommand(runId, account) {
|
|
240
|
+
return `haystack verify hosted status ${runId}${account ? ` --account ${account}` : ''} --wait`;
|
|
241
|
+
}
|
|
242
|
+
function printHostedState(operation, state, options) {
|
|
243
|
+
const nextCommand = TERMINAL_STATUSES.has(state.status)
|
|
244
|
+
? undefined
|
|
245
|
+
: hostedResumeCommand(state.runId, options.account);
|
|
246
|
+
if (options.json) {
|
|
247
|
+
process.stdout.write(`${JSON.stringify(buildHostedJson(operation, state, {
|
|
248
|
+
account: options.account,
|
|
249
|
+
idempotencyKey: options.idempotencyKey,
|
|
250
|
+
nextCommand,
|
|
251
|
+
timedOut: options.timedOut,
|
|
252
|
+
}), null, 2)}\n`);
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
const icon = state.status === 'complete'
|
|
256
|
+
? chalk.green('✓')
|
|
257
|
+
: TERMINAL_STATUSES.has(state.status)
|
|
258
|
+
? chalk.red('✗')
|
|
259
|
+
: chalk.cyan('•');
|
|
260
|
+
console.log(`${icon} Hosted verification ${chalk.bold(state.runId)}: ${state.status}`);
|
|
261
|
+
if (state.repository) {
|
|
262
|
+
console.log(` ${chalk.dim('Repository:')} ${state.repository}`);
|
|
263
|
+
}
|
|
264
|
+
if (state.baseCommit && state.headCommit) {
|
|
265
|
+
console.log(` ${chalk.dim('Commits:')} ${state.baseCommit.slice(0, 12)} → ${state.headCommit.slice(0, 12)}`);
|
|
266
|
+
}
|
|
267
|
+
if (state.error)
|
|
268
|
+
console.log(` ${chalk.dim('Error:')} ${state.error}`);
|
|
269
|
+
if (options.timedOut) {
|
|
270
|
+
console.log(chalk.yellow(' Wait timed out; the production run is still active.'));
|
|
271
|
+
}
|
|
272
|
+
if (nextCommand)
|
|
273
|
+
console.log(` ${chalk.dim('Resume:')} ${nextCommand}`);
|
|
274
|
+
}
|
|
275
|
+
function markNonSuccess(state, timedOut = false) {
|
|
276
|
+
if (timedOut
|
|
277
|
+
|| (state.status !== 'complete' && TERMINAL_STATUSES.has(state.status))) {
|
|
278
|
+
process.exitCode = 2;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
export async function verifyHostedStartCommand(repositoryArg, options) {
|
|
282
|
+
const repository = parseHostedRepository(repositoryArg);
|
|
283
|
+
const auth = await resolveAuthContext({
|
|
284
|
+
preferredLogin: options.account,
|
|
285
|
+
owner: repository.owner,
|
|
286
|
+
repo: repository.repository,
|
|
287
|
+
});
|
|
288
|
+
if (!options.json) {
|
|
289
|
+
console.error(chalk.dim('Submitting the exact commit pair to the hosted verifier…'));
|
|
290
|
+
}
|
|
291
|
+
const started = await startHostedVerification(repositoryArg, options, auth.token);
|
|
292
|
+
const selectedAccount = auth.token.startsWith('hsk_live_')
|
|
293
|
+
? undefined
|
|
294
|
+
: auth.login;
|
|
295
|
+
let state = started.state;
|
|
296
|
+
let timedOut;
|
|
297
|
+
if (options.wait !== false && !TERMINAL_STATUSES.has(state.status)) {
|
|
298
|
+
const waited = await waitForHostedVerification(state.runId, auth.token, pollingOptions(options.interval, options.timeout, current => {
|
|
299
|
+
if (!options.json) {
|
|
300
|
+
console.error(chalk.dim(`Hosted verifier: ${current.status}…`));
|
|
301
|
+
}
|
|
302
|
+
}));
|
|
303
|
+
state = waited.state;
|
|
304
|
+
timedOut = waited.timedOut;
|
|
305
|
+
}
|
|
306
|
+
else if (options.wait !== false) {
|
|
307
|
+
timedOut = false;
|
|
308
|
+
}
|
|
309
|
+
printHostedState('start', state, {
|
|
310
|
+
json: options.json,
|
|
311
|
+
account: selectedAccount,
|
|
312
|
+
idempotencyKey: started.idempotencyKey,
|
|
313
|
+
timedOut,
|
|
314
|
+
});
|
|
315
|
+
markNonSuccess(state, timedOut);
|
|
316
|
+
}
|
|
317
|
+
export async function verifyHostedStatusCommand(runId, options) {
|
|
318
|
+
const auth = await resolveAuthContext({ preferredLogin: options.account });
|
|
319
|
+
const selectedAccount = auth.token.startsWith('hsk_live_')
|
|
320
|
+
? undefined
|
|
321
|
+
: auth.login;
|
|
322
|
+
let state = await getHostedVerification(runId, auth.token);
|
|
323
|
+
let timedOut;
|
|
324
|
+
if (options.wait && !TERMINAL_STATUSES.has(state.status)) {
|
|
325
|
+
const waited = await waitForHostedVerification(runId, auth.token, pollingOptions(options.interval, options.timeout, current => {
|
|
326
|
+
if (!options.json) {
|
|
327
|
+
console.error(chalk.dim(`Hosted verifier: ${current.status}…`));
|
|
328
|
+
}
|
|
329
|
+
}));
|
|
330
|
+
state = waited.state;
|
|
331
|
+
timedOut = waited.timedOut;
|
|
332
|
+
}
|
|
333
|
+
else if (options.wait) {
|
|
334
|
+
timedOut = false;
|
|
335
|
+
}
|
|
336
|
+
printHostedState('status', state, {
|
|
337
|
+
json: options.json,
|
|
338
|
+
account: selectedAccount,
|
|
339
|
+
timedOut,
|
|
340
|
+
});
|
|
341
|
+
markNonSuccess(state, timedOut);
|
|
342
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type Tool } from '@modelcontextprotocol/sdk/types.js';
|
|
2
|
+
export declare const VERIFY_TOOLS: Tool[];
|
|
3
|
+
export interface VerifyMcpOptions {
|
|
4
|
+
server?: string;
|
|
5
|
+
repoRoot?: string;
|
|
6
|
+
token?: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function runVerifyMcpServer(options: VerifyMcpOptions): Promise<void>;
|