MCPcopy
hub / github.com/coder/mux / generateWorkspaceStatus

Function generateWorkspaceStatus

src/node/services/workspaceStatusGenerator.ts:128–219  ·  view source on GitHub ↗
(
  transcript: string,
  candidates: readonly string[],
  aiService: AIService,
  options: BuildWorkspaceStatusPromptOptions = {}
)

Source from the content-addressed store, hash-verified

126 * live provider state rather than guessing from prose.
127 */
128export async function generateWorkspaceStatus(
129 transcript: string,
130 candidates: readonly string[],
131 aiService: AIService,
132 options: BuildWorkspaceStatusPromptOptions = {}
133): Promise<Result<GenerateWorkspaceStatusResult, GenerateWorkspaceStatusFailure>> {
134 if (candidates.length === 0) {
135 return Err({
136 error: {
137 type: "unknown",
138 raw: "No model candidates provided for workspace status generation",
139 },
140 reachedProvider: false,
141 });
142 }
143
144 const maxAttempts = Math.min(candidates.length, 3);
145 let lastError: NameGenerationError | null = null;
146 // Track whether any candidate's createModel call succeeded — i.e., whether
147 // we actually crossed the wire to a provider. If every attempt fails at
148 // construction (no API key, OAuth not connected, provider disabled, etc.),
149 // the failure is about the user's config rather than the transcript and
150 // the caller must keep retrying so a later fix recovers.
151 let reachedProvider = false;
152
153 for (let i = 0; i < maxAttempts; i++) {
154 const modelString = candidates[i];
155
156 const modelResult = await aiService.createModel(modelString, undefined, {
157 agentInitiated: true,
158 });
159 if (!modelResult.success) {
160 lastError = mapModelCreationError(modelResult.error, modelString);
161 log.debug(`Status generation: skipping ${modelString} (${modelResult.error.type})`);
162 continue;
163 }
164 reachedProvider = true;
165
166 try {
167 const currentStream = streamText({
168 model: modelResult.data,
169 prompt: buildWorkspaceStatusPrompt(transcript, options),
170 tools: {
171 propose_status: tool({
172 description: TOOL_DEFINITIONS.propose_status.description,
173 inputSchema: ProposeStatusToolArgsSchema,
174 // eslint-disable-next-line @typescript-eslint/require-await -- AI SDK Tool.execute must return a Promise
175 execute: async (args) => ({ success: true as const, ...args }),
176 }),
177 },
178 });
179
180 const results = await currentStream.toolResults;
181 const toolResult = results.find((r) => r.dynamic !== true && r.toolName === "propose_status");
182
183 if (!toolResult) {
184 lastError = { type: "unknown", raw: "Model did not call propose_status tool" };
185 log.warn("Status generation: model did not call propose_status", { modelString });

Callers 2

runForWorkspaceMethod · 0.90

Calls 9

ErrFunction · 0.90
mapModelCreationErrorFunction · 0.90
OkFunction · 0.90
mapNameGenerationErrorFunction · 0.90
runLanguageModelCleanupFunction · 0.90
debugMethod · 0.80
createModelMethod · 0.65
toolFunction · 0.50

Tested by

no test coverage detected