@iqai/adk 0.8.1 → 0.8.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/CHANGELOG.md +41 -0
- package/README.md +2 -2
- package/dist/constants.d.mts +2 -2
- package/dist/constants.d.ts +2 -2
- package/dist/constants.js +1 -1
- package/dist/constants.mjs +1 -1
- package/dist/index.d.mts +78 -49
- package/dist/index.d.ts +78 -49
- package/dist/index.js +390 -126
- package/dist/index.mjs +390 -126
- package/package.json +10 -4
package/dist/index.mjs
CHANGED
|
@@ -1342,12 +1342,21 @@ var InvocationContext = class _InvocationContext {
|
|
|
1342
1342
|
* The current session of this invocation context. Readonly.
|
|
1343
1343
|
*/
|
|
1344
1344
|
session;
|
|
1345
|
+
/**
|
|
1346
|
+
* Shared flags container so that child/parent contexts stay in sync.
|
|
1347
|
+
*/
|
|
1348
|
+
_invocationFlags;
|
|
1345
1349
|
/**
|
|
1346
1350
|
* Whether to end this invocation.
|
|
1347
1351
|
*
|
|
1348
1352
|
* Set to True in callbacks or tools to terminate this invocation.
|
|
1349
1353
|
*/
|
|
1350
|
-
endInvocation
|
|
1354
|
+
get endInvocation() {
|
|
1355
|
+
return this._invocationFlags.endInvocation;
|
|
1356
|
+
}
|
|
1357
|
+
set endInvocation(value) {
|
|
1358
|
+
this._invocationFlags.endInvocation = value;
|
|
1359
|
+
}
|
|
1351
1360
|
/**
|
|
1352
1361
|
* The queue to receive live requests.
|
|
1353
1362
|
*/
|
|
@@ -1388,7 +1397,9 @@ var InvocationContext = class _InvocationContext {
|
|
|
1388
1397
|
this.agent = options.agent;
|
|
1389
1398
|
this.userContent = options.userContent;
|
|
1390
1399
|
this.session = options.session;
|
|
1391
|
-
this.
|
|
1400
|
+
this._invocationFlags = options.invocationFlags ?? {
|
|
1401
|
+
endInvocation: options.endInvocation || false
|
|
1402
|
+
};
|
|
1392
1403
|
this.liveRequestQueue = options.liveRequestQueue;
|
|
1393
1404
|
this.activeStreamingTools = options.activeStreamingTools;
|
|
1394
1405
|
this.transcriptionCache = options.transcriptionCache;
|
|
@@ -1447,6 +1458,12 @@ var InvocationContext = class _InvocationContext {
|
|
|
1447
1458
|
getSpanCounters() {
|
|
1448
1459
|
return this._spanCounters;
|
|
1449
1460
|
}
|
|
1461
|
+
/**
|
|
1462
|
+
* Exposes shared invocation flags for child contexts.
|
|
1463
|
+
*/
|
|
1464
|
+
getInvocationFlags() {
|
|
1465
|
+
return this._invocationFlags;
|
|
1466
|
+
}
|
|
1450
1467
|
/**
|
|
1451
1468
|
* Creates a child invocation context for a sub-agent
|
|
1452
1469
|
*/
|
|
@@ -1465,7 +1482,7 @@ var InvocationContext = class _InvocationContext {
|
|
|
1465
1482
|
// Update to the new agent
|
|
1466
1483
|
userContent: this.userContent,
|
|
1467
1484
|
session: this.session,
|
|
1468
|
-
|
|
1485
|
+
invocationFlags: this._invocationFlags,
|
|
1469
1486
|
liveRequestQueue: this.liveRequestQueue,
|
|
1470
1487
|
activeStreamingTools: this.activeStreamingTools,
|
|
1471
1488
|
transcriptionCache: this.transcriptionCache,
|
|
@@ -3694,15 +3711,10 @@ var VectorStorageProvider = class {
|
|
|
3694
3711
|
this.memoryCache.delete(id);
|
|
3695
3712
|
}
|
|
3696
3713
|
} else {
|
|
3697
|
-
const
|
|
3714
|
+
const vectorFilter = this.buildDeleteFilter(filter);
|
|
3715
|
+
deleted = await this.vectorStore.delete({ filter: vectorFilter });
|
|
3698
3716
|
for (const [id, record] of this.memoryCache.entries()) {
|
|
3699
3717
|
if (this.matchesFilter(record, filter)) {
|
|
3700
|
-
idsToDelete.push(id);
|
|
3701
|
-
}
|
|
3702
|
-
}
|
|
3703
|
-
if (idsToDelete.length > 0) {
|
|
3704
|
-
deleted = await this.vectorStore.delete({ ids: idsToDelete });
|
|
3705
|
-
for (const id of idsToDelete) {
|
|
3706
3718
|
this.memoryCache.delete(id);
|
|
3707
3719
|
}
|
|
3708
3720
|
}
|
|
@@ -3713,6 +3725,10 @@ var VectorStorageProvider = class {
|
|
|
3713
3725
|
* Count memories matching filter.
|
|
3714
3726
|
*/
|
|
3715
3727
|
async count(filter) {
|
|
3728
|
+
if (this.vectorStore.count) {
|
|
3729
|
+
const vectorFilter = this.buildDeleteFilter(filter);
|
|
3730
|
+
return this.vectorStore.count(vectorFilter);
|
|
3731
|
+
}
|
|
3716
3732
|
let count = 0;
|
|
3717
3733
|
for (const record of this.memoryCache.values()) {
|
|
3718
3734
|
if (this.matchesFilter(record, filter)) {
|
|
@@ -3844,15 +3860,34 @@ var VectorStorageProvider = class {
|
|
|
3844
3860
|
}
|
|
3845
3861
|
return filter;
|
|
3846
3862
|
}
|
|
3863
|
+
/**
|
|
3864
|
+
* Build filter object for vector store delete/count operations.
|
|
3865
|
+
*/
|
|
3866
|
+
buildDeleteFilter(filter) {
|
|
3867
|
+
const vectorFilter = {};
|
|
3868
|
+
if (filter.userId !== void 0) vectorFilter.userId = filter.userId;
|
|
3869
|
+
if (filter.appName !== void 0) vectorFilter.appName = filter.appName;
|
|
3870
|
+
if (filter.sessionId !== void 0)
|
|
3871
|
+
vectorFilter.sessionId = filter.sessionId;
|
|
3872
|
+
if (filter.before !== void 0) vectorFilter.before = filter.before;
|
|
3873
|
+
if (filter.after !== void 0) vectorFilter.after = filter.after;
|
|
3874
|
+
if (this.namespace) vectorFilter.namespace = this.namespace;
|
|
3875
|
+
return vectorFilter;
|
|
3876
|
+
}
|
|
3847
3877
|
/**
|
|
3848
3878
|
* Check if a record matches the given filter.
|
|
3849
3879
|
*/
|
|
3850
3880
|
matchesFilter(record, filter) {
|
|
3851
|
-
if (filter.userId && record.userId !== filter.userId)
|
|
3852
|
-
|
|
3853
|
-
if (filter.
|
|
3854
|
-
|
|
3855
|
-
if (filter.
|
|
3881
|
+
if (filter.userId !== void 0 && record.userId !== filter.userId)
|
|
3882
|
+
return false;
|
|
3883
|
+
if (filter.appName !== void 0 && record.appName !== filter.appName)
|
|
3884
|
+
return false;
|
|
3885
|
+
if (filter.sessionId !== void 0 && record.sessionId !== filter.sessionId)
|
|
3886
|
+
return false;
|
|
3887
|
+
if (filter.before !== void 0 && record.timestamp > filter.before)
|
|
3888
|
+
return false;
|
|
3889
|
+
if (filter.after !== void 0 && record.timestamp < filter.after)
|
|
3890
|
+
return false;
|
|
3856
3891
|
return true;
|
|
3857
3892
|
}
|
|
3858
3893
|
/**
|
|
@@ -4059,11 +4094,12 @@ var LlmSummaryProvider = class {
|
|
|
4059
4094
|
}
|
|
4060
4095
|
const baseUrl = this.baseUrl ?? "https://generativelanguage.googleapis.com/v1beta";
|
|
4061
4096
|
const response = await fetch(
|
|
4062
|
-
`${baseUrl}/models/${this.model}:generateContent
|
|
4097
|
+
`${baseUrl}/models/${this.model}:generateContent`,
|
|
4063
4098
|
{
|
|
4064
4099
|
method: "POST",
|
|
4065
4100
|
headers: {
|
|
4066
|
-
"Content-Type": "application/json"
|
|
4101
|
+
"Content-Type": "application/json",
|
|
4102
|
+
"x-goog-api-key": apiKey
|
|
4067
4103
|
},
|
|
4068
4104
|
body: JSON.stringify({
|
|
4069
4105
|
contents: [{ parts: [{ text: prompt }] }],
|
|
@@ -4444,7 +4480,7 @@ var OPERATIONS = {
|
|
|
4444
4480
|
EXECUTE_TOOL: "execute_tool",
|
|
4445
4481
|
// ============================================
|
|
4446
4482
|
// ADK-specific operations (framework extensions)
|
|
4447
|
-
// These are non-standard but useful for the ADK framework
|
|
4483
|
+
// These are non-standard but useful for the ADK-TS framework
|
|
4448
4484
|
// ============================================
|
|
4449
4485
|
TRANSFER_AGENT: "transfer_agent",
|
|
4450
4486
|
// Multi-agent transfer
|
|
@@ -5560,7 +5596,7 @@ var TracingService = class {
|
|
|
5560
5596
|
[ADK_ATTRS.INVOCATION_ID]: invocationContext.invocationId,
|
|
5561
5597
|
[ADK_ATTRS.EVENT_ID]: eventId,
|
|
5562
5598
|
[ADK_ATTRS.ENVIRONMENT]: getEnvironment() || "",
|
|
5563
|
-
// Content attributes (only if capture is enabled) - ADK namespace for backward compat
|
|
5599
|
+
// Content attributes (only if capture is enabled) - ADK-TS namespace for backward compat
|
|
5564
5600
|
[ADK_ATTRS.LLM_REQUEST]: captureContent ? safeJsonStringify(llmRequestData) : "{}",
|
|
5565
5601
|
[ADK_ATTRS.LLM_RESPONSE]: captureContent ? safeJsonStringify(llmResponseData) : "{}"
|
|
5566
5602
|
});
|
|
@@ -6259,7 +6295,7 @@ var BaseLlm = class {
|
|
|
6259
6295
|
true
|
|
6260
6296
|
// retry may be recommended for transient model errors
|
|
6261
6297
|
);
|
|
6262
|
-
this.logger.error("\u274C ADK LLM Error:", {
|
|
6298
|
+
this.logger.error("\u274C ADK-TS LLM Error:", {
|
|
6263
6299
|
model: this.model,
|
|
6264
6300
|
error: error.message
|
|
6265
6301
|
});
|
|
@@ -7027,7 +7063,7 @@ var AiSdkLlm = class _AiSdkLlm extends BaseLlm {
|
|
|
7027
7063
|
});
|
|
7028
7064
|
}
|
|
7029
7065
|
/**
|
|
7030
|
-
* Convert ADK LlmRequest to AI SDK CoreMessage format
|
|
7066
|
+
* Convert ADK-TS LlmRequest to AI SDK CoreMessage format
|
|
7031
7067
|
*/
|
|
7032
7068
|
convertToAiSdkMessages(llmRequest) {
|
|
7033
7069
|
const messages = [];
|
|
@@ -7077,7 +7113,7 @@ var AiSdkLlm = class _AiSdkLlm extends BaseLlm {
|
|
|
7077
7113
|
return transformedSchema;
|
|
7078
7114
|
}
|
|
7079
7115
|
/**
|
|
7080
|
-
* Convert ADK tools to AI SDK tools format
|
|
7116
|
+
* Convert ADK-TS tools to AI SDK tools format
|
|
7081
7117
|
*/
|
|
7082
7118
|
convertToAiSdkTools(llmRequest) {
|
|
7083
7119
|
const tools = {};
|
|
@@ -7098,7 +7134,7 @@ var AiSdkLlm = class _AiSdkLlm extends BaseLlm {
|
|
|
7098
7134
|
return tools;
|
|
7099
7135
|
}
|
|
7100
7136
|
/**
|
|
7101
|
-
* Convert ADK Content to AI SDK CoreMessage
|
|
7137
|
+
* Convert ADK-TS Content to AI SDK CoreMessage
|
|
7102
7138
|
*/
|
|
7103
7139
|
contentToAiSdkMessage(content) {
|
|
7104
7140
|
const role = this.mapRole(content.role);
|
|
@@ -7200,7 +7236,7 @@ var AiSdkLlm = class _AiSdkLlm extends BaseLlm {
|
|
|
7200
7236
|
return { role: "user", content: contentParts };
|
|
7201
7237
|
}
|
|
7202
7238
|
/**
|
|
7203
|
-
* Map ADK role to AI SDK role
|
|
7239
|
+
* Map ADK-TS role to AI SDK role
|
|
7204
7240
|
*/
|
|
7205
7241
|
mapRole(role) {
|
|
7206
7242
|
switch (role) {
|
|
@@ -7214,7 +7250,7 @@ var AiSdkLlm = class _AiSdkLlm extends BaseLlm {
|
|
|
7214
7250
|
}
|
|
7215
7251
|
}
|
|
7216
7252
|
/**
|
|
7217
|
-
* Map AI SDK finish reason to ADK finish reason
|
|
7253
|
+
* Map AI SDK finish reason to ADK-TS finish reason
|
|
7218
7254
|
*/
|
|
7219
7255
|
mapFinishReason(finishReason) {
|
|
7220
7256
|
switch (finishReason) {
|
|
@@ -7233,6 +7269,21 @@ var AiSdkLlm = class _AiSdkLlm extends BaseLlm {
|
|
|
7233
7269
|
// src/models/anthropic-llm.ts
|
|
7234
7270
|
init_logger();
|
|
7235
7271
|
import Anthropic from "@anthropic-ai/sdk";
|
|
7272
|
+
|
|
7273
|
+
// src/models/llm-utils.ts
|
|
7274
|
+
function safeParseToolArgs(json, logger2) {
|
|
7275
|
+
try {
|
|
7276
|
+
return JSON.parse(json || "{}");
|
|
7277
|
+
} catch (error) {
|
|
7278
|
+
logger2.warn("Failed to parse tool call arguments, using empty args", {
|
|
7279
|
+
rawArgs: json,
|
|
7280
|
+
error: String(error)
|
|
7281
|
+
});
|
|
7282
|
+
return {};
|
|
7283
|
+
}
|
|
7284
|
+
}
|
|
7285
|
+
|
|
7286
|
+
// src/models/anthropic-llm.ts
|
|
7236
7287
|
var DEFAULT_MAX_OUTPUT_TOKENS = 1024;
|
|
7237
7288
|
var THOUGHT_OPEN_TAGS = [
|
|
7238
7289
|
"<thinking>",
|
|
@@ -7438,7 +7489,7 @@ var AnthropicLlm = class extends BaseLlm {
|
|
|
7438
7489
|
functionCall: {
|
|
7439
7490
|
id: block.id,
|
|
7440
7491
|
name: block.name,
|
|
7441
|
-
args:
|
|
7492
|
+
args: safeParseToolArgs(block.inputJson, this.logger)
|
|
7442
7493
|
}
|
|
7443
7494
|
});
|
|
7444
7495
|
}
|
|
@@ -7490,7 +7541,7 @@ var AnthropicLlm = class extends BaseLlm {
|
|
|
7490
7541
|
throw new Error(`Live connection is not supported for ${this.model}.`);
|
|
7491
7542
|
}
|
|
7492
7543
|
/**
|
|
7493
|
-
* Convert Anthropic Message to ADK LlmResponse
|
|
7544
|
+
* Convert Anthropic Message to ADK-TS LlmResponse
|
|
7494
7545
|
*/
|
|
7495
7546
|
anthropicMessageToLlmResponse(message) {
|
|
7496
7547
|
this.logger.debug(
|
|
@@ -7518,7 +7569,7 @@ var AnthropicLlm = class extends BaseLlm {
|
|
|
7518
7569
|
});
|
|
7519
7570
|
}
|
|
7520
7571
|
/**
|
|
7521
|
-
* Convert ADK Content to Anthropic MessageParam
|
|
7572
|
+
* Convert ADK-TS Content to Anthropic MessageParam
|
|
7522
7573
|
*/
|
|
7523
7574
|
contentToAnthropicMessage(content) {
|
|
7524
7575
|
return {
|
|
@@ -7529,39 +7580,39 @@ var AnthropicLlm = class extends BaseLlm {
|
|
|
7529
7580
|
};
|
|
7530
7581
|
}
|
|
7531
7582
|
/**
|
|
7532
|
-
* Convert ADK Part to Anthropic content block
|
|
7583
|
+
* Convert ADK-TS Part to Anthropic content block
|
|
7533
7584
|
*/
|
|
7534
7585
|
partToAnthropicBlock(part) {
|
|
7535
7586
|
if (part.text) return { type: "text", text: part.text };
|
|
7536
|
-
if (part.
|
|
7587
|
+
if (part.functionCall)
|
|
7537
7588
|
return {
|
|
7538
7589
|
type: "tool_use",
|
|
7539
|
-
id: part.
|
|
7540
|
-
name: part.
|
|
7541
|
-
input: part.
|
|
7590
|
+
id: part.functionCall.id || "",
|
|
7591
|
+
name: part.functionCall.name,
|
|
7592
|
+
input: part.functionCall.args || {}
|
|
7542
7593
|
};
|
|
7543
|
-
if (part.
|
|
7594
|
+
if (part.functionResponse)
|
|
7544
7595
|
return {
|
|
7545
7596
|
type: "tool_result",
|
|
7546
|
-
tool_use_id: part.
|
|
7547
|
-
content: String(part.
|
|
7597
|
+
tool_use_id: part.functionResponse.id || "",
|
|
7598
|
+
content: String(part.functionResponse.response?.result || ""),
|
|
7548
7599
|
is_error: false
|
|
7549
7600
|
};
|
|
7550
7601
|
throw new Error("Unsupported part type for Anthropic conversion");
|
|
7551
7602
|
}
|
|
7552
7603
|
/**
|
|
7553
|
-
* Convert Anthropic content block to ADK Part
|
|
7604
|
+
* Convert Anthropic content block to ADK-TS Part
|
|
7554
7605
|
*/
|
|
7555
7606
|
anthropicBlockToPart(block) {
|
|
7556
7607
|
if (block.type === "text") return { text: block.text };
|
|
7557
7608
|
if (block.type === "tool_use")
|
|
7558
7609
|
return {
|
|
7559
|
-
|
|
7610
|
+
functionCall: { id: block.id, name: block.name, args: block.input }
|
|
7560
7611
|
};
|
|
7561
7612
|
throw new Error("Unsupported Anthropic content block type");
|
|
7562
7613
|
}
|
|
7563
7614
|
/**
|
|
7564
|
-
* Convert ADK function declaration to Anthropic tool param
|
|
7615
|
+
* Convert ADK-TS function declaration to Anthropic tool param
|
|
7565
7616
|
*/
|
|
7566
7617
|
functionDeclarationToAnthropicTool(functionDeclaration) {
|
|
7567
7618
|
const properties = {};
|
|
@@ -7581,14 +7632,14 @@ var AnthropicLlm = class extends BaseLlm {
|
|
|
7581
7632
|
};
|
|
7582
7633
|
}
|
|
7583
7634
|
/**
|
|
7584
|
-
* Convert ADK role to Anthropic role format
|
|
7635
|
+
* Convert ADK-TS role to Anthropic role format
|
|
7585
7636
|
*/
|
|
7586
7637
|
toAnthropicRole(role) {
|
|
7587
7638
|
if (role === "model" || role === "assistant") return "assistant";
|
|
7588
7639
|
return "user";
|
|
7589
7640
|
}
|
|
7590
7641
|
/**
|
|
7591
|
-
* Convert Anthropic stop reason to ADK finish reason
|
|
7642
|
+
* Convert Anthropic stop reason to ADK-TS finish reason
|
|
7592
7643
|
*/
|
|
7593
7644
|
toAdkFinishReason(anthropicStopReason) {
|
|
7594
7645
|
if (["end_turn", "stop_sequence", "tool_use"].includes(
|
|
@@ -8185,7 +8236,10 @@ var OpenAiLlm = class extends BaseLlm {
|
|
|
8185
8236
|
functionCall: {
|
|
8186
8237
|
id: toolCall.id,
|
|
8187
8238
|
name: toolCall.function.name,
|
|
8188
|
-
args:
|
|
8239
|
+
args: safeParseToolArgs(
|
|
8240
|
+
toolCall.function.arguments,
|
|
8241
|
+
this.logger
|
|
8242
|
+
)
|
|
8189
8243
|
}
|
|
8190
8244
|
});
|
|
8191
8245
|
}
|
|
@@ -8278,7 +8332,7 @@ var OpenAiLlm = class extends BaseLlm {
|
|
|
8278
8332
|
functionCall: {
|
|
8279
8333
|
id: toolCall.id || "",
|
|
8280
8334
|
name: toolCall.function.name,
|
|
8281
|
-
args:
|
|
8335
|
+
args: safeParseToolArgs(toolCall.function.arguments, this.logger)
|
|
8282
8336
|
}
|
|
8283
8337
|
});
|
|
8284
8338
|
}
|
|
@@ -8297,7 +8351,7 @@ var OpenAiLlm = class extends BaseLlm {
|
|
|
8297
8351
|
});
|
|
8298
8352
|
}
|
|
8299
8353
|
/**
|
|
8300
|
-
* Convert OpenAI message to ADK LlmResponse
|
|
8354
|
+
* Convert OpenAI message to ADK-TS LlmResponse
|
|
8301
8355
|
*/
|
|
8302
8356
|
openAiMessageToLlmResponse(choice, usage) {
|
|
8303
8357
|
const message = choice.message;
|
|
@@ -8312,7 +8366,7 @@ var OpenAiLlm = class extends BaseLlm {
|
|
|
8312
8366
|
functionCall: {
|
|
8313
8367
|
id: toolCall.id,
|
|
8314
8368
|
name: toolCall.function.name,
|
|
8315
|
-
args:
|
|
8369
|
+
args: safeParseToolArgs(toolCall.function.arguments, this.logger)
|
|
8316
8370
|
}
|
|
8317
8371
|
});
|
|
8318
8372
|
}
|
|
@@ -8332,7 +8386,7 @@ var OpenAiLlm = class extends BaseLlm {
|
|
|
8332
8386
|
});
|
|
8333
8387
|
}
|
|
8334
8388
|
/**
|
|
8335
|
-
* Convert ADK Content to OpenAI ChatCompletionMessage
|
|
8389
|
+
* Convert ADK-TS Content to OpenAI ChatCompletionMessage
|
|
8336
8390
|
*/
|
|
8337
8391
|
contentToOpenAiMessage(content) {
|
|
8338
8392
|
const role = this.toOpenAiRole(content.role);
|
|
@@ -8388,7 +8442,7 @@ var OpenAiLlm = class extends BaseLlm {
|
|
|
8388
8442
|
};
|
|
8389
8443
|
}
|
|
8390
8444
|
/**
|
|
8391
|
-
* Convert ADK Part to OpenAI message content
|
|
8445
|
+
* Convert ADK-TS Part to OpenAI message content
|
|
8392
8446
|
*/
|
|
8393
8447
|
partToOpenAiContent(part) {
|
|
8394
8448
|
if (part.text) {
|
|
@@ -8445,7 +8499,7 @@ var OpenAiLlm = class extends BaseLlm {
|
|
|
8445
8499
|
return transformedSchema;
|
|
8446
8500
|
}
|
|
8447
8501
|
/**
|
|
8448
|
-
* Convert ADK function declaration to OpenAI tool
|
|
8502
|
+
* Convert ADK-TS function declaration to OpenAI tool
|
|
8449
8503
|
*/
|
|
8450
8504
|
functionDeclarationToOpenAiTool(functionDeclaration) {
|
|
8451
8505
|
return {
|
|
@@ -8460,7 +8514,7 @@ var OpenAiLlm = class extends BaseLlm {
|
|
|
8460
8514
|
};
|
|
8461
8515
|
}
|
|
8462
8516
|
/**
|
|
8463
|
-
* Convert ADK role to OpenAI role format
|
|
8517
|
+
* Convert ADK-TS role to OpenAI role format
|
|
8464
8518
|
*/
|
|
8465
8519
|
toOpenAiRole(role) {
|
|
8466
8520
|
if (role === "model") {
|
|
@@ -8472,7 +8526,7 @@ var OpenAiLlm = class extends BaseLlm {
|
|
|
8472
8526
|
return "user";
|
|
8473
8527
|
}
|
|
8474
8528
|
/**
|
|
8475
|
-
* Convert OpenAI finish reason to ADK finish reason
|
|
8529
|
+
* Convert OpenAI finish reason to ADK-TS finish reason
|
|
8476
8530
|
*/
|
|
8477
8531
|
toAdkFinishReason(openaiFinishReason) {
|
|
8478
8532
|
switch (openaiFinishReason) {
|
|
@@ -8804,7 +8858,7 @@ var ReadonlyContext = class {
|
|
|
8804
8858
|
// src/agents/callback-context.ts
|
|
8805
8859
|
var CallbackContext = class extends ReadonlyContext {
|
|
8806
8860
|
/**
|
|
8807
|
-
* TODO: make this public for
|
|
8861
|
+
* TODO: make this public for ADK-TS, but private for users.
|
|
8808
8862
|
*/
|
|
8809
8863
|
_eventActions;
|
|
8810
8864
|
_state;
|
|
@@ -8880,7 +8934,7 @@ var ToolContext = class extends CallbackContext {
|
|
|
8880
8934
|
/**
|
|
8881
8935
|
* The function call id of the current tool call. This id was
|
|
8882
8936
|
* returned in the function call event from LLM to identify a function call.
|
|
8883
|
-
* If LLM didn't return this id, ADK will assign one to it. This id is used
|
|
8937
|
+
* If LLM didn't return this id, ADK-TS will assign one to it. This id is used
|
|
8884
8938
|
* to map function call response to the original function call.
|
|
8885
8939
|
*/
|
|
8886
8940
|
functionCallId;
|
|
@@ -9356,7 +9410,7 @@ function mergeParallelFunctionResponseEvents(functionResponseEvents) {
|
|
|
9356
9410
|
}
|
|
9357
9411
|
mergedActions.requestedAuthConfigs = mergedRequestedAuthConfigs;
|
|
9358
9412
|
const mergedEvent = new Event({
|
|
9359
|
-
invocationId:
|
|
9413
|
+
invocationId: baseEvent.invocationId,
|
|
9360
9414
|
author: baseEvent.author,
|
|
9361
9415
|
branch: baseEvent.branch,
|
|
9362
9416
|
content: { role: "user", parts: mergedParts },
|
|
@@ -9408,7 +9462,7 @@ var EnhancedAuthConfig = class {
|
|
|
9408
9462
|
rawAuthCredential;
|
|
9409
9463
|
/**
|
|
9410
9464
|
* Exchanged auth credential after processing
|
|
9411
|
-
* Filled by ADK and client working together
|
|
9465
|
+
* Filled by ADK-TS and client working together
|
|
9412
9466
|
*/
|
|
9413
9467
|
exchangedAuthCredential;
|
|
9414
9468
|
/**
|
|
@@ -10279,7 +10333,7 @@ var FileOperationsTool = class extends BaseTool {
|
|
|
10279
10333
|
async runAsync(args, _context) {
|
|
10280
10334
|
try {
|
|
10281
10335
|
const resolvedPath = this.resolvePath(args.filepath);
|
|
10282
|
-
this.validatePath(resolvedPath);
|
|
10336
|
+
await this.validatePath(resolvedPath);
|
|
10283
10337
|
const encoding = args.encoding || "utf8";
|
|
10284
10338
|
switch (args.operation) {
|
|
10285
10339
|
case "read":
|
|
@@ -10321,15 +10375,38 @@ var FileOperationsTool = class extends BaseTool {
|
|
|
10321
10375
|
return path.isAbsolute(filepath) ? filepath : path.resolve(this.basePath, filepath);
|
|
10322
10376
|
}
|
|
10323
10377
|
/**
|
|
10324
|
-
* Validate that a path is within the base path for security
|
|
10378
|
+
* Validate that a path is within the base path for security.
|
|
10379
|
+
* Resolves symlinks to prevent symlink escape attacks.
|
|
10325
10380
|
*/
|
|
10326
|
-
validatePath(filepath) {
|
|
10327
|
-
const
|
|
10328
|
-
const
|
|
10329
|
-
|
|
10330
|
-
|
|
10331
|
-
|
|
10332
|
-
|
|
10381
|
+
async validatePath(filepath) {
|
|
10382
|
+
const realBasePath = await fs.realpath(this.basePath);
|
|
10383
|
+
const isWithinBase = (p, base) => p === base || p.startsWith(base + path.sep);
|
|
10384
|
+
try {
|
|
10385
|
+
const realPath = await fs.realpath(filepath);
|
|
10386
|
+
if (!isWithinBase(realPath, realBasePath)) {
|
|
10387
|
+
throw new Error(
|
|
10388
|
+
"Access denied: Can't access paths outside the base directory"
|
|
10389
|
+
);
|
|
10390
|
+
}
|
|
10391
|
+
} catch (error) {
|
|
10392
|
+
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
10393
|
+
const parentDir = path.dirname(filepath);
|
|
10394
|
+
let realParent;
|
|
10395
|
+
try {
|
|
10396
|
+
realParent = await fs.realpath(parentDir);
|
|
10397
|
+
} catch {
|
|
10398
|
+
throw new Error(
|
|
10399
|
+
"Access denied: Can't access paths outside the base directory"
|
|
10400
|
+
);
|
|
10401
|
+
}
|
|
10402
|
+
if (!isWithinBase(realParent, realBasePath)) {
|
|
10403
|
+
throw new Error(
|
|
10404
|
+
"Access denied: Can't access paths outside the base directory"
|
|
10405
|
+
);
|
|
10406
|
+
}
|
|
10407
|
+
} else {
|
|
10408
|
+
throw error;
|
|
10409
|
+
}
|
|
10333
10410
|
}
|
|
10334
10411
|
}
|
|
10335
10412
|
/**
|
|
@@ -10427,7 +10504,7 @@ var FileOperationsTool = class extends BaseTool {
|
|
|
10427
10504
|
const results = await Promise.all(
|
|
10428
10505
|
entries.map(async (entry) => {
|
|
10429
10506
|
const entryPath = path.join(dirpath, entry.name);
|
|
10430
|
-
const stats = await fs.
|
|
10507
|
+
const stats = await fs.lstat(entryPath);
|
|
10431
10508
|
return {
|
|
10432
10509
|
name: entry.name,
|
|
10433
10510
|
path: entryPath,
|
|
@@ -10669,6 +10746,62 @@ var googleSearchArgsSchema = z2.object({
|
|
|
10669
10746
|
// src/tools/common/http-request-tool.ts
|
|
10670
10747
|
init_base_tool();
|
|
10671
10748
|
import { Type as Type6 } from "@google/genai";
|
|
10749
|
+
|
|
10750
|
+
// src/tools/utils/url-validation.ts
|
|
10751
|
+
function validateUrlForFetch(urlString) {
|
|
10752
|
+
const url = new URL(urlString);
|
|
10753
|
+
if (url.protocol !== "http:" && url.protocol !== "https:") {
|
|
10754
|
+
throw new Error(
|
|
10755
|
+
`Blocked URL: only http and https protocols are allowed, got ${url.protocol}`
|
|
10756
|
+
);
|
|
10757
|
+
}
|
|
10758
|
+
const hostname = url.hostname.toLowerCase();
|
|
10759
|
+
if (hostname === "localhost" || hostname === "[::1]") {
|
|
10760
|
+
throw new Error("Blocked URL: localhost is not allowed");
|
|
10761
|
+
}
|
|
10762
|
+
const ipv4 = extractIPv4(hostname);
|
|
10763
|
+
if (ipv4 !== null && isPrivateIP(ipv4)) {
|
|
10764
|
+
throw new Error(
|
|
10765
|
+
"Blocked URL: private/internal IP addresses are not allowed"
|
|
10766
|
+
);
|
|
10767
|
+
}
|
|
10768
|
+
if (isPrivateIP(hostname)) {
|
|
10769
|
+
throw new Error(
|
|
10770
|
+
"Blocked URL: private/internal IP addresses are not allowed"
|
|
10771
|
+
);
|
|
10772
|
+
}
|
|
10773
|
+
return url;
|
|
10774
|
+
}
|
|
10775
|
+
function extractIPv4(hostname) {
|
|
10776
|
+
const bare = hostname.replace(/^\[|\]$/g, "");
|
|
10777
|
+
const dottedMatch = bare.match(
|
|
10778
|
+
/^::ffff:(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$/i
|
|
10779
|
+
);
|
|
10780
|
+
if (dottedMatch) return dottedMatch[1];
|
|
10781
|
+
const hexMatch = bare.match(/^::ffff:([0-9a-f]{1,4}):([0-9a-f]{1,4})$/i);
|
|
10782
|
+
if (hexMatch) {
|
|
10783
|
+
const high = Number.parseInt(hexMatch[1], 16);
|
|
10784
|
+
const low = Number.parseInt(hexMatch[2], 16);
|
|
10785
|
+
return `${high >> 8 & 255}.${high & 255}.${low >> 8 & 255}.${low & 255}`;
|
|
10786
|
+
}
|
|
10787
|
+
return null;
|
|
10788
|
+
}
|
|
10789
|
+
function isPrivateIP(hostname) {
|
|
10790
|
+
const match = hostname.match(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/);
|
|
10791
|
+
if (!match) return false;
|
|
10792
|
+
const [, a, b] = match;
|
|
10793
|
+
const first = Number(a);
|
|
10794
|
+
const second = Number(b);
|
|
10795
|
+
if (first === 0) return true;
|
|
10796
|
+
if (first === 127) return true;
|
|
10797
|
+
if (first === 10) return true;
|
|
10798
|
+
if (first === 172 && second >= 16 && second <= 31) return true;
|
|
10799
|
+
if (first === 192 && second === 168) return true;
|
|
10800
|
+
if (first === 169 && second === 254) return true;
|
|
10801
|
+
return false;
|
|
10802
|
+
}
|
|
10803
|
+
|
|
10804
|
+
// src/tools/common/http-request-tool.ts
|
|
10672
10805
|
var HttpRequestTool = class extends BaseTool {
|
|
10673
10806
|
constructor() {
|
|
10674
10807
|
super({
|
|
@@ -10731,7 +10864,7 @@ var HttpRequestTool = class extends BaseTool {
|
|
|
10731
10864
|
params,
|
|
10732
10865
|
timeout = 1e4
|
|
10733
10866
|
} = args;
|
|
10734
|
-
const urlObj =
|
|
10867
|
+
const urlObj = validateUrlForFetch(url);
|
|
10735
10868
|
if (params) {
|
|
10736
10869
|
Object.entries(params).forEach(([key, value]) => {
|
|
10737
10870
|
urlObj.searchParams.append(key, value);
|
|
@@ -10745,7 +10878,8 @@ var HttpRequestTool = class extends BaseTool {
|
|
|
10745
10878
|
method,
|
|
10746
10879
|
headers: requestHeaders,
|
|
10747
10880
|
body,
|
|
10748
|
-
signal: AbortSignal.timeout(timeout)
|
|
10881
|
+
signal: AbortSignal.timeout(timeout),
|
|
10882
|
+
redirect: "manual"
|
|
10749
10883
|
};
|
|
10750
10884
|
const response = await fetch(urlObj.toString(), options);
|
|
10751
10885
|
const responseHeaders = {};
|
|
@@ -11553,16 +11687,16 @@ var BashTool = class _BashTool extends BaseTool {
|
|
|
11553
11687
|
// filesystem formatting
|
|
11554
11688
|
/dd\s+if=/,
|
|
11555
11689
|
// disk operations
|
|
11556
|
-
/wget.*\|\s*sh/,
|
|
11690
|
+
/wget.*\|\s*(sh|bash)/,
|
|
11557
11691
|
// download and execute
|
|
11558
|
-
/curl.*\|\s*bash/,
|
|
11692
|
+
/curl.*\|\s*(bash|sh)/,
|
|
11559
11693
|
// download and execute
|
|
11560
11694
|
/eval\s+['"`]/,
|
|
11561
11695
|
// eval with strings
|
|
11562
|
-
/base64.*\|\s*sh/,
|
|
11696
|
+
/base64.*\|\s*(sh|bash)/,
|
|
11563
11697
|
// decode and execute
|
|
11564
|
-
/nc\s+-.*e/,
|
|
11565
|
-
// netcat reverse shell
|
|
11698
|
+
/(nc|ncat|netcat)\s+-.*e/,
|
|
11699
|
+
// netcat reverse shell (nc, ncat, netcat)
|
|
11566
11700
|
/\/proc\/.*\/mem/,
|
|
11567
11701
|
// memory access
|
|
11568
11702
|
/iptables/,
|
|
@@ -11573,8 +11707,18 @@ var BashTool = class _BashTool extends BaseTool {
|
|
|
11573
11707
|
// ownership changes
|
|
11574
11708
|
/sudo/,
|
|
11575
11709
|
// privilege escalation
|
|
11576
|
-
/su\s
|
|
11710
|
+
/su\s+/,
|
|
11577
11711
|
// user switching
|
|
11712
|
+
/python[23]?(\.\d+)?\s+-c\s/,
|
|
11713
|
+
// python interpreter execution (python, python3, python3.11, etc.)
|
|
11714
|
+
/node\s+(-e|--eval)[\s=]/,
|
|
11715
|
+
// node interpreter execution (-e and --eval)
|
|
11716
|
+
/perl\s+-e\s/,
|
|
11717
|
+
// perl interpreter execution
|
|
11718
|
+
/ruby\s+-e\s/,
|
|
11719
|
+
// ruby interpreter execution
|
|
11720
|
+
/php\s+-r\s/
|
|
11721
|
+
// php interpreter execution
|
|
11578
11722
|
];
|
|
11579
11723
|
// Special characters that enable command chaining/injection
|
|
11580
11724
|
static DANGEROUS_CHARS = /[;&|`$()<>]/;
|
|
@@ -12352,11 +12496,16 @@ var WebFetchTool = class extends BaseTool {
|
|
|
12352
12496
|
}
|
|
12353
12497
|
async runAsync(args, _context) {
|
|
12354
12498
|
try {
|
|
12499
|
+
validateUrlForFetch(args.url);
|
|
12355
12500
|
const response = await axios2.get(args.url, {
|
|
12356
12501
|
timeout: 3e4,
|
|
12357
12502
|
maxRedirects: 5,
|
|
12358
12503
|
headers: {
|
|
12359
12504
|
"User-Agent": "Mozilla/5.0 (compatible; ADK/1.0; +http://example.com)"
|
|
12505
|
+
},
|
|
12506
|
+
beforeRedirect: (options) => {
|
|
12507
|
+
const redirectUrl = typeof options.href === "string" ? options.href : `${options.protocol}//${options.hostname}${options.path}`;
|
|
12508
|
+
validateUrlForFetch(redirectUrl);
|
|
12360
12509
|
}
|
|
12361
12510
|
});
|
|
12362
12511
|
const contentType = response.headers["content-type"] || "";
|
|
@@ -12769,7 +12918,7 @@ var McpSamplingHandler = class {
|
|
|
12769
12918
|
"INVALID_REQUEST_ERROR" /* INVALID_REQUEST_ERROR */
|
|
12770
12919
|
);
|
|
12771
12920
|
}
|
|
12772
|
-
this.logger.debug("Converting MCP request to ADK format");
|
|
12921
|
+
this.logger.debug("Converting MCP request to ADK-TS format");
|
|
12773
12922
|
const adkContents = this.convertMcpMessagesToADK(
|
|
12774
12923
|
mcpParams.messages,
|
|
12775
12924
|
mcpParams.systemPrompt
|
|
@@ -12783,9 +12932,9 @@ var McpSamplingHandler = class {
|
|
|
12783
12932
|
maxOutputTokens: mcpParams.maxTokens
|
|
12784
12933
|
}
|
|
12785
12934
|
});
|
|
12786
|
-
this.logger.debug("Calling ADK sampling handler");
|
|
12935
|
+
this.logger.debug("Calling ADK-TS sampling handler");
|
|
12787
12936
|
const adkResponse = await this.samplingHandler(adkRequest);
|
|
12788
|
-
this.logger.debug("Converting ADK response to MCP format");
|
|
12937
|
+
this.logger.debug("Converting ADK-TS response to MCP format");
|
|
12789
12938
|
const mcpResponse = this.convertADKResponseToMcp(
|
|
12790
12939
|
adkResponse,
|
|
12791
12940
|
requestModel
|
|
@@ -12815,7 +12964,7 @@ var McpSamplingHandler = class {
|
|
|
12815
12964
|
}
|
|
12816
12965
|
}
|
|
12817
12966
|
/**
|
|
12818
|
-
* Convert MCP messages to ADK Content format
|
|
12967
|
+
* Convert MCP messages to ADK-TS Content format
|
|
12819
12968
|
*/
|
|
12820
12969
|
convertMcpMessagesToADK(mcpMessages, systemPrompt) {
|
|
12821
12970
|
const contents = [];
|
|
@@ -12833,7 +12982,7 @@ var McpSamplingHandler = class {
|
|
|
12833
12982
|
return contents;
|
|
12834
12983
|
}
|
|
12835
12984
|
/**
|
|
12836
|
-
* Convert a single MCP message to ADK Content format
|
|
12985
|
+
* Convert a single MCP message to ADK-TS Content format
|
|
12837
12986
|
*/
|
|
12838
12987
|
convertSingleMcpMessageToADK(mcpMessage) {
|
|
12839
12988
|
const adkRole = mcpMessage.role === "assistant" ? "model" : "user";
|
|
@@ -12848,7 +12997,7 @@ var McpSamplingHandler = class {
|
|
|
12848
12997
|
return adkContent;
|
|
12849
12998
|
}
|
|
12850
12999
|
/**
|
|
12851
|
-
* Convert MCP message content to ADK parts format
|
|
13000
|
+
* Convert MCP message content to ADK-TS parts format
|
|
12852
13001
|
*/
|
|
12853
13002
|
convertMcpContentToADKParts(mcpContent) {
|
|
12854
13003
|
const safeText = (value) => typeof value === "string" ? value : "";
|
|
@@ -12901,7 +13050,7 @@ var McpSamplingHandler = class {
|
|
|
12901
13050
|
}
|
|
12902
13051
|
}
|
|
12903
13052
|
/**
|
|
12904
|
-
* Convert ADK response to MCP response format
|
|
13053
|
+
* Convert ADK-TS response to MCP response format
|
|
12905
13054
|
*/
|
|
12906
13055
|
convertADKResponseToMcp(adkResponse, model) {
|
|
12907
13056
|
let responseText = "";
|
|
@@ -12922,7 +13071,7 @@ var McpSamplingHandler = class {
|
|
|
12922
13071
|
model,
|
|
12923
13072
|
// Use the model from the request
|
|
12924
13073
|
role: "assistant",
|
|
12925
|
-
// ADK responses are always from assistant
|
|
13074
|
+
// ADK-TS responses are always from assistant
|
|
12926
13075
|
content: {
|
|
12927
13076
|
type: "text",
|
|
12928
13077
|
text: responseText
|
|
@@ -12932,11 +13081,11 @@ var McpSamplingHandler = class {
|
|
|
12932
13081
|
return mcpResponse;
|
|
12933
13082
|
}
|
|
12934
13083
|
/**
|
|
12935
|
-
* Update the ADK handler
|
|
13084
|
+
* Update the ADK-TS handler
|
|
12936
13085
|
*/
|
|
12937
13086
|
updateHandler(handler) {
|
|
12938
13087
|
this.samplingHandler = handler;
|
|
12939
|
-
this.logger.debug("ADK sampling handler updated");
|
|
13088
|
+
this.logger.debug("ADK-TS sampling handler updated");
|
|
12940
13089
|
}
|
|
12941
13090
|
};
|
|
12942
13091
|
function createSamplingHandler(handler) {
|
|
@@ -13209,13 +13358,13 @@ var McpClientService = class {
|
|
|
13209
13358
|
}
|
|
13210
13359
|
}
|
|
13211
13360
|
/**
|
|
13212
|
-
* Set a new ADK sampling handler
|
|
13361
|
+
* Set a new ADK-TS sampling handler
|
|
13213
13362
|
*/
|
|
13214
13363
|
setSamplingHandler(handler) {
|
|
13215
13364
|
this.mcpSamplingHandler = new McpSamplingHandler(handler);
|
|
13216
13365
|
if (this.client) {
|
|
13217
13366
|
this.setupSamplingHandler(this.client).catch((error) => {
|
|
13218
|
-
this.logger.error("Failed to update ADK sampling handler:", error);
|
|
13367
|
+
this.logger.error("Failed to update ADK-TS sampling handler:", error);
|
|
13219
13368
|
});
|
|
13220
13369
|
}
|
|
13221
13370
|
}
|
|
@@ -13798,6 +13947,9 @@ var McpToolset = class {
|
|
|
13798
13947
|
}
|
|
13799
13948
|
return true;
|
|
13800
13949
|
}
|
|
13950
|
+
isCacheEnabled() {
|
|
13951
|
+
return this.config.cacheConfig?.enabled !== false;
|
|
13952
|
+
}
|
|
13801
13953
|
/**
|
|
13802
13954
|
* Initializes the client service and establishes a connection.
|
|
13803
13955
|
*/
|
|
@@ -13816,9 +13968,9 @@ var McpToolset = class {
|
|
|
13816
13968
|
}
|
|
13817
13969
|
/**
|
|
13818
13970
|
* Set a sampling handler for this MCP toolset.
|
|
13819
|
-
* This allows MCP servers to request LLM completions through your ADK agent.
|
|
13971
|
+
* This allows MCP servers to request LLM completions through your ADK-TS agent.
|
|
13820
13972
|
*
|
|
13821
|
-
* @param handler - ADK sampling handler that receives ADK-formatted messages
|
|
13973
|
+
* @param handler - ADK-TS sampling handler that receives ADK-TS-formatted messages
|
|
13822
13974
|
*/
|
|
13823
13975
|
setSamplingHandler(handler) {
|
|
13824
13976
|
if (!this.clientService) {
|
|
@@ -13852,7 +14004,7 @@ var McpToolset = class {
|
|
|
13852
14004
|
"resource_closed_error" /* RESOURCE_CLOSED_ERROR */
|
|
13853
14005
|
);
|
|
13854
14006
|
}
|
|
13855
|
-
if (this.tools.length > 0 &&
|
|
14007
|
+
if (this.tools.length > 0 && this.isCacheEnabled()) {
|
|
13856
14008
|
return this.tools;
|
|
13857
14009
|
}
|
|
13858
14010
|
if (!this.clientService) {
|
|
@@ -13881,7 +14033,7 @@ var McpToolset = class {
|
|
|
13881
14033
|
}
|
|
13882
14034
|
}
|
|
13883
14035
|
}
|
|
13884
|
-
if (this.
|
|
14036
|
+
if (this.isCacheEnabled()) {
|
|
13885
14037
|
this.tools = tools;
|
|
13886
14038
|
}
|
|
13887
14039
|
return tools;
|
|
@@ -13898,7 +14050,7 @@ var McpToolset = class {
|
|
|
13898
14050
|
}
|
|
13899
14051
|
}
|
|
13900
14052
|
/**
|
|
13901
|
-
* Converts ADK tools to MCP tool format for bidirectional support
|
|
14053
|
+
* Converts ADK-TS tools to MCP tool format for bidirectional support
|
|
13902
14054
|
*/
|
|
13903
14055
|
convertADKToolsToMCP(tools) {
|
|
13904
14056
|
return tools.map((tool) => adkToMcpToolType(tool));
|
|
@@ -14591,10 +14743,7 @@ var CodeExecutionUtils = class _CodeExecutionUtils {
|
|
|
14591
14743
|
* Gets the file content as a base64-encoded string
|
|
14592
14744
|
*/
|
|
14593
14745
|
static getEncodedFileContent(data) {
|
|
14594
|
-
|
|
14595
|
-
if (data instanceof ArrayBuffer) {
|
|
14596
|
-
decodedData = new TextDecoder().decode(data);
|
|
14597
|
-
}
|
|
14746
|
+
const decodedData = data instanceof ArrayBuffer ? new TextDecoder().decode(data) : data;
|
|
14598
14747
|
if (_CodeExecutionUtils.isBase64Encoded(decodedData)) {
|
|
14599
14748
|
return decodedData;
|
|
14600
14749
|
}
|
|
@@ -16557,7 +16706,7 @@ var BaseAgent = class {
|
|
|
16557
16706
|
}
|
|
16558
16707
|
/**
|
|
16559
16708
|
* The resolved beforeAgentCallback field as a list of SingleAgentCallback.
|
|
16560
|
-
* This method is only for use by
|
|
16709
|
+
* This method is only for use by ADK-TS.
|
|
16561
16710
|
*/
|
|
16562
16711
|
get canonicalBeforeAgentCallbacks() {
|
|
16563
16712
|
if (!this.beforeAgentCallback) {
|
|
@@ -16570,7 +16719,7 @@ var BaseAgent = class {
|
|
|
16570
16719
|
}
|
|
16571
16720
|
/**
|
|
16572
16721
|
* The resolved afterAgentCallback field as a list of SingleAgentCallback.
|
|
16573
|
-
* This method is only for use by
|
|
16722
|
+
* This method is only for use by ADK-TS.
|
|
16574
16723
|
*/
|
|
16575
16724
|
get canonicalAfterAgentCallbacks() {
|
|
16576
16725
|
if (!this.afterAgentCallback) {
|
|
@@ -16872,7 +17021,7 @@ var LlmAgent = class _LlmAgent extends BaseAgent {
|
|
|
16872
17021
|
}
|
|
16873
17022
|
/**
|
|
16874
17023
|
* The resolved model field as BaseLLM
|
|
16875
|
-
* This method is only for use by
|
|
17024
|
+
* This method is only for use by ADK-TS
|
|
16876
17025
|
*/
|
|
16877
17026
|
get canonicalModel() {
|
|
16878
17027
|
if (typeof this.model === "string") {
|
|
@@ -16897,7 +17046,7 @@ var LlmAgent = class _LlmAgent extends BaseAgent {
|
|
|
16897
17046
|
}
|
|
16898
17047
|
/**
|
|
16899
17048
|
* The resolved instruction field to construct instruction for this agent
|
|
16900
|
-
* This method is only for use by
|
|
17049
|
+
* This method is only for use by ADK-TS
|
|
16901
17050
|
*/
|
|
16902
17051
|
async canonicalInstruction(ctx) {
|
|
16903
17052
|
if (typeof this.instruction === "string") {
|
|
@@ -16908,7 +17057,7 @@ var LlmAgent = class _LlmAgent extends BaseAgent {
|
|
|
16908
17057
|
}
|
|
16909
17058
|
/**
|
|
16910
17059
|
* The resolved global_instruction field to construct global instruction
|
|
16911
|
-
* This method is only for use by
|
|
17060
|
+
* This method is only for use by ADK-TS
|
|
16912
17061
|
*/
|
|
16913
17062
|
async canonicalGlobalInstruction(ctx) {
|
|
16914
17063
|
if (typeof this.globalInstruction === "string") {
|
|
@@ -16919,7 +17068,7 @@ var LlmAgent = class _LlmAgent extends BaseAgent {
|
|
|
16919
17068
|
}
|
|
16920
17069
|
/**
|
|
16921
17070
|
* The resolved tools field as a list of BaseTool based on the context
|
|
16922
|
-
* This method is only for use by
|
|
17071
|
+
* This method is only for use by ADK-TS
|
|
16923
17072
|
*/
|
|
16924
17073
|
async canonicalTools(_ctx) {
|
|
16925
17074
|
const resolvedTools = [];
|
|
@@ -18324,6 +18473,7 @@ var LangGraphAgent = class extends BaseAgent {
|
|
|
18324
18473
|
* Core logic to run this agent via text-based conversation.
|
|
18325
18474
|
*/
|
|
18326
18475
|
async *runAsyncImpl(context4) {
|
|
18476
|
+
this.results = [];
|
|
18327
18477
|
this.logger.debug(
|
|
18328
18478
|
`Starting graph execution from root node "${this.rootNode}"`
|
|
18329
18479
|
);
|
|
@@ -18515,7 +18665,7 @@ function createBranchContextForSubAgent(agent, subAgent, invocationContext) {
|
|
|
18515
18665
|
agent: subAgent,
|
|
18516
18666
|
userContent: invocationContext.userContent,
|
|
18517
18667
|
session: invocationContext.session,
|
|
18518
|
-
|
|
18668
|
+
invocationFlags: invocationContext.getInvocationFlags(),
|
|
18519
18669
|
liveRequestQueue: invocationContext.liveRequestQueue,
|
|
18520
18670
|
activeStreamingTools: invocationContext.activeStreamingTools,
|
|
18521
18671
|
transcriptionCache: invocationContext.transcriptionCache,
|
|
@@ -19483,8 +19633,29 @@ var GcsArtifactService = class {
|
|
|
19483
19633
|
version
|
|
19484
19634
|
);
|
|
19485
19635
|
const blob = this.bucket.file(blobName);
|
|
19486
|
-
|
|
19487
|
-
|
|
19636
|
+
let data;
|
|
19637
|
+
let contentType;
|
|
19638
|
+
let partType;
|
|
19639
|
+
if (artifact.text !== void 0) {
|
|
19640
|
+
data = artifact.text;
|
|
19641
|
+
contentType = "text/plain";
|
|
19642
|
+
partType = "text";
|
|
19643
|
+
} else if (artifact.inlineData) {
|
|
19644
|
+
data = artifact.inlineData.data;
|
|
19645
|
+
contentType = artifact.inlineData.mimeType;
|
|
19646
|
+
partType = "inlineData";
|
|
19647
|
+
} else if (artifact.fileData) {
|
|
19648
|
+
data = artifact.fileData.fileUri;
|
|
19649
|
+
contentType = artifact.fileData.mimeType || "application/octet-stream";
|
|
19650
|
+
partType = "fileData";
|
|
19651
|
+
} else {
|
|
19652
|
+
throw new Error(
|
|
19653
|
+
"Unsupported artifact Part type: must have text, inlineData, or fileData"
|
|
19654
|
+
);
|
|
19655
|
+
}
|
|
19656
|
+
await blob.save(data, {
|
|
19657
|
+
contentType,
|
|
19658
|
+
metadata: { partType },
|
|
19488
19659
|
preconditionOpts: { ifGenerationMatch: 0 }
|
|
19489
19660
|
});
|
|
19490
19661
|
return version;
|
|
@@ -19518,12 +19689,25 @@ var GcsArtifactService = class {
|
|
|
19518
19689
|
if (!artifactBuffer) {
|
|
19519
19690
|
return null;
|
|
19520
19691
|
}
|
|
19521
|
-
const
|
|
19522
|
-
|
|
19523
|
-
|
|
19524
|
-
|
|
19525
|
-
|
|
19526
|
-
|
|
19692
|
+
const partType = metadata.metadata?.partType;
|
|
19693
|
+
let part;
|
|
19694
|
+
if (partType === "text") {
|
|
19695
|
+
part = { text: artifactBuffer.toString() };
|
|
19696
|
+
} else if (partType === "fileData") {
|
|
19697
|
+
part = {
|
|
19698
|
+
fileData: {
|
|
19699
|
+
fileUri: artifactBuffer.toString(),
|
|
19700
|
+
mimeType: metadata.contentType || "application/octet-stream"
|
|
19701
|
+
}
|
|
19702
|
+
};
|
|
19703
|
+
} else {
|
|
19704
|
+
part = {
|
|
19705
|
+
inlineData: {
|
|
19706
|
+
data: artifactBuffer.toString(),
|
|
19707
|
+
mimeType: metadata.contentType || "application/octet-stream"
|
|
19708
|
+
}
|
|
19709
|
+
};
|
|
19710
|
+
}
|
|
19527
19711
|
return part;
|
|
19528
19712
|
} catch (error) {
|
|
19529
19713
|
if (error?.code === 404) {
|
|
@@ -19647,7 +19831,7 @@ var EvalResult = class {
|
|
|
19647
19831
|
this.evalSetResultName = init.evalSetResultName;
|
|
19648
19832
|
this.evalSetId = init.evalSetId || "";
|
|
19649
19833
|
this.evalCaseResults = init.evalCaseResults || [];
|
|
19650
|
-
this.creationTimestamp = init.creationTimestamp || Date.now()
|
|
19834
|
+
this.creationTimestamp = init.creationTimestamp || Date.now();
|
|
19651
19835
|
}
|
|
19652
19836
|
};
|
|
19653
19837
|
|
|
@@ -19675,6 +19859,8 @@ var BaseEvalService = class {
|
|
|
19675
19859
|
};
|
|
19676
19860
|
|
|
19677
19861
|
// src/evaluation/vertex-ai-eval-facade.ts
|
|
19862
|
+
import { GoogleAuth } from "google-auth-library";
|
|
19863
|
+
import axios4 from "axios";
|
|
19678
19864
|
var ERROR_MESSAGE_SUFFIX = `
|
|
19679
19865
|
You should specify both project id and location. This metric uses Vertex Gen AI
|
|
19680
19866
|
Eval SDK, and it requires google cloud credentials.
|
|
@@ -19685,6 +19871,28 @@ the template below:
|
|
|
19685
19871
|
process.env.GOOGLE_CLOUD_LOCATION = <LOCATION>
|
|
19686
19872
|
process.env.GOOGLE_CLOUD_PROJECT = <PROJECT ID>
|
|
19687
19873
|
`;
|
|
19874
|
+
var VERTEX_AI_EVAL_SCOPES = [
|
|
19875
|
+
"https://www.googleapis.com/auth/cloud-platform"
|
|
19876
|
+
];
|
|
19877
|
+
var VERTEX_AI_METRIC_KEYS = {
|
|
19878
|
+
["response_evaluation_score" /* RESPONSE_EVALUATION_SCORE */]: {
|
|
19879
|
+
inputKey: "coherence_input",
|
|
19880
|
+
resultKey: "coherenceResult"
|
|
19881
|
+
},
|
|
19882
|
+
["safety_v1" /* SAFETY_V1 */]: {
|
|
19883
|
+
inputKey: "safety_input",
|
|
19884
|
+
resultKey: "safetyResult"
|
|
19885
|
+
}
|
|
19886
|
+
};
|
|
19887
|
+
function getMetricKeys(metric) {
|
|
19888
|
+
const keys = VERTEX_AI_METRIC_KEYS[metric];
|
|
19889
|
+
if (!keys) {
|
|
19890
|
+
throw new Error(
|
|
19891
|
+
`Metric "${metric}" is not supported by Vertex AI evaluation.`
|
|
19892
|
+
);
|
|
19893
|
+
}
|
|
19894
|
+
return keys;
|
|
19895
|
+
}
|
|
19688
19896
|
var VertexAiEvalFacade = class _VertexAiEvalFacade {
|
|
19689
19897
|
threshold;
|
|
19690
19898
|
metricName;
|
|
@@ -19709,8 +19917,8 @@ var VertexAiEvalFacade = class _VertexAiEvalFacade {
|
|
|
19709
19917
|
};
|
|
19710
19918
|
try {
|
|
19711
19919
|
const evalCaseResult = await _VertexAiEvalFacade._performEval(
|
|
19712
|
-
|
|
19713
|
-
|
|
19920
|
+
evalCase,
|
|
19921
|
+
this.metricName
|
|
19714
19922
|
);
|
|
19715
19923
|
const score = this._getScore(evalCaseResult);
|
|
19716
19924
|
perInvocationResults.push({
|
|
@@ -19754,8 +19962,9 @@ var VertexAiEvalFacade = class _VertexAiEvalFacade {
|
|
|
19754
19962
|
return "";
|
|
19755
19963
|
}
|
|
19756
19964
|
_getScore(evalResult) {
|
|
19757
|
-
|
|
19758
|
-
|
|
19965
|
+
const meanScore = evalResult?.summaryMetrics?.[0]?.meanScore;
|
|
19966
|
+
if (typeof meanScore === "number" && !Number.isNaN(meanScore)) {
|
|
19967
|
+
return meanScore;
|
|
19759
19968
|
}
|
|
19760
19969
|
return void 0;
|
|
19761
19970
|
}
|
|
@@ -19765,7 +19974,7 @@ var VertexAiEvalFacade = class _VertexAiEvalFacade {
|
|
|
19765
19974
|
}
|
|
19766
19975
|
return 3 /* NOT_EVALUATED */;
|
|
19767
19976
|
}
|
|
19768
|
-
static async _performEval(
|
|
19977
|
+
static async _performEval(evalCase, metric) {
|
|
19769
19978
|
const projectId = process.env.GOOGLE_CLOUD_PROJECT;
|
|
19770
19979
|
const location = process.env.GOOGLE_CLOUD_LOCATION;
|
|
19771
19980
|
if (!projectId) {
|
|
@@ -19774,13 +19983,50 @@ var VertexAiEvalFacade = class _VertexAiEvalFacade {
|
|
|
19774
19983
|
if (!location) {
|
|
19775
19984
|
throw new Error(`Missing location. ${ERROR_MESSAGE_SUFFIX}`);
|
|
19776
19985
|
}
|
|
19777
|
-
|
|
19778
|
-
|
|
19779
|
-
)
|
|
19986
|
+
const auth = new GoogleAuth({ scopes: VERTEX_AI_EVAL_SCOPES });
|
|
19987
|
+
const accessToken = await auth.getAccessToken();
|
|
19988
|
+
if (!accessToken) {
|
|
19989
|
+
throw new Error(
|
|
19990
|
+
"Failed to obtain Google Cloud access token. Ensure Application Default Credentials are configured (e.g. run 'gcloud auth application-default login')."
|
|
19991
|
+
);
|
|
19992
|
+
}
|
|
19993
|
+
const { inputKey, resultKey } = getMetricKeys(metric);
|
|
19994
|
+
const url = `https://${location}-aiplatform.googleapis.com/v1beta1/projects/${projectId}/locations/${location}:evaluateInstances`;
|
|
19995
|
+
const instance = {
|
|
19996
|
+
prediction: evalCase.response
|
|
19997
|
+
};
|
|
19998
|
+
if (metric === "response_evaluation_score" /* RESPONSE_EVALUATION_SCORE */) {
|
|
19999
|
+
instance.reference = evalCase.reference;
|
|
20000
|
+
}
|
|
20001
|
+
const requestBody = {
|
|
20002
|
+
[inputKey]: {
|
|
20003
|
+
metric_spec: {},
|
|
20004
|
+
instance
|
|
20005
|
+
}
|
|
20006
|
+
};
|
|
20007
|
+
let responseData;
|
|
20008
|
+
try {
|
|
20009
|
+
const response = await axios4.post(url, requestBody, {
|
|
20010
|
+
headers: {
|
|
20011
|
+
Authorization: `Bearer ${accessToken}`,
|
|
20012
|
+
"Content-Type": "application/json"
|
|
20013
|
+
}
|
|
20014
|
+
});
|
|
20015
|
+
responseData = response.data;
|
|
20016
|
+
} catch (error) {
|
|
20017
|
+
if (axios4.isAxiosError(error)) {
|
|
20018
|
+
const detail = error.response?.data ? JSON.stringify(error.response.data) : "";
|
|
20019
|
+
throw new Error(
|
|
20020
|
+
`Vertex AI evaluation API request failed: ${error.message}${detail ? ` \u2014 ${detail}` : ""}`
|
|
20021
|
+
);
|
|
20022
|
+
}
|
|
20023
|
+
throw error;
|
|
20024
|
+
}
|
|
20025
|
+
const score = responseData?.[resultKey]?.score;
|
|
19780
20026
|
return {
|
|
19781
20027
|
summaryMetrics: [
|
|
19782
20028
|
{
|
|
19783
|
-
meanScore:
|
|
20029
|
+
meanScore: typeof score === "number" ? score : void 0
|
|
19784
20030
|
}
|
|
19785
20031
|
]
|
|
19786
20032
|
};
|
|
@@ -20236,9 +20482,13 @@ var LocalEvalService = class extends BaseEvalService {
|
|
|
20236
20482
|
super();
|
|
20237
20483
|
this.agent = agent;
|
|
20238
20484
|
this.parallelism = parallelism;
|
|
20239
|
-
this.initializeRunner();
|
|
20485
|
+
this.readyPromise = this.initializeRunner();
|
|
20240
20486
|
}
|
|
20241
20487
|
runner;
|
|
20488
|
+
readyPromise;
|
|
20489
|
+
ensureReady() {
|
|
20490
|
+
return this.readyPromise;
|
|
20491
|
+
}
|
|
20242
20492
|
async initializeRunner() {
|
|
20243
20493
|
if ("ask" in this.agent) {
|
|
20244
20494
|
this.runner = this.agent;
|
|
@@ -20337,9 +20587,7 @@ var LocalEvalService = class extends BaseEvalService {
|
|
|
20337
20587
|
}
|
|
20338
20588
|
async runInference(evalCase) {
|
|
20339
20589
|
const results = [];
|
|
20340
|
-
|
|
20341
|
-
await this.initializeRunner();
|
|
20342
|
-
}
|
|
20590
|
+
await this.ensureReady();
|
|
20343
20591
|
if (evalCase.sessionInput) {
|
|
20344
20592
|
try {
|
|
20345
20593
|
if (this.runner.initializeSession) {
|
|
@@ -22897,6 +23145,7 @@ import { sql } from "kysely";
|
|
|
22897
23145
|
var DatabaseSessionService = class extends BaseSessionService {
|
|
22898
23146
|
db;
|
|
22899
23147
|
initialized = false;
|
|
23148
|
+
initPromise = null;
|
|
22900
23149
|
constructor(config) {
|
|
22901
23150
|
super();
|
|
22902
23151
|
this.db = config.db;
|
|
@@ -22907,12 +23156,26 @@ var DatabaseSessionService = class extends BaseSessionService {
|
|
|
22907
23156
|
}
|
|
22908
23157
|
}
|
|
22909
23158
|
/**
|
|
22910
|
-
* Initialize the database by creating required tables if they don't exist
|
|
23159
|
+
* Initialize the database by creating required tables if they don't exist.
|
|
23160
|
+
* Uses promise deduplication so concurrent callers share a single initialization.
|
|
22911
23161
|
*/
|
|
22912
|
-
|
|
23162
|
+
initializeDatabase() {
|
|
22913
23163
|
if (this.initialized) {
|
|
22914
|
-
return;
|
|
23164
|
+
return Promise.resolve();
|
|
23165
|
+
}
|
|
23166
|
+
if (this.initPromise) {
|
|
23167
|
+
return this.initPromise;
|
|
22915
23168
|
}
|
|
23169
|
+
const promise = this._doInitialize();
|
|
23170
|
+
this.initPromise = promise;
|
|
23171
|
+
promise.catch(() => {
|
|
23172
|
+
if (this.initPromise === promise) {
|
|
23173
|
+
this.initPromise = null;
|
|
23174
|
+
}
|
|
23175
|
+
});
|
|
23176
|
+
return promise;
|
|
23177
|
+
}
|
|
23178
|
+
async _doInitialize() {
|
|
22916
23179
|
try {
|
|
22917
23180
|
await this.db.schema.createTable("sessions").ifNotExists().addColumn("id", "varchar(128)", (col) => col.notNull()).addColumn("app_name", "varchar(128)", (col) => col.notNull()).addColumn("user_id", "varchar(128)", (col) => col.notNull()).addColumn("state", "text", (col) => col.defaultTo("{}")).addColumn(
|
|
22918
23181
|
"create_time",
|
|
@@ -23179,7 +23442,8 @@ var DatabaseSessionService = class extends BaseSessionService {
|
|
|
23179
23442
|
session.lastUpdateTime = this.timestampToUnixSeconds(
|
|
23180
23443
|
updatedSession.update_time
|
|
23181
23444
|
);
|
|
23182
|
-
|
|
23445
|
+
this.updateSessionState(session, event);
|
|
23446
|
+
session.events.push(event);
|
|
23183
23447
|
return event;
|
|
23184
23448
|
});
|
|
23185
23449
|
}
|