@vellumai/cli 0.8.1 → 0.8.3

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.
@@ -1,153 +0,0 @@
1
- const DOCTOR_URL = process.env.DOCTOR_SERVICE_URL?.trim() || "";
2
-
3
- export type ProgressPhase =
4
- | "invoking_prompt"
5
- | "calling_tool"
6
- | "processing_tool_result";
7
-
8
- export interface ProgressEvent {
9
- phase: ProgressPhase;
10
- toolName?: string;
11
- }
12
-
13
- interface DoctorResult {
14
- assistantId: string;
15
- diagnostics: string | null;
16
- recommendation: string | null;
17
- error: string | null;
18
- }
19
-
20
- export interface ChatLogEntry {
21
- role: "user" | "assistant" | "error";
22
- content: string;
23
- }
24
-
25
- type DoctorProgressCallback = (event: ProgressEvent) => void;
26
- type DoctorLogCallback = (message: string) => void;
27
-
28
- async function streamDoctorResponse(
29
- response: globalThis.Response,
30
- onProgress?: DoctorProgressCallback,
31
- onLog?: DoctorLogCallback,
32
- ): Promise<DoctorResult> {
33
- if (!response.body) {
34
- throw new Error(
35
- `No response body from doctor (HTTP ${response.status} ${response.statusText})`,
36
- );
37
- }
38
-
39
- let result: DoctorResult | null = null;
40
- const decoder = new TextDecoder();
41
- let buffer = "";
42
- let chunkCount = 0;
43
- const receivedEventTypes: string[] = [];
44
-
45
- try {
46
- for await (const chunk of response.body) {
47
- chunkCount++;
48
- buffer += decoder.decode(chunk, { stream: true });
49
- const lines = buffer.split("\n");
50
- buffer = lines.pop() ?? "";
51
-
52
- for (const line of lines) {
53
- if (!line.trim()) continue;
54
- const parsed = JSON.parse(line) as { type: string } & Record<
55
- string,
56
- unknown
57
- >;
58
- receivedEventTypes.push(parsed.type);
59
- if (parsed.type === "progress") {
60
- onProgress?.(parsed as unknown as ProgressEvent);
61
- } else if (parsed.type === "log") {
62
- onLog?.((parsed as unknown as { message: string }).message);
63
- } else if (parsed.type === "result") {
64
- result = parsed as unknown as DoctorResult;
65
- }
66
- }
67
- }
68
- } catch (streamErr) {
69
- const detail =
70
- streamErr instanceof Error ? streamErr.message : String(streamErr);
71
- throw new Error(
72
- `Doctor stream interrupted after ${chunkCount} chunks ` +
73
- `(received events: [${receivedEventTypes.join(", ")}]): ${detail}`,
74
- );
75
- }
76
-
77
- if (buffer.trim()) {
78
- const parsed = JSON.parse(buffer) as { type: string } & Record<
79
- string,
80
- unknown
81
- >;
82
- receivedEventTypes.push(parsed.type);
83
- if (parsed.type === "result") {
84
- result = parsed as unknown as DoctorResult;
85
- }
86
- }
87
-
88
- if (!result) {
89
- throw new Error(
90
- `No result received from doctor. ` +
91
- `HTTP ${response.status}, ${chunkCount} chunks read, ` +
92
- `events received: [${receivedEventTypes.join(", ")}], ` +
93
- `trailing buffer: ${buffer.trim() ? JSON.stringify(buffer.trim().slice(0, 200)) : "(empty)"}`,
94
- );
95
- }
96
-
97
- return result;
98
- }
99
-
100
- async function callDoctorDaemon(
101
- assistantId: string,
102
- project?: string,
103
- zone?: string,
104
- userPrompt?: string,
105
- onProgress?: DoctorProgressCallback,
106
- sessionId?: string,
107
- chatContext?: ChatLogEntry[],
108
- onLog?: DoctorLogCallback,
109
- ): Promise<DoctorResult> {
110
- if (!DOCTOR_URL) {
111
- onLog?.("Doctor service not configured (DOCTOR_SERVICE_URL is not set)");
112
- return {
113
- assistantId,
114
- diagnostics: null,
115
- recommendation: null,
116
- error: "Doctor service not configured",
117
- };
118
- }
119
-
120
- const MAX_RETRIES = 2;
121
- let lastError: unknown;
122
-
123
- for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {
124
- try {
125
- const response = await fetch(`${DOCTOR_URL}/doctor`, {
126
- method: "POST",
127
- headers: { "Content-Type": "application/json" },
128
- body: JSON.stringify({
129
- assistantId,
130
- project,
131
- zone,
132
- userPrompt,
133
- sessionId,
134
- chatContext,
135
- }),
136
- });
137
- return await streamDoctorResponse(response, onProgress, onLog);
138
- } catch (err) {
139
- lastError = err;
140
- const errMsg = err instanceof Error ? err.message : String(err);
141
- const logMsg = `[doctor-client] Attempt ${attempt + 1}/${MAX_RETRIES} failed: ${errMsg}`;
142
- onLog?.(logMsg);
143
- if (attempt < MAX_RETRIES - 1) {
144
- await new Promise((resolve) => setTimeout(resolve, 500));
145
- }
146
- }
147
- }
148
-
149
- throw lastError;
150
- }
151
-
152
- export { callDoctorDaemon };
153
- export type { DoctorProgressCallback, DoctorResult };