@inkeep/agents-run-api 0.23.3 → 0.23.5
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/dist/index.cjs +553 -481
- package/dist/index.js +552 -480
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -9149,326 +9149,334 @@ var Agent = class {
|
|
|
9149
9149
|
}
|
|
9150
9150
|
}
|
|
9151
9151
|
async generate(userMessage, runtimeContext) {
|
|
9152
|
-
return tracer.startActiveSpan(
|
|
9153
|
-
|
|
9154
|
-
|
|
9155
|
-
|
|
9156
|
-
|
|
9157
|
-
|
|
9158
|
-
this.streamRequestId = streamRequestId;
|
|
9159
|
-
this.streamHelper = streamRequestId ? getStreamHelper(streamRequestId) : void 0;
|
|
9160
|
-
const conversationId = runtimeContext?.metadata?.conversationId;
|
|
9161
|
-
if (conversationId) {
|
|
9162
|
-
this.setConversationId(conversationId);
|
|
9163
|
-
}
|
|
9164
|
-
const [
|
|
9165
|
-
mcpTools,
|
|
9166
|
-
systemPrompt,
|
|
9167
|
-
thinkingSystemPrompt,
|
|
9168
|
-
functionTools,
|
|
9169
|
-
relationTools,
|
|
9170
|
-
defaultTools
|
|
9171
|
-
] = await tracer.startActiveSpan(
|
|
9172
|
-
"agent.load_tools",
|
|
9173
|
-
{
|
|
9174
|
-
attributes: {
|
|
9175
|
-
"subAgent.name": this.config.name,
|
|
9176
|
-
"session.id": sessionId
|
|
9177
|
-
}
|
|
9178
|
-
},
|
|
9179
|
-
async (childSpan) => {
|
|
9180
|
-
try {
|
|
9181
|
-
const result = await Promise.all([
|
|
9182
|
-
this.getMcpTools(sessionId, streamRequestId),
|
|
9183
|
-
this.buildSystemPrompt(runtimeContext, false),
|
|
9184
|
-
// Normal prompt with data components
|
|
9185
|
-
this.buildSystemPrompt(runtimeContext, true),
|
|
9186
|
-
// Thinking prompt without data components
|
|
9187
|
-
this.getFunctionTools(sessionId, streamRequestId),
|
|
9188
|
-
Promise.resolve(this.getRelationTools(runtimeContext, sessionId)),
|
|
9189
|
-
this.getDefaultTools(streamRequestId)
|
|
9190
|
-
]);
|
|
9191
|
-
childSpan.setStatus({ code: api.SpanStatusCode.OK });
|
|
9192
|
-
return result;
|
|
9193
|
-
} catch (err) {
|
|
9194
|
-
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
9195
|
-
agentsCore.setSpanWithError(childSpan, errorObj);
|
|
9196
|
-
throw err;
|
|
9197
|
-
} finally {
|
|
9198
|
-
childSpan.end();
|
|
9199
|
-
}
|
|
9200
|
-
}
|
|
9201
|
-
);
|
|
9202
|
-
const allTools = {
|
|
9203
|
-
...mcpTools,
|
|
9204
|
-
...functionTools,
|
|
9205
|
-
...relationTools,
|
|
9206
|
-
...defaultTools
|
|
9207
|
-
};
|
|
9208
|
-
const sanitizedTools = this.sanitizeToolsForAISDK(allTools);
|
|
9209
|
-
let conversationHistory = "";
|
|
9210
|
-
const historyConfig = this.config.conversationHistoryConfig ?? createDefaultConversationHistoryConfig();
|
|
9211
|
-
if (historyConfig && historyConfig.mode !== "none") {
|
|
9212
|
-
if (historyConfig.mode === "full") {
|
|
9213
|
-
conversationHistory = await getFormattedConversationHistory({
|
|
9214
|
-
tenantId: this.config.tenantId,
|
|
9215
|
-
projectId: this.config.projectId,
|
|
9216
|
-
conversationId: contextId,
|
|
9217
|
-
currentMessage: userMessage,
|
|
9218
|
-
options: historyConfig,
|
|
9219
|
-
filters: {}
|
|
9220
|
-
});
|
|
9221
|
-
} else if (historyConfig.mode === "scoped") {
|
|
9222
|
-
conversationHistory = await getFormattedConversationHistory({
|
|
9223
|
-
tenantId: this.config.tenantId,
|
|
9224
|
-
projectId: this.config.projectId,
|
|
9225
|
-
conversationId: contextId,
|
|
9226
|
-
currentMessage: userMessage,
|
|
9227
|
-
options: historyConfig,
|
|
9228
|
-
filters: {
|
|
9229
|
-
subAgentId: this.config.id,
|
|
9230
|
-
taskId
|
|
9231
|
-
}
|
|
9232
|
-
});
|
|
9233
|
-
}
|
|
9152
|
+
return tracer.startActiveSpan(
|
|
9153
|
+
"agent.generate",
|
|
9154
|
+
{
|
|
9155
|
+
attributes: {
|
|
9156
|
+
"subagent.id": this.config.id,
|
|
9157
|
+
"subagent.name": this.config.name
|
|
9234
9158
|
}
|
|
9235
|
-
|
|
9236
|
-
|
|
9237
|
-
|
|
9238
|
-
|
|
9239
|
-
const
|
|
9240
|
-
const
|
|
9241
|
-
|
|
9242
|
-
|
|
9243
|
-
|
|
9244
|
-
|
|
9245
|
-
|
|
9159
|
+
},
|
|
9160
|
+
async (span) => {
|
|
9161
|
+
const contextId = runtimeContext?.contextId || "default";
|
|
9162
|
+
const taskId = runtimeContext?.metadata?.taskId || "unknown";
|
|
9163
|
+
const streamRequestId = runtimeContext?.metadata?.streamRequestId;
|
|
9164
|
+
const sessionId = streamRequestId || "fallback-session";
|
|
9165
|
+
try {
|
|
9166
|
+
this.streamRequestId = streamRequestId;
|
|
9167
|
+
this.streamHelper = streamRequestId ? getStreamHelper(streamRequestId) : void 0;
|
|
9168
|
+
const conversationId = runtimeContext?.metadata?.conversationId;
|
|
9169
|
+
if (conversationId) {
|
|
9170
|
+
this.setConversationId(conversationId);
|
|
9171
|
+
}
|
|
9172
|
+
const [
|
|
9173
|
+
mcpTools,
|
|
9174
|
+
systemPrompt,
|
|
9175
|
+
thinkingSystemPrompt,
|
|
9176
|
+
functionTools,
|
|
9177
|
+
relationTools,
|
|
9178
|
+
defaultTools
|
|
9179
|
+
] = await tracer.startActiveSpan(
|
|
9180
|
+
"agent.load_tools",
|
|
9246
9181
|
{
|
|
9247
|
-
|
|
9248
|
-
|
|
9249
|
-
|
|
9250
|
-
},
|
|
9251
|
-
"Requested timeout exceeded maximum allowed, capping to 10 minutes"
|
|
9252
|
-
);
|
|
9253
|
-
}
|
|
9254
|
-
const phase1SystemPrompt = hasStructuredOutput ? thinkingSystemPrompt : systemPrompt;
|
|
9255
|
-
const messages = [];
|
|
9256
|
-
messages.push({ role: "system", content: phase1SystemPrompt });
|
|
9257
|
-
if (conversationHistory.trim() !== "") {
|
|
9258
|
-
messages.push({ role: "user", content: conversationHistory });
|
|
9259
|
-
}
|
|
9260
|
-
messages.push({
|
|
9261
|
-
role: "user",
|
|
9262
|
-
content: userMessage
|
|
9263
|
-
});
|
|
9264
|
-
if (shouldStreamPhase1) {
|
|
9265
|
-
const streamConfig = {
|
|
9266
|
-
...modelSettings,
|
|
9267
|
-
toolChoice: "auto"
|
|
9268
|
-
// Allow natural text + tools
|
|
9269
|
-
};
|
|
9270
|
-
const streamResult = ai.streamText({
|
|
9271
|
-
...streamConfig,
|
|
9272
|
-
messages,
|
|
9273
|
-
tools: sanitizedTools,
|
|
9274
|
-
stopWhen: async ({ steps }) => {
|
|
9275
|
-
const last = steps.at(-1);
|
|
9276
|
-
if (last && "text" in last && last.text) {
|
|
9277
|
-
try {
|
|
9278
|
-
await agentSessionManager.recordEvent(
|
|
9279
|
-
this.getStreamRequestId(),
|
|
9280
|
-
"agent_reasoning",
|
|
9281
|
-
this.config.id,
|
|
9282
|
-
{
|
|
9283
|
-
parts: [{ type: "text", content: last.text }]
|
|
9284
|
-
}
|
|
9285
|
-
);
|
|
9286
|
-
} catch (error) {
|
|
9287
|
-
logger19.debug({ error }, "Failed to track agent reasoning");
|
|
9288
|
-
}
|
|
9289
|
-
}
|
|
9290
|
-
if (steps.length >= 2) {
|
|
9291
|
-
const previousStep = steps[steps.length - 2];
|
|
9292
|
-
if (previousStep && "toolCalls" in previousStep && previousStep.toolCalls) {
|
|
9293
|
-
const hasTransferCall = previousStep.toolCalls.some(
|
|
9294
|
-
(tc) => tc.toolName.startsWith("transfer_to_")
|
|
9295
|
-
);
|
|
9296
|
-
if (hasTransferCall && "toolResults" in previousStep && previousStep.toolResults) {
|
|
9297
|
-
return true;
|
|
9298
|
-
}
|
|
9299
|
-
}
|
|
9182
|
+
attributes: {
|
|
9183
|
+
"subAgent.name": this.config.name,
|
|
9184
|
+
"session.id": sessionId
|
|
9300
9185
|
}
|
|
9301
|
-
return steps.length >= this.getMaxGenerationSteps();
|
|
9302
|
-
},
|
|
9303
|
-
experimental_telemetry: {
|
|
9304
|
-
isEnabled: true,
|
|
9305
|
-
functionId: this.config.id,
|
|
9306
|
-
recordInputs: true,
|
|
9307
|
-
recordOutputs: true
|
|
9308
9186
|
},
|
|
9309
|
-
|
|
9310
|
-
|
|
9311
|
-
|
|
9312
|
-
|
|
9313
|
-
|
|
9314
|
-
|
|
9315
|
-
|
|
9316
|
-
|
|
9317
|
-
|
|
9318
|
-
|
|
9319
|
-
|
|
9320
|
-
|
|
9321
|
-
|
|
9322
|
-
|
|
9323
|
-
|
|
9324
|
-
|
|
9325
|
-
|
|
9326
|
-
|
|
9327
|
-
|
|
9328
|
-
|
|
9187
|
+
async (childSpan) => {
|
|
9188
|
+
try {
|
|
9189
|
+
const result = await Promise.all([
|
|
9190
|
+
this.getMcpTools(sessionId, streamRequestId),
|
|
9191
|
+
this.buildSystemPrompt(runtimeContext, false),
|
|
9192
|
+
// Normal prompt with data components
|
|
9193
|
+
this.buildSystemPrompt(runtimeContext, true),
|
|
9194
|
+
// Thinking prompt without data components
|
|
9195
|
+
this.getFunctionTools(sessionId, streamRequestId),
|
|
9196
|
+
Promise.resolve(this.getRelationTools(runtimeContext, sessionId)),
|
|
9197
|
+
this.getDefaultTools(streamRequestId)
|
|
9198
|
+
]);
|
|
9199
|
+
childSpan.setStatus({ code: api.SpanStatusCode.OK });
|
|
9200
|
+
return result;
|
|
9201
|
+
} catch (err) {
|
|
9202
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
9203
|
+
agentsCore.setSpanWithError(childSpan, errorObj);
|
|
9204
|
+
throw err;
|
|
9205
|
+
} finally {
|
|
9206
|
+
childSpan.end();
|
|
9207
|
+
}
|
|
9208
|
+
}
|
|
9329
9209
|
);
|
|
9330
|
-
|
|
9331
|
-
|
|
9332
|
-
|
|
9333
|
-
|
|
9334
|
-
|
|
9335
|
-
|
|
9336
|
-
|
|
9337
|
-
|
|
9338
|
-
|
|
9339
|
-
|
|
9340
|
-
|
|
9341
|
-
|
|
9342
|
-
|
|
9343
|
-
|
|
9344
|
-
|
|
9345
|
-
|
|
9346
|
-
|
|
9347
|
-
|
|
9348
|
-
|
|
9349
|
-
|
|
9350
|
-
|
|
9351
|
-
|
|
9210
|
+
const allTools = {
|
|
9211
|
+
...mcpTools,
|
|
9212
|
+
...functionTools,
|
|
9213
|
+
...relationTools,
|
|
9214
|
+
...defaultTools
|
|
9215
|
+
};
|
|
9216
|
+
const sanitizedTools = this.sanitizeToolsForAISDK(allTools);
|
|
9217
|
+
let conversationHistory = "";
|
|
9218
|
+
const historyConfig = this.config.conversationHistoryConfig ?? createDefaultConversationHistoryConfig();
|
|
9219
|
+
if (historyConfig && historyConfig.mode !== "none") {
|
|
9220
|
+
if (historyConfig.mode === "full") {
|
|
9221
|
+
conversationHistory = await getFormattedConversationHistory({
|
|
9222
|
+
tenantId: this.config.tenantId,
|
|
9223
|
+
projectId: this.config.projectId,
|
|
9224
|
+
conversationId: contextId,
|
|
9225
|
+
currentMessage: userMessage,
|
|
9226
|
+
options: historyConfig,
|
|
9227
|
+
filters: {}
|
|
9228
|
+
});
|
|
9229
|
+
} else if (historyConfig.mode === "scoped") {
|
|
9230
|
+
conversationHistory = await getFormattedConversationHistory({
|
|
9231
|
+
tenantId: this.config.tenantId,
|
|
9232
|
+
projectId: this.config.projectId,
|
|
9233
|
+
conversationId: contextId,
|
|
9234
|
+
currentMessage: userMessage,
|
|
9235
|
+
options: historyConfig,
|
|
9236
|
+
filters: {
|
|
9237
|
+
subAgentId: this.config.id,
|
|
9238
|
+
taskId
|
|
9352
9239
|
}
|
|
9240
|
+
});
|
|
9353
9241
|
}
|
|
9354
9242
|
}
|
|
9355
|
-
|
|
9356
|
-
|
|
9357
|
-
|
|
9358
|
-
|
|
9359
|
-
|
|
9360
|
-
|
|
9361
|
-
|
|
9362
|
-
|
|
9363
|
-
|
|
9364
|
-
|
|
9365
|
-
|
|
9243
|
+
const primaryModelSettings = this.getPrimaryModel();
|
|
9244
|
+
const modelSettings = ModelFactory.prepareGenerationConfig(primaryModelSettings);
|
|
9245
|
+
let response;
|
|
9246
|
+
let textResponse;
|
|
9247
|
+
const hasStructuredOutput = this.config.dataComponents && this.config.dataComponents.length > 0;
|
|
9248
|
+
const shouldStreamPhase1 = this.getStreamingHelper() && !hasStructuredOutput;
|
|
9249
|
+
const MAX_ALLOWED_TIMEOUT_MS = 6e5;
|
|
9250
|
+
const configuredTimeout = modelSettings.maxDuration ? Math.min(modelSettings.maxDuration * 1e3, MAX_ALLOWED_TIMEOUT_MS) : shouldStreamPhase1 ? CONSTANTS.PHASE_1_TIMEOUT_MS : CONSTANTS.NON_STREAMING_PHASE_1_TIMEOUT_MS;
|
|
9251
|
+
const timeoutMs = Math.min(configuredTimeout, MAX_ALLOWED_TIMEOUT_MS);
|
|
9252
|
+
if (modelSettings.maxDuration && modelSettings.maxDuration * 1e3 > MAX_ALLOWED_TIMEOUT_MS) {
|
|
9253
|
+
logger19.warn(
|
|
9254
|
+
{
|
|
9255
|
+
requestedTimeout: modelSettings.maxDuration * 1e3,
|
|
9256
|
+
appliedTimeout: timeoutMs,
|
|
9257
|
+
maxAllowed: MAX_ALLOWED_TIMEOUT_MS
|
|
9258
|
+
},
|
|
9259
|
+
"Requested timeout exceeded maximum allowed, capping to 10 minutes"
|
|
9260
|
+
);
|
|
9366
9261
|
}
|
|
9367
|
-
const
|
|
9368
|
-
|
|
9369
|
-
|
|
9370
|
-
|
|
9371
|
-
|
|
9372
|
-
...part.kind === "text" && { text: part.text },
|
|
9373
|
-
...part.kind === "data" && { data: part.data }
|
|
9374
|
-
}))
|
|
9375
|
-
};
|
|
9262
|
+
const phase1SystemPrompt = hasStructuredOutput ? thinkingSystemPrompt : systemPrompt;
|
|
9263
|
+
const messages = [];
|
|
9264
|
+
messages.push({ role: "system", content: phase1SystemPrompt });
|
|
9265
|
+
if (conversationHistory.trim() !== "") {
|
|
9266
|
+
messages.push({ role: "user", content: conversationHistory });
|
|
9376
9267
|
}
|
|
9377
|
-
|
|
9378
|
-
|
|
9379
|
-
|
|
9380
|
-
|
|
9381
|
-
|
|
9382
|
-
|
|
9383
|
-
// Force tool usage, prevent text generation
|
|
9384
|
-
};
|
|
9385
|
-
} else {
|
|
9386
|
-
genConfig = {
|
|
9268
|
+
messages.push({
|
|
9269
|
+
role: "user",
|
|
9270
|
+
content: userMessage
|
|
9271
|
+
});
|
|
9272
|
+
if (shouldStreamPhase1) {
|
|
9273
|
+
const streamConfig = {
|
|
9387
9274
|
...modelSettings,
|
|
9388
9275
|
toolChoice: "auto"
|
|
9389
|
-
// Allow
|
|
9276
|
+
// Allow natural text + tools
|
|
9390
9277
|
};
|
|
9391
|
-
|
|
9392
|
-
|
|
9393
|
-
|
|
9394
|
-
|
|
9395
|
-
|
|
9396
|
-
|
|
9397
|
-
|
|
9398
|
-
|
|
9399
|
-
|
|
9400
|
-
|
|
9401
|
-
|
|
9402
|
-
|
|
9403
|
-
|
|
9404
|
-
|
|
9405
|
-
|
|
9406
|
-
|
|
9407
|
-
)
|
|
9408
|
-
|
|
9409
|
-
|
|
9278
|
+
const streamResult = ai.streamText({
|
|
9279
|
+
...streamConfig,
|
|
9280
|
+
messages,
|
|
9281
|
+
tools: sanitizedTools,
|
|
9282
|
+
stopWhen: async ({ steps }) => {
|
|
9283
|
+
const last = steps.at(-1);
|
|
9284
|
+
if (last && "text" in last && last.text) {
|
|
9285
|
+
try {
|
|
9286
|
+
await agentSessionManager.recordEvent(
|
|
9287
|
+
this.getStreamRequestId(),
|
|
9288
|
+
"agent_reasoning",
|
|
9289
|
+
this.config.id,
|
|
9290
|
+
{
|
|
9291
|
+
parts: [{ type: "text", content: last.text }]
|
|
9292
|
+
}
|
|
9293
|
+
);
|
|
9294
|
+
} catch (error) {
|
|
9295
|
+
logger19.debug({ error }, "Failed to track agent reasoning");
|
|
9296
|
+
}
|
|
9410
9297
|
}
|
|
9411
|
-
|
|
9412
|
-
|
|
9413
|
-
|
|
9414
|
-
|
|
9415
|
-
|
|
9416
|
-
|
|
9417
|
-
|
|
9418
|
-
|
|
9419
|
-
|
|
9298
|
+
if (steps.length >= 2) {
|
|
9299
|
+
const previousStep = steps[steps.length - 2];
|
|
9300
|
+
if (previousStep && "toolCalls" in previousStep && previousStep.toolCalls) {
|
|
9301
|
+
const hasTransferCall = previousStep.toolCalls.some(
|
|
9302
|
+
(tc) => tc.toolName.startsWith("transfer_to_")
|
|
9303
|
+
);
|
|
9304
|
+
if (hasTransferCall && "toolResults" in previousStep && previousStep.toolResults) {
|
|
9305
|
+
return true;
|
|
9306
|
+
}
|
|
9420
9307
|
}
|
|
9421
9308
|
}
|
|
9309
|
+
return steps.length >= this.getMaxGenerationSteps();
|
|
9310
|
+
},
|
|
9311
|
+
experimental_telemetry: {
|
|
9312
|
+
isEnabled: true,
|
|
9313
|
+
functionId: this.config.id,
|
|
9314
|
+
recordInputs: true,
|
|
9315
|
+
recordOutputs: true
|
|
9316
|
+
},
|
|
9317
|
+
abortSignal: AbortSignal.timeout(timeoutMs)
|
|
9318
|
+
});
|
|
9319
|
+
const streamHelper = this.getStreamingHelper();
|
|
9320
|
+
if (!streamHelper) {
|
|
9321
|
+
throw new Error("Stream helper is unexpectedly undefined in streaming context");
|
|
9322
|
+
}
|
|
9323
|
+
const session = toolSessionManager.getSession(sessionId);
|
|
9324
|
+
const artifactParserOptions = {
|
|
9325
|
+
sessionId,
|
|
9326
|
+
taskId: session?.taskId,
|
|
9327
|
+
projectId: session?.projectId,
|
|
9328
|
+
artifactComponents: this.artifactComponents,
|
|
9329
|
+
streamRequestId: this.getStreamRequestId(),
|
|
9330
|
+
subAgentId: this.config.id
|
|
9331
|
+
};
|
|
9332
|
+
const parser = new IncrementalStreamParser(
|
|
9333
|
+
streamHelper,
|
|
9334
|
+
this.config.tenantId,
|
|
9335
|
+
contextId,
|
|
9336
|
+
artifactParserOptions
|
|
9337
|
+
);
|
|
9338
|
+
for await (const event of streamResult.fullStream) {
|
|
9339
|
+
switch (event.type) {
|
|
9340
|
+
case "text-delta":
|
|
9341
|
+
await parser.processTextChunk(event.text);
|
|
9342
|
+
break;
|
|
9343
|
+
case "tool-call":
|
|
9344
|
+
parser.markToolResult();
|
|
9345
|
+
break;
|
|
9346
|
+
case "tool-result":
|
|
9347
|
+
parser.markToolResult();
|
|
9348
|
+
break;
|
|
9349
|
+
case "finish":
|
|
9350
|
+
if (event.finishReason === "tool-calls") {
|
|
9351
|
+
parser.markToolResult();
|
|
9352
|
+
}
|
|
9353
|
+
break;
|
|
9354
|
+
case "error":
|
|
9355
|
+
if (event.error instanceof Error) {
|
|
9356
|
+
throw event.error;
|
|
9357
|
+
} else {
|
|
9358
|
+
const errorMessage = event.error?.error?.message;
|
|
9359
|
+
throw new Error(errorMessage);
|
|
9360
|
+
}
|
|
9422
9361
|
}
|
|
9423
|
-
|
|
9424
|
-
|
|
9425
|
-
|
|
9426
|
-
|
|
9427
|
-
|
|
9428
|
-
|
|
9429
|
-
|
|
9430
|
-
|
|
9431
|
-
|
|
9432
|
-
|
|
9433
|
-
|
|
9434
|
-
|
|
9435
|
-
|
|
9436
|
-
|
|
9437
|
-
|
|
9438
|
-
|
|
9439
|
-
|
|
9440
|
-
|
|
9441
|
-
|
|
9442
|
-
|
|
9443
|
-
|
|
9444
|
-
|
|
9445
|
-
|
|
9446
|
-
|
|
9447
|
-
|
|
9448
|
-
|
|
9449
|
-
|
|
9450
|
-
|
|
9451
|
-
|
|
9452
|
-
|
|
9453
|
-
|
|
9454
|
-
|
|
9455
|
-
|
|
9456
|
-
|
|
9457
|
-
|
|
9362
|
+
}
|
|
9363
|
+
await parser.finalize();
|
|
9364
|
+
response = await streamResult;
|
|
9365
|
+
const collectedParts = parser.getCollectedParts();
|
|
9366
|
+
if (collectedParts.length > 0) {
|
|
9367
|
+
response.formattedContent = {
|
|
9368
|
+
parts: collectedParts.map((part) => ({
|
|
9369
|
+
kind: part.kind,
|
|
9370
|
+
...part.kind === "text" && { text: part.text },
|
|
9371
|
+
...part.kind === "data" && { data: part.data }
|
|
9372
|
+
}))
|
|
9373
|
+
};
|
|
9374
|
+
}
|
|
9375
|
+
const streamedContent = parser.getAllStreamedContent();
|
|
9376
|
+
if (streamedContent.length > 0) {
|
|
9377
|
+
response.streamedContent = {
|
|
9378
|
+
parts: streamedContent.map((part) => ({
|
|
9379
|
+
kind: part.kind,
|
|
9380
|
+
...part.kind === "text" && { text: part.text },
|
|
9381
|
+
...part.kind === "data" && { data: part.data }
|
|
9382
|
+
}))
|
|
9383
|
+
};
|
|
9384
|
+
}
|
|
9385
|
+
} else {
|
|
9386
|
+
let genConfig;
|
|
9387
|
+
if (hasStructuredOutput) {
|
|
9388
|
+
genConfig = {
|
|
9389
|
+
...modelSettings,
|
|
9390
|
+
toolChoice: "required"
|
|
9391
|
+
// Force tool usage, prevent text generation
|
|
9392
|
+
};
|
|
9393
|
+
} else {
|
|
9394
|
+
genConfig = {
|
|
9395
|
+
...modelSettings,
|
|
9396
|
+
toolChoice: "auto"
|
|
9397
|
+
// Allow both tools and text generation
|
|
9398
|
+
};
|
|
9399
|
+
}
|
|
9400
|
+
response = await ai.generateText({
|
|
9401
|
+
...genConfig,
|
|
9402
|
+
messages,
|
|
9403
|
+
tools: sanitizedTools,
|
|
9404
|
+
stopWhen: async ({ steps }) => {
|
|
9405
|
+
const last = steps.at(-1);
|
|
9406
|
+
if (last && "text" in last && last.text) {
|
|
9407
|
+
try {
|
|
9408
|
+
await agentSessionManager.recordEvent(
|
|
9409
|
+
this.getStreamRequestId(),
|
|
9410
|
+
"agent_reasoning",
|
|
9411
|
+
this.config.id,
|
|
9412
|
+
{
|
|
9413
|
+
parts: [{ type: "text", content: last.text }]
|
|
9458
9414
|
}
|
|
9459
|
-
|
|
9460
|
-
|
|
9461
|
-
|
|
9462
|
-
|
|
9463
|
-
|
|
9464
|
-
|
|
9465
|
-
|
|
9466
|
-
|
|
9467
|
-
|
|
9468
|
-
|
|
9469
|
-
|
|
9470
|
-
|
|
9471
|
-
|
|
9415
|
+
);
|
|
9416
|
+
} catch (error) {
|
|
9417
|
+
logger19.debug({ error }, "Failed to track agent reasoning");
|
|
9418
|
+
}
|
|
9419
|
+
}
|
|
9420
|
+
if (steps.length >= 2) {
|
|
9421
|
+
const previousStep = steps[steps.length - 2];
|
|
9422
|
+
if (previousStep && "toolCalls" in previousStep && previousStep.toolCalls) {
|
|
9423
|
+
const hasStopTool = previousStep.toolCalls.some(
|
|
9424
|
+
(tc) => tc.toolName.startsWith("transfer_to_") || tc.toolName === "thinking_complete"
|
|
9425
|
+
);
|
|
9426
|
+
if (hasStopTool && "toolResults" in previousStep && previousStep.toolResults) {
|
|
9427
|
+
return true;
|
|
9428
|
+
}
|
|
9429
|
+
}
|
|
9430
|
+
}
|
|
9431
|
+
return steps.length >= this.getMaxGenerationSteps();
|
|
9432
|
+
},
|
|
9433
|
+
experimental_telemetry: {
|
|
9434
|
+
isEnabled: true,
|
|
9435
|
+
functionId: this.config.id,
|
|
9436
|
+
recordInputs: true,
|
|
9437
|
+
recordOutputs: true,
|
|
9438
|
+
metadata: {
|
|
9439
|
+
phase: "planning"
|
|
9440
|
+
}
|
|
9441
|
+
},
|
|
9442
|
+
abortSignal: AbortSignal.timeout(timeoutMs)
|
|
9443
|
+
});
|
|
9444
|
+
}
|
|
9445
|
+
if (response.steps) {
|
|
9446
|
+
const resolvedSteps = await response.steps;
|
|
9447
|
+
response = { ...response, steps: resolvedSteps };
|
|
9448
|
+
}
|
|
9449
|
+
if (hasStructuredOutput && !hasToolCallWithPrefix("transfer_to_")(response)) {
|
|
9450
|
+
const thinkingCompleteCall = response.steps?.flatMap((s) => s.toolCalls || [])?.find((tc) => tc.toolName === "thinking_complete");
|
|
9451
|
+
if (thinkingCompleteCall) {
|
|
9452
|
+
const reasoningFlow = [];
|
|
9453
|
+
if (response.steps) {
|
|
9454
|
+
response.steps.forEach((step) => {
|
|
9455
|
+
if (step.toolCalls && step.toolResults) {
|
|
9456
|
+
step.toolCalls.forEach((call, index) => {
|
|
9457
|
+
const result = step.toolResults[index];
|
|
9458
|
+
if (result) {
|
|
9459
|
+
const storedResult = toolSessionManager.getToolResult(
|
|
9460
|
+
sessionId,
|
|
9461
|
+
result.toolCallId
|
|
9462
|
+
);
|
|
9463
|
+
const toolName = storedResult?.toolName || call.toolName;
|
|
9464
|
+
if (toolName === "thinking_complete") {
|
|
9465
|
+
return;
|
|
9466
|
+
}
|
|
9467
|
+
const actualResult = storedResult?.result || result.result || result;
|
|
9468
|
+
const actualArgs = storedResult?.args || call.args;
|
|
9469
|
+
const cleanResult = actualResult && typeof actualResult === "object" && !Array.isArray(actualResult) ? Object.fromEntries(
|
|
9470
|
+
Object.entries(actualResult).filter(
|
|
9471
|
+
([key]) => key !== "_structureHints"
|
|
9472
|
+
)
|
|
9473
|
+
) : actualResult;
|
|
9474
|
+
const input = actualArgs ? JSON.stringify(actualArgs, null, 2) : "No input";
|
|
9475
|
+
const output = typeof cleanResult === "string" ? cleanResult : JSON.stringify(cleanResult, null, 2);
|
|
9476
|
+
let structureHintsFormatted = "";
|
|
9477
|
+
if (actualResult?._structureHints && this.artifactComponents && this.artifactComponents.length > 0) {
|
|
9478
|
+
const hints = actualResult._structureHints;
|
|
9479
|
+
structureHintsFormatted = `
|
|
9472
9480
|
### \u{1F4CA} Structure Hints for Artifact Creation
|
|
9473
9481
|
|
|
9474
9482
|
**Terminal Field Paths (${hints.terminalPaths?.length || 0} found):**
|
|
@@ -9492,8 +9500,8 @@ ${hints.commonFields?.map((field) => ` \u2022 ${field}`).join("\n") || " None
|
|
|
9492
9500
|
|
|
9493
9501
|
**Forbidden Syntax:** ${hints.forbiddenSyntax || "Use these paths for artifact base selectors."}
|
|
9494
9502
|
`;
|
|
9495
|
-
|
|
9496
|
-
|
|
9503
|
+
}
|
|
9504
|
+
const formattedResult = `## Tool: ${call.toolName}
|
|
9497
9505
|
|
|
9498
9506
|
### \u{1F527} TOOL_CALL_ID: ${result.toolCallId}
|
|
9499
9507
|
|
|
@@ -9502,130 +9510,61 @@ ${input}
|
|
|
9502
9510
|
|
|
9503
9511
|
### Output
|
|
9504
9512
|
${output}${structureHintsFormatted}`;
|
|
9505
|
-
|
|
9506
|
-
|
|
9507
|
-
|
|
9508
|
-
|
|
9509
|
-
|
|
9510
|
-
|
|
9511
|
-
}
|
|
9512
|
-
});
|
|
9513
|
-
}
|
|
9514
|
-
const componentSchemas = [];
|
|
9515
|
-
if (this.config.dataComponents && this.config.dataComponents.length > 0) {
|
|
9516
|
-
this.config.dataComponents.forEach((dc) => {
|
|
9517
|
-
const propsSchema = jsonSchemaToZod(dc.props);
|
|
9518
|
-
componentSchemas.push(
|
|
9519
|
-
z6.z.object({
|
|
9520
|
-
id: z6.z.string(),
|
|
9521
|
-
name: z6.z.literal(dc.name),
|
|
9522
|
-
props: propsSchema
|
|
9523
|
-
})
|
|
9524
|
-
);
|
|
9525
|
-
});
|
|
9526
|
-
}
|
|
9527
|
-
if (this.artifactComponents.length > 0) {
|
|
9528
|
-
const artifactCreateSchemas = ArtifactCreateSchema.getSchemas(
|
|
9529
|
-
this.artifactComponents
|
|
9530
|
-
);
|
|
9531
|
-
componentSchemas.push(...artifactCreateSchemas);
|
|
9532
|
-
componentSchemas.push(ArtifactReferenceSchema.getSchema());
|
|
9533
|
-
}
|
|
9534
|
-
let dataComponentsSchema;
|
|
9535
|
-
if (componentSchemas.length === 1) {
|
|
9536
|
-
dataComponentsSchema = componentSchemas[0];
|
|
9537
|
-
} else {
|
|
9538
|
-
dataComponentsSchema = z6.z.union(
|
|
9539
|
-
componentSchemas
|
|
9540
|
-
);
|
|
9541
|
-
}
|
|
9542
|
-
const structuredModelSettings = ModelFactory.prepareGenerationConfig(
|
|
9543
|
-
this.getStructuredOutputModel()
|
|
9544
|
-
);
|
|
9545
|
-
const phase2TimeoutMs = structuredModelSettings.maxDuration ? structuredModelSettings.maxDuration * 1e3 : CONSTANTS.PHASE_2_TIMEOUT_MS;
|
|
9546
|
-
const shouldStreamPhase2 = this.getStreamingHelper();
|
|
9547
|
-
if (shouldStreamPhase2) {
|
|
9548
|
-
const phase2Messages = [
|
|
9549
|
-
{
|
|
9550
|
-
role: "system",
|
|
9551
|
-
content: await this.buildPhase2SystemPrompt(runtimeContext)
|
|
9552
|
-
}
|
|
9553
|
-
];
|
|
9554
|
-
if (conversationHistory.trim() !== "") {
|
|
9555
|
-
phase2Messages.push({ role: "user", content: conversationHistory });
|
|
9556
|
-
}
|
|
9557
|
-
phase2Messages.push({ role: "user", content: userMessage });
|
|
9558
|
-
phase2Messages.push(...reasoningFlow);
|
|
9559
|
-
const streamResult = ai.streamObject({
|
|
9560
|
-
...structuredModelSettings,
|
|
9561
|
-
messages: phase2Messages,
|
|
9562
|
-
schema: z6.z.object({
|
|
9563
|
-
dataComponents: z6.z.array(dataComponentsSchema)
|
|
9564
|
-
}),
|
|
9565
|
-
experimental_telemetry: {
|
|
9566
|
-
isEnabled: true,
|
|
9567
|
-
functionId: this.config.id,
|
|
9568
|
-
recordInputs: true,
|
|
9569
|
-
recordOutputs: true,
|
|
9570
|
-
metadata: {
|
|
9571
|
-
phase: "structured_generation"
|
|
9513
|
+
reasoningFlow.push({
|
|
9514
|
+
role: "assistant",
|
|
9515
|
+
content: formattedResult
|
|
9516
|
+
});
|
|
9517
|
+
}
|
|
9518
|
+
});
|
|
9572
9519
|
}
|
|
9573
|
-
}
|
|
9574
|
-
abortSignal: AbortSignal.timeout(phase2TimeoutMs)
|
|
9575
|
-
});
|
|
9576
|
-
const streamHelper = this.getStreamingHelper();
|
|
9577
|
-
if (!streamHelper) {
|
|
9578
|
-
throw new Error("Stream helper is unexpectedly undefined in streaming context");
|
|
9520
|
+
});
|
|
9579
9521
|
}
|
|
9580
|
-
const
|
|
9581
|
-
|
|
9582
|
-
|
|
9583
|
-
|
|
9584
|
-
|
|
9585
|
-
|
|
9586
|
-
|
|
9587
|
-
|
|
9588
|
-
|
|
9589
|
-
|
|
9590
|
-
|
|
9591
|
-
|
|
9592
|
-
contextId,
|
|
9593
|
-
artifactParserOptions
|
|
9594
|
-
);
|
|
9595
|
-
for await (const delta of streamResult.partialObjectStream) {
|
|
9596
|
-
if (delta) {
|
|
9597
|
-
await parser.processObjectDelta(delta);
|
|
9598
|
-
}
|
|
9522
|
+
const componentSchemas = [];
|
|
9523
|
+
if (this.config.dataComponents && this.config.dataComponents.length > 0) {
|
|
9524
|
+
this.config.dataComponents.forEach((dc) => {
|
|
9525
|
+
const propsSchema = jsonSchemaToZod(dc.props);
|
|
9526
|
+
componentSchemas.push(
|
|
9527
|
+
z6.z.object({
|
|
9528
|
+
id: z6.z.string(),
|
|
9529
|
+
name: z6.z.literal(dc.name),
|
|
9530
|
+
props: propsSchema
|
|
9531
|
+
})
|
|
9532
|
+
);
|
|
9533
|
+
});
|
|
9599
9534
|
}
|
|
9600
|
-
|
|
9601
|
-
|
|
9602
|
-
|
|
9603
|
-
|
|
9604
|
-
|
|
9605
|
-
|
|
9606
|
-
kind: part.kind,
|
|
9607
|
-
...part.kind === "text" && { text: part.text },
|
|
9608
|
-
...part.kind === "data" && { data: part.data }
|
|
9609
|
-
}))
|
|
9610
|
-
};
|
|
9535
|
+
if (this.artifactComponents.length > 0) {
|
|
9536
|
+
const artifactCreateSchemas = ArtifactCreateSchema.getSchemas(
|
|
9537
|
+
this.artifactComponents
|
|
9538
|
+
);
|
|
9539
|
+
componentSchemas.push(...artifactCreateSchemas);
|
|
9540
|
+
componentSchemas.push(ArtifactReferenceSchema.getSchema());
|
|
9611
9541
|
}
|
|
9612
|
-
|
|
9613
|
-
|
|
9614
|
-
|
|
9615
|
-
}
|
|
9616
|
-
|
|
9617
|
-
|
|
9618
|
-
|
|
9619
|
-
const phase2Messages = [
|
|
9620
|
-
{ role: "system", content: await this.buildPhase2SystemPrompt(runtimeContext) }
|
|
9621
|
-
];
|
|
9622
|
-
if (conversationHistory.trim() !== "") {
|
|
9623
|
-
phase2Messages.push({ role: "user", content: conversationHistory });
|
|
9542
|
+
let dataComponentsSchema;
|
|
9543
|
+
if (componentSchemas.length === 1) {
|
|
9544
|
+
dataComponentsSchema = componentSchemas[0];
|
|
9545
|
+
} else {
|
|
9546
|
+
dataComponentsSchema = z6.z.union(
|
|
9547
|
+
componentSchemas
|
|
9548
|
+
);
|
|
9624
9549
|
}
|
|
9625
|
-
|
|
9626
|
-
|
|
9627
|
-
|
|
9628
|
-
|
|
9550
|
+
const structuredModelSettings = ModelFactory.prepareGenerationConfig(
|
|
9551
|
+
this.getStructuredOutputModel()
|
|
9552
|
+
);
|
|
9553
|
+
const phase2TimeoutMs = structuredModelSettings.maxDuration ? structuredModelSettings.maxDuration * 1e3 : CONSTANTS.PHASE_2_TIMEOUT_MS;
|
|
9554
|
+
const shouldStreamPhase2 = this.getStreamingHelper();
|
|
9555
|
+
if (shouldStreamPhase2) {
|
|
9556
|
+
const phase2Messages = [
|
|
9557
|
+
{
|
|
9558
|
+
role: "system",
|
|
9559
|
+
content: await this.buildPhase2SystemPrompt(runtimeContext)
|
|
9560
|
+
}
|
|
9561
|
+
];
|
|
9562
|
+
if (conversationHistory.trim() !== "") {
|
|
9563
|
+
phase2Messages.push({ role: "user", content: conversationHistory });
|
|
9564
|
+
}
|
|
9565
|
+
phase2Messages.push({ role: "user", content: userMessage });
|
|
9566
|
+
phase2Messages.push(...reasoningFlow);
|
|
9567
|
+
const streamResult = ai.streamObject({
|
|
9629
9568
|
...structuredModelSettings,
|
|
9630
9569
|
messages: phase2Messages,
|
|
9631
9570
|
schema: z6.z.object({
|
|
@@ -9641,65 +9580,135 @@ ${output}${structureHintsFormatted}`;
|
|
|
9641
9580
|
}
|
|
9642
9581
|
},
|
|
9643
9582
|
abortSignal: AbortSignal.timeout(phase2TimeoutMs)
|
|
9644
|
-
})
|
|
9645
|
-
|
|
9646
|
-
|
|
9647
|
-
|
|
9648
|
-
|
|
9649
|
-
|
|
9650
|
-
|
|
9583
|
+
});
|
|
9584
|
+
const streamHelper = this.getStreamingHelper();
|
|
9585
|
+
if (!streamHelper) {
|
|
9586
|
+
throw new Error("Stream helper is unexpectedly undefined in streaming context");
|
|
9587
|
+
}
|
|
9588
|
+
const session = toolSessionManager.getSession(sessionId);
|
|
9589
|
+
const artifactParserOptions = {
|
|
9590
|
+
sessionId,
|
|
9591
|
+
taskId: session?.taskId,
|
|
9592
|
+
projectId: session?.projectId,
|
|
9593
|
+
artifactComponents: this.artifactComponents,
|
|
9594
|
+
streamRequestId: this.getStreamRequestId(),
|
|
9595
|
+
subAgentId: this.config.id
|
|
9596
|
+
};
|
|
9597
|
+
const parser = new IncrementalStreamParser(
|
|
9598
|
+
streamHelper,
|
|
9599
|
+
this.config.tenantId,
|
|
9600
|
+
contextId,
|
|
9601
|
+
artifactParserOptions
|
|
9602
|
+
);
|
|
9603
|
+
for await (const delta of streamResult.partialObjectStream) {
|
|
9604
|
+
if (delta) {
|
|
9605
|
+
await parser.processObjectDelta(delta);
|
|
9606
|
+
}
|
|
9607
|
+
}
|
|
9608
|
+
await parser.finalize();
|
|
9609
|
+
const structuredResponse = await streamResult;
|
|
9610
|
+
const collectedParts = parser.getCollectedParts();
|
|
9611
|
+
if (collectedParts.length > 0) {
|
|
9612
|
+
response.formattedContent = {
|
|
9613
|
+
parts: collectedParts.map((part) => ({
|
|
9614
|
+
kind: part.kind,
|
|
9615
|
+
...part.kind === "text" && { text: part.text },
|
|
9616
|
+
...part.kind === "data" && { data: part.data }
|
|
9617
|
+
}))
|
|
9618
|
+
};
|
|
9619
|
+
}
|
|
9620
|
+
response = {
|
|
9621
|
+
...response,
|
|
9622
|
+
object: structuredResponse.object
|
|
9623
|
+
};
|
|
9624
|
+
textResponse = JSON.stringify(structuredResponse.object, null, 2);
|
|
9625
|
+
} else {
|
|
9626
|
+
const { withJsonPostProcessing: withJsonPostProcessing2 } = await Promise.resolve().then(() => (init_json_postprocessor(), json_postprocessor_exports));
|
|
9627
|
+
const phase2Messages = [
|
|
9628
|
+
{ role: "system", content: await this.buildPhase2SystemPrompt(runtimeContext) }
|
|
9629
|
+
];
|
|
9630
|
+
if (conversationHistory.trim() !== "") {
|
|
9631
|
+
phase2Messages.push({ role: "user", content: conversationHistory });
|
|
9632
|
+
}
|
|
9633
|
+
phase2Messages.push({ role: "user", content: userMessage });
|
|
9634
|
+
phase2Messages.push(...reasoningFlow);
|
|
9635
|
+
const structuredResponse = await ai.generateObject(
|
|
9636
|
+
withJsonPostProcessing2({
|
|
9637
|
+
...structuredModelSettings,
|
|
9638
|
+
messages: phase2Messages,
|
|
9639
|
+
schema: z6.z.object({
|
|
9640
|
+
dataComponents: z6.z.array(dataComponentsSchema)
|
|
9641
|
+
}),
|
|
9642
|
+
experimental_telemetry: {
|
|
9643
|
+
isEnabled: true,
|
|
9644
|
+
functionId: this.config.id,
|
|
9645
|
+
recordInputs: true,
|
|
9646
|
+
recordOutputs: true,
|
|
9647
|
+
metadata: {
|
|
9648
|
+
phase: "structured_generation"
|
|
9649
|
+
}
|
|
9650
|
+
},
|
|
9651
|
+
abortSignal: AbortSignal.timeout(phase2TimeoutMs)
|
|
9652
|
+
})
|
|
9653
|
+
);
|
|
9654
|
+
response = {
|
|
9655
|
+
...response,
|
|
9656
|
+
object: structuredResponse.object
|
|
9657
|
+
};
|
|
9658
|
+
textResponse = JSON.stringify(structuredResponse.object, null, 2);
|
|
9659
|
+
}
|
|
9660
|
+
} else {
|
|
9661
|
+
textResponse = response.text || "";
|
|
9651
9662
|
}
|
|
9652
9663
|
} else {
|
|
9653
|
-
textResponse = response.text || "";
|
|
9664
|
+
textResponse = response.steps[response.steps.length - 1].text || "";
|
|
9654
9665
|
}
|
|
9655
|
-
|
|
9656
|
-
|
|
9657
|
-
|
|
9658
|
-
|
|
9659
|
-
|
|
9660
|
-
|
|
9661
|
-
|
|
9662
|
-
|
|
9663
|
-
|
|
9664
|
-
|
|
9665
|
-
|
|
9666
|
-
|
|
9667
|
-
|
|
9668
|
-
|
|
9669
|
-
|
|
9670
|
-
|
|
9671
|
-
|
|
9672
|
-
|
|
9673
|
-
|
|
9674
|
-
|
|
9675
|
-
contextId
|
|
9676
|
-
|
|
9677
|
-
} else if (textResponse) {
|
|
9678
|
-
formattedContent = await responseFormatter.formatResponse(textResponse, contextId);
|
|
9666
|
+
span.setStatus({ code: api.SpanStatusCode.OK });
|
|
9667
|
+
span.end();
|
|
9668
|
+
let formattedContent = response.formattedContent || null;
|
|
9669
|
+
if (!formattedContent) {
|
|
9670
|
+
const session = toolSessionManager.getSession(sessionId);
|
|
9671
|
+
const responseFormatter = new ResponseFormatter(this.config.tenantId, {
|
|
9672
|
+
sessionId,
|
|
9673
|
+
taskId: session?.taskId,
|
|
9674
|
+
projectId: session?.projectId,
|
|
9675
|
+
contextId,
|
|
9676
|
+
artifactComponents: this.artifactComponents,
|
|
9677
|
+
streamRequestId: this.getStreamRequestId(),
|
|
9678
|
+
subAgentId: this.config.id
|
|
9679
|
+
});
|
|
9680
|
+
if (response.object) {
|
|
9681
|
+
formattedContent = await responseFormatter.formatObjectResponse(
|
|
9682
|
+
response.object,
|
|
9683
|
+
contextId
|
|
9684
|
+
);
|
|
9685
|
+
} else if (textResponse) {
|
|
9686
|
+
formattedContent = await responseFormatter.formatResponse(textResponse, contextId);
|
|
9687
|
+
}
|
|
9679
9688
|
}
|
|
9689
|
+
const formattedResponse = {
|
|
9690
|
+
...response,
|
|
9691
|
+
formattedContent
|
|
9692
|
+
};
|
|
9693
|
+
if (streamRequestId) {
|
|
9694
|
+
const generationType = response.object ? "object_generation" : "text_generation";
|
|
9695
|
+
agentSessionManager.recordEvent(streamRequestId, "agent_generate", this.config.id, {
|
|
9696
|
+
parts: (formattedContent?.parts || []).map((part) => ({
|
|
9697
|
+
type: part.kind === "text" ? "text" : part.kind === "data" ? "tool_result" : "text",
|
|
9698
|
+
content: part.text || JSON.stringify(part.data)
|
|
9699
|
+
})),
|
|
9700
|
+
generationType
|
|
9701
|
+
});
|
|
9702
|
+
}
|
|
9703
|
+
return formattedResponse;
|
|
9704
|
+
} catch (error) {
|
|
9705
|
+
const errorToThrow = error instanceof Error ? error : new Error(String(error));
|
|
9706
|
+
agentsCore.setSpanWithError(span, errorToThrow);
|
|
9707
|
+
span.end();
|
|
9708
|
+
throw errorToThrow;
|
|
9680
9709
|
}
|
|
9681
|
-
const formattedResponse = {
|
|
9682
|
-
...response,
|
|
9683
|
-
formattedContent
|
|
9684
|
-
};
|
|
9685
|
-
if (streamRequestId) {
|
|
9686
|
-
const generationType = response.object ? "object_generation" : "text_generation";
|
|
9687
|
-
agentSessionManager.recordEvent(streamRequestId, "agent_generate", this.config.id, {
|
|
9688
|
-
parts: (formattedContent?.parts || []).map((part) => ({
|
|
9689
|
-
type: part.kind === "text" ? "text" : part.kind === "data" ? "tool_result" : "text",
|
|
9690
|
-
content: part.text || JSON.stringify(part.data)
|
|
9691
|
-
})),
|
|
9692
|
-
generationType
|
|
9693
|
-
});
|
|
9694
|
-
}
|
|
9695
|
-
return formattedResponse;
|
|
9696
|
-
} catch (error) {
|
|
9697
|
-
const errorToThrow = error instanceof Error ? error : new Error(String(error));
|
|
9698
|
-
agentsCore.setSpanWithError(span, errorToThrow);
|
|
9699
|
-
span.end();
|
|
9700
|
-
throw errorToThrow;
|
|
9701
9710
|
}
|
|
9702
|
-
|
|
9711
|
+
);
|
|
9703
9712
|
}
|
|
9704
9713
|
};
|
|
9705
9714
|
|
|
@@ -12069,7 +12078,17 @@ var generatePreviewRoute = zodOpenapi.createRoute({
|
|
|
12069
12078
|
tenantId: z6.z.string(),
|
|
12070
12079
|
projectId: z6.z.string(),
|
|
12071
12080
|
id: z6.z.string()
|
|
12072
|
-
})
|
|
12081
|
+
}),
|
|
12082
|
+
body: {
|
|
12083
|
+
content: {
|
|
12084
|
+
"application/json": {
|
|
12085
|
+
schema: z6.z.object({
|
|
12086
|
+
instructions: z6.z.string().optional().describe("Custom instructions for modifying the component"),
|
|
12087
|
+
existingCode: z6.z.string().optional().describe("Existing component code to modify")
|
|
12088
|
+
})
|
|
12089
|
+
}
|
|
12090
|
+
}
|
|
12091
|
+
}
|
|
12073
12092
|
},
|
|
12074
12093
|
responses: {
|
|
12075
12094
|
200: {
|
|
@@ -12090,7 +12109,18 @@ var generatePreviewRoute = zodOpenapi.createRoute({
|
|
|
12090
12109
|
});
|
|
12091
12110
|
app4.openapi(generatePreviewRoute, async (c) => {
|
|
12092
12111
|
const { tenantId, projectId, id } = c.req.valid("param");
|
|
12093
|
-
|
|
12112
|
+
const body = c.req.valid("json");
|
|
12113
|
+
const { instructions, existingCode } = body;
|
|
12114
|
+
logger26.info(
|
|
12115
|
+
{
|
|
12116
|
+
tenantId,
|
|
12117
|
+
projectId,
|
|
12118
|
+
dataComponentId: id,
|
|
12119
|
+
hasInstructions: !!instructions,
|
|
12120
|
+
hasExistingCode: !!existingCode
|
|
12121
|
+
},
|
|
12122
|
+
"Generating component preview"
|
|
12123
|
+
);
|
|
12094
12124
|
const dataComponent = await agentsCore.getDataComponent(dbClient_default)({
|
|
12095
12125
|
scopes: { tenantId, projectId },
|
|
12096
12126
|
dataComponentId: id
|
|
@@ -12110,7 +12140,7 @@ app4.openapi(generatePreviewRoute, async (c) => {
|
|
|
12110
12140
|
message: "Project base model configuration is required"
|
|
12111
12141
|
});
|
|
12112
12142
|
}
|
|
12113
|
-
const prompt = buildGenerationPrompt(dataComponent);
|
|
12143
|
+
const prompt = buildGenerationPrompt(dataComponent, instructions, existingCode);
|
|
12114
12144
|
try {
|
|
12115
12145
|
const modelConfig = ModelFactory.prepareGenerationConfig(project.models.base);
|
|
12116
12146
|
const previewSchema = z6.z.object({
|
|
@@ -12126,10 +12156,12 @@ app4.openapi(generatePreviewRoute, async (c) => {
|
|
|
12126
12156
|
c.header("Content-Type", "text/plain; charset=utf-8");
|
|
12127
12157
|
c.header("Cache-Control", "no-cache");
|
|
12128
12158
|
c.header("Connection", "keep-alive");
|
|
12159
|
+
const existingData = existingCode && dataComponent.preview?.data ? dataComponent.preview.data : null;
|
|
12129
12160
|
return streaming.stream(c, async (stream3) => {
|
|
12130
12161
|
try {
|
|
12131
12162
|
for await (const partialObject of result.partialObjectStream) {
|
|
12132
|
-
|
|
12163
|
+
const outputObject = instructions && existingData ? { ...partialObject, data: existingData } : partialObject;
|
|
12164
|
+
await stream3.write(JSON.stringify(outputObject) + "\n");
|
|
12133
12165
|
}
|
|
12134
12166
|
} catch (error) {
|
|
12135
12167
|
logger26.error(
|
|
@@ -12152,10 +12184,50 @@ app4.openapi(generatePreviewRoute, async (c) => {
|
|
|
12152
12184
|
});
|
|
12153
12185
|
}
|
|
12154
12186
|
});
|
|
12155
|
-
function buildGenerationPrompt(dataComponent) {
|
|
12187
|
+
function buildGenerationPrompt(dataComponent, instructions, existingCode) {
|
|
12156
12188
|
const propsSchema = dataComponent.props || {};
|
|
12157
12189
|
const propsJson = JSON.stringify(propsSchema, null, 2);
|
|
12158
12190
|
const componentName = sanitizeComponentName(dataComponent.name);
|
|
12191
|
+
if (instructions && existingCode) {
|
|
12192
|
+
return `You are an expert React and Tailwind CSS developer. You need to modify an existing React component based on specific instructions.
|
|
12193
|
+
|
|
12194
|
+
COMPONENT DETAILS:
|
|
12195
|
+
- Original Name: ${dataComponent.name}
|
|
12196
|
+
- Component Function Name: ${componentName}
|
|
12197
|
+
- Description: ${dataComponent.description}
|
|
12198
|
+
- Props Schema (JSON Schema): ${propsJson}
|
|
12199
|
+
|
|
12200
|
+
EXISTING COMPONENT CODE:
|
|
12201
|
+
\`\`\`jsx
|
|
12202
|
+
${existingCode}
|
|
12203
|
+
\`\`\`
|
|
12204
|
+
|
|
12205
|
+
MODIFICATION INSTRUCTIONS:
|
|
12206
|
+
${instructions}
|
|
12207
|
+
|
|
12208
|
+
REQUIREMENTS:
|
|
12209
|
+
1. Modify the existing component code according to the instructions
|
|
12210
|
+
2. Keep using Tailwind CSS SEMANTIC COLOR CLASSES (bg-background, text-foreground, etc.)
|
|
12211
|
+
3. Maintain the balanced spacing and design principles from the original
|
|
12212
|
+
4. Keep using lucide-react icons where appropriate
|
|
12213
|
+
5. DO NOT include export statements - just the imports and function
|
|
12214
|
+
6. DO NOT include TypeScript type annotations
|
|
12215
|
+
7. Component name should remain: ${componentName}
|
|
12216
|
+
8. DO NOT regenerate sample data - keep the same data structure
|
|
12217
|
+
|
|
12218
|
+
OUTPUT FORMAT:
|
|
12219
|
+
You need to generate only one thing:
|
|
12220
|
+
1. "code": The modified React component code as a string
|
|
12221
|
+
|
|
12222
|
+
Return ONLY the code field, the data field will be reused from the existing preview.
|
|
12223
|
+
|
|
12224
|
+
EXAMPLE OUTPUT:
|
|
12225
|
+
{
|
|
12226
|
+
"code": "import { Mail, User } from 'lucide-react';\\n\\nfunction ${componentName}(props) {\\n // Modified component code here\\n}"
|
|
12227
|
+
}
|
|
12228
|
+
|
|
12229
|
+
Focus on making the requested changes while maintaining the component's quality and design principles.`;
|
|
12230
|
+
}
|
|
12159
12231
|
return `You are an expert React and Tailwind CSS developer. Generate a beautiful, modern React component for displaying data and sample data to preview it.
|
|
12160
12232
|
|
|
12161
12233
|
COMPONENT DETAILS:
|